This commit is contained in:
Pavel 2023-12-07 17:47:39 +03:00
parent 2e039739dd
commit 4088e7ecf4
9 changed files with 471 additions and 126 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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