fpPS4/kernel/ps4_map_mm.pas
2023-02-14 19:04:34 +03:00

1927 lines
44 KiB
ObjectPascal

unit ps4_map_mm;
{$mode objfpc}{$H+}
interface
uses
Windows,
RWLock,
sys_types,
sys_crt,
mmap,
mm_adr_direct,
mm_adr_virtual,
mm_adr_name,
Classes,
SysUtils;
{
Flexible memory: elf sections, stack, calloc, cpu only
Direct memory: phisical mapped, cpu/gpu mem
Pooled memory: section of direct memory, 64 KiB blocks,
The application program can use a total of 5184 MiB (5824 MiB in NEO mode) physical memory.
If there is no specification, 448 MiB will be assigned as flexible memory.
Physical Address Space and Direct Memory Areas is guaranteed to be aligned to a 2 MiB boundary.
Unmapped area : 0x0000 0000 0000 - 0x0000 0040 0000 Size: 0x0000 0040 0000 (4MB)
System managed area : 0x0000 0040 0000 - 0x0007 FFFF C000 Size: 0x0007 FFBF C000 (31GB)
System reserved area: 0x0007 FFFF C000 - 0x0010 0000 0000 Size: 0x0008 0000 4000 (32GB)
User area : 0x0010 0000 0000 - 0x00FC 0000 0000 Size: 0x00EC 0000 0000 (944GB)
System reserved area: 0x00FC 0000 0000 - 0x00FF FFFF FFFF Size: 0x0003 FFFF FFFF (15GB)
}
//FFFF FF|FF FFFF FFFF
//0000 00|FF FFFF FFFF
//mirror |addr
var
MMLock:System.TRTLCriticalSection;
DirectManager :TDirectManager;
VirtualManager:TVirtualManager;
NamedManager :TNamedManager;
Const
SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB
type
pSceKernelDirectMemoryQueryInfo=^SceKernelDirectMemoryQueryInfo;
SceKernelDirectMemoryQueryInfo=packed record
start:QWORD;
__end:QWORD;
mType:Integer;
align:Integer;
end;
const
SCE_KERNEL_VIRTUAL_RANGE_NAME_SIZE=32;
SCE_KERNEL_DMQ_FIND_NEXT=1;
SCE_KERNEL_VQ_FIND_NEXT =1;
type
pSceKernelVirtualQueryInfo=^SceKernelVirtualQueryInfo;
SceKernelVirtualQueryInfo=packed record
pstart:Pointer;
pend :Pointer;
offset:QWORD;
protection:Integer;
memoryType:Integer;
bits:bitpacked record
isFlexibleMemory:0..1;
isDirectMemory :0..1;
isStack :0..1;
isPooledMemory :0..1;
isCommitted :0..1;
end;
name:array[0..SCE_KERNEL_VIRTUAL_RANGE_NAME_SIZE-1] of AnsiChar;
align:array[0..6] of Byte;
end;
const
//SceKernelMapEntryOperation
SCE_KERNEL_MAP_OP_MAP_DIRECT =0;
SCE_KERNEL_MAP_OP_UNMAP =1;
SCE_KERNEL_MAP_OP_PROTECT =2;
SCE_KERNEL_MAP_OP_MAP_FLEXIBLE=3;
SCE_KERNEL_MAP_OP_TYPE_PROTECT=4;
type
pSceKernelBatchMapEntry=^SceKernelBatchMapEntry;
SceKernelBatchMapEntry=packed record
start:Pointer;
offset:QWORD;
length:QWORD;
protection:Byte;
mtype:Byte;
pad1:Word;
operation:Integer;
end;
function ps4_sceKernelGetDirectMemorySize:Int64; SysV_ABI_CDecl;
function ps4_getpagesize:Integer; SysV_ABI_CDecl;
function ps4_sceKernelAvailableFlexibleMemorySize(sizeOut:PQWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelConfiguredFlexibleMemorySize(sizeOut:PQWORD):Integer; SysV_ABI_CDecl;
//direct
function ps4_sceKernelAllocateDirectMemory(
searchStart:QWORD;
searchEnd:QWORD;
length:QWORD;
alignment:QWORD;
memoryType:Integer;
physicalAddrDest:PQWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelAllocateMainDirectMemory(
length:QWORD;
alignment:QWORD;
memoryType:Integer;
physicalAddrDest:PQWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelAvailableDirectMemorySize(
searchStart:QWORD;
searchEnd:QWORD;
alignment:QWORD;
physAddrOut:PQWORD;
sizeOut:PQWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelDirectMemoryQuery(
offset:QWORD;
flags:Integer;
info:pSceKernelDirectMemoryQueryInfo;
infoSize:QWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelGetDirectMemoryType(
start:QWORD;
memoryTypeOut:PInteger;
regionStartOut:PQWORD;
regionEndOut:PQWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelCheckedReleaseDirectMemory(start,len:QWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelReleaseDirectMemory(start,len:QWORD):Integer; SysV_ABI_CDecl;
//mapping
function ps4_mmap(addr:Pointer;
len:size_t;
prot,flags,fd:Integer;
offset:size_t):Pointer; SysV_ABI_CDecl;
function ps4_sceKernelMmap(addr:Pointer;
len:size_t;
prot,flags,fd:Integer;
offset:size_t;
res:PPointer):Integer; SysV_ABI_CDecl;
function ps4_munmap(addr:Pointer;len:size_t):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMunmap(addr:Pointer;len:size_t):Integer; SysV_ABI_CDecl;
function ps4_sceKernelReleaseFlexibleMemory(addr:Pointer;len:size_t):Integer; SysV_ABI_CDecl;
function ps4_mprotect(addr:Pointer;len:size_t;prot:Integer):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMprotect(addr:Pointer;len:QWORD;prot:Integer):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMtypeprotect(addr:Pointer;len:size_t;mtype,prot:Integer):Integer; SysV_ABI_CDecl;
function ps4_sceKernelQueryMemoryProtection(addr:Pointer;
pStart,pEnd:PPointer;
pProt:PInteger):Integer; SysV_ABI_CDecl;
function ps4_sceKernelVirtualQuery(addr:Pointer;
flags:Integer;
info:pSceKernelVirtualQueryInfo;
infoSize:QWORD):Integer; SysV_ABI_CDecl;
Function ps4_sceKernelSetVirtualRangeName(addr:Pointer;len:QWORD;pname:PChar):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMapFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMapNamedFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
name:PChar):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMapNamedSystemFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
name:PChar):Integer; SysV_ABI_CDecl;
function ps4_sceKernelReserveVirtualRange(
virtualAddrDest:PPointer;
length:QWORD;
flags:Integer;
alignment:QWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMapDirectMemory2(
virtualAddrDest:PPointer;
length:QWORD;
mtype,prots,flags:Integer;
physicalAddr:QWORD;
alignment:QWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMapDirectMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
physicalAddr:QWORD;
alignment:QWORD):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMapNamedDirectMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
physicalAddr:QWORD;
alignment:QWORD;
name:Pchar):Integer; SysV_ABI_CDecl;
//
function ps4_sceKernelBatchMap(
entries:pSceKernelBatchMapEntry;
numberOfEntries:Integer;
numberOfEntriesOut:PInteger
):Integer; SysV_ABI_CDecl;
function ps4_sceKernelBatchMap2(
entries:pSceKernelBatchMapEntry;
numberOfEntries:Integer;
numberOfEntriesOut:PInteger;
flags:Integer):Integer; SysV_ABI_CDecl;
//
function ps4_mlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
function ps4_munlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
function ps4_mlockall(flags:Integer):Integer; SysV_ABI_CDecl;
function ps4_munlockall:Integer; SysV_ABI_CDecl;
function ps4_sceKernelMlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMunlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMlockall(flags:Integer):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMunlockall:Integer; SysV_ABI_CDecl;
//
function ps4_msync(addr:Pointer;len:size_t;flags:Integer):Integer; SysV_ABI_CDecl;
function ps4_sceKernelMsync(addr:Pointer;len:size_t;flags:Integer):Integer; SysV_ABI_CDecl;
type
TGpuMemAlloc=function(addr:Pointer;len:size_t):Pointer;
TGpuMemFree =procedure(h:Pointer);
TGpuMemBlock=record
pAddr:Pointer;
nSize:Int64;
Handle:Pointer;
end;
TGpuMemCb=record
Alloc:TGpuMemAlloc;
Free :TGpuMemFree;
end;
var
GpuMemCb:TGpuMemCb;
Function TryGetGpuMemBlockByAddr(addr:Pointer;var block:TGpuMemBlock):Boolean;
Procedure RegistredStack;
Procedure UnRegistredStack;
var
SceKernelFlexibleMemorySize:QWORD=0;
Procedure _mem_init;
Procedure _mem_print;
implementation
uses
ps4_program,
sys_kernel,
sys_signal;
Procedure INIT_MLOCK; inline;
begin
System.InitCriticalSection(MMLock);
end;
Procedure MLOCK; inline;
begin
System.EnterCriticalSection(MMLock);
end;
Procedure MUNLOCK; inline;
begin
System.LeaveCriticalSection(MMLock);
end;
function IsPowerOfTwo(x:QWORD):Boolean; inline;
begin
Result:=(x and (x - 1))=0;
end;
function fastIntLog2(i:QWORD):QWORD; inline;
begin
Result:=BsfQWORD(i);
end;
function str_mem_type(memoryType:Integer):RawByteString;
begin
Result:='';
Case memoryType of
SCE_KERNEL_WB_ONION :Result:='WB_ONION';
SCE_KERNEL_WC_GARLIC:Result:='WC_GARLIC';
SCE_KERNEL_WB_GARLIC:Result:='WB_GARLIC';
else
Result:=IntToStr(memoryType);
end;
end;
function test_KP_flags(flags:Integer):RawByteString;
begin
Result:='';
if (flags and SCE_KERNEL_PROT_CPU_READ) <>0 then Result:=Result+' CPU_READ';
if (flags and SCE_KERNEL_PROT_CPU_WRITE)<>0 then Result:=Result+' CPU_WRIT';
if (flags and SCE_KERNEL_PROT_CPU_EXEC) <>0 then Result:=Result+' CPU_EXEC';
if (flags and SCE_KERNEL_PROT_GPU_READ) <>0 then Result:=Result+' GPU_READ';
if (flags and SCE_KERNEL_PROT_GPU_WRITE)<>0 then Result:=Result+' GPU_WRIT';
end;
Function TryGetGpuMemBlockByAddr(addr:Pointer;var block:TGpuMemBlock):Boolean;
var
pb:PVirtualAdrBlock;
label
__exit;
begin
Result:=False;
pb:=nil;
MLOCK;
if VirtualManager.TryGetMapBlockByAddr(addr,pb) then
begin
if (not pb^.isgpu) {(pb^.F.btype<>BT_GPUM)} then goto __exit;
if (pb^.Handle=nil) then
begin
if (GpuMemCb.Alloc=nil) then goto __exit;
pb^.Handle:=GpuMemCb.Alloc(pb^.Offset,pb^.Size);
if (pb^.Handle=nil) then goto __exit;
end;
block.pAddr :=pb^.Offset;
block.nSize :=pb^.Size;
block.Handle:=pb^.Handle;
Result:=true;
end;
__exit:
MUNLOCK;
end;
function __free_block(block:PVirtualAdrBlock):Integer;
begin
Result:=0;
if (block=nil) then Exit;
//if (block^.F.btype<>BT_GPUM) then Exit;
if (block^.Handle<>nil) then Exit;
if (GpuMemCb.Free<>nil) then Exit;
GpuMemCb.Free(block^.Handle);
block^.Handle:=nil;
end;
Procedure RegistredStack;
//var
// block:PBlock;
begin
//MLOCK;
//block:=AllocMem(SizeOf(TBlock));
//if (block=nil) then Exit;
//block^.pAddr:=StackBottom;
//block^.nSize:=StackLength;
//block^.bType:=BT_STACK;
//PageMM.FMapBlockSet.Insert(block);
//MUNLOCK;
end;
Procedure UnRegistredStack;
begin
//MLOCK;
//PageMM._DeleteBlockByAddr(StackBottom);
//MUNLOCK;
end;
function ps4_sceKernelGetDirectMemorySize:Int64; SysV_ABI_CDecl;
begin
Result:=SCE_KERNEL_MAIN_DMEM_SIZE;
_set_errno(0);
end;
function ps4_getpagesize:Integer; SysV_ABI_CDecl;
begin
Result:=PHYSICAL_PAGE_SIZE;
_set_errno(0);
end;
function ps4_sceKernelAvailableFlexibleMemorySize(sizeOut:PQWORD):Integer; SysV_ABI_CDecl;
var
flex:QWORD;
begin
Result:=0;
if (sizeOut=nil) then
begin
_set_errno(EINVAL);
Exit(SCE_KERNEL_ERROR_EINVAL);
end;
_sig_lock;
MLOCK;
flex:=VirtualManager.stat.flex;
MUNLOCK;
_sig_unlock;
if (flex<SceKernelFlexibleMemorySize) then
begin
flex:=SceKernelFlexibleMemorySize-flex;
end else
begin
flex:=0;
end;
sizeOut^:=flex;
end;
function ps4_sceKernelConfiguredFlexibleMemorySize(sizeOut:PQWORD):Integer; SysV_ABI_CDecl;
begin
Result:=0;
if (sizeOut=nil) then
begin
_set_errno(EINVAL);
Exit(SCE_KERNEL_ERROR_EINVAL);
end;
sizeOut^:=SceKernelFlexibleMemorySize;
end;
function _test_mtype(mtype:Integer):Boolean; inline;
begin
Case mtype of
SCE_KERNEL_WB_ONION..SCE_KERNEL_WB_GARLIC:Result:=True;
else
Result:=False;
end;
end;
//direct
function _sceKernelAllocateDirectMemory(
searchStart:QWORD;
searchEnd:QWORD;
length:QWORD;
alignment:QWORD;
memoryType:Integer;
physicalAddrDest:PQWORD):Integer;
begin
Result:=EINVAL;
Writeln('srchd:',HexStr(searchStart,10),'..',HexStr(searchEnd,10),' len:',HexStr(length,10));
Writeln('align:',HexStr(alignment,10),' ','mType:',str_mem_type(memoryType));
if (physicalAddrDest=nil) or (length=0) or (searchEnd<=searchStart) then Exit;
if (searchEnd>SCE_KERNEL_MAIN_DMEM_SIZE) then Exit;
if (alignment=0) then alignment:=LOGICAL_PAGE_SIZE;
if not IsAlign(length ,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(alignment,LOGICAL_PAGE_SIZE) then Exit;
if not IsPowerOfTwo(alignment) then Exit;
if (fastIntLog2(alignment)>31) then Exit;
if not _test_mtype(memoryType) then Exit;
searchStart:=AlignUp(searchStart,LOGICAL_PAGE_SIZE);
_sig_lock;
MLOCK;
Result:=DirectManager.Alloc(searchStart,searchEnd,length,alignment,Byte(memoryType),physicalAddrDest^);
MUNLOCK;
_sig_unlock;
end;
function _sceKernelAllocateMainDirectMemory(
length:QWORD;
alignment:QWORD;
memoryType:Integer;
physicalAddrDest:PQWORD):Integer;
begin
Result:=EINVAL;
Writeln('srchm: len:',HexStr(length,10));
Writeln('align:',HexStr(alignment,10),' ','mType:',str_mem_type(memoryType));
if (physicalAddrDest=nil) or (length=0) then Exit;
if (alignment=0) then alignment:=LOGICAL_PAGE_SIZE;
if not IsAlign(length ,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(alignment,LOGICAL_PAGE_SIZE) then Exit;
if not IsPowerOfTwo(alignment) then Exit;
if (fastIntLog2(alignment)>31) then Exit;
if not _test_mtype(memoryType) then Exit;
_sig_lock;
MLOCK;
Result:=DirectManager.Alloc(length,alignment,Byte(memoryType),physicalAddrDest^);
MUNLOCK;
_sig_unlock;
end;
function _sceKernelAvailableDirectMemorySize(
searchStart:QWORD;
searchEnd:QWORD;
alignment:QWORD;
physAddrOut:PQWORD;
sizeOut:PQWORD):Integer;
var
FAdrOut,FSizeOut:QWORD;
begin
Result:=EINVAL;
if (searchEnd<=searchStart) then Exit;
if (searchEnd>SCE_KERNEL_MAIN_DMEM_SIZE) then Exit;
if (alignment=0) then alignment:=LOGICAL_PAGE_SIZE;
if not IsAlign(searchStart,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(searchEnd ,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(alignment ,LOGICAL_PAGE_SIZE) then Exit;
if not IsPowerOfTwo(alignment) then Exit;
if (fastIntLog2(alignment)>31) then Exit;
searchStart:=AlignUp(searchStart,LOGICAL_PAGE_SIZE);
FAdrOut :=0;
FSizeOut:=0;
_sig_lock;
MLOCK;
Result:=DirectManager.QueryAvailable(searchStart,searchEnd,alignment,FAdrOut,FSizeOut);
MUNLOCK;
_sig_unlock;
if (Result=0) then
begin
if (physAddrOut<>nil) then
begin
physAddrOut^:=FAdrOut;
end;
if (sizeOut<>nil) then
begin
sizeOut^:=FSizeOut;
end;
end;
end;
function _sceKernelDirectMemoryQuery(
offset:QWORD;
flags:Integer;
info:pSceKernelDirectMemoryQueryInfo;
infoSize:QWORD):Integer;
var
ROut:TDirectAdrNode;
begin
Result:=EINVAL;
if (info=nil) or (infoSize<>SizeOf(SceKernelDirectMemoryQueryInfo)) then Exit;
if not IsAlign(offset,LOGICAL_PAGE_SIZE) then Exit;
ROut:=Default(TDirectAdrNode);
_sig_lock;
MLOCK;
Result:=DirectManager.Query(offset,(flags=SCE_KERNEL_DMQ_FIND_NEXT),ROut);
MUNLOCK;
_sig_unlock;
info^:=Default(SceKernelDirectMemoryQueryInfo);
if (Result=0) then
begin
info^.start:=ROut.Offset;
info^.__end:=ROut.Offset+ROut.Size;
info^.mType:=ROut.F.mtype;
end;
end;
function _sceKernelGetDirectMemoryType(
start:QWORD;
memoryTypeOut:PInteger;
regionStartOut:PQWORD;
regionEndOut:PQWORD):Integer;
var
ROut:TDirectAdrNode;
begin
Result:=EINVAL;
if (memoryTypeOut=nil) then Exit;
if (regionStartOut=nil) then Exit;
if (regionEndOut=nil) then Exit;
start:=AlignDw(start,PHYSICAL_PAGE_SIZE);
ROut:=Default(TDirectAdrNode);
_sig_lock;
MLOCK;
Result:=DirectManager.QueryMType(start,ROut);
MUNLOCK;
_sig_unlock;
if (Result=0) then
begin
memoryTypeOut ^:=ROut.F.mtype;
regionStartOut^:=ROut.Offset;
regionEndOut ^:=ROut.Offset+ROut.Size;
end;
end;
function _sceKernelCheckedReleaseDirectMemory(start,len:QWORD):Integer;
begin
Result:=EINVAL;
if not IsAlign(start,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(len ,LOGICAL_PAGE_SIZE) then Exit;
_sig_lock;
MLOCK;
Result:=DirectManager.CheckRelease(start,len);
if (Result=0) then
begin
Result:=DirectManager.Release(start,len);
end;
MUNLOCK;
_sig_unlock;
end;
function _sceKernelReleaseDirectMemory(start,len:QWORD):Integer;
begin
Result:=EINVAL;
if not IsAlign(start,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(len ,LOGICAL_PAGE_SIZE) then Exit;
_sig_lock;
MLOCK;
Result:=DirectManager.Release(start,len);
MUNLOCK;
_sig_unlock;
end;
//
function ps4_sceKernelAllocateDirectMemory(
searchStart:QWORD;
searchEnd:QWORD;
length:QWORD;
alignment:QWORD;
memoryType:Integer;
physicalAddrDest:PQWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelAllocateDirectMemory(
searchStart,
searchEnd,
length,
alignment,
memoryType,
physicalAddrDest);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelAllocateDirectMemory:',Result);
end;
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelAllocateMainDirectMemory(
length:QWORD;
alignment:QWORD;
memoryType:Integer;
physicalAddrDest:PQWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelAllocateMainDirectMemory(
length,
alignment,
memoryType,
physicalAddrDest);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelAllocateMainDirectMemory:',Result);
end;
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelAvailableDirectMemorySize(
searchStart:QWORD;
searchEnd:QWORD;
alignment:QWORD;
physAddrOut:PQWORD;
sizeOut:PQWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelAvailableDirectMemorySize(
searchStart,
searchEnd,
alignment,
physAddrOut,
sizeOut);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelAvailableDirectMemorySize:',Result);
end;
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelDirectMemoryQuery(
offset:QWORD;
flags:Integer;
info:pSceKernelDirectMemoryQueryInfo;
infoSize:QWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelDirectMemoryQuery(
offset,
flags,
info,
infoSize);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelDirectMemoryQuery:',Result);
end;
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelGetDirectMemoryType(
start:QWORD;
memoryTypeOut:PInteger;
regionStartOut:PQWORD;
regionEndOut:PQWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelGetDirectMemoryType(
start,
memoryTypeOut,
regionStartOut,
regionEndOut);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelGetDirectMemoryType:',Result);
end;
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelCheckedReleaseDirectMemory(start,len:QWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelCheckedReleaseDirectMemory(start,len);
if (Result<>0) then
begin
Result:=_sceKernelCheckedReleaseDirectMemory(start,len);
Writeln(StdWrn,'[WARN]:sceKernelCheckedReleaseDirectMemory:',Result);
end;
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelReleaseDirectMemory(start,len:QWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelReleaseDirectMemory(start,len);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelReleaseDirectMemory:',Result);
end;
_set_errno(Result);
Result:=px2sce(Result);
end;
//mapping
//flag:MAP_VOID fd=-1 //reserve
//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,fd:Integer;offset:size_t;var res:Pointer):Integer;
begin
Result:=EINVAL;
if not IsAlign(addr ,PHYSICAL_PAGE_SIZE) then Exit;
//if not IsAlign(len ,PHYSICAL_PAGE_SIZE) then Exit;
if not IsAlign(offset,PHYSICAL_PAGE_SIZE) then Exit;
if (align<PHYSICAL_PAGE_SIZE) then align:=PHYSICAL_PAGE_SIZE;
_sig_lock;
MLOCK;
if (flags and MAP_VOID)<>0 then //reserved
begin
Result:=VirtualManager.mmap(addr,len,align,prot,flags,-1,0,res);
end else
if (flags and MAP_ANON)<>0 then //flex
begin
Result:=VirtualManager.mmap(addr,len,align,prot,flags,-1,0,res);
end else
if (fd>=0) then
begin
if (fd=0) then //direct (psevdo dmem fd=0)
begin
Result:=DirectManager.CheckMMap(offset,len);
if (Result=0) then
begin
Result:=VirtualManager.mmap(addr,len,align,prot,flags,fd,offset,res);
if (Result=0) then
begin
Result:=DirectManager.mmap_addr(offset,len,res);
end;
end;
end else
begin //map file
Result:=VirtualManager.mmap(addr,len,align,prot,flags,fd,offset,res);
end;
end;
MUNLOCK;
_sig_unlock;
end;
function _mmap(addr:Pointer;
len:size_t;
prots,flags,fd:Integer;
offset:size_t;
var res:Pointer):Integer;
var
align:size_t;
begin
Result:=EINVAL;
if ((prots and $ffffffc8)<>0) then Exit;
if not IsAlign(addr,PHYSICAL_PAGE_SIZE) then Exit;
align:=(flags and MAP_ALIGNMENT_MASK) shr MAP_ALIGNMENT_BIT;
align:=1 shl align;
flags:=flags and (not MAP_ALIGNMENT_MASK);
Result:=__mmap(addr,len,align,prots,flags,fd,offset,res);
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;
MLOCK;
Result:=DirectManager.CheckMMap(physicalAddr,length);
if (Result=0) then
begin
Result:=VirtualManager.mmap(addr,length,alignment,prots,flags,0,physicalAddr,res);
if (Result=0) then
begin
Result:=DirectManager.mmap_addr(physicalAddr,length,res,mtype);
end;
end;
MUNLOCK;
_sig_unlock;
end;
function __munmap(addr:Pointer;len:size_t):Integer;
begin
Result:=VirtualManager.Release(addr,len,True);
if (Result=0) then
begin
NamedManager.Mname(addr,len,nil);
end;
end;
function __unmap_direct(Offset,Size:QWORD):Integer;
begin
Result:=DirectManager.unmap_addr(Offset,Size);
end;
function __mtype_direct(Offset,Size:QWORD;mtype:Integer):Integer;
begin
Result:=DirectManager.mmap_type(Offset,Size,mtype);
end;
function _munmap(addr:Pointer;len:size_t):Integer;
begin
Result:=EINVAL;
_sig_lock;
MLOCK;
Result:=VirtualManager.Release(addr,len,False);
if (Result=0) then
begin
NamedManager.Mname(addr,len,nil);
end;
MUNLOCK;
_sig_unlock;
end;
function _mprotect(addr:Pointer;len:size_t;prot:Integer):Integer;
begin
Result:=EINVAL;
_sig_lock;
MLOCK;
Result:=VirtualManager.Protect(addr,len,prot);
MUNLOCK;
_sig_unlock;
end;
function _sys_mtypeprotect(addr:Pointer;len:size_t;mtype,prot:Integer):Integer;
begin
Result:=EINVAL;
_sig_lock;
MLOCK;
Result:=VirtualManager.Mtypeprotect(addr,len,mtype,prot);
MUNLOCK;
_sig_unlock;
end;
function _sys_query_memory_protection(addr:Pointer;
pStart,pEnd:PPointer;
pProt:PInteger):Integer;
var
ROut:TVirtualAdrNode;
begin
Result:=0;
ROut:=Default(TVirtualAdrNode);
_sig_lock;
MLOCK;
Result:=VirtualManager.QueryProt(addr,ROut);
MUNLOCK;
_sig_unlock;
if (Result=0) then
begin
if (pStart<>nil) then
begin
pStart^:=ROut.Offset;
end;
if (pEnd<>nil) then
begin
pEnd ^:=ROut.Offset+ROut.Size;
end;
if (pProt<>nil) then
begin
pProt ^:=ROut.F.prot;
end;
end;
end;
function _sys_virtual_query(addr:Pointer;
flags:Integer;
info:pSceKernelVirtualQueryInfo;
infoSize:QWORD):Integer;
var
VOut:TVirtualAdrNode;
DOut:TDirectAdrNode;
Name:TName;
Committed:Boolean;
begin
Result:=EFAULT;
if (info=nil) then Exit;
if (infoSize<>SizeOf(SceKernelVirtualQueryInfo)) then Exit;
VOut:=Default(TVirtualAdrNode);
DOut:=Default(TDirectAdrNode);
Name:=Default(TName);
_sig_lock;
MLOCK;
Result:=VirtualManager.Query(addr,(flags=SCE_KERNEL_VQ_FIND_NEXT),VOut);
if (Result=0) and (VOut.F.direct=1) then
begin
Result:=DirectManager.QueryMType(VOut.addr,DOut);
end;
if (Result=0) then
begin
NamedManager.Query(addr,@name);
end;
MUNLOCK;
_sig_unlock;
info^:=Default(SceKernelVirtualQueryInfo);
if (Result=0) then
begin
Committed:=(VOut.F.Free=0) and (VOut.F.reserv=0);
info^.pstart :=VOut.Offset;
info^.pend :=VOut.Offset+VOut.Size;
info^.offset :=VOut.addr;
info^.protection :=VOut.F.prot;
info^.memoryType :=DOut.F.mtype;
info^.bits.isFlexibleMemory:=Byte((VOut.F.direct=0) and Committed);
info^.bits.isDirectMemory :=VOut.F.direct;
info^.bits.isStack :=VOut.F.stack;
info^.bits.isPooledMemory :=VOut.F.polled;
info^.bits.isCommitted :=Byte(Committed);
info^.name :=Name;
end;
end;
Function _sys_mname(addr:Pointer;len:QWORD;pname:PChar):Integer;
begin
Result:=EFAULT;
if (pname=nil) then Exit;
if (StrLen(pname)>32) then Exit;
_sig_lock;
MLOCK;
Result:=NamedManager.Mname(addr,len,pname);
MUNLOCK;
_sig_unlock;
end;
function _sceKernelMapFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer):Integer;
var
addr:Pointer;
begin
Result:=SCE_KERNEL_ERROR_EINVAL;
if ((flags and $ffbfff6f)<>0) then Exit;
if ((prots and $ffffffc8)<>0) then Exit;
if (length<LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(length,LOGICAL_PAGE_SIZE) 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(StdWrn,'[WARNING] map(addr=0, flags=MAP_FIXED)');
end;
if (((flags and MAP_FIXED)=0) and (addr=nil)) then
begin
addr:=Pointer($880000000);
end;
Result:=__mmap(addr,length,0,prots,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;
end;
function _sceKernelMapNamedSystemFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
name:PChar):Integer;
var
addr:Pointer;
begin
Result:=SCE_KERNEL_ERROR_EINVAL;
if ((flags and $ffbfff6f)<>0) then Exit;
if ((prots and $ffffffc8)<>0) then Exit;
if (length<LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(length,LOGICAL_PAGE_SIZE) 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;
if (((flags and MAP_FIXED)=0) and (addr=nil)) then
begin
addr:=Pointer($880000000);
end;
Result:=__mmap(addr,length,0,prots,flags or MAP_ANON or MAP_SYSTEM,-1,0,addr);
_set_errno(Result);
if (Result<>0) then
begin
Result:=px2sce(Result);
end else
begin
_sys_mname(addr,length,name);
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 (length<LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(length ,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(alignment,LOGICAL_PAGE_SIZE) then Exit;
if not IsPowerOfTwo(alignment) then Exit;
if (alignment<LOGICAL_PAGE_SIZE) then alignment:=LOGICAL_PAGE_SIZE;
if (fastIntLog2(alignment)>31) 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;
if (((flags and MAP_FIXED)=0) and (addr=nil)) then
begin
addr:=Pointer($880000000);
end;
Result:=__mmap(addr,length,alignment,0,flags or MAP_VOID or MAP_SHARED,-1,0,addr);
_set_errno(Result);
if (Result<>0) then
begin
Result:=px2sce(Result);
end else
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 (length<LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(length ,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(physicalAddr,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(alignment ,LOGICAL_PAGE_SIZE) then Exit;
if not IsPowerOfTwo(alignment) then Exit;
if (alignment<LOGICAL_PAGE_SIZE) then alignment:=LOGICAL_PAGE_SIZE;
if (fastIntLog2(alignment)>31) then Exit;
addr:=virtualAddrDest^;
if not IsAlign(addr,LOGICAL_PAGE_SIZE) then Exit;
if (((flags and MAP_FIXED)=0) and (addr=nil)) then
begin
addr:=Pointer($880000000);
end;
Result:=__sys_mmap_dmem(addr,length,alignment,mtype,prots,flags,physicalAddr,addr);
_set_errno(Result);
if (Result<>0) then
begin
Result:=px2sce(Result);
end else
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 (length<LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(length ,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(physicalAddr,LOGICAL_PAGE_SIZE) then Exit;
if not IsAlign(alignment ,LOGICAL_PAGE_SIZE) then Exit;
if not IsPowerOfTwo(alignment) then Exit;
if (alignment<LOGICAL_PAGE_SIZE) then alignment:=LOGICAL_PAGE_SIZE;
if (fastIntLog2(alignment)>31) 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 (((flags and MAP_FIXED)=0) and (addr=nil)) then
begin
addr:=Pointer($880000000);
end;
Result:=__mmap(addr,length,alignment,prots,_flags or MAP_SHARED,0,physicalAddr,addr);
_set_errno(Result);
if (Result<>0) then
begin
Result:=px2sce(Result);
end else
begin
virtualAddrDest^:=addr;
Result:=0;
end;
end;
////
////
function ps4_mmap(addr:Pointer;
len:size_t;
prot,flags,fd:Integer;
offset:size_t):Pointer; SysV_ABI_CDecl;
var
err:Integer;
begin
if (((flags and MAP_FIXED)=0) and (addr=nil)) then
begin
addr:=Pointer($880000000);
end;
err:=_mmap(addr,len,prot,flags,fd,offset,addr);
_set_errno(err);
if (err=0) then
begin
Result:=addr;
end else
begin
Writeln(StdWrn,'[WARN]:mmap:',err);
Result:=MAP_FAILED;
end;
end;
function ps4_sceKernelMmap(addr:Pointer;
len:size_t;
prot,flags,fd:Integer;
offset:size_t;
res:PPointer):Integer; SysV_ABI_CDecl;
begin
if (((flags and MAP_FIXED)=0) and (addr=nil)) then
begin
addr:=Pointer($880000000);
end;
Result:=_mmap(addr,len,prot,flags,fd,offset,addr);
_set_errno(Result);
if (Result=0) then
begin
res^:=addr;
end else
begin
Writeln(StdWrn,'[WARN]:sceKernelMmap:',Result);
end;
Result:=px2sce(Result);
end;
function ps4_munmap(addr:Pointer;len:size_t):Integer; SysV_ABI_CDecl;
begin
Result:=_munmap(addr,len);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:munmap:',Result);
end;
Result:=_set_errno(Result);
end;
function ps4_sceKernelMunmap(addr:Pointer;len:size_t):Integer; SysV_ABI_CDecl;
begin
Result:=_munmap(addr,len);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMunmap:',Result);
end;
Result:=px2sce(Result);
end;
function ps4_sceKernelReleaseFlexibleMemory(addr:Pointer;len:size_t):Integer; SysV_ABI_CDecl;
begin
Result:=_munmap(addr,len);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelReleaseFlexibleMemory:',Result);
end;
Result:=px2sce(Result);
end;
function ps4_mprotect(addr:Pointer;
len:size_t;
prot:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_mprotect(addr,len,prot);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:mprotect:',Result);
end;
Result:=_set_errno(Result);
end;
function ps4_sceKernelMprotect(addr:Pointer;
len:size_t;
prot:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_mprotect(addr,len,prot);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMprotect:',Result);
end;
Result:=px2sce(Result);
end;
function ps4_sceKernelMtypeprotect(addr:Pointer;
len:size_t;
mtype,prot:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_mtypeprotect(addr,len,mtype,prot);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMtypeprotect:',Result);
end;
Result:=px2sce(Result);
end;
function ps4_sceKernelQueryMemoryProtection(addr:Pointer;
pStart,pEnd:PPointer;
pProt:PInteger):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_query_memory_protection(addr,pStart,pEnd,pProt);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelQueryMemoryProtection:',Result);
end;
Result:=px2sce(Result);
end;
function ps4_sceKernelVirtualQuery(addr:Pointer;
flags:Integer;
info:pSceKernelVirtualQueryInfo;
infoSize:QWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_virtual_query(addr,flags,info,infoSize);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelVirtualQuery:',Result);
end;
Result:=px2sce(Result);
end;
Function ps4_sceKernelSetVirtualRangeName(addr:Pointer;len:QWORD;pname:PChar):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_mname(addr,len,pname);
_set_errno(Result);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelSetVirtualRangeName:',Result);
end;
Result:=px2sce(Result);
end;
function ps4_sceKernelMapFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelMapFlexibleMemory(virtualAddrDest,length,prots,flags);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMapFlexibleMemory:',Result);
end;
end;
function ps4_sceKernelMapNamedFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
name:PChar):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelMapFlexibleMemory(virtualAddrDest,length,prots,flags);
if (Result=0) then
begin
_sys_mname(virtualAddrDest^,length,name);
end else
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMapNamedFlexibleMemory:',Result);
end;
end;
function ps4_sceKernelMapNamedSystemFlexibleMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
name:PChar):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelMapNamedSystemFlexibleMemory(virtualAddrDest,length,prots,flags,name);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMapNamedSystemFlexibleMemory:',Result);
end;
end;
function ps4_sceKernelReserveVirtualRange(
virtualAddrDest:PPointer;
length:QWORD;
flags:Integer;
alignment:QWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelReserveVirtualRange(virtualAddrDest,length,flags,alignment);
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelReserveVirtualRange:',Result);
end;
end;
function ps4_sceKernelMapDirectMemory2(
virtualAddrDest:PPointer;
length:QWORD;
mtype,prots,flags:Integer;
physicalAddr:QWORD;
alignment:QWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelMapDirectMemory2(virtualAddrDest,length,mtype,prots,flags,physicalAddr,alignment);
if _isgpu(prots) then
begin
Writeln('GPU:',HexStr(virtualAddrDest^),'..',HexStr(virtualAddrDest^+length));
end;
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMapDirectMemory2:',Result);
end;
end;
function ps4_sceKernelMapDirectMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
physicalAddr:QWORD;
alignment:QWORD):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelMapDirectMemory(virtualAddrDest,length,prots,flags,physicalAddr,alignment);
if _isgpu(prots) then
begin
Writeln('GPU:',HexStr(virtualAddrDest^),'..',HexStr(virtualAddrDest^+length));
end;
if (Result<>0) then
begin
Writeln(StdWrn,'[WARN]:sceKernelMapDirectMemory:',Result);
end;
end;
function ps4_sceKernelMapNamedDirectMemory(
virtualAddrDest:PPointer;
length:QWORD;
prots,flags:Integer;
physicalAddr:QWORD;
alignment:QWORD;
name:Pchar):Integer; SysV_ABI_CDecl;
begin
Result:=_sceKernelMapDirectMemory(virtualAddrDest,length,prots,flags,physicalAddr,alignment);
if _isgpu(prots) then
begin
Writeln('GPU:',HexStr(virtualAddrDest^),'..',HexStr(virtualAddrDest^+length));
end;
if (Result=0) then
begin
_sys_mname(virtualAddrDest^,length,name);
end else
begin
Writeln(StdWrn,'[WARN]:sceKernelMapNamedDirectMemory:',Result);
end;
end;
//
function ps4_sceKernelBatchMap(
entries:pSceKernelBatchMapEntry;
numberOfEntries:Integer;
numberOfEntriesOut:PInteger
):Integer; SysV_ABI_CDecl;
begin
Result:=ps4_sceKernelBatchMap2(
entries,
numberOfEntries,
numberOfEntriesOut,
MAP_FIXED);
//There is a function with the same name exported from the libkernel_pre250mmap
// library, it differs only in that the flag is 0x410 (MAP_FIXED or MAP_STACK)
end;
function ps4_sceKernelBatchMap2(
entries:pSceKernelBatchMapEntry;
numberOfEntries:Integer;
numberOfEntriesOut:PInteger;
flags:Integer):Integer; SysV_ABI_CDecl;
label
_exit,_exit_lock;
var
i:Integer;
begin
if (entries=nil) then
begin
numberOfEntries:=0;
_set_errno(EFAULT);
Result:=SCE_KERNEL_ERROR_EFAULT;
goto _exit;
end;
if (numberOfEntries=0) then
begin
numberOfEntries:=0;
_set_errno(EINVAL);
Result:=SCE_KERNEL_ERROR_EINVAL;
goto _exit;
end;
_sig_lock;
MLOCK;
For i:=0 to numberOfEntries-1 do
begin
Case entries[i].operation of
SCE_KERNEL_MAP_OP_MAP_DIRECT:
begin
Result:=ps4_sceKernelMapDirectMemory(
@entries[i].start,
entries[i].length,
entries[i].protection,
flags,
entries[i].offset,
0);
end;
SCE_KERNEL_MAP_OP_UNMAP:
begin
Result:=ps4_sceKernelMunmap(entries[i].start,
entries[i].length);
end;
SCE_KERNEL_MAP_OP_PROTECT:
begin
Result:=ps4_sceKernelMprotect(entries[i].start,
entries[i].length,
entries[i].protection);
end;
SCE_KERNEL_MAP_OP_MAP_FLEXIBLE:
begin
Result:=ps4_sceKernelMapFlexibleMemory(@entries[i].start,
entries[i].length,
entries[i].protection,
flags);
end;
SCE_KERNEL_MAP_OP_TYPE_PROTECT:
begin
Result:=ps4_sceKernelMtypeprotect(entries[i].start,
entries[i].length,
entries[i].mtype,
entries[i].protection);
end;
else
begin
numberOfEntries:=i;
_set_errno(EINVAL);
Result:=SCE_KERNEL_ERROR_EINVAL;
goto _exit_lock;
end;
end;
if (Result<>0) then
begin
numberOfEntries:=i;
goto _exit_lock;
end;
end;
_exit_lock:
MUNLOCK;
_sig_unlock;
_exit:
if (numberOfEntriesOut<>nil) then numberOfEntriesOut^:=numberOfEntries;
end;
//
function _sys_check_mmaped(addr:Pointer;len:qword):Integer;
begin
_sig_lock;
MLOCK;
Result:=VirtualManager.check_mmaped(addr,len);
MUNLOCK;
_sig_unlock;
end;
function _sys_mlockall(flags:Integer):Integer;
const
MNALL=not Integer(MCL_CURRENT or MCL_FUTURE);
begin
if (flags=0) or ((flags and MNALL)<>0) then Exit(EINVAL);
Result:=0;
end;
function ps4_mlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
begin
Result:=_set_errno(_sys_check_mmaped(addr,len));
end;
function ps4_munlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
begin
Result:=_set_errno(_sys_check_mmaped(addr,len));
end;
function ps4_mlockall(flags:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_set_errno(_sys_mlockall(flags));
end;
function ps4_munlockall:Integer; SysV_ABI_CDecl;
begin
Result:=_set_errno(0);
end;
function ps4_sceKernelMlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_check_mmaped(addr,len);
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelMunlock(addr:Pointer;len:qword):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_check_mmaped(addr,len);
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelMlockall(flags:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_mlockall(flags);
_set_errno(Result);
Result:=px2sce(Result);
end;
function ps4_sceKernelMunlockall:Integer; SysV_ABI_CDecl;
begin
_set_errno(0);
Result:=0;
end;
////
function _sys_msync(addr:Pointer;len:size_t;flags:Integer):Integer;
begin
if not IsAlign(addr,PHYSICAL_PAGE_SIZE) then Exit(EINVAL);
if ((flags and MS_ASYNC)<>0) and ((flags and MS_INVALIDATE)<>0) then Exit(EINVAL);
_sig_lock;
MLOCK;
Result:=VirtualManager.check_mmaped(addr,len);
MUNLOCK;
_sig_unlock;
if (Result=0) then
begin
FlushViewOfFile(addr,len);
end;
end;
function ps4_msync(addr:Pointer;len:size_t;flags:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_set_errno(_sys_msync(addr,len,flags));
end;
function ps4_sceKernelMsync(addr:Pointer;len:size_t;flags:Integer):Integer; SysV_ABI_CDecl;
begin
Result:=_sys_msync(addr,len,flags);
_set_errno(Result);
Result:=px2sce(Result);
end;
Procedure _mem_init;
var
p:PQWORD;
begin
SceKernelFlexibleMemorySize:=(448*1024*1024);
p:=GetSceKernelFlexibleMemorySize;
if (p<>nil) then
begin
SceKernelFlexibleMemorySize:=p^;
end;
end;
Procedure _mem_print;
begin
Writeln('---[Virtual]---');
VirtualManager.Print;
Writeln('---[Named]---');
NamedManager.Print;
Writeln('---[Direct]---');
DirectManager.Print;
end;
initialization
INIT_MLOCK;
DirectManager :=TDirectManager .Create;
DirectManager .OnMemoryUnmapCb:=@__munmap;
VirtualManager:=TVirtualManager.Create($400000,$FFFFFFFFFF);
VirtualManager.OnDirectUnmapCb:=@__unmap_direct;
VirtualManager.OnDirectMtypeCb:=@__mtype_direct;
VirtualManager.OnFreeBlockCb :=@__free_block;
VirtualManager._mmap_sys(Pointer($400000),$7FFBFC000);
NamedManager :=TNamedManager.Create($400000,$FFFFFFFFFF);
end.