diff --git a/sys/kern/kern_budget.pas b/sys/kern/kern_budget.pas index c5439e1d..e2518ffe 100644 --- a/sys/kern/kern_budget.pas +++ b/sys/kern/kern_budget.pas @@ -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 diff --git a/sys/kern/kern_dmem.pas b/sys/kern/kern_dmem.pas index bd32314e..2ad21228 100644 --- a/sys/kern/kern_dmem.pas +++ b/sys/kern/kern_dmem.pas @@ -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; diff --git a/sys/kern/kern_sysctl.pas b/sys/kern/kern_sysctl.pas index 16fc2f55..de87c114 100644 --- a/sys/kern/kern_sysctl.pas +++ b/sys/kern/kern_sysctl.pas @@ -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 diff --git a/sys/vfs/vsys_generic.pas b/sys/vfs/vsys_generic.pas index 5fe31ade..60321c8d 100644 --- a/sys/vfs/vsys_generic.pas +++ b/sys/vfs/vsys_generic.pas @@ -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; diff --git a/sys/vm/dmem_map.pas b/sys/vm/dmem_map.pas index eb0ba2f4..e70acd81 100644 --- a/sys/vm/dmem_map.pas +++ b/sys/vm/dmem_map.pas @@ -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; diff --git a/sys/vm/rmem_map.pas b/sys/vm/rmem_map.pas index f1ab3c77..0baa8e21 100644 --- a/sys/vm/rmem_map.pas +++ b/sys/vm/rmem_map.pas @@ -6,6 +6,7 @@ unit rmem_map; interface uses + vm, vmparam, kern_mtx; @@ -481,7 +482,7 @@ begin } if (startmap^.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; diff --git a/sys/vm/sys_vm_object.pas b/sys/vm/sys_vm_object.pas index 1b0437fc..774a0efd 100644 --- a/sys/vm/sys_vm_object.pas +++ b/sys/vm/sys_vm_object.pas @@ -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 diff --git a/sys/vm/vm_map.pas b/sys/vm/vm_map.pas index d4b2fff8..0d092671 100644 --- a/sys/vm/vm_map.pas +++ b/sys/vm/vm_map.pas @@ -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=obj^.size) and + (offidxstart@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 diff --git a/sys/vm/vm_mmap.pas b/sys/vm/vm_mmap.pas index 19281368..c91b6850 100644 --- a/sys/vm/vm_mmap.pas +++ b/sys/vm/vm_mmap.pas @@ -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