diff --git a/kernel/mm.txt b/kernel/mm.txt index 999cdfd9..e926f6e5 100644 --- a/kernel/mm.txt +++ b/kernel/mm.txt @@ -34,7 +34,7 @@ int _sceKernelMapDirectMemory adr = *virtualAddrDest; if ((((_direct_pool_id == 1) && ((APP_INFO[4] & 2) == 0)) && (((long)physicalAddr < 0x3000000000 || (0x301fffffff < physicalAddr)))) && - (((flags & 0x400U) == 0 && (0x24fffff < SDK_VERSION)))) { + (((flags & SCE_KERNEL_MAP_DMEM_COMPAT) == 0 && (0x24fffff < SDK_VERSION)))) { ret1 = sceKernelMapDirectMemory2 (virtualAddrDest,length,-1,protections,flags,physicalAddr,alignment); return ret1; @@ -330,3 +330,102 @@ int sceKernelReleaseFlexibleMemory(void *addr,size_t len) return ret1; } +int sceKernelQueryMemoryProtection(void *addr,void **start,void **end,int *prot) + +{ + int ret1; + int *perror; + void *_start; + void *_end; + uint _prot; + long __guard; + int err; + + __guard = __stack_chk_guard._0_8_; + ret1 = sys_query_memory_protection(addr,&_start); + if (ret1 == 0) { + if (start != (void **)0x0) { + *start = _start; + } + if (end != (void **)0x0) { + *end = _end; + } + ret1 = 0; + if (prot != (int *)0x0) { + *prot = _prot & 0x37; + } + } + else { + perror = (int *)__error(); + err = *perror; + ret1 = err + -0x7ffe0000; + if (err == 0) { + ret1 = err; + } + } + if (__stack_chk_guard._0_8_ != __guard) { + /* WARNING: Subroutine does not return */ + __stack_chk_fail(); + } + return ret1; +} + +int sceKernelVirtualQuery(void *addr,int flags,void *info,qword infoSize) + +{ + int ret1; + int err; + int *perror; + + ret1 = sys_virtual_query(); + err = 0; + if (ret1 == -1) { + perror = (int *)__error(); + ret1 = *perror; + err = ret1 + -0x7ffe0000; + if (ret1 == 0) { + err = ret1; + } + } + return err; +} + +int sceKernelMtypeprotect(void *addr,qword len,int type,int prot) + +{ + int ret1; + int err; + int *perror; + + ret1 = sys_mtypeprotect(); + err = 0; + if (ret1 == -1) { + perror = (int *)__error(); + ret1 = *perror; + err = ret1 + -0x7ffe0000; + if (ret1 == 0) { + err = ret1; + } + } + return err; +} + +int sceKernelSetVirtualRangeName(void *addr,qword len,char *name) + +{ + int ret1; + int err; + int *perror; + + ret1 = sys_mname(); + err = 0; + if (ret1 == -1) { + perror = (int *)__error(); + ret1 = *perror; + err = ret1 + -0x7ffe0000; + if (ret1 == 0) { + err = ret1; + } + } + return err; +} diff --git a/kernel/mm_adr_virtual.pas b/kernel/mm_adr_virtual.pas index 7d00eee7..4179d19b 100644 --- a/kernel/mm_adr_virtual.pas +++ b/kernel/mm_adr_virtual.pas @@ -154,7 +154,7 @@ type Function check_fixed(Offset:Pointer;Size:QWORD;flags:Byte;fd:Integer):Integer; Function mmap(Offset:Pointer;Size,Align:QWORD;prot,flags:Byte;fd:Integer;addr:QWORD;var AdrOut:Pointer):Integer; - Function CheckedAlloc(Offset:Pointer;Size:QWORD):Integer; + procedure Protect(Offset:Pointer;Size:QWORD;prot:Integer); Function Release(Offset:Pointer;Size:QWORD):Integer; procedure Print; @@ -1113,40 +1113,98 @@ begin end; end; -///////// - -Function TVirtualManager.CheckedAlloc(Offset:Pointer;Size:QWORD):Integer; +procedure TVirtualManager.Protect(Offset:Pointer;Size:QWORD;prot:Integer); var - It:TAllcPoolNodeSet.Iterator; key:TVirtualAdrNode; - FEndO:Pointer; -begin - Result:=0; - if (Size=0) then Exit(EINVAL); - if (OffsetFhi) then Exit(EINVAL); + FEndN,FEndO:Pointer; + FSize:QWORD; - FEndO:=Offset+Size; - - key:=Default(TVirtualAdrNode); - key.Offset:=Offset; - - It:=FAllcSet.find_le(key); - While (It.Item<>nil) do + function _fetch:Boolean; begin - key:=It.Item^; + Result:=False; - if (Offset>=key.Offset) then + if _FetchNode_m(M_LE or C_FR or C_LE,Offset,key) then begin - if not key.IsFree then - begin - Exit(ENOMEM); - end; + FEndN:=Offset+Size; + FEndO:=key.Offset+key.Size; + + _Devide(Offset,Size,key); + + Result:=True; + end else + if _FetchNode_m(M_BE or C_FR or C_BE,Offset,key) then + begin + FEndN:=Offset+Size; + FEndO:=key.Offset+key.Size; + + _Devide(key.Offset,FEndN-key.Offset,key); + + Result:=True; + end; + end; + + function _map:Boolean; + begin + Result:=False; + + //new save + if (key.block=nil) then + begin + key.F.prot:=prot; + end else + begin + key.block^.Protect(@key,prot); end; - if (key.Offset>=FEndO) then Break; + _Merge(key); - It.Next; + if (FEndO>=FEndN) then Exit(True); + + FSize:=FEndO-Offset; + + Offset:=Offset+FSize; + Size :=Size -FSize; end; + + function _skip:Boolean; inline; + begin + Result:=False; + + FEndN:=Offset+Size; + FEndO:=key.Offset+key.Size; + + if (FEndO>=FEndN) then Exit(True); + + FSize:=FEndO-Offset; + + Offset:=Offset+FSize; + Size :=Size -FSize; + end; + +begin + + repeat + + key:=Default(TVirtualAdrNode); + key.Offset:=Offset; + + if _fetch then + begin + if _map then Break; + end else + if _Find_m(M_LE,key) then + begin + if _skip then Break; + end else + if _Find_m(M_BE,key) then + begin + if _skip then Break; + end else + begin + Break; + end; + + until false; end; Function TVirtualManager.Release(Offset:Pointer;Size:QWORD):Integer; @@ -1291,11 +1349,34 @@ begin until false; end; -function _alloc_str(IsFree:Boolean):RawByteString; +function _alloc_str(var key:TVirtualAdrNode):RawByteString; begin - Case IsFree of - True :Result:='FREE'; - FAlse:Result:='ALLC'; + if (key.F.Free<>0) then + begin + Result:='FREE'; + end else + if (key.F.reserv<>0) then + begin + Result:='RSRV'; + end else + if (key.F.direct<>0) then + begin + Result:='DRCT'; + end else + if (key.F.stack<>0) then + begin + Result:='STCK'; + end else + if (key.F.polled<>0) then + begin + Result:='POOL'; + end else + if (key.F.mapped<>0) then + begin + Result:='FMAP'; + end else + begin + Result:='ALLC'; end; end; @@ -1313,7 +1394,7 @@ begin HexStr(QWORD(key.Offset+key.Size),10),':', HexStr(key.Size,10),'#', HexStr(qword(key.addr),10),'#', - _alloc_str(key.IsFree),'#'); + _alloc_str(key),'#'); It.Next; end; diff --git a/kernel/ps4_map_mm.pas b/kernel/ps4_map_mm.pas index 72fad397..55d1f5ec 100644 --- a/kernel/ps4_map_mm.pas +++ b/kernel/ps4_map_mm.pas @@ -1616,7 +1616,7 @@ end; //flag:MAP_ANON fd=-1 //flex //flag:MAP_SHARED fd=/dev/dmem%d offset=physicalAddr //direct -function __mmap(addr:Pointer;len,align:size_t;prot,flags:Integer;fd:Integer;offset:size_t;var res:Pointer):Integer; +function __mmap(addr:Pointer;len,align:size_t;prot,flags,fd:Integer;offset:size_t;var res:Pointer):Integer; begin Result:=EINVAL; @@ -1668,6 +1668,36 @@ begin _sig_unlock; end; +function __sys_mmap_dmem( + addr:Pointer; + length:QWORD; + alignment:QWORD; + mtype,prots,flags:Integer; + physicalAddr:QWORD; + var res:Pointer):Integer; +begin + Result:=0; + + _sig_lock; + rwlock_wrlock(PageMM.FLock); //rw + + Result:=DirectManager.CheckedMMap(physicalAddr,length); + + if (Result=0) then + begin + flags:=flags or MAP_SHARED; + Result:=VirtualManager.mmap(addr,length,alignment,prots,flags,0,physicalAddr,res); + + if (Result=0) then + begin + Result:=DirectManager.mmap_addr(physicalAddr,length,addr,mtype); + end; + end; + + rwlock_unlock(PageMM.FLock); + _sig_unlock; +end; + function __munmap(addr:Pointer;len:size_t):Integer; begin Result:=VirtualManager.Release(addr,len); @@ -1692,49 +1722,183 @@ end; function _sceKernelMapFlexibleMemory( virtualAddrDest:PPointer; length:QWORD; - prot,flags:Integer; - physicalAddr:QWORD; - alignment:QWORD):Integer; SysV_ABI_CDecl; + prots,flags:Integer):Integer; var addr:Pointer; begin Result:=SCE_KERNEL_ERROR_EINVAL; - if ((($3fff < length) and ((length and $3fff)=0)) and - (((flags and $ffbfff6f) or (prot and $ffffffc8))=0)) then + if ((flags and $ffbfff6f)<>0) then Exit; + if ((prots and $ffffffc8)<>0) then Exit; + + if (length 0) and (addr=nil)) then begin - addr:=virtualAddrDest^; - - if (((flags and MAP_FIXED)<>0) and (addr=nil)) then + if (SDK_VERSION > $16fffff) then begin - if ($16fffff < SDK_VERSION) then - begin - Exit(SCE_KERNEL_ERROR_EINVAL); - end; - flags:=flags and $ffffffef; - Writeln('[WARNING] map(addr=0, flags=MAP_FIXED)'); - end else - if (addr=nil) then - begin - addr:=Pointer($001000000000); + Exit(SCE_KERNEL_ERROR_EINVAL); end; - - Result:=__mmap(addr,length,0,prot,flags or MAP_ANON,-1,0,addr); - _set_errno(Result); - - if (Result<>0) then - begin - Result:=px2sce(Result); - end else - begin - virtualAddrDest^:=addr; - Result:=0; - end; - + flags:=flags and $ffffffef; + Writeln('[WARNING] map(addr=0, flags=MAP_FIXED)'); end; + if (addr=nil) then + begin + addr:=Pointer($880000000); + end; + + Result:=__mmap(addr,length,0,prots,flags or MAP_ANON,-1,0,addr); + + if (Result=0) then + begin + virtualAddrDest^:=addr; + Result:=0; + end; end; +function _sceKernelReserveVirtualRange( + virtualAddrDest:PPointer; + length:QWORD; + flags:Integer; + alignment:QWORD):Integer; +var + addr:Pointer; +begin + Result:=SCE_KERNEL_ERROR_EINVAL; + + if ((flags and $ffbfff6f)<>0) then Exit; + + if (length31) then Exit; + + addr:=virtualAddrDest^; + if not IsAlign(addr,LOGICAL_PAGE_SIZE) then Exit; + + if (((flags and MAP_FIXED) <> 0) and (addr=nil)) then + begin + if (SDK_VERSION > $16fffff) then + begin + Exit(SCE_KERNEL_ERROR_EINVAL); + end; + flags:=flags and $ffffffef; + Writeln('[WARNING] map(addr=0, flags=MAP_FIXED)'); + end; + + Result:=__mmap(addr,length,alignment,0,flags or MAP_VOID or MAP_SHARED,-1,0,addr); + + if (Result=0) then + begin + virtualAddrDest^:=addr; + Result:=0; + end; +end; + +function _sceKernelMapDirectMemory2( + virtualAddrDest:PPointer; + length:QWORD; + mtype,prots,flags:Integer; + physicalAddr:QWORD; + alignment:QWORD):Integer; +var + addr:Pointer; +begin + Result:=SCE_KERNEL_ERROR_EINVAL; + + if ((flags and $1f000000)<>0) then Exit; + if ((prots and $ffffffc8)<>0) then Exit; + + if (length31) then Exit; + + addr:=virtualAddrDest^; + if not IsAlign(addr,LOGICAL_PAGE_SIZE) then Exit; + + Result:=__sys_mmap_dmem(addr,length,alignment,mtype,prots,flags,physicalAddr,addr); + + if (Result=0) then + begin + virtualAddrDest^:=addr; + Result:=0; + end; +end; + +function _sceKernelMapDirectMemory( + virtualAddrDest:PPointer; + length:QWORD; + prots,flags:Integer; + physicalAddr:QWORD; + alignment:QWORD):Integer; +var + addr:Pointer; + _flags:Integer; +begin + Result:=SCE_KERNEL_ERROR_EINVAL; + + if ((physicalAddr < $3000000000) or (physicalAddr > $301fffffff)) and + ((flags and SCE_KERNEL_MAP_DMEM_COMPAT)=0) and (SDK_VERSION > $24fffff) then + begin + Result:=_sceKernelMapDirectMemory2(virtualAddrDest,length,-1,prots,flags,physicalAddr,alignment); + Exit; + end; + + if ((flags and $1f000000)<>0) then Exit; + if ((prots and $ffffffc8)<>0) then Exit; + + if (length31) then Exit; + + addr:=virtualAddrDest^; + if not IsAlign(addr,LOGICAL_PAGE_SIZE) then Exit; + + _flags:=flags and $fffffbff; + + if (((flags and MAP_FIXED) <> 0) and (addr=nil)) then + begin + if (SDK_VERSION > $16fffff) then + begin + Exit(SCE_KERNEL_ERROR_EINVAL); + end; + _flags:=flags and $fffffbef; + Writeln('[WARNING] map(addr=0, flags=MAP_FIXED)'); + end; + + if (addr=nil) then + begin + addr:=Pointer($880000000); + end; + + Result:=__mmap(addr,length,alignment,prots,_flags or MAP_SHARED,0,physicalAddr,addr); + + if (Result=0) then + begin + virtualAddrDest^:=addr; + Result:=0; + end; +end; + + //// //// diff --git a/ps4_program.pas b/ps4_program.pas index 52560094..f52a4c1d 100644 --- a/ps4_program.pas +++ b/ps4_program.pas @@ -177,6 +177,8 @@ function GetSceProcParam:Pointer; function GetSceUserMainThreadName:PChar; function GetSceUserMainThreadPriority:PDWORD; function GetSceUserMainThreadStackSize:PDWORD; +function GetSceKernelMemParam:Pointer; +function GetSceKernelFlexibleMemorySize:PQWORD; Function get_dev_progname:RawByteString; @@ -1558,6 +1560,34 @@ begin end; end; +function GetSceKernelMemParam:Pointer; +var + p:PSceProcParam; +begin + Result:=nil; + p:=GetSceProcParam; + if (p=nil) then Exit; + + if (P^.Header.Size>=qword(@PSceProcParam(nil)^._sceKernelMemParam)+SizeOf(Pointer)) then + begin + Result:=p^._sceKernelMemParam; + end; +end; + +function GetSceKernelFlexibleMemorySize:PQWORD; +var + p:PSceKernelMemParam; +begin + Result:=nil; + p:=GetSceKernelMemParam; + if (p=nil) then Exit; + + if (P^.Size>=qword(@PSceKernelMemParam(nil)^.sceKernelFlexibleMemorySize)+SizeOf(Pointer)) then + begin + Result:=p^.sceKernelFlexibleMemorySize; + end; +end; + Function get_dev_progname:RawByteString; begin Result:=''; diff --git a/rtl/mmap.pas b/rtl/mmap.pas index 9bbcdd10..48007f25 100644 --- a/rtl/mmap.pas +++ b/rtl/mmap.pas @@ -71,6 +71,7 @@ const function _isgpu(prot:Integer):Boolean; inline; function __map_prot_page(prot:Integer):DWORD; +function __win_prot_page(prot:DWORD):Integer; function __map_prot_file(prot:Integer):DWORD; function _VirtualAlloc (Addr:Pointer;dwSize:PTRUINT;prot:Integer):Integer; @@ -81,6 +82,7 @@ function _VirtualFree (Addr:Pointer):Integer; function _VirtualMmap (Addr:Pointer;len:size_t;prot,fd:Integer;offst:size_t):Integer; function _VirtualUnmap (addr:Pointer):Integer; function _VirtualProtect (addr:Pointer;len:size_t;prot:Integer):Integer; +function _VirtualQuery (addr:Pointer;paddr:PPointer;psize:Pptruint;pprots,pflags:PInteger):Integer; implementation @@ -120,6 +122,29 @@ begin end; end; +function __win_prot_page(prot:DWORD):Integer; +begin + Result:=0; + + prot:=prot and ( + PAGE_NOACCESS or + PAGE_READONLY or + PAGE_READWRITE or + PAGE_EXECUTE or + PAGE_EXECUTE_READ or + PAGE_EXECUTE_READWRITE); + + Case prot of + PAGE_NOACCESS :Result:=0; + PAGE_READONLY :Result:=PROT_READ; + PAGE_READWRITE :Result:=PROT_READ or PROT_WRITE; + PAGE_EXECUTE :Result:=PROT_EXEC; + PAGE_EXECUTE_READ :Result:=PROT_EXEC or PROT_READ; + PAGE_EXECUTE_READWRITE:Result:=PROT_EXEC or PROT_READ or PROT_WRITE; + else; + end; +end; + function __map_prot_file(prot:Integer):DWORD; begin Result:= 0; @@ -256,6 +281,58 @@ begin end; end; +function _win_state(state:DWORD):Integer; inline; +begin + Case state of + MEM_COMMIT :Result:=MAP_FIXED; + MEM_RESERVE:Result:=MAP_VOID; + else Result:=0; + end; +end; + +function _win_mtype(mtype:DWORD):Integer; inline; +begin + Case mtype of + MEM_PRIVATE:Result:=MAP_ANON; + else Result:=MAP_SHARED; + + end; +end; + +function _VirtualQuery(addr:Pointer;paddr:PPointer;psize:Pptruint;pprots,pflags:PInteger):Integer; +var + Info:TMemoryBasicInformation; +begin + Result:=0; + Info:=Default(TMemoryBasicInformation); + Result:=VirtualQuery(addr,Info,SizeOf(TMemoryBasicInformation)); + if (Result=0) then + begin + Result:=GetLastError; + end else + begin + if (paddr<>nil) then + begin + paddr^:=Info.AllocationBase; + end; + + if (psize<>nil) then + begin + psize^:=Info.RegionSize+(ptruint(Info.BaseAddress)-ptruint(Info.AllocationBase)); + end; + + if (pprots<>nil) then + begin + pprots^:=__win_prot_page(Info.Protect); + end; + + if (pflags<>nil) then + begin + pflags^:=_win_state(Info.State) or _win_mtype(Info._Type) + end; + end; +end; + end.