mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
b6926ffff1
commit
2dd09a7e6f
|
@ -17,10 +17,17 @@ uses
|
||||||
vuio,
|
vuio,
|
||||||
subr_uio,
|
subr_uio,
|
||||||
vm,
|
vm,
|
||||||
|
dmem_map,
|
||||||
kern_dmem;
|
kern_dmem;
|
||||||
|
|
||||||
Const
|
type
|
||||||
SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB
|
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;
|
Function dmem_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
|
||||||
begin
|
begin
|
||||||
|
@ -33,6 +40,13 @@ begin
|
||||||
begin
|
begin
|
||||||
PQWORD(data)^:=SCE_KERNEL_MAIN_DMEM_SIZE;
|
PQWORD(data)^:=SCE_KERNEL_MAIN_DMEM_SIZE;
|
||||||
end;
|
end;
|
||||||
|
$C0208016: //sceKernelAvailableDirectMemorySize
|
||||||
|
begin
|
||||||
|
with PAvailableDirectMemorySize(data)^ do
|
||||||
|
begin
|
||||||
|
Result:=dmem_map_query_available(@dmem,start,__end,align,start,osize);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
else
|
else
|
||||||
Assert(False);
|
Assert(False);
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -281,7 +281,9 @@ begin
|
||||||
|
|
||||||
{ Exit if the directory is not empty. }
|
{ Exit if the directory is not empty. }
|
||||||
if (TAILQ_NEXT(de_dotdot,@de_dotdot^.de_list)<>nil) then
|
if (TAILQ_NEXT(de_dotdot,@de_dotdot^.de_list)<>nil) then
|
||||||
|
begin
|
||||||
Exit;
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
dd:=devfs_parent_dirent(de);
|
dd:=devfs_parent_dirent(de);
|
||||||
Assert(dd<>nil, 'devfs_rmdir_empty: nil dd');
|
Assert(dd<>nil, 'devfs_rmdir_empty: nil dd');
|
||||||
|
@ -329,7 +331,9 @@ begin
|
||||||
devfs_dir_unref_de(dm, dd);
|
devfs_dir_unref_de(dm, dd);
|
||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
dd:=nil;
|
dd:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
mtx_lock(devfs_de_interlock);
|
mtx_lock(devfs_de_interlock);
|
||||||
vp:=de^.de_vnode;
|
vp:=de^.de_vnode;
|
||||||
|
@ -353,7 +357,9 @@ begin
|
||||||
vdrop(vp);
|
vdrop(vp);
|
||||||
sx_xlock(@dm^.dm_lock);
|
sx_xlock(@dm^.dm_lock);
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
mtx_unlock(devfs_de_interlock);
|
mtx_unlock(devfs_de_interlock);
|
||||||
|
end;
|
||||||
|
|
||||||
if (de^.de_symlink<>nil) then
|
if (de^.de_symlink<>nil) then
|
||||||
begin
|
begin
|
||||||
|
|
|
@ -5,13 +5,35 @@ unit kern_dmem;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
dmem_map;
|
||||||
|
|
||||||
|
var
|
||||||
|
dmem:t_dmem_map;
|
||||||
|
|
||||||
|
procedure init_dmem_map;
|
||||||
|
|
||||||
function sys_dmem_container(d_pool_id:Integer):Integer;
|
function sys_dmem_container(d_pool_id:Integer):Integer;
|
||||||
|
//
|
||||||
|
function sys_blockpool_open(flags:Integer):Integer;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
errno,
|
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
|
const
|
||||||
default_pool_id=1;
|
default_pool_id=1;
|
||||||
|
@ -34,6 +56,67 @@ begin
|
||||||
end;
|
end;
|
||||||
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.
|
end.
|
||||||
|
|
|
@ -60,9 +60,19 @@ begin
|
||||||
goto _err;
|
goto _err;
|
||||||
end;
|
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);
|
Result:=copyout(@data,pvalue,vlen);
|
||||||
if (Result<>0) then
|
if (Result<>0) then
|
||||||
|
|
|
@ -173,7 +173,8 @@ begin
|
||||||
Exit(ENOEXEC);
|
Exit(ENOEXEC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,i);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,i);
|
||||||
end; //R_X86_64_DTPMOD64
|
end; //R_X86_64_DTPMOD64
|
||||||
|
|
||||||
R_X86_64_DTPOFF64:
|
R_X86_64_DTPOFF64:
|
||||||
|
@ -194,7 +195,8 @@ begin
|
||||||
Exit(ENOEXEC);
|
Exit(ENOEXEC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,i);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,i);
|
||||||
end; //R_X86_64_DTPOFF64
|
end; //R_X86_64_DTPOFF64
|
||||||
|
|
||||||
R_X86_64_TPOFF64:
|
R_X86_64_TPOFF64:
|
||||||
|
@ -214,7 +216,8 @@ begin
|
||||||
Exit(ENOEXEC);
|
Exit(ENOEXEC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,i);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,i);
|
||||||
end; //R_X86_64_TPOFF64
|
end; //R_X86_64_TPOFF64
|
||||||
|
|
||||||
else;
|
else;
|
||||||
|
@ -260,7 +263,8 @@ begin
|
||||||
Exit(ENOEXEC);
|
Exit(ENOEXEC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,i);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,i);
|
||||||
end; //R_X86_64_PC32
|
end; //R_X86_64_PC32
|
||||||
|
|
||||||
R_X86_64_DTPOFF32:
|
R_X86_64_DTPOFF32:
|
||||||
|
@ -281,7 +285,8 @@ begin
|
||||||
Exit(ENOEXEC);
|
Exit(ENOEXEC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,i);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,i);
|
||||||
end; //R_X86_64_DTPOFF32
|
end; //R_X86_64_DTPOFF32
|
||||||
|
|
||||||
|
|
||||||
|
@ -302,7 +307,8 @@ begin
|
||||||
Exit(ENOEXEC);
|
Exit(ENOEXEC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,i);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,i);
|
||||||
end; //R_X86_64_TPOFF32
|
end; //R_X86_64_TPOFF32
|
||||||
|
|
||||||
else;
|
else;
|
||||||
|
@ -339,7 +345,8 @@ begin
|
||||||
Exit(ENOEXEC);
|
Exit(ENOEXEC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,i);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,i);
|
||||||
|
|
||||||
goto _next;
|
goto _next;
|
||||||
end;
|
end;
|
||||||
|
@ -407,7 +414,8 @@ begin
|
||||||
Exit(4);
|
Exit(4);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
set_relo_bits(obj,idofs);
|
if (def<>@dynlibs_info.sym_nops) then
|
||||||
|
set_relo_bits(obj,idofs);
|
||||||
|
|
||||||
if (flags=0) then Exit;
|
if (flags=0) then Exit;
|
||||||
|
|
||||||
|
|
|
@ -394,7 +394,7 @@ begin
|
||||||
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
||||||
s:=elf_phdr[s].p_offset;
|
s:=elf_phdr[s].p_offset;
|
||||||
MinSeg:=MinInt64(s,MinSeg);
|
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);
|
MaxSeg:=MaxInt64(s,MaxSeg);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -436,9 +436,9 @@ begin
|
||||||
Assert(false,'src_ofs>=obj_size');
|
Assert(false,'src_ofs>=obj_size');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if ((src_ofs+mem_size)>=obj_size) then
|
if ((src_ofs+mem_size)>obj_size) then
|
||||||
begin
|
begin
|
||||||
Assert(false,'(src_ofs+mem_size)>=obj_size');
|
Assert(false,'(src_ofs+mem_size)>obj_size');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (dst_ofs>=MaxSeg) then
|
if (dst_ofs>=MaxSeg) then
|
||||||
|
@ -446,9 +446,9 @@ begin
|
||||||
Assert(false,'dst_ofs>=MaxSeg');
|
Assert(false,'dst_ofs>=MaxSeg');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if ((dst_ofs+mem_size)>=MaxSeg) then
|
if ((dst_ofs+mem_size)>MaxSeg) then
|
||||||
begin
|
begin
|
||||||
Assert(false,'(dst_ofs+mem_size)>=MaxSeg');
|
Assert(false,'(dst_ofs+mem_size)>MaxSeg');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Move( (Pointer(self_hdr) +src_ofs)^, //src
|
Move( (Pointer(self_hdr) +src_ofs)^, //src
|
||||||
|
@ -633,7 +633,7 @@ begin
|
||||||
addr^:=SCE_REPLAY_EXEC_START;
|
addr^:=SCE_REPLAY_EXEC_START;
|
||||||
end;
|
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;
|
end;
|
||||||
|
|
||||||
procedure rtld_munmap(base:Pointer;size:QWORD);
|
procedure rtld_munmap(base:Pointer;size:QWORD);
|
||||||
|
|
|
@ -38,9 +38,9 @@ const
|
||||||
MAP_SELF =$80000; // map decryped SELF file
|
MAP_SELF =$80000; // map decryped SELF file
|
||||||
|
|
||||||
MAP_ALIGNMENT_BIT =24;
|
MAP_ALIGNMENT_BIT =24;
|
||||||
MAP_ALIGNMENT_SHIFT=$1f000000;
|
MAP_ALIGNMENT_SHIFT=24;
|
||||||
MAP_ALIGNMENT_MASK =$ff shl MAP_ALIGNMENT_BIT;
|
MAP_ALIGNMENT_MASK =$ff shl MAP_ALIGNMENT_SHIFT;
|
||||||
MAP_ALIGNED_SUPER =$01 shl MAP_ALIGNMENT_BIT;
|
MAP_ALIGNED_SUPER =$01 shl MAP_ALIGNMENT_SHIFT;
|
||||||
//MAP_ALIGNED(n) ((n) << MAP_ALIGNMENT_SHIFT)
|
//MAP_ALIGNED(n) ((n) << MAP_ALIGNMENT_SHIFT)
|
||||||
|
|
||||||
MCL_CURRENT=$0001; // Lock only current memory
|
MCL_CURRENT=$0001; // Lock only current memory
|
||||||
|
|
|
@ -24,6 +24,7 @@ uses
|
||||||
vmount,
|
vmount,
|
||||||
vfiledesc,
|
vfiledesc,
|
||||||
vm_map,
|
vm_map,
|
||||||
|
kern_dmem,
|
||||||
kern_mtxpool,
|
kern_mtxpool,
|
||||||
vsys_generic,
|
vsys_generic,
|
||||||
vfs_subr,
|
vfs_subr,
|
||||||
|
@ -93,6 +94,7 @@ begin
|
||||||
vmountinit;
|
vmountinit;
|
||||||
fd_table_init;
|
fd_table_init;
|
||||||
vminit;
|
vminit;
|
||||||
|
init_dmem_map;
|
||||||
mtx_pool_setup_dynamic;
|
mtx_pool_setup_dynamic;
|
||||||
selectinit;
|
selectinit;
|
||||||
vntblinit;
|
vntblinit;
|
||||||
|
|
|
@ -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 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 dynlib_get_obj_member(handle:Integer;num:Byte;pout:PPointer):Integer;
|
||||||
function budget_get_ptype_of_budget(key:Integer):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 __sys_dynlib_get_info_for_libdbg(handle:Integer;info:Pointer):Integer;
|
||||||
function fdatasync(fd:Integer):Integer;
|
function fdatasync(fd:Integer):Integer;
|
||||||
function __sys_dynlib_get_list2(pArray:PInteger;numArray:QWORD;pActualNum:PQWORD):Integer;
|
function __sys_dynlib_get_list2(pArray:PInteger;numArray:QWORD;pActualNum:PQWORD):Integer;
|
||||||
|
@ -1836,6 +1837,13 @@ asm
|
||||||
jmp cerror
|
jmp cerror
|
||||||
end;
|
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;
|
function __sys_dynlib_get_info_for_libdbg(handle:Integer;info:Pointer):Integer; assembler; nostackframe;
|
||||||
asm
|
asm
|
||||||
movq $656,%rax
|
movq $656,%rax
|
||||||
|
|
|
@ -3322,7 +3322,7 @@ const
|
||||||
),
|
),
|
||||||
(//[653]
|
(//[653]
|
||||||
sy_narg:1;
|
sy_narg:1;
|
||||||
sy_call:nil;
|
sy_call:@sys_blockpool_open;
|
||||||
sy_name:'sys_blockpool_open'
|
sy_name:'sys_blockpool_open'
|
||||||
),
|
),
|
||||||
(//[654]
|
(//[654]
|
||||||
|
|
|
@ -641,6 +641,10 @@
|
||||||
<Filename Value="..\dev\dev_dmem.pas"/>
|
<Filename Value="..\dev\dev_dmem.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="..\vm\dmem_map.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
|
|
@ -199,6 +199,7 @@ function _nullop():Integer;
|
||||||
function _eopnotsupp():Integer;
|
function _eopnotsupp():Integer;
|
||||||
function _enxio():Integer;
|
function _enxio():Integer;
|
||||||
function _enodev():Integer;
|
function _enodev():Integer;
|
||||||
|
function _einval():Integer;
|
||||||
|
|
||||||
procedure dev_lock();
|
procedure dev_lock();
|
||||||
procedure dev_unlock();
|
procedure dev_unlock();
|
||||||
|
@ -503,6 +504,11 @@ begin
|
||||||
Exit(ENODEV);
|
Exit(ENODEV);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function _einval():Integer;
|
||||||
|
begin
|
||||||
|
Exit(EINVAL);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure dead_strategy(bp:Pointer);
|
procedure dead_strategy(bp:Pointer);
|
||||||
begin
|
begin
|
||||||
//biofinish(bp, nil, ENXIO);
|
//biofinish(bp, nil, ENXIO);
|
||||||
|
@ -896,7 +902,9 @@ begin
|
||||||
len:=Length(R);
|
len:=Length(R);
|
||||||
|
|
||||||
if (len > sizeof(dev^.__si_namebuf) - 1) then
|
if (len > sizeof(dev^.__si_namebuf) - 1) then
|
||||||
|
begin
|
||||||
Exit(ENAMETOOLONG);
|
Exit(ENAMETOOLONG);
|
||||||
|
end;
|
||||||
|
|
||||||
Move(PChar(R)^,dev^.__si_namebuf,len);
|
Move(PChar(R)^,dev^.__si_namebuf,len);
|
||||||
|
|
||||||
|
@ -909,10 +917,14 @@ begin
|
||||||
begin
|
begin
|
||||||
{ Treat multiple sequential slashes as single. }
|
{ Treat multiple sequential slashes as single. }
|
||||||
while (from[0]='/') and (from[1]='/') do
|
while (from[0]='/') and (from[1]='/') do
|
||||||
|
begin
|
||||||
Inc(from);
|
Inc(from);
|
||||||
|
end;
|
||||||
{ Trailing slash is considered invalid. }
|
{ Trailing slash is considered invalid. }
|
||||||
if (from[0]='/') and (from[1]=#0) then
|
if (from[0]='/') and (from[1]=#0) then
|
||||||
|
begin
|
||||||
Exit(EINVAL);
|
Exit(EINVAL);
|
||||||
|
end;
|
||||||
_to^:=from^;
|
_to^:=from^;
|
||||||
//
|
//
|
||||||
Inc(from);
|
Inc(from);
|
||||||
|
@ -921,7 +933,9 @@ begin
|
||||||
_to^:=#0;
|
_to^:=#0;
|
||||||
|
|
||||||
if (dev^.__si_namebuf[0]=#0) then
|
if (dev^.__si_namebuf[0]=#0) then
|
||||||
|
begin
|
||||||
Exit(EINVAL);
|
Exit(EINVAL);
|
||||||
|
end;
|
||||||
|
|
||||||
{ Disallow '.' and '..' components. }
|
{ Disallow '.' and '..' components. }
|
||||||
s:=@dev^.__si_namebuf;
|
s:=@dev^.__si_namebuf;
|
||||||
|
@ -931,16 +945,24 @@ begin
|
||||||
while (q^<>'/') and (q^<>#0) do Inc(q);
|
while (q^<>'/') and (q^<>#0) do Inc(q);
|
||||||
|
|
||||||
if (q - s=1) and (s[0]='.') then
|
if (q - s=1) and (s[0]='.') then
|
||||||
|
begin
|
||||||
Exit(EINVAL);
|
Exit(EINVAL);
|
||||||
|
end;
|
||||||
if (q - s=2) and (s[0]='.') and (s[1]='.') then
|
if (q - s=2) and (s[0]='.') and (s[1]='.') then
|
||||||
|
begin
|
||||||
Exit(EINVAL);
|
Exit(EINVAL);
|
||||||
|
end;
|
||||||
if (q^<>'/') then
|
if (q^<>'/') then
|
||||||
|
begin
|
||||||
break;
|
break;
|
||||||
|
end;
|
||||||
s:=q + 1;
|
s:=q + 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (devfs_dev_exists(dev^.__si_namebuf)<>0) then
|
if (devfs_dev_exists(dev^.__si_namebuf)<>0) then
|
||||||
|
begin
|
||||||
Exit(EEXIST);
|
Exit(EEXIST);
|
||||||
|
end;
|
||||||
|
|
||||||
Exit(0);
|
Exit(0);
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -1217,7 +1217,9 @@ var
|
||||||
begin
|
begin
|
||||||
error:=falloc_noinstall(@fp);
|
error:=falloc_noinstall(@fp);
|
||||||
if (error<>0) then
|
if (error<>0) then
|
||||||
|
begin
|
||||||
Exit(error); { no reference held on error }
|
Exit(error); { no reference held on error }
|
||||||
|
end;
|
||||||
|
|
||||||
error:=finstall(fp,@fd,flags);
|
error:=finstall(fp,@fd,flags);
|
||||||
if (error<>0) then
|
if (error<>0) then
|
||||||
|
@ -1232,7 +1234,9 @@ begin
|
||||||
fdrop(fp); { release local reference }
|
fdrop(fp); { release local reference }
|
||||||
|
|
||||||
if (resultfd<>nil) then
|
if (resultfd<>nil) then
|
||||||
|
begin
|
||||||
resultfd^:=fd;
|
resultfd^:=fd;
|
||||||
|
end;
|
||||||
|
|
||||||
Exit(0);
|
Exit(0);
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -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<map^.min_offset) then
|
||||||
|
begin
|
||||||
|
start:=map^.min_offset;
|
||||||
|
end;
|
||||||
|
if (__end>map^.max_offset) then
|
||||||
|
begin
|
||||||
|
__end:=map^.max_offset;
|
||||||
|
end;
|
||||||
|
if (start>__end) then
|
||||||
|
begin
|
||||||
|
start:=__end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_lock(map:p_dmem_map);
|
||||||
|
begin
|
||||||
|
mtx_lock(map^.lock);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_trylock(map:p_dmem_map):Boolean;
|
||||||
|
begin
|
||||||
|
Result:=mtx_trylock(map^.lock);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_process_deferred;
|
||||||
|
var
|
||||||
|
td:p_kthread;
|
||||||
|
entry,next:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
td:=curkthread;
|
||||||
|
if (td=nil) then Exit;
|
||||||
|
entry:=td^.td_map_def_user;
|
||||||
|
td^.td_map_def_user:=nil;
|
||||||
|
while (entry<>nil) do
|
||||||
|
begin
|
||||||
|
next:=entry^.next;
|
||||||
|
dmem_map_entry_deallocate(entry);
|
||||||
|
entry:=next;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_unlock(map:p_dmem_map);
|
||||||
|
begin
|
||||||
|
mtx_unlock(map^.lock);
|
||||||
|
dmem_map_process_deferred();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_locked(map:p_dmem_map):Boolean; inline;
|
||||||
|
begin
|
||||||
|
Result:=mtx_owned(map^.lock);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure DMEM_MAP_ASSERT_LOCKED(map:p_dmem_map); inline;
|
||||||
|
begin
|
||||||
|
Assert(dmem_map_locked(map));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure _dmem_map_init(map:p_dmem_map;min,max:DWORD);
|
||||||
|
begin
|
||||||
|
map^.header.next:=@map^.header;
|
||||||
|
map^.header.prev:=@map^.header;
|
||||||
|
map^.min_offset :=min;
|
||||||
|
map^.max_offset :=max;
|
||||||
|
map^.header.adj_free:=(max-min);
|
||||||
|
map^.header.max_free:=(max-min);
|
||||||
|
map^.nentries:=0;
|
||||||
|
map^.size :=0;
|
||||||
|
map^.root:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_init(map:p_dmem_map;min,max:QWORD);
|
||||||
|
begin
|
||||||
|
_dmem_map_init(map, OFF_TO_IDX(min), OFF_TO_IDX(max));
|
||||||
|
mtx_init(map^.lock,'dmem');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_entry_dispose(map:p_dmem_map;entry:p_dmem_map_entry); inline;
|
||||||
|
begin
|
||||||
|
FreeMem(entry);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_entry_create(map:p_dmem_map):p_dmem_map_entry;
|
||||||
|
var
|
||||||
|
new_entry:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
new_entry:=AllocMem(SizeOf(t_dmem_map_entry));
|
||||||
|
Assert((new_entry<>nil),'dmem_map_entry_create: kernel resources exhausted');
|
||||||
|
Result:=new_entry;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_entry_set_max_free(entry:p_dmem_map_entry);
|
||||||
|
begin
|
||||||
|
entry^.max_free:=entry^.adj_free;
|
||||||
|
if (entry^.left<>nil) then
|
||||||
|
if (entry^.left^.max_free>entry^.max_free) then
|
||||||
|
begin
|
||||||
|
entry^.max_free:=entry^.left^.max_free;
|
||||||
|
end;
|
||||||
|
if (entry^.right<>nil) then
|
||||||
|
if (entry^.right^.max_free>entry^.max_free) then
|
||||||
|
begin
|
||||||
|
entry^.max_free:=entry^.right^.max_free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_entry_splay(addr:DWORD;root:p_dmem_map_entry):p_dmem_map_entry;
|
||||||
|
var
|
||||||
|
llist,rlist:p_dmem_map_entry;
|
||||||
|
ltree,rtree:p_dmem_map_entry;
|
||||||
|
y :p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
{ Special case of empty tree. }
|
||||||
|
if (root=nil) then Exit(root);
|
||||||
|
|
||||||
|
llist:=nil;
|
||||||
|
rlist:=nil;
|
||||||
|
repeat
|
||||||
|
{ root is never nil in here. }
|
||||||
|
if (addr<root^.start) then
|
||||||
|
begin
|
||||||
|
y:=root^.left;
|
||||||
|
if (y=nil) then break;
|
||||||
|
if (addr<y^.start) and (y^.left<>nil) then
|
||||||
|
begin
|
||||||
|
{ Rotate right and put y on rlist. }
|
||||||
|
root^.left:=y^.right;
|
||||||
|
y^.right:=root;
|
||||||
|
dmem_map_entry_set_max_free(root);
|
||||||
|
root:=y^.left;
|
||||||
|
y^.left:=rlist;
|
||||||
|
rlist:=y;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
{ Put root on rlist. }
|
||||||
|
root^.left:=rlist;
|
||||||
|
rlist:=root;
|
||||||
|
root:=y;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
if (addr>=root^.__end) then
|
||||||
|
begin
|
||||||
|
y:=root^.right;
|
||||||
|
if (y=nil) then break;
|
||||||
|
if (addr>=y^.__end) and (y^.right<>nil) then
|
||||||
|
begin
|
||||||
|
{ Rotate left and put y on llist. }
|
||||||
|
root^.right:=y^.left;
|
||||||
|
y^.left:=root;
|
||||||
|
dmem_map_entry_set_max_free(root);
|
||||||
|
root:=y^.right;
|
||||||
|
y^.right:=llist;
|
||||||
|
llist:=y;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
{ Put root on llist. }
|
||||||
|
root^.right:=llist;
|
||||||
|
llist:=root;
|
||||||
|
root:=y;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Pass Two: Walk back up the two spines, flip the pointers
|
||||||
|
* and set max_free. The subtrees of the root go at the
|
||||||
|
* bottom of llist and rlist.
|
||||||
|
}
|
||||||
|
ltree:=root^.left;
|
||||||
|
while (llist<>nil) do
|
||||||
|
begin
|
||||||
|
y:=llist^.right;
|
||||||
|
llist^.right:=ltree;
|
||||||
|
dmem_map_entry_set_max_free(llist);
|
||||||
|
ltree:=llist;
|
||||||
|
llist:=y;
|
||||||
|
end;
|
||||||
|
rtree:=root^.right;
|
||||||
|
while (rlist<>nil) do
|
||||||
|
begin
|
||||||
|
y:=rlist^.left;
|
||||||
|
rlist^.left:=rtree;
|
||||||
|
dmem_map_entry_set_max_free(rlist);
|
||||||
|
rtree:=rlist;
|
||||||
|
rlist:=y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Final assembly: add ltree and rtree as subtrees of root.
|
||||||
|
}
|
||||||
|
root^.left:=ltree;
|
||||||
|
root^.right:=rtree;
|
||||||
|
dmem_map_entry_set_max_free(root);
|
||||||
|
|
||||||
|
Result:=(root);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_entry_link(
|
||||||
|
map :p_dmem_map;
|
||||||
|
after_where:p_dmem_map_entry;
|
||||||
|
entry :p_dmem_map_entry);
|
||||||
|
begin
|
||||||
|
DMEM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
|
Inc(map^.nentries);
|
||||||
|
entry^.prev:=after_where;
|
||||||
|
entry^.next:=after_where^.next;
|
||||||
|
entry^.next^.prev:=entry;
|
||||||
|
after_where^.next:=entry;
|
||||||
|
|
||||||
|
if (after_where<>@map^.header) then
|
||||||
|
begin
|
||||||
|
if (after_where<>map^.root) then
|
||||||
|
begin
|
||||||
|
dmem_map_entry_splay(after_where^.start, map^.root);
|
||||||
|
end;
|
||||||
|
entry^.right:=after_where^.right;
|
||||||
|
entry^.left:=after_where;
|
||||||
|
after_where^.right:=nil;
|
||||||
|
after_where^.adj_free:=entry^.start - after_where^.__end;
|
||||||
|
dmem_map_entry_set_max_free(after_where);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
entry^.right:=map^.root;
|
||||||
|
entry^.left:=nil;
|
||||||
|
end;
|
||||||
|
if (entry^.next=@map^.header) then
|
||||||
|
begin
|
||||||
|
entry^.adj_free:=map^.max_offset-entry^.__end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
entry^.adj_free:=entry^.next^.start-entry^.__end;
|
||||||
|
end;
|
||||||
|
dmem_map_entry_set_max_free(entry);
|
||||||
|
map^.root:=entry;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_entry_unlink(
|
||||||
|
map :p_dmem_map;
|
||||||
|
entry :p_dmem_map_entry);
|
||||||
|
var
|
||||||
|
next,prev,root:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
DMEM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
|
if (entry<>map^.root) then
|
||||||
|
begin
|
||||||
|
dmem_map_entry_splay(entry^.start, map^.root);
|
||||||
|
end;
|
||||||
|
if (entry^.left=nil) then
|
||||||
|
begin
|
||||||
|
root:=entry^.right;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
root:=dmem_map_entry_splay(entry^.start, entry^.left);
|
||||||
|
root^.right:=entry^.right;
|
||||||
|
if (root^.next=@map^.header) then
|
||||||
|
begin
|
||||||
|
root^.adj_free:=map^.max_offset-root^.__end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
root^.adj_free:=entry^.next^.start-root^.__end;
|
||||||
|
end;
|
||||||
|
dmem_map_entry_set_max_free(root);
|
||||||
|
end;
|
||||||
|
map^.root:=root;
|
||||||
|
|
||||||
|
prev:=entry^.prev;
|
||||||
|
next:=entry^.next;
|
||||||
|
next^.prev:=prev;
|
||||||
|
prev^.next:=next;
|
||||||
|
Dec(map^.nentries);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_entry_resize_free(map:p_dmem_map;entry:p_dmem_map_entry);
|
||||||
|
begin
|
||||||
|
if (entry<>map^.root) then
|
||||||
|
begin
|
||||||
|
map^.root:=dmem_map_entry_splay(entry^.start, map^.root);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (entry^.next=@map^.header) then
|
||||||
|
begin
|
||||||
|
entry^.adj_free:=map^.max_offset-entry^.__end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
entry^.adj_free:=entry^.next^.start-entry^.__end;
|
||||||
|
end;
|
||||||
|
dmem_map_entry_set_max_free(entry);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_lookup_entry(
|
||||||
|
map :p_dmem_map;
|
||||||
|
address :DWORD;
|
||||||
|
entry :pp_dmem_map_entry):Boolean;
|
||||||
|
var
|
||||||
|
cur:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
DMEM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
|
{
|
||||||
|
* If the map is empty, then the map entry immediately preceding
|
||||||
|
* "address" is the map's header.
|
||||||
|
}
|
||||||
|
cur:=map^.root;
|
||||||
|
if (cur=nil) then
|
||||||
|
begin
|
||||||
|
entry^:=@map^.header;
|
||||||
|
end else
|
||||||
|
if (address>=cur^.start) and (cur^.__end>address) then
|
||||||
|
begin
|
||||||
|
entry^:=cur;
|
||||||
|
Exit(TRUE);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
{
|
||||||
|
* Splay requires a write lock on the map. However, it only
|
||||||
|
* restructures the binary search tree; it does not otherwise
|
||||||
|
* change the map. Thus, the map's timestamp need not change
|
||||||
|
* on a temporary upgrade.
|
||||||
|
}
|
||||||
|
cur:=dmem_map_entry_splay(address,cur);
|
||||||
|
map^.root:=cur;
|
||||||
|
|
||||||
|
{
|
||||||
|
* If "address" is contained within a map entry, the new root
|
||||||
|
* is that map entry. Otherwise, the new root is a map entry
|
||||||
|
* immediately before or after "address".
|
||||||
|
}
|
||||||
|
if (address>=cur^.start) then
|
||||||
|
begin
|
||||||
|
entry^:=cur;
|
||||||
|
if (cur^.__end>address) then
|
||||||
|
begin
|
||||||
|
Exit(TRUE);
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
entry^:=cur^.prev;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result:=(FALSE);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_insert(
|
||||||
|
map :p_dmem_map;
|
||||||
|
start :DWORD;
|
||||||
|
__end :DWORD;
|
||||||
|
m_type :DWORD):Integer;
|
||||||
|
var
|
||||||
|
new_entry :p_dmem_map_entry;
|
||||||
|
prev_entry:p_dmem_map_entry;
|
||||||
|
temp_entry:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
DMEM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
|
{
|
||||||
|
* Check that the start and end points are not bogus.
|
||||||
|
}
|
||||||
|
if (start<map^.min_offset) or (__end>map^.max_offset) or (start>=__end) then
|
||||||
|
begin
|
||||||
|
Exit(EINVAL);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Find the entry prior to the proposed starting address; if it's part
|
||||||
|
* of an existing entry, this range is bogus.
|
||||||
|
}
|
||||||
|
if dmem_map_lookup_entry(map,start,@temp_entry) then
|
||||||
|
begin
|
||||||
|
Exit(EAGAIN);
|
||||||
|
end;
|
||||||
|
|
||||||
|
prev_entry:=temp_entry;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Assert that the next entry doesn't overlap the end point.
|
||||||
|
}
|
||||||
|
if (prev_entry^.next<>@map^.header) and
|
||||||
|
(prev_entry^.next^.start<__end) then
|
||||||
|
begin
|
||||||
|
Exit(EAGAIN);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (prev_entry<>@map^.header) and
|
||||||
|
(prev_entry^.__end=start) then
|
||||||
|
begin
|
||||||
|
{
|
||||||
|
* We were able to extend the object. Determine if we
|
||||||
|
* can extend the previous map entry to include the
|
||||||
|
* new range as well.
|
||||||
|
}
|
||||||
|
if (prev_entry^.m_type=m_type) then
|
||||||
|
begin
|
||||||
|
map^.size:=map^.size+(__end - prev_entry^.__end);
|
||||||
|
prev_entry^.__end:=__end;
|
||||||
|
//change size
|
||||||
|
|
||||||
|
//pmap_enter_object
|
||||||
|
|
||||||
|
dmem_map_entry_resize_free(map, prev_entry);
|
||||||
|
dmem_map_simplify_entry(map, prev_entry);
|
||||||
|
Exit(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* NOTE: if conditionals fail, object can be nil here. This occurs
|
||||||
|
* in things like the buffer map where we manage kva but do not manage
|
||||||
|
* backing objects.
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
* Create a new entry
|
||||||
|
}
|
||||||
|
new_entry:=dmem_map_entry_create(map);
|
||||||
|
new_entry^.start:=start;
|
||||||
|
new_entry^.__end:=__end;
|
||||||
|
|
||||||
|
new_entry^.m_type:=m_type;
|
||||||
|
new_entry^.avail_ssize:=0;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Insert the new entry into the list
|
||||||
|
}
|
||||||
|
dmem_map_entry_link(map, prev_entry, new_entry);
|
||||||
|
map^.size:=map^.size+(new_entry^.__end - new_entry^.start);
|
||||||
|
|
||||||
|
dmem_map_simplify_entry(map, new_entry);
|
||||||
|
|
||||||
|
//pmap_enter_object
|
||||||
|
|
||||||
|
Result:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Function dmem_map_query_available(map:p_dmem_map;start,__end,align:QWORD;var oaddr,osize:QWORD):Integer;
|
||||||
|
const
|
||||||
|
max_valid=QWORD($5000000000);
|
||||||
|
var
|
||||||
|
entry:p_dmem_map_entry;
|
||||||
|
|
||||||
|
r_addr,r_size:QWORD;
|
||||||
|
t_addr,t_size:QWORD;
|
||||||
|
t__end,t_free:QWORD;
|
||||||
|
begin
|
||||||
|
Result:=0;
|
||||||
|
|
||||||
|
if not IsPowerOfTwo(align) then
|
||||||
|
begin
|
||||||
|
Exit(EINVAL);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (align<PAGE_SIZE) then align:=PAGE_SIZE;
|
||||||
|
|
||||||
|
start:=(not (start shr 63)) and start;
|
||||||
|
if (start>max_valid) then start:=max_valid;
|
||||||
|
|
||||||
|
__end:=(not (__end shr 63)) and __end;
|
||||||
|
if (__end>max_valid) then __end:=max_valid;
|
||||||
|
|
||||||
|
start:=AlignUp(start,align);
|
||||||
|
|
||||||
|
dmem_map_lock(map);
|
||||||
|
|
||||||
|
if (map^.root=nil) then
|
||||||
|
begin
|
||||||
|
if (start>=IDX_TO_OFF(map^.max_offset)) then
|
||||||
|
begin
|
||||||
|
r_addr:=0;
|
||||||
|
r_size:=0;
|
||||||
|
Result:=ENOMEM;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
r_addr:=start;
|
||||||
|
r_size:=IDX_TO_OFF(map^.max_offset)-start;
|
||||||
|
Result:=0;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
r_addr:=0;
|
||||||
|
r_size:=0;
|
||||||
|
Result:=ENOMEM;
|
||||||
|
|
||||||
|
map^.root:=dmem_map_entry_splay(OFF_TO_IDX(start), map^.root);
|
||||||
|
entry:=map^.root;
|
||||||
|
|
||||||
|
while (entry<>nil) do
|
||||||
|
begin
|
||||||
|
if (entry^.adj_free<>0) then
|
||||||
|
begin
|
||||||
|
t__end:=IDX_TO_OFF(entry^.__end);
|
||||||
|
t_free:=IDX_TO_OFF(entry^.adj_free);
|
||||||
|
t_addr:=AlignUp(t__end,align);
|
||||||
|
if (__end<t_addr) then Break;
|
||||||
|
t_size:=(t_addr-t__end);
|
||||||
|
if (t_size<t_free) then
|
||||||
|
begin
|
||||||
|
t_size:=t_free-t_size;
|
||||||
|
if (t_size>r_size) then
|
||||||
|
begin
|
||||||
|
r_addr:=t_addr;
|
||||||
|
r_size:=t_size;
|
||||||
|
end;
|
||||||
|
Result:=0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
entry:=entry^.next;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
dmem_map_unlock(map);
|
||||||
|
|
||||||
|
oaddr:=r_addr;
|
||||||
|
osize:=r_size;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_findspace(map :p_dmem_map;
|
||||||
|
start :DWORD;
|
||||||
|
length:DWORD;
|
||||||
|
addr :PDWORD):Integer;
|
||||||
|
label
|
||||||
|
_nxt;
|
||||||
|
var
|
||||||
|
entry:p_dmem_map_entry;
|
||||||
|
st:DWORD;
|
||||||
|
begin
|
||||||
|
{
|
||||||
|
* Request must fit within min/max VM address and must avoid
|
||||||
|
* address wrap.
|
||||||
|
}
|
||||||
|
if (start<map^.min_offset) then
|
||||||
|
begin
|
||||||
|
start:=map^.min_offset;
|
||||||
|
end;
|
||||||
|
if (start + length>map^.max_offset) or (start + length<start) then
|
||||||
|
begin
|
||||||
|
Exit(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Empty tree means wide open address space. }
|
||||||
|
if (map^.root=nil) then
|
||||||
|
begin
|
||||||
|
addr^:=start;
|
||||||
|
Exit(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* After splay, if start comes before root node, then there
|
||||||
|
* must be a gap from start to the root.
|
||||||
|
}
|
||||||
|
map^.root:=dmem_map_entry_splay(start, map^.root);
|
||||||
|
if (start + length<=map^.root^.start) then
|
||||||
|
begin
|
||||||
|
addr^:=start;
|
||||||
|
Exit(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Root is the last node that might begin its gap before
|
||||||
|
* start, and this is the last comparison where address
|
||||||
|
* wrap might be a problem.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start>map^.root^.__end) then
|
||||||
|
begin
|
||||||
|
st:=start;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
st:=map^.root^.__end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (length<=map^.root^.__end + map^.root^.adj_free - st) then
|
||||||
|
begin
|
||||||
|
addr^:=st;
|
||||||
|
Exit(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ With max_free, can immediately tell if no solution. }
|
||||||
|
entry:=map^.root^.right;
|
||||||
|
|
||||||
|
if (entry=nil) then
|
||||||
|
begin
|
||||||
|
Exit(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (length>entry^.max_free) then
|
||||||
|
begin
|
||||||
|
Exit(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Search the right subtree in the order: left subtree, root,
|
||||||
|
* right subtree (first fit). The previous splay implies that
|
||||||
|
* all regions in the right subtree have addresses>start.
|
||||||
|
}
|
||||||
|
while (entry<>nil) do
|
||||||
|
begin
|
||||||
|
if (entry^.left<>nil) then
|
||||||
|
begin
|
||||||
|
if not (entry^.left^.max_free>=length) then goto _nxt;
|
||||||
|
entry:=entry^.left;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
_nxt:
|
||||||
|
if (entry^.adj_free>=length) then
|
||||||
|
begin
|
||||||
|
addr^:=entry^.__end;
|
||||||
|
Exit(0);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
entry:=entry^.right;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Can't get here, so panic if we do. }
|
||||||
|
Assert(false,'dmem_map_findspace: max_free corrupt');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_fixed(map :p_dmem_map;
|
||||||
|
start :DWORD;
|
||||||
|
length :DWORD;
|
||||||
|
m_type :DWORD;
|
||||||
|
overwr :Integer):Integer;
|
||||||
|
var
|
||||||
|
__end:DWORD;
|
||||||
|
begin
|
||||||
|
__end:=start + length;
|
||||||
|
dmem_map_lock(map);
|
||||||
|
DMEM_MAP_RANGE_CHECK(map, start, __end);
|
||||||
|
if (overwr<>0) then
|
||||||
|
begin
|
||||||
|
dmem_map_delete(map, start, __end);
|
||||||
|
end;
|
||||||
|
Result:= dmem_map_insert(map, start, __end, m_type);
|
||||||
|
dmem_map_unlock(map);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_simplify_entry(map:p_dmem_map;entry:p_dmem_map_entry);
|
||||||
|
var
|
||||||
|
next,prev:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
//if ((entry^.eflags and (MAP_ENTRY_IS_SUB_MAP))<>0) then
|
||||||
|
//begin
|
||||||
|
// Exit;
|
||||||
|
//end;
|
||||||
|
|
||||||
|
prev:=entry^.prev;
|
||||||
|
if (prev<>@map^.header) then
|
||||||
|
begin
|
||||||
|
if (prev^.__end=entry^.start) and
|
||||||
|
(prev^.m_type=entry^.m_type) then
|
||||||
|
begin
|
||||||
|
dmem_map_entry_unlink(map, prev);
|
||||||
|
entry^.start:=prev^.start;
|
||||||
|
|
||||||
|
//change
|
||||||
|
if (entry^.prev<>@map^.header) then
|
||||||
|
begin
|
||||||
|
dmem_map_entry_resize_free(map, entry^.prev);
|
||||||
|
end;
|
||||||
|
|
||||||
|
dmem_map_entry_dispose(map, prev);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
next:=entry^.next;
|
||||||
|
if (next<>@map^.header) then
|
||||||
|
begin
|
||||||
|
if (entry^.__end=next^.start) and
|
||||||
|
(next^.m_type=entry^.m_type) then
|
||||||
|
begin
|
||||||
|
dmem_map_entry_unlink(map, next);
|
||||||
|
entry^.__end:=next^.__end;
|
||||||
|
//change
|
||||||
|
dmem_map_entry_resize_free(map, entry);
|
||||||
|
|
||||||
|
dmem_map_entry_dispose(map, next);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure _dmem_map_clip_start(map:p_dmem_map;entry:p_dmem_map_entry;start:DWORD);
|
||||||
|
var
|
||||||
|
new_entry:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
DMEM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
|
dmem_map_simplify_entry(map, entry);
|
||||||
|
|
||||||
|
new_entry:=dmem_map_entry_create(map);
|
||||||
|
new_entry^:=entry^;
|
||||||
|
|
||||||
|
new_entry^.__end:=start;
|
||||||
|
entry^.start:=start;
|
||||||
|
|
||||||
|
dmem_map_entry_link(map, entry^.prev, new_entry);
|
||||||
|
|
||||||
|
//if ((entry^.eflags and MAP_ENTRY_IS_SUB_MAP)=0) then
|
||||||
|
//begin
|
||||||
|
// vm_object_reference(new_entry^.vm_obj);
|
||||||
|
//end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_clip_start(map:p_dmem_map;entry:p_dmem_map_entry;start:DWORD);
|
||||||
|
begin
|
||||||
|
if (start>entry^.start) then
|
||||||
|
begin
|
||||||
|
_dmem_map_clip_start(map,entry,start);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure _dmem_map_clip_end(map:p_dmem_map;entry:p_dmem_map_entry;__end:DWORD);
|
||||||
|
var
|
||||||
|
new_entry:p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
DMEM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
|
{
|
||||||
|
* Create a new entry and insert it AFTER the specified entry
|
||||||
|
}
|
||||||
|
new_entry:=dmem_map_entry_create(map);
|
||||||
|
new_entry^:=entry^;
|
||||||
|
|
||||||
|
new_entry^.start:=__end;
|
||||||
|
entry^.__end:=__end;
|
||||||
|
|
||||||
|
dmem_map_entry_link(map, entry, new_entry);
|
||||||
|
|
||||||
|
//if ((entry^.eflags and MAP_ENTRY_IS_SUB_MAP)=0) then
|
||||||
|
//begin
|
||||||
|
// vm_object_reference(new_entry^.vm_obj);
|
||||||
|
//end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_clip_end(map:p_dmem_map;entry:p_dmem_map_entry;__end:DWORD);
|
||||||
|
begin
|
||||||
|
if (__end<entry^.__end) then
|
||||||
|
begin
|
||||||
|
_dmem_map_clip_end(map,entry,__end);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dmem_map_entry_delete(map:p_dmem_map;entry:p_dmem_map_entry);
|
||||||
|
var
|
||||||
|
size:DWORD;
|
||||||
|
begin
|
||||||
|
dmem_map_entry_unlink(map, entry);
|
||||||
|
size:=entry^.__end - entry^.start;
|
||||||
|
map^.size:=map^.size-size;
|
||||||
|
|
||||||
|
entry^.next:=curkthread^.td_map_def_user;
|
||||||
|
curkthread^.td_map_def_user:=entry;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function dmem_map_delete(map:p_dmem_map;start:DWORD;__end:DWORD):Integer;
|
||||||
|
var
|
||||||
|
entry :p_dmem_map_entry;
|
||||||
|
first_entry:p_dmem_map_entry;
|
||||||
|
next :p_dmem_map_entry;
|
||||||
|
begin
|
||||||
|
DMEM_MAP_ASSERT_LOCKED(map);
|
||||||
|
if (start=__end) then
|
||||||
|
begin
|
||||||
|
Exit(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Find the start of the region, and clip it
|
||||||
|
}
|
||||||
|
if (not dmem_map_lookup_entry(map, start, @first_entry)) then
|
||||||
|
begin
|
||||||
|
entry:=first_entry^.next;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
entry:=first_entry;
|
||||||
|
dmem_map_clip_start(map, entry, start);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
|
* Step through all entries in this region
|
||||||
|
}
|
||||||
|
while (entry<>@map^.header) and (entry^.start<__end) do
|
||||||
|
begin
|
||||||
|
|
||||||
|
dmem_map_clip_end(map, entry, __end);
|
||||||
|
|
||||||
|
next:=entry^.next;
|
||||||
|
|
||||||
|
//pmap_remove(map^.pmap,entry^.start,entry^.__end,entry^.protection);
|
||||||
|
|
||||||
|
{
|
||||||
|
* Delete the entry only after removing all pmap
|
||||||
|
* entries pointing to its pages. (Otherwise, its
|
||||||
|
* page frames may be reallocated, and any modify bits
|
||||||
|
* will be set in the wrong object!)
|
||||||
|
}
|
||||||
|
dmem_map_entry_delete(map, entry);
|
||||||
|
entry:=next;
|
||||||
|
end;
|
||||||
|
Result:=(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
|
@ -81,9 +81,9 @@ const
|
||||||
MAP_SELF =$80000; // map decryped SELF file
|
MAP_SELF =$80000; // map decryped SELF file
|
||||||
|
|
||||||
MAP_ALIGNMENT_BIT =24;
|
MAP_ALIGNMENT_BIT =24;
|
||||||
MAP_ALIGNMENT_SHIFT=$1f000000;
|
MAP_ALIGNMENT_SHIFT=24;
|
||||||
MAP_ALIGNMENT_MASK =$ff shl MAP_ALIGNMENT_BIT;
|
MAP_ALIGNMENT_MASK =$ff shl MAP_ALIGNMENT_SHIFT;
|
||||||
MAP_ALIGNED_SUPER =$01 shl MAP_ALIGNMENT_BIT;
|
MAP_ALIGNED_SUPER =$01 shl MAP_ALIGNMENT_SHIFT;
|
||||||
//MAP_ALIGNED(n) ((n) << MAP_ALIGNMENT_SHIFT)
|
//MAP_ALIGNED(n) ((n) << MAP_ALIGNMENT_SHIFT)
|
||||||
|
|
||||||
MCL_CURRENT=$0001; // Lock only current memory
|
MCL_CURRENT=$0001; // Lock only current memory
|
||||||
|
|
|
@ -54,8 +54,8 @@ type
|
||||||
root:vm_map_entry_t; // Root of a binary search tree
|
root:vm_map_entry_t; // Root of a binary search tree
|
||||||
pmap:pmap_t; // (c) Physical map
|
pmap:pmap_t; // (c) Physical map
|
||||||
busy:Integer;
|
busy:Integer;
|
||||||
property min_offset:vm_offset_t read header.start;
|
property min_offset:vm_offset_t read header.start write header.start;
|
||||||
property max_offset:vm_offset_t read header.__end;
|
property max_offset:vm_offset_t read header.__end write header.__end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
p_vmspace=^vmspace;
|
p_vmspace=^vmspace;
|
||||||
|
@ -212,6 +212,8 @@ function vm_map_find(map :vm_map_t;
|
||||||
max :vm_prot_t;
|
max :vm_prot_t;
|
||||||
cow :Integer):Integer;
|
cow :Integer):Integer;
|
||||||
|
|
||||||
|
procedure vm_map_simplify_entry(map:vm_map_t;entry:vm_map_entry_t);
|
||||||
|
|
||||||
function vm_map_fixed(map :vm_map_t;
|
function vm_map_fixed(map :vm_map_t;
|
||||||
vm_obj :vm_object_t;
|
vm_obj :vm_object_t;
|
||||||
offset :vm_ooffset_t;
|
offset :vm_ooffset_t;
|
||||||
|
@ -254,6 +256,11 @@ var
|
||||||
sgrowsiz:QWORD=vmparam.SGROWSIZ;
|
sgrowsiz:QWORD=vmparam.SGROWSIZ;
|
||||||
stack_guard_page:Integer=0;
|
stack_guard_page:Integer=0;
|
||||||
|
|
||||||
|
function OFF_TO_IDX(x:QWORD):DWORD; inline;
|
||||||
|
begin
|
||||||
|
Result:=QWORD(x) shr PAGE_SHIFT;
|
||||||
|
end;
|
||||||
|
|
||||||
function VMFS_ALIGNED_SPACE(x:QWORD):QWORD; inline; // find a range with fixed alignment
|
function VMFS_ALIGNED_SPACE(x:QWORD):QWORD; inline; // find a range with fixed alignment
|
||||||
begin
|
begin
|
||||||
Result:=x shl 8;
|
Result:=x shl 8;
|
||||||
|
@ -331,13 +338,6 @@ begin
|
||||||
FillChar(g_vmspace,SizeOf(vmspace),0);
|
FillChar(g_vmspace,SizeOf(vmspace),0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure vm_map_zinit(map:vm_map_t);
|
|
||||||
begin
|
|
||||||
map^.nentries:=0;
|
|
||||||
map^.size:=0;
|
|
||||||
mtx_init(map^.lock,'vm map (system)');
|
|
||||||
end;
|
|
||||||
|
|
||||||
function vmspace_pmap(vm:p_vmspace):pmap_t; inline;
|
function vmspace_pmap(vm:p_vmspace):pmap_t; inline;
|
||||||
begin
|
begin
|
||||||
Result:=@vm^.vm_pmap;
|
Result:=@vm^.vm_pmap;
|
||||||
|
@ -381,7 +381,9 @@ function vm_map_trylock(map:vm_map_t):Boolean;
|
||||||
begin
|
begin
|
||||||
Result:=mtx_trylock(map^.lock);
|
Result:=mtx_trylock(map^.lock);
|
||||||
if Result then
|
if Result then
|
||||||
|
begin
|
||||||
Inc(map^.timestamp);
|
Inc(map^.timestamp);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure vm_map_process_deferred;
|
procedure vm_map_process_deferred;
|
||||||
|
@ -449,8 +451,8 @@ begin
|
||||||
map^.header.next:=@map^.header;
|
map^.header.next:=@map^.header;
|
||||||
map^.header.prev:=@map^.header;
|
map^.header.prev:=@map^.header;
|
||||||
map^.pmap:=pmap;
|
map^.pmap:=pmap;
|
||||||
map^.header.start:=min;
|
map^.min_offset:=min;
|
||||||
map^.header.__end:=max;
|
map^.max_offset:=max;
|
||||||
map^.header.adj_free:=(max-min);
|
map^.header.adj_free:=(max-min);
|
||||||
map^.header.max_free:=(max-min);
|
map^.header.max_free:=(max-min);
|
||||||
map^.flags:=0;
|
map^.flags:=0;
|
||||||
|
@ -601,7 +603,9 @@ begin
|
||||||
root:=y;
|
root:=y;
|
||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
break;
|
break;
|
||||||
|
end;
|
||||||
until false;
|
until false;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -639,7 +643,7 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
* vm_map_entry_beginun,end;link:
|
* vm_map_entry_{un,}link:
|
||||||
*
|
*
|
||||||
* Insert/remove entries from maps.
|
* Insert/remove entries from maps.
|
||||||
}
|
}
|
||||||
|
@ -649,6 +653,7 @@ procedure vm_map_entry_link(
|
||||||
entry :vm_map_entry_t);
|
entry :vm_map_entry_t);
|
||||||
begin
|
begin
|
||||||
VM_MAP_ASSERT_LOCKED(map);
|
VM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
Inc(map^.nentries);
|
Inc(map^.nentries);
|
||||||
entry^.prev:=after_where;
|
entry^.prev:=after_where;
|
||||||
entry^.next:=after_where^.next;
|
entry^.next:=after_where^.next;
|
||||||
|
@ -658,7 +663,9 @@ begin
|
||||||
if (after_where<>@map^.header) then
|
if (after_where<>@map^.header) then
|
||||||
begin
|
begin
|
||||||
if (after_where<>map^.root) then
|
if (after_where<>map^.root) then
|
||||||
|
begin
|
||||||
vm_map_entry_splay(after_where^.start, map^.root);
|
vm_map_entry_splay(after_where^.start, map^.root);
|
||||||
|
end;
|
||||||
entry^.right:=after_where^.right;
|
entry^.right:=after_where^.right;
|
||||||
entry^.left:=after_where;
|
entry^.left:=after_where;
|
||||||
after_where^.right:=nil;
|
after_where^.right:=nil;
|
||||||
|
@ -680,7 +687,6 @@ begin
|
||||||
map^.root:=entry;
|
map^.root:=entry;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure vm_map_entry_unlink(
|
procedure vm_map_entry_unlink(
|
||||||
map :vm_map_t;
|
map :vm_map_t;
|
||||||
entry :vm_map_entry_t);
|
entry :vm_map_entry_t);
|
||||||
|
@ -688,6 +694,7 @@ var
|
||||||
next,prev,root:vm_map_entry_t;
|
next,prev,root:vm_map_entry_t;
|
||||||
begin
|
begin
|
||||||
VM_MAP_ASSERT_LOCKED(map);
|
VM_MAP_ASSERT_LOCKED(map);
|
||||||
|
|
||||||
if (entry<>map^.root) then
|
if (entry<>map^.root) then
|
||||||
begin
|
begin
|
||||||
vm_map_entry_splay(entry^.start, map^.root);
|
vm_map_entry_splay(entry^.start, map^.root);
|
||||||
|
@ -806,13 +813,13 @@ begin
|
||||||
Exit(TRUE);
|
Exit(TRUE);
|
||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
entry^:=cur^.prev;
|
entry^:=cur^.prev;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
Result:=(FALSE);
|
Result:=(FALSE);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure vm_map_simplify_entry(map:vm_map_t;entry:vm_map_entry_t); forward;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
* vm_map_insert:
|
* vm_map_insert:
|
||||||
*
|
*
|
||||||
|
@ -1068,9 +1075,13 @@ begin
|
||||||
* address wrap.
|
* address wrap.
|
||||||
}
|
}
|
||||||
if (start<map^.min_offset) then
|
if (start<map^.min_offset) then
|
||||||
|
begin
|
||||||
start:=map^.min_offset;
|
start:=map^.min_offset;
|
||||||
|
end;
|
||||||
if (start + length>map^.max_offset) or (start + length<start) then
|
if (start + length>map^.max_offset) or (start + length<start) then
|
||||||
|
begin
|
||||||
Exit(1);
|
Exit(1);
|
||||||
|
end;
|
||||||
|
|
||||||
{ Empty tree means wide open address space. }
|
{ Empty tree means wide open address space. }
|
||||||
if (map^.root=nil) then
|
if (map^.root=nil) then
|
||||||
|
@ -1114,10 +1125,14 @@ begin
|
||||||
entry:=map^.root^.right;
|
entry:=map^.root^.right;
|
||||||
|
|
||||||
if (entry=nil) then
|
if (entry=nil) then
|
||||||
|
begin
|
||||||
Exit(1);
|
Exit(1);
|
||||||
|
end;
|
||||||
|
|
||||||
if (length>entry^.max_free) then
|
if (length>entry^.max_free) then
|
||||||
|
begin
|
||||||
Exit(1);
|
Exit(1);
|
||||||
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
* Search the right subtree in the order: left subtree, root,
|
* Search the right subtree in the order: left subtree, root,
|
||||||
|
@ -1138,7 +1153,9 @@ begin
|
||||||
addr^:=entry^.__end;
|
addr^:=entry^.__end;
|
||||||
Exit(0);
|
Exit(0);
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
entry:=entry^.right;
|
entry:=entry^.right;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1208,7 +1225,9 @@ begin
|
||||||
Assert((find_space and $ff)=0,'bad VMFS flags');
|
Assert((find_space and $ff)=0,'bad VMFS flags');
|
||||||
alignment:=vm_offset_t(1) shl (find_space shr 8);
|
alignment:=vm_offset_t(1) shl (find_space shr 8);
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
alignment:=0;
|
alignment:=0;
|
||||||
|
end;
|
||||||
initial_addr:=addr^;
|
initial_addr:=addr^;
|
||||||
again:
|
again:
|
||||||
start:=initial_addr;
|
start:=initial_addr;
|
||||||
|
@ -1266,7 +1285,9 @@ var
|
||||||
prevsize, esize:vm_size_t;
|
prevsize, esize:vm_size_t;
|
||||||
begin
|
begin
|
||||||
if ((entry^.eflags and (MAP_ENTRY_IS_SUB_MAP))<>0) then
|
if ((entry^.eflags and (MAP_ENTRY_IS_SUB_MAP))<>0) then
|
||||||
|
begin
|
||||||
Exit;
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
prev:=entry^.prev;
|
prev:=entry^.prev;
|
||||||
if (prev<>@map^.header) then
|
if (prev<>@map^.header) then
|
||||||
|
@ -1285,7 +1306,9 @@ begin
|
||||||
entry^.offset:=prev^.offset;
|
entry^.offset:=prev^.offset;
|
||||||
//change
|
//change
|
||||||
if (entry^.prev<>@map^.header) then
|
if (entry^.prev<>@map^.header) then
|
||||||
|
begin
|
||||||
vm_map_entry_resize_free(map, entry^.prev);
|
vm_map_entry_resize_free(map, entry^.prev);
|
||||||
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
* If the backing object is a vnode object,
|
* If the backing object is a vnode object,
|
||||||
|
@ -1371,7 +1394,9 @@ end;
|
||||||
procedure vm_map_clip_start(map:vm_map_t;entry:vm_map_entry_t;start:vm_offset_t);
|
procedure vm_map_clip_start(map:vm_map_t;entry:vm_map_entry_t;start:vm_offset_t);
|
||||||
begin
|
begin
|
||||||
if (start>entry^.start) then
|
if (start>entry^.start) then
|
||||||
|
begin
|
||||||
_vm_map_clip_start(map,entry,start);
|
_vm_map_clip_start(map,entry,start);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1413,7 +1438,9 @@ end;
|
||||||
procedure vm_map_clip_end(map:vm_map_t;entry:vm_map_entry_t;__end:vm_offset_t);
|
procedure vm_map_clip_end(map:vm_map_t;entry:vm_map_entry_t;__end:vm_offset_t);
|
||||||
begin
|
begin
|
||||||
if (__end<entry^.__end) then
|
if (__end<entry^.__end) then
|
||||||
|
begin
|
||||||
_vm_map_clip_end(map,entry,__end);
|
_vm_map_clip_end(map,entry,__end);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1782,7 +1809,9 @@ begin
|
||||||
Exit(KERN_INVALID_ARGUMENT);
|
Exit(KERN_INVALID_ARGUMENT);
|
||||||
end;
|
end;
|
||||||
if (start=__end) then
|
if (start=__end) then
|
||||||
|
begin
|
||||||
Exit(KERN_SUCCESS);
|
Exit(KERN_SUCCESS);
|
||||||
|
end;
|
||||||
vm_map_lock(map);
|
vm_map_lock(map);
|
||||||
VM_MAP_RANGE_CHECK(map, start, __end);
|
VM_MAP_RANGE_CHECK(map, start, __end);
|
||||||
|
|
||||||
|
@ -1791,7 +1820,9 @@ begin
|
||||||
entry:=temp_entry;
|
entry:=temp_entry;
|
||||||
vm_map_clip_start(map, entry, start);
|
vm_map_clip_start(map, entry, start);
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
entry:=temp_entry^.next;
|
entry:=temp_entry^.next;
|
||||||
|
end;
|
||||||
|
|
||||||
while ((entry<>@map^.header) and (entry^.start<__end)) do
|
while ((entry<>@map^.header) and (entry^.start<__end)) do
|
||||||
begin
|
begin
|
||||||
|
@ -2002,7 +2033,9 @@ var
|
||||||
begin
|
begin
|
||||||
VM_MAP_ASSERT_LOCKED(map);
|
VM_MAP_ASSERT_LOCKED(map);
|
||||||
if (start=__end) then
|
if (start=__end) then
|
||||||
|
begin
|
||||||
Exit(KERN_SUCCESS);
|
Exit(KERN_SUCCESS);
|
||||||
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
* Find the start of the region, and clip it
|
* Find the start of the region, and clip it
|
||||||
|
@ -2077,24 +2110,32 @@ var
|
||||||
tmp_entry:vm_map_entry_t;
|
tmp_entry:vm_map_entry_t;
|
||||||
begin
|
begin
|
||||||
if (not vm_map_lookup_entry(map, start, @tmp_entry)) then
|
if (not vm_map_lookup_entry(map, start, @tmp_entry)) then
|
||||||
|
begin
|
||||||
Exit(FALSE);
|
Exit(FALSE);
|
||||||
|
end;
|
||||||
|
|
||||||
entry:=tmp_entry;
|
entry:=tmp_entry;
|
||||||
|
|
||||||
while (start<__end) do
|
while (start<__end) do
|
||||||
begin
|
begin
|
||||||
if (entry=@map^.header) then
|
if (entry=@map^.header) then
|
||||||
|
begin
|
||||||
Exit (FALSE);
|
Exit (FALSE);
|
||||||
|
end;
|
||||||
{
|
{
|
||||||
* No holes allowed!
|
* No holes allowed!
|
||||||
}
|
}
|
||||||
if (start<entry^.start) then
|
if (start<entry^.start) then
|
||||||
|
begin
|
||||||
Exit(FALSE);
|
Exit(FALSE);
|
||||||
|
end;
|
||||||
{
|
{
|
||||||
* Check protection associated with entry.
|
* Check protection associated with entry.
|
||||||
}
|
}
|
||||||
if ((entry^.protection and protection)<>protection) then
|
if ((entry^.protection and protection)<>protection) then
|
||||||
|
begin
|
||||||
Exit(FALSE);
|
Exit(FALSE);
|
||||||
|
end;
|
||||||
{ go to next entry }
|
{ go to next entry }
|
||||||
start:=entry^.__end;
|
start:=entry^.__end;
|
||||||
entry:=entry^.next;
|
entry:=entry^.next;
|
||||||
|
@ -2127,7 +2168,9 @@ begin
|
||||||
if (addrbos<vm_map_min(map)) or
|
if (addrbos<vm_map_min(map)) or
|
||||||
(addrbos>vm_map_max(map)) or
|
(addrbos>vm_map_max(map)) or
|
||||||
(addrbos + max_ssize<addrbos) then
|
(addrbos + max_ssize<addrbos) then
|
||||||
|
begin
|
||||||
Exit(KERN_NO_SPACE);
|
Exit(KERN_NO_SPACE);
|
||||||
|
end;
|
||||||
|
|
||||||
growsize:=sgrowsiz;
|
growsize:=sgrowsiz;
|
||||||
|
|
||||||
|
@ -2199,18 +2242,26 @@ begin
|
||||||
if (rv=KERN_SUCCESS) then
|
if (rv=KERN_SUCCESS) then
|
||||||
begin
|
begin
|
||||||
if (prev_entry<>@map^.header) then
|
if (prev_entry<>@map^.header) then
|
||||||
|
begin
|
||||||
vm_map_clip_end(map, prev_entry, bot);
|
vm_map_clip_end(map, prev_entry, bot);
|
||||||
|
end;
|
||||||
|
|
||||||
new_entry:=prev_entry^.next;
|
new_entry:=prev_entry^.next;
|
||||||
if (new_entry^.__end<>top) or (new_entry^.start<>bot) then
|
if (new_entry^.__end<>top) or (new_entry^.start<>bot) then
|
||||||
|
begin
|
||||||
Assert(false,'Bad entry start/end for new stack entry');
|
Assert(false,'Bad entry start/end for new stack entry');
|
||||||
|
end;
|
||||||
|
|
||||||
new_entry^.avail_ssize:=max_ssize - init_ssize;
|
new_entry^.avail_ssize:=max_ssize - init_ssize;
|
||||||
if ((orient and MAP_STACK_GROWS_DOWN)<>0) then
|
if ((orient and MAP_STACK_GROWS_DOWN)<>0) then
|
||||||
|
begin
|
||||||
new_entry^.eflags:=new_entry^.eflags or MAP_ENTRY_GROWS_DOWN;
|
new_entry^.eflags:=new_entry^.eflags or MAP_ENTRY_GROWS_DOWN;
|
||||||
|
end;
|
||||||
|
|
||||||
if ((orient and MAP_STACK_GROWS_UP)<>0) then
|
if ((orient and MAP_STACK_GROWS_UP)<>0) then
|
||||||
|
begin
|
||||||
new_entry^.eflags:=new_entry^.eflags or MAP_ENTRY_GROWS_UP;
|
new_entry^.eflags:=new_entry^.eflags or MAP_ENTRY_GROWS_UP;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
vm_map_unlock(map);
|
vm_map_unlock(map);
|
||||||
|
@ -2293,8 +2344,11 @@ begin
|
||||||
stack_entry:=prev_entry
|
stack_entry:=prev_entry
|
||||||
else
|
else
|
||||||
stack_entry:=next_entry;
|
stack_entry:=next_entry;
|
||||||
|
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
stack_entry:=prev_entry;
|
stack_entry:=prev_entry;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (stack_entry=next_entry) then
|
if (stack_entry=next_entry) then
|
||||||
|
@ -2371,7 +2425,9 @@ begin
|
||||||
growsize:=sgrowsiz;
|
growsize:=sgrowsiz;
|
||||||
grow_amount:=roundup(grow_amount, growsize);
|
grow_amount:=roundup(grow_amount, growsize);
|
||||||
if (grow_amount>stack_entry^.avail_ssize) then
|
if (grow_amount>stack_entry^.avail_ssize) then
|
||||||
|
begin
|
||||||
grow_amount:=stack_entry^.avail_ssize;
|
grow_amount:=stack_entry^.avail_ssize;
|
||||||
|
end;
|
||||||
if (is_procstack<>0) and (ctob(g_vmspace.vm_ssize) + grow_amount>stacklim) then
|
if (is_procstack<>0) and (ctob(g_vmspace.vm_ssize) + grow_amount>stacklim) then
|
||||||
begin
|
begin
|
||||||
grow_amount:=trunc_page(stacklim) - ctob(g_vmspace.vm_ssize);
|
grow_amount:=trunc_page(stacklim) - ctob(g_vmspace.vm_ssize);
|
||||||
|
@ -2402,7 +2458,9 @@ begin
|
||||||
stack_entry^.avail_ssize:=max_grow;
|
stack_entry^.avail_ssize:=max_grow;
|
||||||
addr:=__end;
|
addr:=__end;
|
||||||
if (stack_guard_page<>0) then
|
if (stack_guard_page<>0) then
|
||||||
|
begin
|
||||||
addr:=addr+PAGE_SIZE;
|
addr:=addr+PAGE_SIZE;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
rv:=vm_map_insert(map, nil, 0, addr, stack_entry^.start,
|
rv:=vm_map_insert(map, nil, 0, addr, stack_entry^.start,
|
||||||
|
@ -2412,7 +2470,9 @@ begin
|
||||||
if (rv=KERN_SUCCESS) then
|
if (rv=KERN_SUCCESS) then
|
||||||
begin
|
begin
|
||||||
if (prev_entry<>@map^.header) then
|
if (prev_entry<>@map^.header) then
|
||||||
|
begin
|
||||||
vm_map_clip_end(map, prev_entry, addr);
|
vm_map_clip_end(map, prev_entry, addr);
|
||||||
|
end;
|
||||||
new_entry:=prev_entry^.next;
|
new_entry:=prev_entry^.next;
|
||||||
Assert(new_entry=stack_entry^.prev, 'foo');
|
Assert(new_entry=stack_entry^.prev, 'foo');
|
||||||
Assert(new_entry^.__end=stack_entry^.start, 'foo');
|
Assert(new_entry^.__end=stack_entry^.start, 'foo');
|
||||||
|
@ -2438,7 +2498,9 @@ begin
|
||||||
stack_entry^.avail_ssize:=__end - stack_entry^.__end;
|
stack_entry^.avail_ssize:=__end - stack_entry^.__end;
|
||||||
addr:=__end;
|
addr:=__end;
|
||||||
if (stack_guard_page<>0) then
|
if (stack_guard_page<>0) then
|
||||||
|
begin
|
||||||
addr:=addr-PAGE_SIZE;
|
addr:=addr-PAGE_SIZE;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
grow_amount:=addr - stack_entry^.__end;
|
grow_amount:=addr - stack_entry^.__end;
|
||||||
|
@ -2460,13 +2522,19 @@ begin
|
||||||
rv:=KERN_SUCCESS;
|
rv:=KERN_SUCCESS;
|
||||||
|
|
||||||
if (next_entry<>@map^.header) then
|
if (next_entry<>@map^.header) then
|
||||||
|
begin
|
||||||
vm_map_clip_start(map, next_entry, addr);
|
vm_map_clip_start(map, next_entry, addr);
|
||||||
|
end;
|
||||||
end else
|
end else
|
||||||
|
begin
|
||||||
rv:=KERN_FAILURE;
|
rv:=KERN_FAILURE;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (rv=KERN_SUCCESS) and (is_procstack<>0) then
|
if (rv=KERN_SUCCESS) and (is_procstack<>0) then
|
||||||
|
begin
|
||||||
g_vmspace.vm_ssize:=g_vmspace.vm_ssize+btoc(grow_amount);
|
g_vmspace.vm_ssize:=g_vmspace.vm_ssize+btoc(grow_amount);
|
||||||
|
end;
|
||||||
|
|
||||||
vm_map_unlock(map);
|
vm_map_unlock(map);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue