diff --git a/gui/game_run.pas b/gui/game_run.pas index 19e4ceae..a968a271 100644 --- a/gui/game_run.pas +++ b/gui/game_run.pas @@ -31,6 +31,7 @@ uses //internal libs ps4_libSceSystemService, + ps4_libSceUserService, ps4_libSceIpmi, ps4_libSceDialogs, ps4_libSceAvSetting diff --git a/rtl/ntapi.pas b/rtl/ntapi.pas index 4290f3e0..09e58540 100644 --- a/rtl/ntapi.pas +++ b/rtl/ntapi.pas @@ -73,6 +73,8 @@ const ThreadSetTlsArrayAddress = 15; ThreadIsIoPending = 16; ThreadHideFromDebugger = 17; + ThreadNameInformation = 38; + ThreadSystemThreadInformation = 40; //ProcessInformationClass ProcessBasicInformation=0; @@ -155,6 +157,8 @@ const MEM_COALESCE_PLACEHOLDERS=$01; MEM_PRESERVE_PLACEHOLDER =$02; + MEM_RESET_UNDO=$1000000; + OBJ_INHERIT =$00000002; OBJ_PERMANENT =$00000010; OBJ_EXCLUSIVE =$00000020; diff --git a/sys/dev/dev_gc.pas b/sys/dev/dev_gc.pas index c9ee1531..8e6d4d83 100644 --- a/sys/dev/dev_gc.pas +++ b/sys/dev/dev_gc.pas @@ -20,7 +20,8 @@ uses vm_pmap, sys_vm_object, vm_pager, - subr_backtrace; + subr_backtrace, + bittype; var gc_page:Pointer; @@ -43,6 +44,49 @@ type param3:DWORD; end; + p_Submit=^t_Submit; + t_Submit=packed record + arg0 :DWORD; + count:DWORD; + cmds :PQWORD; + end; + +function PM4_TYPE(token:DWORD):Byte; inline; +begin + Result:=(token shr 30) and 3; +end; + +function PM4_LENGTH_DW(token:DWORD):WORD; inline; +begin + Result:=((token shr 16) and $3FFF) + 2; +end; + +type + PPM4_TYPE_3_HEADER=^PM4_TYPE_3_HEADER; + PM4_TYPE_3_HEADER=bitpacked record + predicate:bit1; //1 + shaderType:bit1; //1 + reserved:bit6; //6 + opcode:Byte; //8 + count:bit14; //14 + _type:bit2; //2 + end; + + PPM4CMDINDIRECTBUFFER=^PM4CMDINDIRECTBUFFER; + PM4CMDINDIRECTBUFFER=bitpacked record + ibBaseLo :DWORD; ///< Indirect buffer base address, must be 4 byte aligned + ibBaseHi32 :DWORD; ///< Indirect buffer base address + // + ibSize :bit20; ///< Indirect buffer size + chain :bit1; ///< set to chain to IB allocations + offLoadPolling:bit1; + volatile__CI :bit1; + valid :bit1; + vmid :bit4; ///< Virtual memory domain ID for command buffer + cachePolicy :bit2; + reserved1 :bit2; + end; + Function gc_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer; begin Result:=0; @@ -79,6 +123,7 @@ begin end; $C008811B: //sceGnmAreSubmitsAllowed begin + //ret1 = mmap_addr(0xfe0100000,0x4000,1,(ulong *)&paddr,&local_50); PPointer(data)^:=@gc_AreSubmitsAllowed; end; @@ -98,7 +143,32 @@ begin $C0048114: //sceGnmFlushGarlic begin Writeln('sceGnmFlushGarlic'); - end + end; + + $C0108102: //submit + begin + Writeln(p_Submit(data)^.arg0); + Writeln(p_Submit(data)^.count); + Writeln(HexStr(p_Submit(data)^.cmds)); + + //IT_INDIRECT_BUFFER_CNST = $00000033; ccb + //IT_COND_INDIRECT_BUFFER = $0000003f; dcb + + //opcode 0x33 0x3F + //if ((op != L'\xc0023300') && (op != L'\xc0023f00')) { + // printf("## %s: invalid opcode = 0x%08x\n","gc_insert_indirect_buffer"); + // ret1 = 0x804c0010; + // goto LAB_ffffffff826bd78b; + //} + //if ((_buffer[1] & 0xfffff00000000) == 0) { + // printf("## %s: invalid ib_size = 0x%05x\n","gc_insert_indirect_buffer",0); + // ret1 = 0x804c0011; + // goto LAB_ffffffff826bd78b; + //} + + + Assert(False); + end; else diff --git a/sys/kern/kern_exec.pas b/sys/kern/kern_exec.pas index 2da290bf..8c04eb29 100644 --- a/sys/kern/kern_exec.pas +++ b/sys/kern/kern_exec.pas @@ -1422,21 +1422,7 @@ begin Move(p_proc.p_comm, td^.td_name, sizeof(td^.td_name)); KernSetThreadDebugName(td,'ps4:'); - { - * mark as execed, wakeup the process that vforked (if any) and tell - * it that it now has its own resources back - } - p_proc.p_flag:=p_proc.p_flag or P_EXEC; - - { - * Notify others that we exec'd, and clear the P_INEXEC flag - * as we're now a bona fide freshly-execed process. - } - KNOTE_LOCKED(@p_proc.p_klist, NOTE_EXEC); - p_proc.p_flag:=p_proc.p_flag and (not P_INEXEC); - - { clear 'fork but no exec' flag, as we _are_ execing } - //p^.p_acflag:= and ~AFORK; + PROC_UNLOCK(); { * Free any previous argument cache and replace it with @@ -1446,8 +1432,6 @@ begin p_proc.p_args:=newargs; newargs:=nil; - PROC_UNLOCK(); - dynlib_proc_initialize_step3(imgp); if (dynlibs_info.libkernel=nil) then @@ -1456,6 +1440,26 @@ begin goto exec_fail_dealloc; end; + PROC_LOCK(); + + { + * mark as execed, wakeup the process that vforked (if any) and tell + * it that it now has its own resources back + } + p_proc.p_flag:=p_proc.p_flag or P_EXEC; + + { + * Notify others that we exec'd, and clear the P_INEXEC flag + * as we're now a bona fide freshly-execed process. + } + KNOTE_LOCKED(@p_proc.p_klist, NOTE_EXEC); + p_proc.p_flag:=p_proc.p_flag and (not P_INEXEC); + + { clear 'fork but no exec' flag, as we _are_ execing } + //p^.p_acflag:= and ~AFORK; + + PROC_UNLOCK(); + vms:=p_proc.p_vmspace; { Set values passed into the program in registers. } @@ -1556,6 +1560,13 @@ done2: VFS_UNLOCK_GIANT(vfslocked); exec_free_args(args); + if (error<>0) then + begin + // sorry, no more process anymore. exit gracefully + //exit1(td, W_EXITCODE(0, SIGABRT)); + // NOT REACHED + end; + Exit(error); end; diff --git a/sys/kern/kern_thread.pas b/sys/kern/kern_thread.pas index d44cee4e..f7ad645f 100644 --- a/sys/kern/kern_thread.pas +++ b/sys/kern/kern_thread.pas @@ -325,13 +325,17 @@ end; procedure KernSetThreadDebugName(newtd:p_kthread;prefix:PChar); var - td:p_kthread; - backup:array[0..1] of QWORD; + //td:p_kthread; + //backup:array[0..1] of QWORD; name:shortstring; begin name:=shortstring(prefix)+shortstring(newtd^.td_name); + cpu_thread_set_name(newtd,name); + + { td:=curkthread; + if (td<>nil) then begin //prevent bullshit in ntdll:__chkstk @@ -349,6 +353,7 @@ begin PQWORD(td^.td_kstack.stack)[-1]:=backup[0]; PQWORD(td^.td_kstack.stack)[-2]:=backup[1]; end; + } end; procedure before_start(td:p_kthread); diff --git a/sys/md/md_exception.pas b/sys/md/md_exception.pas index c4e0e50d..1b924eda 100644 --- a/sys/md/md_exception.pas +++ b/sys/md/md_exception.pas @@ -327,7 +327,7 @@ begin Writeln(stderr,_get_msg(Msg),' (',FName,', line ',LineNo,').'); print_backtrace(stderr,Get_pc_addr,get_frame,2); - sleep(-1); + //sleep(-1); if IsDebuggerPresent then Raise EAssertionFailed. @@ -340,6 +340,8 @@ begin // int3 //end; + sleep(-1); + md_halt(217); end; diff --git a/sys/md/md_map.pas b/sys/md/md_map.pas index 0ab4d88a..2994a3e2 100644 --- a/sys/md/md_map.pas +++ b/sys/md/md_map.pas @@ -47,7 +47,9 @@ function md_memfd_open (var hMem:THandle;hFile:THandle):Integer; function md_memfd_close (hMem:THandle):Integer; function md_protect(base:Pointer;size:QWORD;prot:Integer):Integer; -function md_reset (base:Pointer;size:QWORD;prot:Integer):Integer; + +function md_dontneed(base:Pointer;size:QWORD):Integer; +function md_activate(base:Pointer;size:QWORD):Integer; function md_mmap (var base:Pointer;size:QWORD;prot:Integer):Integer; function md_unmap (base:Pointer;size:QWORD):Integer; @@ -212,7 +214,7 @@ begin ); end; -function md_reset(base:Pointer;size:QWORD;prot:Integer):Integer; +function md_dontneed(base:Pointer;size:QWORD):Integer; begin Result:=NtAllocateVirtualMemory( NtCurrentProcess, @@ -220,7 +222,19 @@ begin 0, @size, MEM_RESET, - prot + PAGE_NOACCESS + ); +end; + +function md_activate(base:Pointer;size:QWORD):Integer; +begin + Result:=NtAllocateVirtualMemory( + NtCurrentProcess, + @base, + 0, + @size, + MEM_RESET_UNDO, + PAGE_NOACCESS ); end; diff --git a/sys/md/md_thread.pas b/sys/md/md_thread.pas index c53ca7df..8b3c6310 100644 --- a/sys/md/md_thread.pas +++ b/sys/md/md_thread.pas @@ -8,7 +8,8 @@ interface uses ntapi, windows, - kern_thr; + kern_thr, + sysutils; Const SYS_STACK_RSRV=64*1024; @@ -32,6 +33,8 @@ function cpu_thread_finished(td:p_kthread):Boolean; function cpuset_setaffinity(td:p_kthread;new:Ptruint):Integer; function cpu_set_priority(td:p_kthread;prio:Integer):Integer; +function cpu_thread_set_name(td:p_kthread;const name:shortstring):Integer; + procedure seh_wrapper_before(td:p_kthread;var func:Pointer); procedure seh_wrapper_after (td:p_kthread;func:Pointer); @@ -320,6 +323,27 @@ begin Result:=NtSetInformationThread(td^.td_handle,ThreadBasePriority,@prio,SizeOf(Integer)); end; +function cpu_thread_set_name(td:p_kthread;const name:shortstring):Integer; +var + W:array[0..255] of WideChar; + UNAME:UNICODE_STRING; + L:DWORD; +begin + Result:=0; + if (td=nil) then Exit; + if (td^.td_handle=0) or (td^.td_handle=THandle(-1)) then Exit; + + L:=Utf8ToUnicode(@W,length(W),@name[1],length(name)); + + W:=UTF8Decode(name); + + UNAME.Length :=L*SizeOf(WideChar); + UNAME.MaximumLength:=UNAME.Length; + UNAME.Buffer :=@W; + + Result:=NtSetInformationThread(td^.td_handle,ThreadNameInformation,@UNAME,SizeOf(UNAME)); +end; + procedure main_wrapper; assembler; nostackframe; asm subq $40, %rsp diff --git a/sys/md/vm_pmap.pas b/sys/md/vm_pmap.pas index d427b175..d0cec3ba 100644 --- a/sys/md/vm_pmap.pas +++ b/sys/md/vm_pmap.pas @@ -92,24 +92,20 @@ procedure pmap_enter_object(pmap :pmap_t; procedure pmap_protect(pmap :pmap_t; obj :vm_object_t; - offset:vm_ooffset_t; start :vm_offset_t; __end :vm_offset_t; prot :vm_prot_t); -procedure pmap_madv_free(pmap :pmap_t; - obj :vm_object_t; - offset:vm_ooffset_t; - start :vm_offset_t; - __end :vm_offset_t; - prot :vm_prot_t); +procedure pmap_madvise(pmap :pmap_t; + obj :vm_object_t; + start :vm_offset_t; + __end :vm_offset_t; + advise:Integer); procedure pmap_remove(pmap :pmap_t; obj :vm_object_t; - offset:vm_ooffset_t; start :vm_offset_t; - __end :vm_offset_t; - prot :vm_prot_t); + __end :vm_offset_t); implementation @@ -760,14 +756,11 @@ end; procedure pmap_protect(pmap :pmap_t; obj :vm_object_t; - offset:vm_ooffset_t; start :vm_offset_t; __end :vm_offset_t; prot :vm_prot_t); label _default; -var - size:QWORD; begin Writeln('pmap_protect:',HexStr(start,11),':',HexStr(__end,11),':prot:',HexStr(prot,2)); @@ -816,19 +809,18 @@ begin pmap_mark(start,__end,prot and VM_RWX); end; -procedure pmap_madv_free(pmap :pmap_t; - obj :vm_object_t; - offset:vm_ooffset_t; - start :vm_offset_t; - __end :vm_offset_t; - prot :vm_prot_t); +procedure pmap_madvise(pmap :pmap_t; + obj :vm_object_t; + start :vm_offset_t; + __end :vm_offset_t; + advise:Integer); label _default; var size:QWORD; r:Integer; begin - Writeln('pmap_madv_free:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2)); + Writeln('pmap_madv_free:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(advise,2)); r:=0; case vm_object_type(obj) of @@ -840,7 +832,7 @@ begin size:=(__end-start); - r:=md_reset(Pointer(start),size,wprots[prot and VM_RWX]); + r:=md_dontneed(Pointer(start),size); end; OBJT_DEVICE: begin @@ -875,16 +867,14 @@ end; procedure pmap_remove(pmap :pmap_t; obj :vm_object_t; - offset:vm_ooffset_t; start :vm_offset_t; - __end :vm_offset_t; - prot :vm_prot_t); + __end :vm_offset_t); label _default; var r:Integer; begin - Writeln('pmap_remove:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2)); + Writeln('pmap_remove:',HexStr(start,11),':',HexStr(__end,11)); pmap_unmark(start,__end); @@ -910,10 +900,10 @@ begin if ((obj^.flags and OBJ_DMEM_EXT)<>0) then begin - Writeln('pmap_remove_gpuobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2)); + Writeln('pmap_remove_gpuobj:',HexStr(start,11),':',HexStr(__end,11)); end else begin - Writeln('pmap_remove_devobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2)); + Writeln('pmap_remove_devobj:',HexStr(start,11),':',HexStr(__end,11)); end; goto _default; diff --git a/sys/test/ps4_libsceuserservice.pas b/sys/test/ps4_libsceuserservice.pas new file mode 100644 index 00000000..a0943c42 --- /dev/null +++ b/sys/test/ps4_libsceuserservice.pas @@ -0,0 +1,166 @@ +unit ps4_libSceUserService; + +{$mode objfpc}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +uses + subr_dynlib, + atomic, + Classes, + SysUtils; + +const + SCE_USER_SERVICE_MAX_LOGIN_USERS=4; + SCE_USER_SERVICE_USER_ID_INVALID=Integer($FFFFFFFF); + +type + PUserServiceInitializeParams=^TUserServiceInitializeParams; + TUserServiceInitializeParams=packed record + priority:DWORD; + end; + + PUserServiceLoginUserIdList=^TUserServiceLoginUserIdList; + TUserServiceLoginUserIdList=packed record + userId:array[0..SCE_USER_SERVICE_MAX_LOGIN_USERS-1] of Integer; + end; + +const +//SceUserServiceEventType + SCE_USER_SERVICE_EVENT_TYPE_LOGIN =0; + SCE_USER_SERVICE_EVENT_TYPE_LOGOUT =1; + +type + pSceUserServiceEvent=^SceUserServiceEvent; + SceUserServiceEvent=packed record + eventType:Integer; //SceUserServiceEventType + userId:Integer; //SceUserServiceUserId + end; + + TUserServiceEventCallback=procedure(event:pSceUserServiceEvent;arg:Pointer); + +implementation + +const + SCE_USER_SERVICE_ERROR_NOT_INITIALIZED =-2137653246; //0x80960002 + SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT=-2137653243; //0x80960005 + SCE_USER_SERVICE_ERROR_NO_EVENT =-2137653241; //0x80960007 + SCE_USER_SERVICE_ERROR_BUFFER_TOO_SHORT=-2137653238; //0x8096000A + +function ps4_sceUserServiceInitialize(params:PUserServiceInitializeParams):Integer; +begin + Result:=0; +end; + +function ps4_sceUserServiceInitialize2(threadPriority:Integer;cpuAffinityMask:qword):Integer; +begin + Result:=0; +end; + +function ps4_sceUserServiceTerminate:Integer; +begin + Result:=0; +end; + +function ps4_sceUserServiceGetLoginUserIdList(List:PUserServiceLoginUserIdList):Integer; +var + i:Integer; +begin + Result:=-1; + if (List=nil) then Exit; + List^.userId[0]:=1; + For i:=1 to SCE_USER_SERVICE_MAX_LOGIN_USERS-1 do + List^.userId[i]:=SCE_USER_SERVICE_USER_ID_INVALID; + Result:=0; +end; + +function ps4_sceUserServiceGetInitialUser(pUserId:PInteger):Integer; +begin + if (pUserId=nil) then Exit(SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT); + pUserId^:=1; + Result:=0; +end; + +function ps4_sceUserServiceGetUserName(userId:Integer;userName:PChar;size:size_t):Integer; +Const + cuser:PChar='user'#0; +begin + if (userName=nil) then Exit(SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT); + if (size0) then + if (obj^.hfile<>0) then begin r:=md_memfd_close(obj^.hfile); if (r<>0) then @@ -281,15 +287,18 @@ begin end; end; - r:=md_file_mmap_ex(entry^.obj^.hfile, - Pointer(entry^.start), - entry^.offset, - entry^.size, //unaligned size - MD_PROT_RW); - if (r<>0) then + if (entry^.obj^.hfile<>0) then begin - Writeln('failed md_file_mmap_ex(',HexStr(entry^.start,11),',',HexStr(entry^.start+size,11),'):0x',HexStr(r,8)); - Assert(false,'vm_map'); + r:=md_file_mmap_ex(entry^.obj^.hfile, + Pointer(entry^.start), + entry^.offset, + entry^.size, //unaligned size + MD_PROT_RW); + if (r<>0) then + begin + Writeln('failed md_file_mmap_ex(',HexStr(entry^.start,11),',',HexStr(entry^.start+size,11),'):0x',HexStr(r,8)); + Assert(false,'vm_map'); + end; end; if (prot<>MD_PROT_RW) then @@ -384,11 +393,15 @@ begin if (p^.start<>0) and (p^.start<>p^.__end) then begin - r:=md_file_unmap_ex(Pointer(p^.start)); - if (r<>0) then + // + if (stat.obj^.hfile<>0) then begin - Writeln('failed md_file_unmap_ex(',HexStr(p^.start,11),',',HexStr(p^.__end,11),'):0x',HexStr(r,8)); - Assert(false,'vm_remap'); + r:=md_file_unmap_ex(Pointer(p^.start)); + if (r<>0) then + begin + Writeln('failed md_file_unmap_ex(',HexStr(p^.start,11),',',HexStr(p^.__end,11),'):0x',HexStr(r,8)); + Assert(false,'vm_remap'); + end; end; // //Writeln('md_file_unmap_ex(',HexStr(p^.start,11),',',HexStr(p^.__end,11),'):0x',HexStr(r,8)); @@ -440,6 +453,7 @@ begin begin //map new if (ets[i]^.obj<>nil) then + if (stat.obj^.hfile<>0) then begin r:=md_file_mmap_ex(stat.obj^.hfile, Pointer(ets[i]^.start), @@ -482,6 +496,7 @@ var r:Integer; begin if (entry^.obj<>nil) then + if (entry^.obj^.hfile<>0) then begin r:=md_file_unmap_ex(Pointer(entry^.start)); if (r<>0) then @@ -1066,6 +1081,55 @@ begin end; end; +procedure vm_nt_map_madvise(map:p_vm_nt_map; + start:vm_offset_t; + __end:vm_offset_t; + advise:Integer); +var + entry:p_vm_nt_entry; + base,size:vm_size_t; + r:Integer; +begin + if (start=__end) then Exit; + + if (not vm_nt_map_lookup_entry(map, start, @entry)) then + begin + entry:=entry^.next; + end else + begin + entry:=entry; + end; + + while (entry<>@map^.header) and (entry^.start<__end) do + begin + base:=entry^.start; + size:=entry^.__end; + + if (base__end) then + begin + size:=__end; + end; + + size:=size-base; + + case advise of + MADV_WILLNEED:r:=md_dontneed(Pointer(base),size); + MADV_DONTNEED, + MADV_FREE :r:=md_activate(Pointer(base),size); + else; + end; + + //ignore errors + + entry:=entry^.next; + end; +end; + end. diff --git a/sys/vm/vm_object.pas b/sys/vm/vm_object.pas index 237fabeb..403a8873 100644 --- a/sys/vm/vm_object.pas +++ b/sys/vm/vm_object.pas @@ -33,10 +33,17 @@ function vm_object_coalesce(prev_object:vm_object_t; next_size :vm_ooffset_t; reserved :Boolean):Boolean; +procedure vm_object_madvise(pmap :Pointer; + obj :vm_object_t; + start :vm_offset_t; + __end :vm_offset_t; + advise:Integer); + implementation uses vmparam, + vm_pmap, vnode, vnode_if, vmount, @@ -409,5 +416,96 @@ begin Result:=(TRUE); end; +{ + vm_object_madvise: + + Implements the madvise function at the object/page level. + + MADV_WILLNEED (any object) + + Activate the specified pages if they are resident. + + MADV_DONTNEED (any object) + + Deactivate the specified pages if they are resident. + + MADV_FREE (OBJT_DEFAULT/OBJT_SWAP objects, + OBJ_ONEMAPPING only) + + Deactivate and clean the specified pages if they are + resident. This permits the process to reuse the pages + without faulting or the kernel to reclaim the pages + without I/O. +} +procedure vm_object_madvise(pmap :Pointer; + obj :vm_object_t; + start :vm_offset_t; + __end :vm_offset_t; + advise:Integer); +label + unlock_tobject; +begin + if (obj=nil) then + begin + + case advise of + MADV_WILLNEED, + MADV_DONTNEED, + MADV_FREE : + begin + pmap_madvise(pmap, + obj, + start, + __end, + advise); + end + else; + end; + + Exit; + end; + + VM_OBJECT_LOCK(obj); + + { + * MADV_FREE only operates on OBJT_DEFAULT or OBJT_SWAP pages + * and those pages must be OBJ_ONEMAPPING. + } + if (advise=MADV_FREE) then + begin + if ((obj^.otype<>OBJT_DEFAULT) and + (obj^.otype<>OBJT_SELF) and // + (obj^.otype<>OBJT_SWAP)) or + ((obj^.flags and OBJ_ONEMAPPING)=0) then + begin + goto unlock_tobject; + end; + end else + if (obj^.otype=OBJT_PHYS) then + begin + goto unlock_tobject; + end; + + case advise of + MADV_WILLNEED, + MADV_DONTNEED, + MADV_FREE : + begin + pmap_madvise(pmap, + obj, + start, + __end, + advise); + end + else; + end; + + unlock_tobject: + VM_OBJECT_UNLOCK(obj); +end; + + + + end.