This commit is contained in:
Pavel 2023-09-01 22:27:07 +03:00
parent ecb06685e4
commit 46d4ec8066
9 changed files with 533 additions and 30 deletions

View File

@ -19,6 +19,7 @@ uses
vm,
dmem_map,
kern_dmem,
vm_object,
trap;
type
@ -87,6 +88,18 @@ begin
Assert(False);
end;
Function dmem_mmap_single2(dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer):Integer;
//byte *maxprotp,uint *flagsp
begin
Result:=0;
Writeln('dmem_mmap_single2("',dev^.si_name,'",0x',HexStr(offset^,8),',0x',HexStr(size,8),',',nprot,')');
print_backtrace_td(stderr);
Assert(False);
end;
const
dmem_cdevsw:t_cdevsw=(
d_version :D_VERSION;

View File

@ -10,6 +10,59 @@ uses
dmem_map,
rmem_map;
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;
p__end:Pointer;
offset:QWORD;
protection:Integer;
memoryType:Integer;
bits:bitpacked record
isFlexibleMemory:0..1; //1
isDirectMemory :0..1; //2
isStack :0..1; //4
isPooledMemory :0..1; //8
isCommitted :0..1; //16
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;
var
dobj:vm_object_t;
dmem:t_dmem_map;
@ -27,13 +80,20 @@ function sys_mmap_dmem(vaddr :Pointer;
flags :DWORD;
phaddr:QWORD):Pointer;
function sys_virtual_query(addr:Pointer;
flags:DWORD;
info:Pointer;
infoSize:QWORD):Integer;
implementation
uses
errno,
systm,
vm,
vmparam,
vm_map,
kern_authinfo,
kern_thr;
//////////
@ -65,6 +125,8 @@ end;
procedure init_dmem_map;
begin
dobj:=vm_object_allocate(OBJT_PHYS,OFF_TO_IDX(SCE_KERNEL_MAIN_DMEM_SIZE));
dobj^.flags:=dobj^.flags or OBJ_DMEM_EXT;
dmem_map_init(@dmem,0,SCE_KERNEL_MAIN_DMEM_SIZE);
rmem_map_init(@rmap,0,SCE_KERNEL_MAIN_DMEM_SIZE);
end;
@ -152,7 +214,7 @@ begin
if (not rmem_map_lookup_entry(@rmap,OFF_TO_IDX(phaddr),@rentry)) or //not found
((p_proc.p_dmem_aliasing and 1)<>0) then //aliasing
begin
err:=dmem_map_mtype(@dmem,OFF_TO_IDX(phaddr),OFF_TO_IDX(phaddr+length),mtype);
err:=dmem_map_set_mtype(@dmem,OFF_TO_IDX(phaddr),OFF_TO_IDX(phaddr+length),mtype);
if (err=0) then
begin
@ -325,6 +387,347 @@ begin
td^.td_retval[0]:=addr;
end;
function IN_CUSALIST_1:Boolean;
begin
case String(g_appinfo.CUSANAME) of
'CUSA00663',
'CUSA01270',
'CUSA00966',
'CUSA01199',
'CUSA00606',
'CUSA00605',
'CUSA00476':
Result:=False;
else;
Result:=False;
end;
end;
function IN_CUSALIST_2:Boolean;
begin
case String(g_appinfo.CUSANAME) of
'CUSA00345',
'CUSA00380',
'CUSA00432',
'CUSA01086',
'CUSA01101',
'CUSA01276',
'CUSA01374',
'CUSA01382',
'CUSA01405':
Result:=False;
else;
Result:=False;
end;
end;
function get_obj_mtype(obj:vm_map_object):Byte;
begin
Result:=QWORD(obj^.handle);
end;
procedure dmem_vmo_get_type(map:vm_map_t;
entry:vm_map_entry_t;
addr:QWORD;
qinfo:pSceKernelVirtualQueryInfo;
sdk_version_big_4ffffff:Boolean);
var
obj:vm_map_object;
start,relofs:QWORD;
d_start,d_start2:QWORD;
d_end,d_end2:QWORD;
d_mtype:DWORD;
ret:Integer;
otype:objtype_t;
begin
qinfo^:=Default(SceKernelVirtualQueryInfo);
qinfo^.name:=entry^.name;
obj:=entry^.vm_obj;
if (obj<>nil) and (obj^.otype=OBJT_BLOCKPOOL) then
begin
qinfo^.bits.isPooledMemory:=1;
Assert(false,'dmem_vmo_get_type:OBJT_BLOCKPOOL');
//qinfo^.bits:=qinfo->bits and $ef or ((ret1 and 1) shl 4);
qinfo^.offset:=QWORD(qinfo^.pstart) - entry^.start;
Exit;
end;
qinfo^.pstart :=Pointer(entry^.start);
qinfo^.p__end :=Pointer(entry^.__end);
qinfo^.protection:=entry^.max_protection and entry^.protection;
qinfo^.memoryType:=0;
if (obj<>nil) then
begin
if ((obj^.flags and OBJ_DMEM_EXT)<>0) then
begin
start :=entry^.start;
relofs:=entry^.offset - start;
if (addr < start) then
begin
addr:=start;
end;
ret:=dmem_map_get_mtype(@dmem,obj,addr + relofs,@d_start2,@d_end2,@d_mtype);
if (ret<>0) then
begin
Assert(false,'dmem_vmo_get_type error %d');
end;
qinfo^.bits.isDirectMemory:=1;
qinfo^.bits.isCommitted :=1;
d_start:=(d_start2 - relofs);
if ((d_start2 - relofs) <= entry^.start) then
begin
d_start:=entry^.start;
end;
qinfo^.pstart:=Pointer(d_start);
d_end:=(d_end2 - relofs);
if (entry^.__end <= (d_end2 - relofs)) then
begin
d_end:=entry^.__end;
end;
qinfo^.p__end :=Pointer(d_end);
qinfo^.memoryType:=d_mtype;
qinfo^.offset :=d_start + relofs;
Exit;
end;
otype:=obj^.otype;
if (OBJT_PHYSHM < otype) then Exit;
case otype of
OBJT_DEFAULT,
OBJT_SWAP ,
OBJT_VNODE ,
OBJT_JITSHM ,
OBJT_SELF :; //skip
OBJT_PHYSHM :
begin
qinfo^.memoryType:=get_obj_mtype(obj);
qinfo^.offset :=entry^.offset;
qinfo^.bits.isCommitted:=1;
end;
else
begin
Exit;
end;
end;
end;
if (entry^.max_protection<>0) then
begin
qinfo^.bits.isFlexibleMemory:=1;
//if wired_count>0 then
begin
qinfo^.bits.isCommitted:=1;
end;
if ((entry^.eflags and (MAP_ENTRY_GROWS_DOWN or MAP_ENTRY_GROWS_UP))<>0) then
begin
qinfo^.bits.isStack:=1;
end;
end;
end;
function sys_virtual_query(addr:Pointer;
flags:DWORD; //SCE_KERNEL_VQ_FIND_NEXT
info:Pointer; //pSceKernelVirtualQueryInfo
infoSize:QWORD):Integer;
label
_next,
_dmem_vmo_get_type;
var
td:p_kthread;
map:vm_map_t;
entry,next:vm_map_entry_t;
rbp,rip:PPointer;
sdk_version_big_4ffffff:Boolean;
is_libsys_call:Boolean;
qinfo:SceKernelVirtualQueryInfo;
size:QWORD;
start:QWORD;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
QWORD(addr):=QWORD(addr) and $ffffffffffffc000;
map:=@g_vmspace.vm_map;
if (vm_map_max(map) < QWORD(addr)) then
begin
Exit(EINVAL);
end;
rbp:=Pointer(td^.td_frame.tf_rbp);
repeat
if ((QWORD(rbp) shr 47)<>0) then
begin
sdk_version_big_4ffffff:=(p_proc.p_sdk_version > $4ffffff);
is_libsys_call :=false;
Break;
end;
rip:=fuword(rbp[1]);
rbp:=fuword(rbp[0]);
if (QWORD(rip)=QWORD(-1)) or
(QWORD(rbp)=QWORD(-1)) then
begin
sdk_version_big_4ffffff:=(p_proc.p_sdk_version > $4ffffff);
is_libsys_call :=false;
Break;
end;
if (p_proc.libkernel_start_addr > rip) or
(p_proc.libkernel___end_addr <= rip) then
begin
if (QWORD(rip) - QWORD($7f0000000) < QWORD($800000000)) then
begin
sdk_version_big_4ffffff:=true;
is_libsys_call :=true;
end else
begin
sdk_version_big_4ffffff:=(p_proc.p_sdk_version > $4ffffff);
is_libsys_call :=false;
end;
Break;
end;
until false;
vm_map_lock(map);
if not vm_map_lookup_entry(map,QWORD(addr),@entry) then
begin
if ((flags and SCE_KERNEL_VQ_FIND_NEXT)<>0) then
begin
next:=entry^.next;
if (next<>@map^.header) then
begin
addr :=Pointer(next^.start);
entry:=next;
goto _next;
end;
end;
//not found
vm_map_unlock(map);
Exit(EACCES);
end;
_next:
qinfo:=Default(SceKernelVirtualQueryInfo);
if is_libsys_call or
((entry^.start shr 28) < 127) or
(entry^.__end > QWORD($ff0000000)) then
begin
_dmem_vmo_get_type:
dmem_vmo_get_type(map,entry,QWORD(addr),@qinfo,sdk_version_big_4ffffff);
vm_map_unlock(map);
size:=$48;
if (infoSize < $48) then
begin
size:=infoSize and $ffffffff;
end;
end else
begin
if IN_CUSALIST_1 then
begin
vm_map_unlock(map);
if ((flags and SCE_KERNEL_VQ_FIND_NEXT)=0) then
begin
if (QWORD(addr) < QWORD($fecc6c000)) then Exit(EACCES);
end;
qinfo.pstart :=Pointer($fecc6c000);
qinfo.p__end :=Pointer($ff0000000);
qinfo.protection:=3;
qinfo.memoryType:=0;
qinfo.bits.isFlexibleMemory:=1;
size:=infoSize and $ffffffff;
if (infoSize > $47) then
begin
size:=$48;
end;
end else
if IN_CUSALIST_2 then
begin
vm_map_unlock(map);
if ((flags and SCE_KERNEL_VQ_FIND_NEXT)=0) then
begin
if (QWORD(addr) < QWORD($fee6bc000)) then Exit(EACCES);
end;
qinfo.pstart :=Pointer($fee6bc000);
qinfo.p__end :=Pointer($ff0000000);
qinfo.protection:=3;
qinfo.memoryType:=0;
qinfo.bits.isFlexibleMemory:=1;
size:=infoSize and $ffffffff;
if (infoSize > $47) then
begin
size:=$48;
end;
end else
begin
if ((flags and SCE_KERNEL_VQ_FIND_NEXT)=0) then
begin
vm_map_unlock(map);
Exit(EACCES);
end;
start:=entry^.start;
while (start > QWORD($7efffffff)) and (entry^.__end < QWORD($ff0000001)) do
begin
next:=entry^.next;
if (next<>@map^.header) then
begin
vm_map_unlock(map);
Exit(EACCES);
end;
addr :=Pointer(next^.start);
entry:=next;
start:=QWORD(addr);
end;
goto _dmem_vmo_get_type;
end;
end;
Result:=copyout(@qinfo,info,size);
end;

View File

@ -993,6 +993,9 @@ begin
if (dynlibs_info.libkernel<>nil) then
begin
imgp^.entry_addr:=dynlibs_info.libkernel^.entry_addr;
p_proc.libkernel_start_addr:=dynlibs_info.libkernel^.map_base;
p_proc.libkernel___end_addr:=dynlibs_info.libkernel^.map_base + dynlibs_info.libkernel^.text_size;
end;
_dyn_not_exist:

View File

@ -320,6 +320,9 @@ var
p_sdk_version:Integer;
p_sce_replay_exec:Integer;
libkernel_start_addr:Pointer;
libkernel___end_addr:Pointer;
p_ptc:Int64;
p_nsignals:Int64;

View File

@ -158,7 +158,7 @@ function thr_set_name(id:DWORD;pname:PChar):Integer;
function rtprio_thread(func,tid:Integer;rtp:Pointer):Integer;
function pread(fd:Integer;buf:Pointer;nbyte:QWORD;offset:Int64):Integer;
function pwrite(fd:Integer;buf:Pointer;nbyte:QWORD;offset:Int64):Integer;
function mmap(_addr:Pointer;_len:QWORD;_prot:Integer;_flags:Integer;_fd:Integer;_pos:QWORD):Pointer;
function mmap(vaddr:Pointer;vlen:QWORD;prot:Integer;flags:Integer;fd:Integer;pos:QWORD):Pointer;
function lseek(fd:Integer;offset:Int64;whence:Integer):Integer;
function truncate(path:PChar;length:Int64):Integer;
function ftruncate(fd:Integer;length:Int64):Integer;
@ -208,6 +208,7 @@ function budget_create(name:pchar;ptype:DWORD;unk_ptr1:Pointer;unk_count:DWORD;
function budget_delete(key:Integer):Integer;
function budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer;
function budget_set(key:Integer):Integer;
function virtual_query(addr:Pointer;flags:DWORD;info:Pointer;infoSize:QWORD):Integer;
function is_in_sandbox():Integer;
function dmem_container(d_pool_id:Integer):Integer;
function get_authinfo(pid:Integer;info:Pointer):Integer;
@ -232,13 +233,14 @@ function thr_get_name(id:DWORD;pname:PChar):Integer;
function set_gpo(uiBits:DWORD):Integer;
function ipmimgr_call(op,kid:Integer;res:PInteger;params:Pointer;paramsSize:QWORD):Integer;
function get_gpo(pbits:PByte):Integer;
function mmap_dmem(addr:PPointer;length:QWORD;mtype:DWORD;prot:DWORD;flags:DWORD;phaddr:QWORD):Integer;
function mmap_dmem(vaddr:Pointer;length:QWORD;mtype:DWORD;prot:DWORD;flags:DWORD;phaddr:QWORD):Pointer;
function thr_suspend_ucontext(tid:Integer):Integer;
function thr_resume_ucontext(tid:Integer):Integer;
function thr_get_ucontext(tid:Integer;ucp:Pointer):Integer;
function set_timezone_info(data_ptr:Pointer;data_count_dw:Integer):Integer;
function utc_to_localtime(time:QWORD;local_time,tsec:Pointer;dstsec:PInteger):Integer;
function localtime_to_utc(time:QWORD;tz_type:Integer;utc_time,tsec:Pointer;dstsec:PInteger):Integer;
function set_chicken_switches(flags:Integer):Integer;
function dynlib_get_obj_member(handle:Integer;num:Byte;pout:PPointer):Integer;
function budget_get_ptype_of_budget(key:Integer):Integer;
function blockpool_open(flags:Integer):Integer;
@ -1312,7 +1314,7 @@ asm
jmp cerror
end;
function mmap(_addr:Pointer;_len:QWORD;_prot:Integer;_flags:Integer;_fd:Integer;_pos:QWORD):Pointer; assembler; nostackframe;
function mmap(vaddr:Pointer;vlen:QWORD;prot:Integer;flags:Integer;fd:Integer;pos:QWORD):Pointer; assembler; nostackframe;
asm
movq $477,%rax
call fast_syscall
@ -1662,6 +1664,13 @@ asm
jmp cerror
end;
function virtual_query(addr:Pointer;flags:DWORD;info:Pointer;infoSize:QWORD):Integer; assembler; nostackframe;
asm
movq $572,%rax
call fast_syscall
jmp cerror
end;
function is_in_sandbox():Integer; assembler; nostackframe;
asm
movq $585,%rax
@ -1830,7 +1839,7 @@ asm
jmp cerror
end;
function mmap_dmem(addr:PPointer;length:QWORD;mtype:DWORD;prot:DWORD;flags:DWORD;phaddr:QWORD):Integer; assembler; nostackframe;
function mmap_dmem(vaddr:Pointer;length:QWORD;mtype:DWORD;prot:DWORD;flags:DWORD;phaddr:QWORD):Pointer; assembler; nostackframe;
asm
movq $628,%rax
call fast_syscall
@ -1879,6 +1888,13 @@ asm
jmp cerror
end;
function set_chicken_switches(flags:Integer):Integer; assembler; nostackframe;
asm
movq $643,%rax
call fast_syscall
jmp cerror
end;
function dynlib_get_obj_member(handle:Integer;num:Byte;pout:PPointer):Integer; assembler; nostackframe;
asm
movq $649,%rax

View File

@ -2922,7 +2922,7 @@ const
),
(//[572]
sy_narg:4;
sy_call:nil;
sy_call:@sys_virtual_query;
sy_name:'sys_virtual_query'
),
(//[573]
@ -3277,7 +3277,7 @@ const
),
(//[643]
sy_narg:1;
sy_call:nil;
sy_call:@sys_set_chicken_switches;
sy_name:'sys_set_chicken_switches'
),
(//[644]

View File

@ -7,6 +7,7 @@ interface
uses
vmparam,
vm_object,
kern_mtx;
Const
@ -33,15 +34,15 @@ type
pp_dmem_map_entry=^p_dmem_map_entry;
p_dmem_map_entry=^t_dmem_map_entry;
t_dmem_map_entry=packed record
prev :p_dmem_map_entry; // previous entry
next :p_dmem_map_entry; // next entry
left :p_dmem_map_entry; // left child in binary search tree
right :p_dmem_map_entry; // right child in binary search tree
start :DWORD; // start address
__end :DWORD; // end address
adj_free :DWORD; // amount of adjacent free space
max_free :DWORD; // max free space in subtree
m_type :DWORD; // memory type
prev :p_dmem_map_entry; // previous entry
next :p_dmem_map_entry; // next entry
left :p_dmem_map_entry; // left child in binary search tree
right :p_dmem_map_entry; // right child in binary search tree
start :DWORD; // start address
__end :DWORD; // end address
adj_free:DWORD; // amount of adjacent free space
max_free:DWORD; // max free space in subtree
m_type :DWORD; // memory type
end;
p_dmem_map=^t_dmem_map;
@ -99,10 +100,17 @@ procedure dmem_map_entry_delete(map:p_dmem_map;entry:p_dmem_map_entry);
function dmem_map_delete(map:p_dmem_map;start:DWORD;__end:DWORD):Integer;
function dmem_map_mtype(map :p_dmem_map;
start:DWORD;
__end:DWORD;
new :DWORD):Integer;
function dmem_map_set_mtype(map :p_dmem_map;
start:DWORD;
__end:DWORD;
new :DWORD):Integer;
function dmem_map_get_mtype(map :p_dmem_map;
obj :vm_object_t;
offset:QWORD;
pstart:PQWORD;
p__end:PQWORD;
pmtype:PInteger):Integer;
implementation
@ -1050,10 +1058,10 @@ begin
Result:=(0);
end;
function dmem_map_mtype(map :p_dmem_map;
start:DWORD;
__end:DWORD;
new :DWORD):Integer;
function dmem_map_set_mtype(map :p_dmem_map;
start:DWORD;
__end:DWORD;
new :DWORD):Integer;
var
current,entry:p_dmem_map_entry;
@ -1073,6 +1081,7 @@ begin
//
end else
begin
dmem_map_unlock(map);
Exit(EACCES);
end;
@ -1084,6 +1093,7 @@ begin
if (current^.__end<__end) then
begin
dmem_map_unlock(map);
Exit(EACCES);
end;
@ -1124,6 +1134,44 @@ begin
Result:=0;
end;
function dmem_map_get_mtype(map :p_dmem_map;
obj :vm_object_t;
offset:QWORD;
pstart:PQWORD;
p__end:PQWORD;
pmtype:PInteger):Integer;
var
entry:p_dmem_map_entry;
begin
if ((obj^.flags and OBJ_DMEM_EXT)=0) then
begin
Exit(ENODEV);
end;
if (Int64(offset)<0) then
begin
Exit(EINVAL);
end;
dmem_map_lock(map);
if (dmem_map_lookup_entry(map, offset, @entry)) then
begin
pstart^:=entry^.start;
p__end^:=entry^.__end;
pmtype^:=entry^.m_type;
Result:=0;
end else
begin
Result:=ENOENT;
end;
dmem_map_unlock(map);
Result:=0;
end;
end.

View File

@ -96,11 +96,11 @@ const
//MAP_ENTRY_NEEDS_WAKEUP =$0200; // waiters in transition
MAP_ENTRY_NOCOREDUMP =$0400; // don't include in a core
MAP_ENTRY_GROWS_DOWN=$1000; // Top-down stacks
MAP_ENTRY_GROWS_UP =$2000; // Bottom-up stacks
MAP_ENTRY_GROWS_DOWN =$1000; // Top-down stacks
MAP_ENTRY_GROWS_UP =$2000; // Bottom-up stacks
MAP_ENTRY_WIRE_SKIPPED=$4000;
MAP_ENTRY_VN_WRITECNT =$8000; // writeable vnode mapping
MAP_ENTRY_WIRE_SKIPPED =$4000;
MAP_ENTRY_VN_WRITECNT =$8000; // writeable vnode mapping
//vm_flags_t values
//MAP_WIREFUTURE =$01; // wire all future pages
@ -1288,14 +1288,30 @@ end;
procedure vm_map_simplify_entry(map:vm_map_t;entry:vm_map_entry_t);
var
next,prev:vm_map_entry_t;
prevsize, esize:vm_size_t;
prevsize,esize:vm_size_t;
obj:vm_map_object;
begin
if ((entry^.eflags and (MAP_ENTRY_IS_SUB_MAP))<>0) or
if ((entry^.eflags and (MAP_ENTRY_IS_SUB_MAP))<>0) or //0x20000 MAP_ENTRY_IN_TRANSITION
(entry^.inheritance=VM_INHERIT_HOLE) then
begin
Exit;
end;
obj:=entry^.vm_obj;
if (obj<>nil) then
begin
if (p_proc.p_sdk_version<=$1ffffff) and
((obj^.flags and OBJ_DMEM_EXT)<>0) then
begin
Exit;
end;
if (obj^.otype=OBJT_BLOCKPOOL) then
begin
Exit;
end;
end;
prev:=entry^.prev;
if (prev<>@map^.header) then
begin

View File

@ -62,6 +62,7 @@ const
OBJ_COLORED =$1000; // pg_color is defined
OBJ_ONEMAPPING =$2000; // One USE (a single, non-forked) mapping flag
OBJ_DISCONNECTWNT=$4000; // disconnect from vnode wanted
OBJ_DMEM_EXT =$8000;
OBJPC_SYNC =$1; // sync I/O
OBJPC_INVAL =$2; // invalidate