mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
2e039739dd
commit
4088e7ecf4
|
@ -5,6 +5,19 @@ unit kern_budget;
|
|||
|
||||
interface
|
||||
|
||||
uses
|
||||
vm,
|
||||
sys_vm_object;
|
||||
|
||||
procedure budget_enter_object(obj :vm_object_t;
|
||||
len :vm_ooffset_t);
|
||||
|
||||
procedure budget_remove(obj :vm_object_t;
|
||||
len :vm_ooffset_t);
|
||||
|
||||
function get_mlock_avail():QWORD;
|
||||
function get_mlock_total():QWORD;
|
||||
|
||||
function sys_budget_create(name:pchar;ptype:DWORD;unk_ptr1:Pointer;unk_count:DWORD;unk_ptr2:Pointer):Integer;
|
||||
function sys_budget_delete(key:Integer):Integer;
|
||||
function sys_budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer;
|
||||
|
@ -20,6 +33,71 @@ uses
|
|||
kern_thr,
|
||||
kern_proc;
|
||||
|
||||
var
|
||||
budget_total :QWORD=(448*1024*1024);
|
||||
budget_malloc:QWORD=0;
|
||||
budget_dmem :QWORD=0;
|
||||
|
||||
procedure budget_enter_object(obj :vm_object_t;
|
||||
len :vm_ooffset_t);
|
||||
label
|
||||
_inc_malloc;
|
||||
begin
|
||||
if (obj=nil) then
|
||||
begin
|
||||
_inc_malloc:
|
||||
System.InterlockedExchangeAdd64(budget_malloc,len);
|
||||
end else
|
||||
if (obj^.otype in [OBJT_DEFAULT,OBJT_SWAP,OBJT_VNODE,OBJT_SELF]) and
|
||||
((obj^.flags and OBJ_DMEM_EXT2)=0) then
|
||||
begin
|
||||
goto _inc_malloc;
|
||||
end;
|
||||
|
||||
if (obj<>nil) then
|
||||
if (obj^.otype=OBJT_PHYSHM) then
|
||||
begin
|
||||
System.InterlockedExchangeAdd64(budget_dmem,len);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure budget_remove(obj :vm_object_t;
|
||||
len :vm_ooffset_t);
|
||||
label
|
||||
_dec_malloc;
|
||||
begin
|
||||
if (obj=nil) then
|
||||
begin
|
||||
_dec_malloc:
|
||||
System.InterlockedExchangeAdd64(budget_malloc,-len);
|
||||
end else
|
||||
if (obj^.otype in [OBJT_DEFAULT,OBJT_SWAP,OBJT_VNODE,OBJT_SELF]) and
|
||||
((obj^.flags and OBJ_DMEM_EXT2)=0) then
|
||||
begin
|
||||
goto _dec_malloc;
|
||||
end;
|
||||
|
||||
if (obj<>nil) then
|
||||
if (obj^.otype=OBJT_PHYSHM) then
|
||||
begin
|
||||
System.InterlockedExchangeAdd64(budget_dmem,-len);
|
||||
end;
|
||||
end;
|
||||
|
||||
function get_mlock_avail():QWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
if (budget_total>budget_malloc) then
|
||||
begin
|
||||
Result:=budget_total-budget_malloc;
|
||||
end;
|
||||
end;
|
||||
|
||||
function get_mlock_total():QWORD;
|
||||
begin
|
||||
Result:=budget_total;
|
||||
end;
|
||||
|
||||
function sys_budget_create(name:pchar;ptype:DWORD;unk_ptr1:Pointer;unk_count:DWORD;unk_ptr2:Pointer):Integer;
|
||||
begin
|
||||
//name != null
|
||||
|
|
|
@ -125,11 +125,13 @@ end;
|
|||
|
||||
procedure init_dmem_map;
|
||||
begin
|
||||
dobj:=vm_object_allocate(OBJT_PHYS,OFF_TO_IDX(SCE_KERNEL_MAIN_DMEM_SIZE));
|
||||
dobj:=vm_object_allocate(OBJT_PHYSHM,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);
|
||||
|
||||
g_vmspace.vm_map.rmap:=@rmap;
|
||||
end;
|
||||
|
||||
const
|
||||
|
@ -167,6 +169,18 @@ begin
|
|||
Result:=p_proc.p_sdk_version > $2ffffff;
|
||||
end;
|
||||
|
||||
function vm_mmap_to_errno(rv:Integer):Integer; inline;
|
||||
begin
|
||||
Case rv of
|
||||
KERN_SUCCESS :Result:=0;
|
||||
KERN_INVALID_ADDRESS,
|
||||
KERN_NO_SPACE :Result:=ENOMEM;
|
||||
KERN_PROTECTION_FAILURE:Result:=EACCES;
|
||||
else
|
||||
Result:=EINVAL;
|
||||
end;
|
||||
end;
|
||||
|
||||
function kern_mmap_dmem(map :vm_map_t;
|
||||
addr :p_vm_offset_t;
|
||||
phaddr:QWORD;
|
||||
|
@ -221,20 +235,13 @@ begin
|
|||
if (err=0) then
|
||||
begin
|
||||
err:=vm_map_insert(map, dobj, phaddr, vaddr, v_end, prot, prot, 0);
|
||||
err:=vm_mmap_to_errno(err);
|
||||
|
||||
if (err=0) then
|
||||
begin
|
||||
err:=rmem_map_insert(@rmap, OFF_TO_IDX(vaddr), OFF_TO_IDX(phaddr), OFF_TO_IDX(phaddr+length));
|
||||
|
||||
if (err=0) then
|
||||
begin
|
||||
addr^:=vaddr;
|
||||
end else
|
||||
begin
|
||||
vm_map_delete(map,vaddr,v_end);
|
||||
end;
|
||||
|
||||
addr^:=vaddr;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
@ -256,6 +263,7 @@ begin
|
|||
//find free space
|
||||
|
||||
err:=vm_map_findspace(map,vaddr,length,@faddr);
|
||||
err:=vm_mmap_to_errno(err);
|
||||
|
||||
if (err=0) then
|
||||
begin
|
||||
|
@ -278,6 +286,7 @@ begin
|
|||
end;
|
||||
|
||||
err:=vm_map_findspace(map,next^.__end,length,@faddr);
|
||||
err:=vm_mmap_to_errno(err);
|
||||
until (err<>0);
|
||||
end;
|
||||
|
||||
|
|
|
@ -68,7 +68,9 @@ const
|
|||
KERN_SCHED =$101; //(OID_AUTO) Scheduler
|
||||
|
||||
//CTL_VM subtypes
|
||||
KERN_VM_PS4DEV=1; //vm parameters for PS4 (DevKit only)
|
||||
KERN_VM_PS4DEV=1; //vm parameters for PS4 (DevKit only)
|
||||
|
||||
KERN_VM_BUDGETS=$100; //(OID_AUTO) VM budgets
|
||||
|
||||
//KERN_PROC subtypes
|
||||
KERN_PROC_APPINFO =35; //Application information
|
||||
|
@ -107,6 +109,10 @@ const
|
|||
KERN_VM_PS4DEV_TRCMEM_TOTAL=$100; //(OID_AUTO) trace memory total
|
||||
KERN_VM_PS4DEV_TRCMEM_AVAIL=$101; //(OID_AUTO) trace memory available
|
||||
|
||||
//KERN_VM_BUDGETS
|
||||
KERN_VM_BUDGETS_MLOCK_AVAIL=$100; //(OID_AUTO) Available MLOCK budget
|
||||
KERN_VM_BUDGETS_MLOCK_TOTAL=$101; //(OID_AUTO) Total MLOCK budget
|
||||
|
||||
//SYSCTL_HANDLER_ARGS oidp:p_sysctl_oid;arg1:Pointer;arg2:ptrint;req:p_sysctl_req
|
||||
|
||||
type
|
||||
|
@ -166,6 +172,7 @@ uses
|
|||
md_arc4random,
|
||||
kern_proc,
|
||||
md_proc,
|
||||
kern_budget,
|
||||
subr_backtrace;
|
||||
|
||||
var
|
||||
|
@ -338,9 +345,11 @@ begin
|
|||
end;
|
||||
|
||||
function sysctl_kern_arandom(oidp:p_sysctl_oid;arg1:Pointer;arg2:ptrint;req:p_sysctl_req):Integer;
|
||||
type
|
||||
t_data_256=array[0..255] of Byte;
|
||||
var
|
||||
len:Integer;
|
||||
data:array[0..254] of Byte;
|
||||
data:t_data_256;
|
||||
begin
|
||||
len:=256;
|
||||
if (req^.oldlen < 256) then
|
||||
|
@ -348,7 +357,8 @@ begin
|
|||
len:=req^.oldlen;
|
||||
end;
|
||||
|
||||
arc4rand(@data,len,0);
|
||||
data:=Default(t_data_256);
|
||||
//arc4rand(@data,len,0); ASLR?
|
||||
|
||||
Result:=SYSCTL_OUT(req,@data,len);
|
||||
end;
|
||||
|
@ -507,6 +517,12 @@ begin
|
|||
Result:=0;
|
||||
|
||||
case RawByteString(name) of
|
||||
'kern.sdk_version':
|
||||
begin
|
||||
oid[0]:=CTL_KERN;
|
||||
oid[1]:=KERN_SDKVERSION;
|
||||
len^ :=2;
|
||||
end;
|
||||
'kern.smp.cpus':
|
||||
begin
|
||||
oid[0]:=CTL_KERN;
|
||||
|
@ -548,12 +564,21 @@ begin
|
|||
oid[2]:=KERN_VM_PS4DEV_TRCMEM_AVAIL;
|
||||
len^ :=3;
|
||||
end;
|
||||
'kern.sdk_version':
|
||||
'vm.budgets.mlock_avail':
|
||||
begin
|
||||
oid[0]:=CTL_KERN;
|
||||
oid[1]:=KERN_SDKVERSION;
|
||||
len^ :=2;
|
||||
oid[0]:=CTL_VM;
|
||||
oid[1]:=KERN_VM_BUDGETS;
|
||||
oid[2]:=KERN_VM_BUDGETS_MLOCK_AVAIL;
|
||||
len^ :=3;
|
||||
end;
|
||||
'vm.budgets.mlock_total':
|
||||
begin
|
||||
oid[0]:=CTL_VM;
|
||||
oid[1]:=KERN_VM_BUDGETS;
|
||||
oid[2]:=KERN_VM_BUDGETS_MLOCK_TOTAL;
|
||||
len^ :=3;
|
||||
end;
|
||||
|
||||
|
||||
else
|
||||
print_backtrace_td(stderr);
|
||||
|
@ -666,6 +691,41 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function sysctl_mlock_avail(oidp:p_sysctl_oid;arg1:Pointer;arg2:ptrint;req:p_sysctl_req):Integer;
|
||||
var
|
||||
val:QWORD;
|
||||
begin
|
||||
val:=get_mlock_avail;
|
||||
Result:=SYSCTL_OUT(req,@val,SizeOf(QWORD));
|
||||
end;
|
||||
|
||||
function sysctl_mlock_total(oidp:p_sysctl_oid;arg1:Pointer;arg2:ptrint;req:p_sysctl_req):Integer;
|
||||
var
|
||||
val:QWORD;
|
||||
begin
|
||||
val:=get_mlock_total;
|
||||
Result:=SYSCTL_OUT(req,@val,SizeOf(QWORD));
|
||||
end;
|
||||
|
||||
function sysctl_vm(name:PInteger;namelen:DWORD;noid:p_sysctl_oid;req:p_sysctl_req):Integer;
|
||||
begin
|
||||
if (namelen=0) then Exit(ENOTDIR);
|
||||
Result:=ENOENT;
|
||||
|
||||
case name[0] of
|
||||
|
||||
KERN_VM_BUDGETS_MLOCK_AVAIL:Result:=SYSCTL_HANDLE(noid,name,$80000008,@sysctl_mlock_avail); //sceKernelAvailableFlexibleMemorySize
|
||||
KERN_VM_BUDGETS_MLOCK_TOTAL:Result:=SYSCTL_HANDLE(noid,name,$80000008,@sysctl_mlock_total); //sceKernelConfiguredFlexibleMemorySize
|
||||
|
||||
else
|
||||
begin
|
||||
print_backtrace_td(stderr);
|
||||
Writeln(StdErr,'Unhandled sysctl_vm:',name[0]);
|
||||
Assert(False);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function sysctl_sysctl(name:PInteger;namelen:DWORD;noid:p_sysctl_oid;req:p_sysctl_req):Integer;
|
||||
begin
|
||||
if (namelen=0) then Exit(ENOTDIR);
|
||||
|
@ -742,6 +802,7 @@ begin
|
|||
case name[0] of
|
||||
CTL_UNSPEC :Result:=sysctl_sysctl (name+1,namelen-1,noid,req);
|
||||
CTL_KERN :Result:=sysctl_kern (name+1,namelen-1,noid,req);
|
||||
CTL_VM :Result:=sysctl_vm (name+1,namelen-1,noid,req);
|
||||
CTL_HW :Result:=sysctl_hw (name+1,namelen-1,noid,req);
|
||||
CTL_MACHDEP:Result:=sysctl_machdep(name+1,namelen-1,noid,req);
|
||||
else
|
||||
|
|
|
@ -115,6 +115,7 @@ uses
|
|||
kern_thread,
|
||||
kern_proc,
|
||||
md_time,
|
||||
subr_backtrace,
|
||||
sys_capability;
|
||||
|
||||
var
|
||||
|
@ -541,6 +542,7 @@ begin
|
|||
(((com and (IOC_IN or IOC_OUT))<>0) and (size=0)) or
|
||||
(((com and IOC_VOID)<>0) and (size > 0) and (size<>sizeof(Integer))) then
|
||||
begin
|
||||
Writeln('com:0x',HexStr(com,16),':ENOTTY');
|
||||
Exit(ENOTTY);
|
||||
end;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ uses
|
|||
kern_mtx;
|
||||
|
||||
Const
|
||||
SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB
|
||||
SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB //$120000000; 4GB (normal/pro?)
|
||||
|
||||
SCE_KERNEL_WB_ONION = 0;
|
||||
SCE_KERNEL_WC_GARLIC = 3;
|
||||
|
|
|
@ -6,6 +6,7 @@ unit rmem_map;
|
|||
interface
|
||||
|
||||
uses
|
||||
vm,
|
||||
vmparam,
|
||||
kern_mtx;
|
||||
|
||||
|
@ -481,7 +482,7 @@ begin
|
|||
}
|
||||
if (start<map^.min_offset) or (__end>map^.max_offset) or (start>=__end) then
|
||||
begin
|
||||
Exit(EINVAL);
|
||||
Exit(KERN_INVALID_ADDRESS);
|
||||
end;
|
||||
|
||||
{
|
||||
|
@ -490,7 +491,7 @@ begin
|
|||
}
|
||||
if rmem_map_lookup_entry(map,start,@temp_entry) then
|
||||
begin
|
||||
Exit(EAGAIN);
|
||||
Exit(KERN_NO_SPACE);
|
||||
end;
|
||||
|
||||
prev_entry:=temp_entry;
|
||||
|
@ -510,7 +511,7 @@ begin
|
|||
|
||||
rmem_map_entry_resize_free(map, prev_entry);
|
||||
rmem_map_simplify_entry(map, prev_entry);
|
||||
Exit(0);
|
||||
Exit(KERN_SUCCESS);
|
||||
end;
|
||||
|
||||
if (prev_entry=@map^.header) then Break;
|
||||
|
@ -538,7 +539,7 @@ begin
|
|||
|
||||
//rmem_rmap_enter(map,start,__end);
|
||||
|
||||
Result:=0;
|
||||
Result:=KERN_SUCCESS;
|
||||
end;
|
||||
|
||||
function rmem_map_fixed(map :p_rmem_map;
|
||||
|
|
|
@ -62,6 +62,7 @@ const
|
|||
OBJ_ONEMAPPING =$2000; // One USE (a single, non-forked) mapping flag
|
||||
OBJ_DISCONNECTWNT=$4000; // disconnect from vnode wanted
|
||||
OBJ_DMEM_EXT =$8000;
|
||||
OBJ_DMEM_EXT2 =$0020;
|
||||
|
||||
OBJPC_SYNC =$1; // sync I/O
|
||||
OBJPC_INVAL =$2; // invalidate
|
||||
|
|
|
@ -54,6 +54,7 @@ type
|
|||
flags:vm_flags_t; // flags for this vm_map
|
||||
root:vm_map_entry_t; // Root of a binary search tree
|
||||
pmap:pmap_t; // (c) Physical map
|
||||
rmap:Pointer;
|
||||
busy:Integer;
|
||||
property min_offset:vm_offset_t read header.start write header.start;
|
||||
property max_offset:vm_offset_t read header.__end write header.__end;
|
||||
|
@ -260,7 +261,9 @@ procedure vminit; //SYSINIT
|
|||
implementation
|
||||
|
||||
uses
|
||||
kern_proc;
|
||||
kern_proc,
|
||||
rmem_map,
|
||||
kern_budget;
|
||||
|
||||
var
|
||||
sgrowsiz:QWORD=vmparam.SGROWSIZ;
|
||||
|
@ -830,6 +833,46 @@ begin
|
|||
Result:=(FALSE);
|
||||
end;
|
||||
|
||||
function vm_object_rmap_insert(map :vm_map_t;
|
||||
obj :vm_object_t;
|
||||
start :vm_offset_t;
|
||||
__end :vm_offset_t;
|
||||
offset:vm_ooffset_t):Integer;
|
||||
var
|
||||
rmap:p_rmem_map;
|
||||
length:vm_offset_t;
|
||||
begin
|
||||
rmap:=map^.rmap;
|
||||
length:=__end-start;
|
||||
|
||||
rmem_map_lock(rmap);
|
||||
|
||||
Result:=rmem_map_insert(rmap, OFF_TO_IDX(start), OFF_TO_IDX(offset), OFF_TO_IDX(offset+length));
|
||||
|
||||
rmem_map_unlock(rmap);
|
||||
end;
|
||||
|
||||
function vm_object_rmap_release(map :vm_map_t;
|
||||
obj :vm_object_t;
|
||||
start :vm_offset_t;
|
||||
__end :vm_offset_t;
|
||||
offset:vm_ooffset_t):Integer;
|
||||
var
|
||||
rmap:p_rmem_map;
|
||||
length:vm_offset_t;
|
||||
begin
|
||||
rmap:=map^.rmap;
|
||||
length:=__end-start;
|
||||
|
||||
rmem_map_lock(rmap);
|
||||
|
||||
Result:=rmem_map_delete(rmap, OFF_TO_IDX(offset), OFF_TO_IDX(offset+length));
|
||||
|
||||
rmem_map_unlock(rmap);
|
||||
end;
|
||||
|
||||
procedure vm_map_delete_internal(map:vm_map_t;entry:vm_map_entry_t;__end:vm_offset_t); forward;
|
||||
|
||||
{
|
||||
* vm_map_insert:
|
||||
*
|
||||
|
@ -860,6 +903,36 @@ var
|
|||
protoeflags:vm_eflags_t;
|
||||
inheritance:vm_inherit_t;
|
||||
charge_prev_obj:Boolean;
|
||||
|
||||
function _enter_object:Integer;
|
||||
begin
|
||||
Result:=KERN_SUCCESS;
|
||||
|
||||
if (cow<>-1) then
|
||||
begin
|
||||
budget_enter_object(obj,__end-start);
|
||||
|
||||
if (obj<>nil) then
|
||||
begin
|
||||
if ((obj^.flags and OBJ_DMEM_EXT2)<>0) or (obj^.otype=OBJT_PHYSHM) then
|
||||
begin
|
||||
Result:=vm_object_rmap_insert(map,obj,start,__end,offset);
|
||||
end;
|
||||
end;
|
||||
|
||||
if (Result=KERN_SUCCESS) then
|
||||
begin
|
||||
pmap_enter_object(map^.pmap,
|
||||
obj,
|
||||
offset,
|
||||
start,
|
||||
__end,
|
||||
prot);
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
VM_MAP_ASSERT_LOCKED(map);
|
||||
|
||||
|
@ -974,19 +1047,15 @@ charged:
|
|||
prev_entry^.__end:=__end;
|
||||
//change size
|
||||
|
||||
if (cow<>-1) then
|
||||
Result:=_enter_object;
|
||||
|
||||
if (Result=KERN_SUCCESS) then
|
||||
begin
|
||||
pmap_enter_object(map^.pmap,
|
||||
obj,
|
||||
offset,
|
||||
start,
|
||||
__end,
|
||||
prot);
|
||||
vm_map_entry_resize_free(map, prev_entry);
|
||||
vm_map_simplify_entry(map, prev_entry);
|
||||
end;
|
||||
|
||||
vm_map_entry_resize_free(map, prev_entry);
|
||||
vm_map_simplify_entry(map, prev_entry);
|
||||
Exit(KERN_SUCCESS);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
{
|
||||
|
@ -1047,18 +1116,12 @@ charged:
|
|||
vm_map_simplify_entry(map, new_entry);
|
||||
end;
|
||||
|
||||
if (cow<>-1) then
|
||||
Result:=_enter_object;
|
||||
|
||||
if (Result<>KERN_SUCCESS) then
|
||||
begin
|
||||
pmap_enter_object(map^.pmap,
|
||||
obj,
|
||||
offset,
|
||||
start,
|
||||
__end,
|
||||
prot);
|
||||
|
||||
vm_map_delete_internal(map,new_entry,__end);
|
||||
end;
|
||||
|
||||
Result:=KERN_SUCCESS;
|
||||
end;
|
||||
|
||||
{
|
||||
|
@ -2030,7 +2093,7 @@ end;
|
|||
}
|
||||
procedure vm_map_entry_delete(map:vm_map_t;entry:vm_map_entry_t);
|
||||
var
|
||||
vm_obj:vm_object_t;
|
||||
obj:vm_object_t;
|
||||
offidxstart,offidx_end,count:vm_pindex_t;
|
||||
size:vm_ooffset_t;
|
||||
begin
|
||||
|
@ -2040,21 +2103,22 @@ begin
|
|||
end;
|
||||
|
||||
vm_map_entry_unlink(map, entry);
|
||||
vm_obj:=entry^.vm_obj;
|
||||
obj:=entry^.vm_obj;
|
||||
size:=entry^.__end - entry^.start;
|
||||
map^.size:=map^.size-size;
|
||||
|
||||
if ((entry^.eflags and MAP_ENTRY_IS_SUB_MAP)=0) and
|
||||
(vm_obj<>nil) then
|
||||
(obj<>nil) then
|
||||
if (obj^.otype<>OBJT_BLOCKPOOL) then
|
||||
begin
|
||||
count:=OFF_TO_IDX(size);
|
||||
offidxstart:=OFF_TO_IDX(entry^.offset);
|
||||
offidx_end:=offidxstart + count;
|
||||
VM_OBJECT_LOCK(vm_obj);
|
||||
if (vm_obj^.ref_count<>1) and
|
||||
(((vm_obj^.flags and (OBJ_NOSPLIT or OBJ_ONEMAPPING))=OBJ_ONEMAPPING)) then
|
||||
VM_OBJECT_LOCK(obj);
|
||||
if (obj^.ref_count<>1) and
|
||||
(((obj^.flags and (OBJ_NOSPLIT or OBJ_ONEMAPPING))=OBJ_ONEMAPPING)) then
|
||||
begin
|
||||
vm_object_collapse(vm_obj);
|
||||
vm_object_collapse(obj);
|
||||
|
||||
{
|
||||
* The option OBJPR_NOTMAPPED can be passed here
|
||||
|
@ -2062,15 +2126,15 @@ begin
|
|||
* pmap_remove() on the only mapping to this range
|
||||
* of pages.
|
||||
}
|
||||
vm_object_page_remove(vm_obj, offidxstart, offidx_end, OBJPR_NOTMAPPED);
|
||||
vm_object_page_remove(obj, offidxstart, offidx_end, OBJPR_NOTMAPPED);
|
||||
|
||||
if (offidx_end>=vm_obj^.size) and
|
||||
(offidxstart<vm_obj^.size) then
|
||||
if (offidx_end>=obj^.size) and
|
||||
(offidxstart<obj^.size) then
|
||||
begin
|
||||
vm_obj^.size:=offidxstart;
|
||||
obj^.size:=offidxstart;
|
||||
end;
|
||||
end;
|
||||
VM_OBJECT_UNLOCK(vm_obj);
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
end else
|
||||
begin
|
||||
entry^.vm_obj:=nil;
|
||||
|
@ -2082,6 +2146,28 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure vm_map_delete_internal(map:vm_map_t;entry:vm_map_entry_t;__end:vm_offset_t);
|
||||
var
|
||||
next:vm_map_entry_t;
|
||||
begin
|
||||
while (entry<>@map^.header) and (entry^.start<__end) do
|
||||
begin
|
||||
|
||||
if (entry^.inheritance=VM_INHERIT_HOLE) then
|
||||
begin
|
||||
entry:=entry^.next;
|
||||
continue;
|
||||
end;
|
||||
|
||||
vm_map_clip_end(map, entry, __end);
|
||||
|
||||
next:=entry^.next;
|
||||
|
||||
vm_map_entry_delete(map, entry);
|
||||
entry:=next;
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
* vm_map_delete: [ internal use only ]
|
||||
*
|
||||
|
@ -2093,6 +2179,7 @@ var
|
|||
entry :vm_map_entry_t;
|
||||
first_entry:vm_map_entry_t;
|
||||
next :vm_map_entry_t;
|
||||
obj :vm_object_t;
|
||||
begin
|
||||
VM_MAP_ASSERT_LOCKED(map);
|
||||
|
||||
|
@ -2110,9 +2197,50 @@ begin
|
|||
end else
|
||||
begin
|
||||
entry:=first_entry;
|
||||
|
||||
if ((entry^.eflags and MAP_ENTRY_IS_SUB_MAP)<>0) then
|
||||
begin
|
||||
Exit(KERN_INVALID_ARGUMENT);
|
||||
end;
|
||||
|
||||
obj:=entry^.vm_obj;
|
||||
|
||||
if (obj<>nil) then
|
||||
if (obj^.otype=OBJT_BLOCKPOOL) then
|
||||
begin
|
||||
Exit(KERN_INVALID_ARGUMENT);
|
||||
end;
|
||||
|
||||
vm_map_clip_start(map, entry, start);
|
||||
end;
|
||||
|
||||
//check
|
||||
next:=entry;
|
||||
while (next<>@map^.header) and (next^.start<__end) do
|
||||
begin
|
||||
|
||||
if ((next^.eflags and MAP_ENTRY_IS_SUB_MAP)<>0) then
|
||||
begin
|
||||
Exit(KERN_INVALID_ARGUMENT);
|
||||
end;
|
||||
|
||||
obj:=next^.vm_obj;
|
||||
|
||||
if (obj<>nil) then
|
||||
if (obj^.otype=OBJT_BLOCKPOOL) then
|
||||
begin
|
||||
Exit(KERN_INVALID_ARGUMENT);
|
||||
end;
|
||||
|
||||
if (next^.inheritance=VM_INHERIT_HOLE) then
|
||||
begin
|
||||
next:=next^.next;
|
||||
continue;
|
||||
end;
|
||||
|
||||
next:=entry^.next;
|
||||
end;
|
||||
|
||||
{
|
||||
* Step through all entries in this region
|
||||
}
|
||||
|
@ -2129,8 +2257,19 @@ begin
|
|||
|
||||
next:=entry^.next;
|
||||
|
||||
budget_remove(entry^.vm_obj,
|
||||
entry^.__end-entry^.start);
|
||||
|
||||
pmap_remove(map^.pmap,entry^.start,entry^.__end,entry^.protection);
|
||||
|
||||
if (obj<>nil) then
|
||||
begin
|
||||
if ((obj^.flags and (OBJ_DMEM_EXT or OBJ_DMEM_EXT2))<>0) or (obj^.otype=OBJT_PHYSHM) then
|
||||
begin
|
||||
Result:=vm_object_rmap_release(map,obj,entry^.start,entry^.__end,entry^.offset);
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
* Delete the entry only after removing all pmap
|
||||
* entries pointing to its pages. (Otherwise, its
|
||||
|
|
|
@ -302,6 +302,15 @@ begin
|
|||
Exit(error);
|
||||
end;
|
||||
|
||||
function vm_mmap_dmem(handle :Pointer;
|
||||
objsize :vm_size_t;
|
||||
foff :p_vm_ooffset_t;
|
||||
objp :p_vm_object_t):Integer;
|
||||
begin
|
||||
//todo
|
||||
Exit(EOPNOTSUPP);
|
||||
end;
|
||||
|
||||
function vm_mmap_to_errno(rv:Integer):Integer; inline;
|
||||
begin
|
||||
Case rv of
|
||||
|
@ -332,14 +341,14 @@ function vm_mmap2(map :vm_map_t;
|
|||
handle :Pointer;
|
||||
foff :vm_ooffset_t):Integer;
|
||||
var
|
||||
vm_obj:vm_object_t;
|
||||
obj:vm_object_t;
|
||||
docow,error,findspace,rv:Integer;
|
||||
fitit:Boolean;
|
||||
writecounted:Boolean;
|
||||
begin
|
||||
if (size=0) then Exit(0);
|
||||
|
||||
vm_obj:=nil;
|
||||
obj:=nil;
|
||||
|
||||
size:=round_page(size);
|
||||
|
||||
|
@ -367,16 +376,27 @@ begin
|
|||
Case handle_type of
|
||||
OBJT_DEVICE:
|
||||
begin
|
||||
error:=vm_mmap_cdev(size,prot,@maxprot,@flags,handle,@foff,@vm_obj);
|
||||
error:=vm_mmap_cdev(size,prot,@maxprot,@flags,handle,@foff,@obj);
|
||||
end;
|
||||
OBJT_SELF, //same as file
|
||||
OBJT_VNODE:
|
||||
begin
|
||||
error:=vm_mmap_vnode(size,prot,@maxprot,@flags,handle,@foff,@vm_obj,@writecounted);
|
||||
error:=vm_mmap_vnode(size,prot,@maxprot,@flags,handle,@foff,@obj,@writecounted);
|
||||
end;
|
||||
OBJT_SWAP:
|
||||
begin
|
||||
error:=vm_mmap_shm(size,prot,@maxprot,@flags,handle,@foff,@vm_obj);
|
||||
error:=vm_mmap_shm(size,prot,@maxprot,@flags,handle,@foff,@obj);
|
||||
end;
|
||||
OBJT_PHYSHM:
|
||||
begin
|
||||
error:=EACCES;
|
||||
if ((prot and (VM_PROT_WRITE or VM_PROT_GPU_WRITE))=0) or
|
||||
((maxprot and VM_PROT_WRITE)<>0) then
|
||||
begin
|
||||
error:=vm_mmap_dmem(handle,size,@foff,@obj);
|
||||
end;
|
||||
end;
|
||||
|
||||
OBJT_DEFAULT:
|
||||
begin
|
||||
if (handle=nil) then
|
||||
|
@ -395,7 +415,7 @@ begin
|
|||
|
||||
if ((flags and MAP_ANON)<>0) then
|
||||
begin
|
||||
vm_obj:=nil;
|
||||
obj:=nil;
|
||||
docow:=0;
|
||||
if (handle=nil) then foff:=0;
|
||||
end else
|
||||
|
@ -437,10 +457,10 @@ begin
|
|||
begin
|
||||
findspace:=VMFS_OPTIMAL_SPACE;
|
||||
end;
|
||||
rv:=vm_map_find(map, vm_obj, foff, addr, size, findspace, prot, maxprot, docow);
|
||||
rv:=vm_map_find(map, obj, foff, addr, size, findspace, prot, maxprot, docow);
|
||||
end else
|
||||
begin
|
||||
rv:=vm_map_fixed(map, vm_obj, foff, addr^, size, prot, maxprot, docow,
|
||||
rv:=vm_map_fixed(map, obj, foff, addr^, size, prot, maxprot, docow,
|
||||
ord((flags and MAP_NO_OVERWRITE)=0));
|
||||
end;
|
||||
|
||||
|
@ -454,7 +474,7 @@ begin
|
|||
//vnode_pager_release_writecount(vm_obj, 0, size);
|
||||
end;
|
||||
|
||||
vm_object_deallocate(vm_obj);
|
||||
vm_object_deallocate(obj);
|
||||
end;
|
||||
Exit(vm_mmap_to_errno(rv));
|
||||
end;
|
||||
|
@ -604,70 +624,104 @@ begin
|
|||
Result:=Pointer(fget_mmap(fd,rights,@cap_maxprot,@fp));
|
||||
if (Result<>nil) then goto _done;
|
||||
|
||||
if (fp^.f_type=DTYPE_SHM) then
|
||||
begin
|
||||
handle:=fp^.f_data;
|
||||
handle_type:=OBJT_SWAP;
|
||||
maxprot:=VM_PROT_NONE;
|
||||
case fp^.f_type of
|
||||
DTYPE_VNODE:
|
||||
begin
|
||||
vp:=fp^.f_vnode;
|
||||
|
||||
// FREAD should always be set.
|
||||
if ((fp^.f_flag and FREAD)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_EXECUTE or VM_PROT_READ;
|
||||
end;
|
||||
if ((fp^.f_flag and FWRITE)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_WRITE;
|
||||
end;
|
||||
goto _map;
|
||||
maxprot:=VM_PROT_EXECUTE;
|
||||
|
||||
if (vp^.v_mount<>nil) then
|
||||
if ((p_mount(vp^.v_mount)^.mnt_flag and MNT_NOEXEC)<>0) then
|
||||
begin
|
||||
maxprot:=VM_PROT_NONE;
|
||||
end;
|
||||
|
||||
if ((fp^.f_flag and FREAD)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_READ;
|
||||
end else
|
||||
if ((prot and VM_PROT_READ)<>0) then
|
||||
begin
|
||||
Result:=Pointer(EACCES);
|
||||
goto _done;
|
||||
end;
|
||||
|
||||
if ((flags and MAP_SHARED)<>0) then
|
||||
begin
|
||||
if ((fp^.f_flag and FWRITE)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_WRITE;
|
||||
end else
|
||||
if ((prot and VM_PROT_WRITE)<>0) then
|
||||
begin
|
||||
Result:=Pointer(EACCES);
|
||||
goto _done;
|
||||
end;
|
||||
end else
|
||||
if (vp^.v_type<>VCHR) or ((fp^.f_flag and FWRITE)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_WRITE;
|
||||
cap_maxprot:=cap_maxprot or VM_PROT_WRITE;
|
||||
end;
|
||||
|
||||
handle:=vp;
|
||||
handle_type:=OBJT_VNODE;
|
||||
end;
|
||||
|
||||
DTYPE_SHM:
|
||||
begin
|
||||
handle:=fp^.f_data;
|
||||
handle_type:=OBJT_SWAP;
|
||||
maxprot:=VM_PROT_NONE;
|
||||
|
||||
// FREAD should always be set.
|
||||
if ((fp^.f_flag and FREAD)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or (VM_PROT_EXECUTE or VM_PROT_READ);
|
||||
end;
|
||||
if ((fp^.f_flag and FWRITE)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_WRITE;
|
||||
end;
|
||||
goto _map;
|
||||
end;
|
||||
|
||||
DTYPE_PHYSHM:
|
||||
begin
|
||||
handle:=fp^.f_data;
|
||||
handle_type:=OBJT_PHYSHM;
|
||||
|
||||
prot:=VM_PROT_READ or VM_PROT_GPU_READ;
|
||||
|
||||
if ((fp^.f_flag and FREAD)=0) then
|
||||
begin
|
||||
prot:=VM_PROT_NONE;
|
||||
end;
|
||||
|
||||
maxprot:=prot or (VM_PROT_WRITE or VM_PROT_GPU_WRITE);
|
||||
|
||||
if ((fp^.f_flag and FWRITE)=0) then
|
||||
begin
|
||||
maxprot:=prot;
|
||||
end;
|
||||
end;
|
||||
|
||||
DTYPE_BLOCKPOOL:
|
||||
begin
|
||||
handle:=fp^.f_data;
|
||||
handle_type:=OBJT_BLOCKPOOL;
|
||||
maxprot:=VM_PROT_ALL;
|
||||
end;
|
||||
|
||||
else
|
||||
begin
|
||||
Writeln('DTYPE_',fp^.f_type,' TODO');
|
||||
Result:=Pointer(ENODEV);
|
||||
goto _done;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (fp^.f_type<>DTYPE_VNODE) then
|
||||
begin
|
||||
Result:=Pointer(ENODEV);
|
||||
goto _done;
|
||||
end;
|
||||
|
||||
vp:=fp^.f_vnode;
|
||||
|
||||
maxprot:=VM_PROT_EXECUTE;
|
||||
|
||||
if (vp^.v_mount<>nil) then
|
||||
if ((p_mount(vp^.v_mount)^.mnt_flag and MNT_NOEXEC)<>0) then
|
||||
begin
|
||||
maxprot:=VM_PROT_NONE;
|
||||
end;
|
||||
|
||||
if ((fp^.f_flag and FREAD)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_READ;
|
||||
end else
|
||||
if ((prot and VM_PROT_READ)<>0) then
|
||||
begin
|
||||
Result:=Pointer(EACCES);
|
||||
goto _done;
|
||||
end;
|
||||
|
||||
if ((flags and MAP_SHARED)<>0) then
|
||||
begin
|
||||
if ((fp^.f_flag and FWRITE)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_WRITE;
|
||||
end else
|
||||
if ((prot and VM_PROT_WRITE)<>0) then
|
||||
begin
|
||||
Result:=Pointer(EACCES);
|
||||
goto _done;
|
||||
end;
|
||||
end else
|
||||
if (vp^.v_type<>VCHR) or ((fp^.f_flag and FWRITE)<>0) then
|
||||
begin
|
||||
maxprot:=maxprot or VM_PROT_WRITE;
|
||||
cap_maxprot:=cap_maxprot or VM_PROT_WRITE;
|
||||
end;
|
||||
|
||||
handle:=vp;
|
||||
handle_type:=OBJT_VNODE;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
|
|
Loading…
Reference in New Issue