From 2dd09a7e6fb27f892d51a2a950498bda2a4ccdba Mon Sep 17 00:00:00 2001
From: Pavel <68122101+red-prig@users.noreply.github.com>
Date: Wed, 2 Aug 2023 16:53:09 +0300
Subject: [PATCH] +
---
sys/dev/dev_dmem.pas | 18 +-
sys/fs/devfs/devfs_devs.pas | 6 +
sys/kern/kern_dmem.pas | 85 +++-
sys/kern/kern_regmgr.pas | 14 +-
sys/kern/kern_reloc.pas | 24 +-
sys/kern/kern_rtld.pas | 12 +-
sys/sys_mmap.pas | 6 +-
sys/sys_sysinit.pas | 2 +
sys/syscalls.pas | 8 +
sys/sysent.pas | 2 +-
sys/test/project1.lpi | 4 +
sys/vfs/kern_conf.pas | 22 +
sys/vfs/kern_descrip.pas | 4 +
sys/vm/dmem_map.pas | 956 ++++++++++++++++++++++++++++++++++++
sys/vm/vm.pas | 6 +-
sys/vm/vm_map.pas | 98 +++-
16 files changed, 1226 insertions(+), 41 deletions(-)
create mode 100644 sys/vm/dmem_map.pas
diff --git a/sys/dev/dev_dmem.pas b/sys/dev/dev_dmem.pas
index b9664253..ff62e6c7 100644
--- a/sys/dev/dev_dmem.pas
+++ b/sys/dev/dev_dmem.pas
@@ -17,10 +17,17 @@ uses
vuio,
subr_uio,
vm,
+ dmem_map,
kern_dmem;
-Const
- SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB
+type
+ PAvailableDirectMemorySize=^TAvailableDirectMemorySize;
+ TAvailableDirectMemorySize=packed record
+ start:QWORD; //in,out
+ __end:QWORD; //in
+ align:QWORD; //in
+ osize:QWORD; //out
+ end;
Function dmem_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
begin
@@ -33,6 +40,13 @@ begin
begin
PQWORD(data)^:=SCE_KERNEL_MAIN_DMEM_SIZE;
end;
+ $C0208016: //sceKernelAvailableDirectMemorySize
+ begin
+ with PAvailableDirectMemorySize(data)^ do
+ begin
+ Result:=dmem_map_query_available(@dmem,start,__end,align,start,osize);
+ end;
+ end;
else
Assert(False);
end;
diff --git a/sys/fs/devfs/devfs_devs.pas b/sys/fs/devfs/devfs_devs.pas
index f2ead96f..e0e135ab 100644
--- a/sys/fs/devfs/devfs_devs.pas
+++ b/sys/fs/devfs/devfs_devs.pas
@@ -281,7 +281,9 @@ begin
{ Exit if the directory is not empty. }
if (TAILQ_NEXT(de_dotdot,@de_dotdot^.de_list)<>nil) then
+ begin
Exit;
+ end;
dd:=devfs_parent_dirent(de);
Assert(dd<>nil, 'devfs_rmdir_empty: nil dd');
@@ -329,7 +331,9 @@ begin
devfs_dir_unref_de(dm, dd);
end;
end else
+ begin
dd:=nil;
+ end;
mtx_lock(devfs_de_interlock);
vp:=de^.de_vnode;
@@ -353,7 +357,9 @@ begin
vdrop(vp);
sx_xlock(@dm^.dm_lock);
end else
+ begin
mtx_unlock(devfs_de_interlock);
+ end;
if (de^.de_symlink<>nil) then
begin
diff --git a/sys/kern/kern_dmem.pas b/sys/kern/kern_dmem.pas
index 1d730b5a..1108df43 100644
--- a/sys/kern/kern_dmem.pas
+++ b/sys/kern/kern_dmem.pas
@@ -5,13 +5,35 @@ unit kern_dmem;
interface
+uses
+ dmem_map;
+
+var
+ dmem:t_dmem_map;
+
+procedure init_dmem_map;
+
function sys_dmem_container(d_pool_id:Integer):Integer;
+//
+function sys_blockpool_open(flags:Integer):Integer;
implementation
uses
errno,
- kern_thr;
+ kern_thr,
+ kern_descrip,
+ vfile,
+ vfcntl,
+ kern_conf,
+ vstat;
+
+//////////
+
+procedure init_dmem_map;
+begin
+ dmem_map_init(@dmem,0,SCE_KERNEL_MAIN_DMEM_SIZE);
+end;
const
default_pool_id=1;
@@ -34,6 +56,67 @@ begin
end;
end;
+////////////
+
+function blockpool_ioctl(fp:p_file;com:QWORD;data:Pointer):Integer;
+begin
+ Assert(False);
+ Result:=0;
+end;
+
+function blockpool_stat(fp:p_file;sb:p_stat):Integer;
+begin
+ Assert(False);
+ Result:=0;
+end;
+
+function blockpool_close(fp:p_file):Integer;
+begin
+ Assert(False);
+ Result:=0;
+end;
+
+const
+ blockpool_ops:fileops=(
+ fo_read :fo_rdwr_t(@_enxio);
+ fo_write :fo_rdwr_t(@_enxio);
+ fo_truncate:fo_truncate_t(@_enxio);
+ fo_ioctl :@blockpool_ioctl;
+ fo_poll :fo_poll_t(@_eopnotsupp);
+ fo_kqfilter:fo_kqfilter_t(@_eopnotsupp);
+ fo_stat :@blockpool_stat;
+ fo_close :@blockpool_close;
+ fo_chmod :fo_chmod_t(@_einval);
+ fo_chown :fo_chown_t(@_einval);
+ fo_flags :0;
+ );
+
+function sys_blockpool_open(flags:Integer):Integer;
+var
+ td:p_kthread;
+ bp:Pointer;
+ fp:p_file;
+ fd:Integer;
+begin
+ td:=curkthread;
+ if (td=nil) then Exit(-1);
+ //0x100000(O_CLOEXEC) | 0x400000(ASLR_FD????)
+ if ((flags and $ffafffff)<>0) then Exit(EINVAL);
+
+ flags:=flags or FWRITE;
+
+ fd:=0;
+ Result:=falloc(@fp,@fd,flags);
+ if (Result<>0) then Exit();
+
+ bp:=nil; /////
+
+ finit(fp, flags, DTYPE_BLOCKPOOL, bp, @blockpool_ops);
+
+ fdrop(fp);
+
+ td^.td_retval[0]:=fd;
+end;
end.
diff --git a/sys/kern/kern_regmgr.pas b/sys/kern/kern_regmgr.pas
index 71f36814..f77983b4 100644
--- a/sys/kern/kern_regmgr.pas
+++ b/sys/kern/kern_regmgr.pas
@@ -60,9 +60,19 @@ begin
goto _err;
end;
- Writeln(' enc:0x',HexStr(qword(data.enc),16),' val1:0x',HexStr(data.val1,8),' val12:0x',HexStr(data.val2,8));
+ case qword(data.enc) of
+ QWORD($0C82671ADF0EEB34):data.val2:=0; //_malloc_init_lv2
+ QWORD($1AC46343411B3F40):data.val2:=0; //libSceSysmodule (bit 1,2 -> load debug lib)
+ QWORD($503F69BDE385A6AC):data.val2:=0; //libSceSysmodule (print errors?)
+ QWORD($2D946F62AEF8F878):data.val2:=0; //libSceSysmodule (preload module?)
+ QWORD($1BE26343C3D71F40):data.val2:=0; //libkernel
+ QWORD($68436EECF1CFD447):data.val2:=0; //libSceLibcInternal (sceLibcHeapGetTraceInfo -> get_segment_info)
- data.val2:=0;
+ else
+ begin
+ Writeln(' enc:0x',HexStr(qword(data.enc),16),' val1:0x',HexStr(data.val1,8),' val12:0x',HexStr(data.val2,8));
+ end;
+ end;
Result:=copyout(@data,pvalue,vlen);
if (Result<>0) then
diff --git a/sys/kern/kern_reloc.pas b/sys/kern/kern_reloc.pas
index bf1df91f..443fe9ef 100644
--- a/sys/kern/kern_reloc.pas
+++ b/sys/kern/kern_reloc.pas
@@ -173,7 +173,8 @@ begin
Exit(ENOEXEC);
end;
- set_relo_bits(obj,i);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,i);
end; //R_X86_64_DTPMOD64
R_X86_64_DTPOFF64:
@@ -194,7 +195,8 @@ begin
Exit(ENOEXEC);
end;
- set_relo_bits(obj,i);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,i);
end; //R_X86_64_DTPOFF64
R_X86_64_TPOFF64:
@@ -214,7 +216,8 @@ begin
Exit(ENOEXEC);
end;
- set_relo_bits(obj,i);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,i);
end; //R_X86_64_TPOFF64
else;
@@ -260,7 +263,8 @@ begin
Exit(ENOEXEC);
end;
- set_relo_bits(obj,i);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,i);
end; //R_X86_64_PC32
R_X86_64_DTPOFF32:
@@ -281,7 +285,8 @@ begin
Exit(ENOEXEC);
end;
- set_relo_bits(obj,i);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,i);
end; //R_X86_64_DTPOFF32
@@ -302,7 +307,8 @@ begin
Exit(ENOEXEC);
end;
- set_relo_bits(obj,i);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,i);
end; //R_X86_64_TPOFF32
else;
@@ -339,7 +345,8 @@ begin
Exit(ENOEXEC);
end;
- set_relo_bits(obj,i);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,i);
goto _next;
end;
@@ -407,7 +414,8 @@ begin
Exit(4);
end;
- set_relo_bits(obj,idofs);
+ if (def<>@dynlibs_info.sym_nops) then
+ set_relo_bits(obj,idofs);
if (flags=0) then Exit;
diff --git a/sys/kern/kern_rtld.pas b/sys/kern/kern_rtld.pas
index 3b4fcf16..415790d7 100644
--- a/sys/kern/kern_rtld.pas
+++ b/sys/kern/kern_rtld.pas
@@ -394,7 +394,7 @@ begin
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
s:=elf_phdr[s].p_offset;
MinSeg:=MinInt64(s,MinSeg);
- s:=s+minInt64(self_segs[i].filesz,self_segs[i].filesz);
+ s:=s+minInt64(self_segs[i].filesz,self_segs[i].memsz);
MaxSeg:=MaxInt64(s,MaxSeg);
end;
@@ -436,9 +436,9 @@ begin
Assert(false,'src_ofs>=obj_size');
end;
- if ((src_ofs+mem_size)>=obj_size) then
+ if ((src_ofs+mem_size)>obj_size) then
begin
- Assert(false,'(src_ofs+mem_size)>=obj_size');
+ Assert(false,'(src_ofs+mem_size)>obj_size');
end;
if (dst_ofs>=MaxSeg) then
@@ -446,9 +446,9 @@ begin
Assert(false,'dst_ofs>=MaxSeg');
end;
- if ((dst_ofs+mem_size)>=MaxSeg) then
+ if ((dst_ofs+mem_size)>MaxSeg) then
begin
- Assert(false,'(dst_ofs+mem_size)>=MaxSeg');
+ Assert(false,'(dst_ofs+mem_size)>MaxSeg');
end;
Move( (Pointer(self_hdr) +src_ofs)^, //src
@@ -633,7 +633,7 @@ begin
addr^:=SCE_REPLAY_EXEC_START;
end;
- Result:=vm_mmap2(map,addr,size,0,0,MAP_ANON or MAP_PRIVATE,OBJT_DEFAULT,nil,0);
+ Result:=vm_mmap2(map,addr,size,0,0,MAP_ANON or MAP_PRIVATE or (21 shl MAP_ALIGNMENT_BIT),OBJT_DEFAULT,nil,0);
end;
procedure rtld_munmap(base:Pointer;size:QWORD);
diff --git a/sys/sys_mmap.pas b/sys/sys_mmap.pas
index 0b89b032..6bfd1ac5 100644
--- a/sys/sys_mmap.pas
+++ b/sys/sys_mmap.pas
@@ -38,9 +38,9 @@ const
MAP_SELF =$80000; // map decryped SELF file
MAP_ALIGNMENT_BIT =24;
- MAP_ALIGNMENT_SHIFT=$1f000000;
- MAP_ALIGNMENT_MASK =$ff shl MAP_ALIGNMENT_BIT;
- MAP_ALIGNED_SUPER =$01 shl MAP_ALIGNMENT_BIT;
+ MAP_ALIGNMENT_SHIFT=24;
+ MAP_ALIGNMENT_MASK =$ff shl MAP_ALIGNMENT_SHIFT;
+ MAP_ALIGNED_SUPER =$01 shl MAP_ALIGNMENT_SHIFT;
//MAP_ALIGNED(n) ((n) << MAP_ALIGNMENT_SHIFT)
MCL_CURRENT=$0001; // Lock only current memory
diff --git a/sys/sys_sysinit.pas b/sys/sys_sysinit.pas
index 68a52351..79f424a4 100644
--- a/sys/sys_sysinit.pas
+++ b/sys/sys_sysinit.pas
@@ -24,6 +24,7 @@ uses
vmount,
vfiledesc,
vm_map,
+ kern_dmem,
kern_mtxpool,
vsys_generic,
vfs_subr,
@@ -93,6 +94,7 @@ begin
vmountinit;
fd_table_init;
vminit;
+ init_dmem_map;
mtx_pool_setup_dynamic;
selectinit;
vntblinit;
diff --git a/sys/syscalls.pas b/sys/syscalls.pas
index 9f4f3afd..24a02998 100644
--- a/sys/syscalls.pas
+++ b/sys/syscalls.pas
@@ -234,6 +234,7 @@ function utc_to_localtime(time:QWORD;local_time,tsec:Pointer;dstsec:PInteger):I
function localtime_to_utc(time:QWORD;tz_type:Integer;utc_time,tsec:Pointer;dstsec:PInteger):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;
function __sys_dynlib_get_info_for_libdbg(handle:Integer;info:Pointer):Integer;
function fdatasync(fd:Integer):Integer;
function __sys_dynlib_get_list2(pArray:PInteger;numArray:QWORD;pActualNum:PQWORD):Integer;
@@ -1836,6 +1837,13 @@ asm
jmp cerror
end;
+function blockpool_open(flags:Integer):Integer; assembler; nostackframe;
+asm
+ movq $653,%rax
+ call fast_syscall
+ jmp cerror
+end;
+
function __sys_dynlib_get_info_for_libdbg(handle:Integer;info:Pointer):Integer; assembler; nostackframe;
asm
movq $656,%rax
diff --git a/sys/sysent.pas b/sys/sysent.pas
index cb630622..01d1746d 100644
--- a/sys/sysent.pas
+++ b/sys/sysent.pas
@@ -3322,7 +3322,7 @@ const
),
(//[653]
sy_narg:1;
- sy_call:nil;
+ sy_call:@sys_blockpool_open;
sy_name:'sys_blockpool_open'
),
(//[654]
diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi
index cfd1755b..22747383 100644
--- a/sys/test/project1.lpi
+++ b/sys/test/project1.lpi
@@ -641,6 +641,10 @@
+
+
+
+
diff --git a/sys/vfs/kern_conf.pas b/sys/vfs/kern_conf.pas
index 283db99b..cc532b6e 100644
--- a/sys/vfs/kern_conf.pas
+++ b/sys/vfs/kern_conf.pas
@@ -199,6 +199,7 @@ function _nullop():Integer;
function _eopnotsupp():Integer;
function _enxio():Integer;
function _enodev():Integer;
+function _einval():Integer;
procedure dev_lock();
procedure dev_unlock();
@@ -503,6 +504,11 @@ begin
Exit(ENODEV);
end;
+function _einval():Integer;
+begin
+ Exit(EINVAL);
+end;
+
procedure dead_strategy(bp:Pointer);
begin
//biofinish(bp, nil, ENXIO);
@@ -896,7 +902,9 @@ begin
len:=Length(R);
if (len > sizeof(dev^.__si_namebuf) - 1) then
+ begin
Exit(ENAMETOOLONG);
+ end;
Move(PChar(R)^,dev^.__si_namebuf,len);
@@ -909,10 +917,14 @@ begin
begin
{ Treat multiple sequential slashes as single. }
while (from[0]='/') and (from[1]='/') do
+ begin
Inc(from);
+ end;
{ Trailing slash is considered invalid. }
if (from[0]='/') and (from[1]=#0) then
+ begin
Exit(EINVAL);
+ end;
_to^:=from^;
//
Inc(from);
@@ -921,7 +933,9 @@ begin
_to^:=#0;
if (dev^.__si_namebuf[0]=#0) then
+ begin
Exit(EINVAL);
+ end;
{ Disallow '.' and '..' components. }
s:=@dev^.__si_namebuf;
@@ -931,16 +945,24 @@ begin
while (q^<>'/') and (q^<>#0) do Inc(q);
if (q - s=1) and (s[0]='.') then
+ begin
Exit(EINVAL);
+ end;
if (q - s=2) and (s[0]='.') and (s[1]='.') then
+ begin
Exit(EINVAL);
+ end;
if (q^<>'/') then
+ begin
break;
+ end;
s:=q + 1;
end;
if (devfs_dev_exists(dev^.__si_namebuf)<>0) then
+ begin
Exit(EEXIST);
+ end;
Exit(0);
end;
diff --git a/sys/vfs/kern_descrip.pas b/sys/vfs/kern_descrip.pas
index baadc4cd..bbb71a0d 100644
--- a/sys/vfs/kern_descrip.pas
+++ b/sys/vfs/kern_descrip.pas
@@ -1217,7 +1217,9 @@ var
begin
error:=falloc_noinstall(@fp);
if (error<>0) then
+ begin
Exit(error); { no reference held on error }
+ end;
error:=finstall(fp,@fd,flags);
if (error<>0) then
@@ -1232,7 +1234,9 @@ begin
fdrop(fp); { release local reference }
if (resultfd<>nil) then
+ begin
resultfd^:=fd;
+ end;
Exit(0);
end;
diff --git a/sys/vm/dmem_map.pas b/sys/vm/dmem_map.pas
new file mode 100644
index 00000000..22814cc3
--- /dev/null
+++ b/sys/vm/dmem_map.pas
@@ -0,0 +1,956 @@
+unit dmem_map;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ vmparam,
+ kern_mtx;
+
+Const
+ SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB
+
+ SCE_KERNEL_WB_ONION = 0;
+ SCE_KERNEL_WC_GARLIC = 3;
+ SCE_KERNEL_WB_GARLIC =10;
+
+ //deprecated
+ SCE_KERNEL_WB_ONION_NONVOLATILE = 1;
+ SCE_KERNEL_WC_GARLIC_VOLATILE = 2;
+ SCE_KERNEL_WC_GARLIC_NONVOLATILE = 3;
+ SCE_KERNEL_WT_ONION_VOLATILE = 4;
+ SCE_KERNEL_WT_ONION_NONVOLATILE = 5;
+ SCE_KERNEL_WP_ONION_VOLATILE = 6;
+ SCE_KERNEL_WP_ONION_NONVOLATILE = 7;
+ SCE_KERNEL_UC_GARLIC_VOLATILE = 8;
+ SCE_KERNEL_UC_GARLIC_NONVOLATILE = 9;
+
+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
+ avail_ssize :DWORD; // amt can grow if this is a stack
+ 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;
+ t_dmem_map=packed object
+ header :t_dmem_map_entry; // List of entries
+ lock :mtx; // Lock for map data
+ nentries:DWORD; // Number of entries
+ size :DWORD; // size
+ root :p_dmem_map_entry; // Root of a binary search tree
+ property min_offset:DWORD read header.start write header.start;
+ property max_offset:DWORD read header.__end write header.__end;
+ end;
+
+procedure dmem_map_entry_deallocate(entry:p_dmem_map_entry);
+
+procedure dmem_map_lock(map:p_dmem_map);
+function dmem_map_trylock(map:p_dmem_map):Boolean;
+procedure dmem_map_unlock(map:p_dmem_map);
+function dmem_map_locked(map:p_dmem_map):Boolean; inline;
+
+procedure dmem_map_init(map:p_dmem_map;min,max:QWORD);
+
+procedure dmem_map_entry_dispose(map:p_dmem_map;entry:p_dmem_map_entry); inline;
+function dmem_map_entry_create(map:p_dmem_map):p_dmem_map_entry;
+
+function dmem_map_lookup_entry(
+ map :p_dmem_map;
+ address :DWORD;
+ entry :pp_dmem_map_entry):Boolean;
+
+function dmem_map_insert(
+ map :p_dmem_map;
+ start :DWORD;
+ __end :DWORD;
+ m_type :DWORD):Integer;
+
+Function dmem_map_query_available(map:p_dmem_map;start,__end,align:QWORD;var oaddr,osize:QWORD):Integer;
+
+function dmem_map_findspace(map :p_dmem_map;
+ start :DWORD;
+ length:DWORD;
+ addr :PDWORD):Integer;
+
+function dmem_map_fixed(map :p_dmem_map;
+ start :DWORD;
+ length :DWORD;
+ m_type :DWORD;
+ overwr :Integer):Integer;
+
+procedure dmem_map_simplify_entry(map:p_dmem_map;entry:p_dmem_map_entry);
+
+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;
+
+implementation
+
+uses
+ errno,
+ kern_thr;
+
+function IDX_TO_OFF(x:DWORD):QWORD; inline;
+begin
+ Result:=QWORD(x) shl PAGE_SHIFT;
+end;
+
+function OFF_TO_IDX(x:QWORD):DWORD; inline;
+begin
+ Result:=QWORD(x) shr PAGE_SHIFT;
+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 AlignUp(addr:PtrUInt;alignment:PtrUInt):PtrUInt; inline;
+var
+ tmp:PtrUInt;
+begin
+ if (alignment=0) then Exit(addr);
+ tmp:=addr+PtrUInt(alignment-1);
+ Result:=tmp-(tmp mod alignment)
+end;
+
+function AlignDw(addr:PtrUInt;alignment:PtrUInt):PtrUInt; inline;
+begin
+ Result:=addr-(addr mod alignment);
+end;
+
+procedure dmem_map_entry_deallocate(entry:p_dmem_map_entry);
+begin
+ //if ((entry^.eflags and MAP_ENTRY_IS_SUB_MAP)=0) then
+ //begin
+ // vm_object_deallocate(entry^.vm_obj);
+ //end;
+ Freemem(entry);
+end;
+
+procedure DMEM_MAP_RANGE_CHECK(map:p_dmem_map;var start,__end:DWORD);
+begin
+ if (start