FPPS4/sys/md/vm_pmap.pas

1248 lines
27 KiB
Plaintext

unit vm_pmap;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
subr_backtrace,
vm,
vmparam,
sys_vm_object,
vnode,
vuio,
kern_mtx,
kern_rangelock,
md_map,
vm_pmap_prot,
vm_tracking_map,
vm_nt_map;
const
PMAPP_BLK_SHIFT =29;
PMAPP_BLK_SIZE =QWORD(QWORD(1) shl PMAPP_BLK_SHIFT);
PMAPP_BLK_MASK =PMAPP_BLK_SIZE-1;
PMAPP_BLK_PRIV_BLOCKS=QWORD(VM_MAXUSER_ADDRESS ) shr PMAPP_BLK_SHIFT;
PMAPP_BLK_DMEM_BLOCKS=QWORD(VM_MAX_GPU_ADDRESS-VM_MIN_GPU_ADDRESS) shr PMAPP_BLK_SHIFT;
var
PRIV_FD:array[0..PMAPP_BLK_PRIV_BLOCKS-1] of vm_nt_file_obj;
DMEM_FD:array[0..PMAPP_BLK_DMEM_BLOCKS-1] of vm_nt_file_obj;
DEV_INFO:record
DEV_FD :vm_nt_file_obj;
DEV_SIZE:QWORD;
DEV_POS :QWORD;
DEV_PTR :Pointer;
end;
function uplift(addr:Pointer):Pointer;
procedure iov_uplift(iov:p_iovec);
type
p_pmap=^t_pmap;
t_pmap=packed object
rmlock:rangelock;
rm_mtx:mtx;
nt_map:t_vm_nt_map;
tr_map:t_vm_track_map;
end;
pmap_t=p_pmap;
function atop(x:QWORD):DWORD; inline;
function ptoa(x:DWORD):QWORD; inline;
function ctob(x:QWORD):QWORD; inline;
function btoc(x:QWORD):QWORD; inline;
function dev_mem_alloc(pages:Integer):Pointer;
function pmap_reserve(wr:Boolean):DWORD;
procedure pmap_pinit(pmap:p_pmap);
procedure pmap_align_superpage(obj :vm_object_t;
offset:vm_ooffset_t;
addr :p_vm_offset_t;
size :vm_size_t);
function pmap_wlock(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
function pmap_rlock(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
procedure pmap_unlock(pmap:pmap_t;cookie:Pointer);
procedure pmap_enter_object(pmap :pmap_t;
obj :vm_object_t;
offset :vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
procedure pmap_protect(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
{
procedure _pmap_prot_fix(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
mode :Integer);
procedure _pmap_prot_int(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
prot :vm_prot_t);
}
procedure pmap_prot_track(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
prots:Byte);
procedure pmap_madvise(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
advise:Integer);
procedure pmap_remove(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t);
function pmap_mirror_map(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
procedure pmap_mirror_unmap(pmap:pmap_t;
base:Pointer;
size:QWORD);
function pmap_danger_zone(pmap:pmap_t;
addr:vm_offset_t;
size:vm_offset_t):Boolean;
implementation
uses
ntapi,
sys_bootparam;
function atop(x:QWORD):DWORD; inline;
begin
Result:=QWORD(x) shr PAGE_SHIFT;
end;
function ptoa(x:DWORD):QWORD; inline;
begin
Result:=QWORD(x) shl PAGE_SHIFT;
end;
function ctob(x:QWORD):QWORD; inline;
begin
Result:=QWORD(x) shl PAGE_SHIFT;
end;
function btoc(x:QWORD):QWORD; inline;
begin
Result:=((x+PAGE_MASK) shr PAGE_SHIFT);
end;
procedure vm_map_lock (map:Pointer;tm:Boolean=True); external;
procedure vm_map_unlock(map:Pointer;def:Boolean=True); external;
procedure dmem_init;
var
base:Pointer;
i,r:Integer;
begin
for i:=0 to PMAPP_BLK_DMEM_BLOCKS-2 do
begin
base:=Pointer(VM_MIN_GPU_ADDRESS+i*PMAPP_BLK_SIZE);
r:=md_split(base,PMAPP_BLK_SIZE);
if (r<>0) then
begin
Writeln('failed md_split(',HexStr(base),',',HexStr(base+PMAPP_BLK_SIZE),'):0x',HexStr(r,8));
Assert(false,'dmem_init');
end;
end;
end;
procedure dev_mem_init;
var
r:Integer;
begin
DEV_INFO.DEV_SIZE:=VM_MAX_DEV_ADDRESS-VM_MIN_DEV_ADDRESS;
R:=md_memfd_create(DEV_INFO.DEV_FD.hfile,DEV_INFO.DEV_SIZE,VM_RW);
if (r<>0) then
begin
Writeln('failed md_memfd_create(',HexStr(DEV_INFO.DEV_SIZE,11),'):0x',HexStr(r,8));
Assert(false,'dev_mem_init');
end;
DEV_INFO.DEV_FD.maxp:=VM_RW;
DEV_INFO.DEV_PTR:=Pointer(VM_MIN_DEV_ADDRESS);
r:=md_reserve_ex(DEV_INFO.DEV_PTR,DEV_INFO.DEV_SIZE);
if (r<>0) then
begin
Writeln('failed md_reserve(',HexStr(DEV_INFO.DEV_SIZE,11),'):0x',HexStr(r,8));
Assert(false,'dev_mem_init');
end;
DEV_INFO.DEV_PTR:=Pointer(VM_MIN_DEV_ADDRESS); //force
r:=md_split(DEV_INFO.DEV_PTR,DEV_INFO.DEV_SIZE);
if (r<>0) then
begin
Writeln('failed md_split(',HexStr(DEV_INFO.DEV_PTR),',',HexStr(DEV_INFO.DEV_SIZE,11),'):0x',HexStr(r,8));
Assert(false,'dev_mem_init');
end;
r:=md_file_mmap_ex(DEV_INFO.DEV_FD.hfile,DEV_INFO.DEV_PTR,0,DEV_INFO.DEV_SIZE,VM_RW);
if (r<>0) then
begin
Writeln('failed md_file_mmap_ex(',HexStr(DEV_INFO.DEV_SIZE,11),'):0x',HexStr(r,8));
Assert(false,'dev_mem_init');
end;
end;
function dev_mem_alloc(pages:Integer):Pointer;
var
size:QWORD;
begin
size:=pages*PAGE_SIZE;
if (size>(DEV_INFO.DEV_SIZE-DEV_INFO.DEV_POS)) then
begin
Assert(false,'dev_mem_alloc limit');
Exit(nil);
end;
Result:=DEV_INFO.DEV_PTR+DEV_INFO.DEV_POS;
DEV_INFO.DEV_POS:=DEV_INFO.DEV_POS+size;
end;
function pmap_reserve(wr:Boolean):DWORD;
var
base:Pointer;
size:QWORD;
i:Integer;
begin
Result:=0;
if Length(pmap_mem)<>0 then
begin
For i:=0 to High(pmap_mem) do
begin
base:=Pointer(pmap_mem[i].start);
size:=pmap_mem[i].__end-pmap_mem[i].start;
Result:=md_reserve_ex(base,size);
if (Result<>0) then
begin
if wr then
begin
Writeln('failed md_reserve_ex(',HexStr(base),',',HexStr(base+size),'):0x',HexStr(Result,8));
end;
//STATUS_COMMITMENT_LIMIT = $C000012D
Exit;
end;
pmap_mem[i].start:=QWORD(base);
if wr then
begin
Writeln('md_reserve_ex(',HexStr(base),',',HexStr(base+size),'):0x',HexStr(Result,8));
end;
end;
end;
//dmem mirror
base:=Pointer(VM_MIN_GPU_ADDRESS);
size:=VM_MAX_GPU_ADDRESS-VM_MIN_GPU_ADDRESS;
Result:=md_reserve_ex(base,size);
if (Result<>0) then
begin
if wr then
begin
Writeln('failed md_reserve_ex(',HexStr(base),',',HexStr(base+size),'):0x',HexStr(Result,8));
end;
Exit;
end;
end;
procedure pmap_pinit(pmap:p_pmap);
var
i,r:Integer;
begin
r:=pmap_reserve(True);
Assert(r=0,'pmap_pinit');
dmem_init;
dev_mem_init;
if (PAGE_PROT=nil) then
begin
r:=md_mmap(PAGE_PROT,PAGE_MAP_COUNT,VM_RW);
if (r<>0) then
begin
Writeln('failed md_mmap(',HexStr(PAGE_MAP_COUNT,11),'):0x',HexStr(r,8));
Assert(false,'pmap_pinit');
end;
end;
rangelock_init(@pmap^.rmlock);
mtx_init(pmap^.rm_mtx,'pmap');
vm_nt_map_init(@pmap^.nt_map,VM_MINUSER_ADDRESS,VM_MAXUSER_ADDRESS);
//exclude
if Length(pmap_mem)>1 then
begin
For i:=0 to High(pmap_mem)-1 do
begin
vm_nt_map_insert(@pmap^.nt_map,
nil,0,
pmap_mem[ i].__end,
pmap_mem[i+1].start,
pmap_mem[i+1].start-pmap_mem[i].__end,
0);
end;
end;
vm_track_map_init(@pmap^.tr_map,VM_MINUSER_ADDRESS,VM_MAXUSER_ADDRESS);
pmap^.tr_map.pmap:=pmap;
end;
type
t_fd_info=record
start :QWORD;
__end :QWORD;
obj :p_vm_nt_file_obj;
offset:QWORD;
end;
function get_priv_block_count:Integer;
var
i:Integer;
begin
Result:=0;
For i:=0 to High(PRIV_FD) do
begin
if (PRIV_FD[i].hfile<>0) then
begin
Inc(Result);
end;
end;
end;
procedure get_priv_fd(var info:t_fd_info);
var
o:QWORD;
e:QWORD;
d:QWORD;
i:DWORD;
r:DWORD;
begin
o:=info.start;
//current block id
i:=o shr PMAPP_BLK_SHIFT;
if (PRIV_FD[i].hfile=0) then
begin
R:=md_memfd_create(PRIV_FD[i].hfile,PMAPP_BLK_SIZE,VM_RW);
PRIV_FD[i].flags:=NT_FILE_FREE;
PRIV_FD[i].maxp :=VM_RW;
if (r<>0) then
begin
Writeln('failed md_memfd_create(',HexStr(PMAPP_BLK_SIZE,11),'):0x',HexStr(r,8));
Writeln(' priv_block_count=',get_priv_block_count);
print_backtrace_td(stderr);
Assert(false,'get_priv_fd');
end;
end;
info.obj:=@PRIV_FD[i];
vm_nt_file_obj_reference(info.obj);
//current block offset
o:=o and PMAPP_BLK_MASK;
//mem size
d:=info.__end-info.start;
//max offset
e:=o+d;
// |start end|
// |offset |max
if (e>PMAPP_BLK_SIZE) then
begin
e:=PMAPP_BLK_SIZE-o;
e:=e+info.start;
info.__end:=e;
end;
end;
procedure get_dmem_fd(var info:t_fd_info);
var
base:Pointer;
BLK_SIZE:QWORD;
MEM_SIZE:QWORD;
o:QWORD;
e:QWORD;
i:DWORD;
r:DWORD;
begin
o:=info.offset;
//get mem size
MEM_SIZE:=(info.__end-info.start);
if (o>=(VM_MIN_DEV_ADDRESS-VM_MIN_GPU_ADDRESS)) then
begin
//dev
BLK_SIZE:=DEV_INFO.DEV_SIZE;
info.obj:=@DEV_INFO.DEV_FD;
end else
begin
//dmem
BLK_SIZE:=PMAPP_BLK_SIZE;
//current block id
i:=o shr PMAPP_BLK_SHIFT;
if (DMEM_FD[i].hfile=0) then
begin
R:=md_memfd_create(DMEM_FD[i].hfile,BLK_SIZE,VM_RW);
DMEM_FD[i].maxp:=VM_RW;
if (r<>0) then
begin
Writeln('failed md_memfd_create(',HexStr(BLK_SIZE,11),'):0x',HexStr(r,8));
Assert(false,'get_dmem_fd');
end;
//dmem mirror
base:=Pointer(VM_MIN_GPU_ADDRESS+i*PMAPP_BLK_SIZE);
r:=md_file_mmap_ex(DMEM_FD[i].hfile,base,0,BLK_SIZE,VM_RW);
if (r<>0) then
begin
Writeln('failed md_file_mmap_ex(',HexStr(base),',',HexStr(base+BLK_SIZE),'):0x',HexStr(r,8));
Assert(false,'get_dmem_fd');
end;
end;
info.obj:=@DMEM_FD[i];
end;
vm_nt_file_obj_reference(info.obj);
//current block offset
o:=o and PMAPP_BLK_MASK;
//max offset
e:=o+MEM_SIZE;
// |start end|
// |offset |max
if (e>BLK_SIZE) then
begin
e:=BLK_SIZE-o;
e:=e+info.start;
info.__end:=e;
end;
end;
{
* Increase the starting virtual address of the given mapping if a
* different alignment might result in more superpage mappings.
}
procedure pmap_align_superpage(obj :vm_object_t;
offset:vm_ooffset_t;
addr :p_vm_offset_t;
size :vm_size_t);
var
superpage_offset:vm_offset_t;
begin
if (size < NBPDR) then Exit;
if (obj<>nil) then
if ((obj^.flags and OBJ_COLORED)<>0) then
begin
offset:=offset+ptoa(obj^.pg_color);
end;
superpage_offset:=offset and PDRMASK;
if (size - ((NBPDR - superpage_offset) and PDRMASK) < NBPDR) or
((addr^ and PDRMASK)=superpage_offset) then
begin
Exit;
end;
if ((addr^ and PDRMASK) < superpage_offset) then
begin
addr^:=(addr^ and (not PDRMASK)) + superpage_offset
end else
begin
addr^:=((addr^ + PDRMASK) and (not PDRMASK)) + superpage_offset;
end;
end;
function uplift(addr:Pointer):Pointer;
begin
Result:=Pointer(QWORD(addr) and (VM_MAXUSER_ADDRESS-1));
end;
procedure iov_uplift(iov:p_iovec);
begin
if (QWORD(iov^.iov_base)>=VM_MAXUSER_ADDRESS) then
begin
iov^:=Default(iovec);
Exit;
end;
if ((QWORD(iov^.iov_base)+iov^.iov_len)>VM_MAXUSER_ADDRESS) then
begin
iov^.iov_len:=VM_MAXUSER_ADDRESS-QWORD(iov^.iov_base);
Exit;
end;
end;
function get_vnode_handle(obj:vm_object_t):THandle;
var
vp:p_vnode;
begin
Result:=0;
vp:=obj^.handle;
if (vp<>nil) then
begin
VI_LOCK(vp);
Result:=THandle(vp^.v_un);
VI_UNLOCK(vp);
end;
end;
function pmap_wlock(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
begin
//Writeln('pmap_wlock:',HexStr(start,10),'..',HexStr(__end,10));
Result:=rangelock_wlock(@pmap^.rmlock,start,__end,@pmap^.rm_mtx);
end;
function pmap_rlock(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
begin
//Writeln('pmap_rlock:',HexStr(start,10),'..',HexStr(__end,10));
Result:=rangelock_rlock(@pmap^.rmlock,start,__end,@pmap^.rm_mtx);
end;
procedure pmap_unlock(pmap:pmap_t;cookie:Pointer);
begin
//Writeln('pmap_unlock:',HexStr(p_rl_q_entry(cookie)^.rl_q_start,10),'..',HexStr(p_rl_q_entry(cookie)^.rl_q_end,10));
rangelock_unlock(@pmap^.rmlock,cookie,@pmap^.rm_mtx);
end;
procedure pmap_copy(src_obj :p_vm_nt_file_obj;
src_ofs :vm_ooffset_t;
dst_obj :p_vm_nt_file_obj;
dst_ofs :vm_ooffset_t;
size :vm_ooffset_t;
max_size:vm_ooffset_t);
var
start :vm_ooffset_t;
__end :vm_ooffset_t;
src,dst:Pointer;
r:Integer;
begin
if (size>max_size) then
begin
size:=max_size;
end;
start :=src_ofs and (not (MD_ALLOC_GRANULARITY-1)); //dw
__end :=src_ofs+size; //up
src_ofs:=src_ofs and (MD_ALLOC_GRANULARITY-1);
src:=nil;
r:=md_file_mmap(src_obj^.hfile,src,start,__end-start,VM_PROT_READ);
if (r<>0) then
begin
Writeln('failed md_file_mmap:0x',HexStr(r,8));
Assert(false,'pmap_copy');
end;
start :=dst_ofs and (not (MD_ALLOC_GRANULARITY-1)); //dw
__end :=dst_ofs+size; //up
dst_ofs:=dst_ofs and (MD_ALLOC_GRANULARITY-1);
dst:=nil;
r:=md_file_mmap(dst_obj^.hfile,dst,start,__end-start,VM_RW);
if (r<>0) then
begin
Writeln('failed md_file_mmap:0x',HexStr(r,8));
Assert(false,'pmap_copy');
end;
Move((src+src_ofs)^,(dst+dst_ofs)^,size);
md_cacheflush(dst,size,DCACHE);
r:=md_file_unmap(dst,0);
if (r<>0) then
begin
Writeln('failed md_file_unmap:0x',HexStr(r,8));
Assert(false,'pmap_copy');
end;
r:=md_file_unmap(src,0);
if (r<>0) then
begin
Writeln('failed md_file_unmap:0x',HexStr(r,8));
Assert(false,'pmap_copy');
end;
end;
{
* Maps a sequence of resident pages belonging to the same object.
* The sequence begins with the given page m_start. This page is
* mapped at the given virtual address start. Each subsequent page is
* mapped at a virtual address that is offset from start by the same
* amount as the page is offset from m_start within the object. The
* last page in the sequence is the page with the largest offset from
* m_start that can be mapped at a virtual address less than the given
* virtual address end. Not every virtual page between start and end
* is mapped; only those for which a resident page exists with the
* corresponding offset from m_start are mapped.
}
procedure pmap_enter_object(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
label
_default;
var
fd:THandle;
md:THandle;
size:QWORD;
delta:QWORD;
paddi:QWORD;
info:t_fd_info;
cow :p_vm_nt_file_obj;
lock:Pointer;
max:Integer;
r:Integer;
begin
if (p_print_pmap) then
begin
Writeln('pmap_enter_object:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
end;
lock:=pmap_wlock(pmap,start,__end);
ppmap_mark_rwx(start,__end,prot);
r:=0;
case vm_object_type(obj) of
OBJT_SELF , // same?
OBJT_DEFAULT:
begin
_default:
Assert((prot and VM_PROT_COPY)=0);
info.start:=start;
info.__end:=__end;
while (info.start<>info.__end) do
begin
get_priv_fd(info);
delta:=(info.__end-info.start);
if (delta=0) then Break;
r:=vm_nt_map_insert(@pmap^.nt_map,
info.obj,
info.start and PMAPP_BLK_MASK, //block local offset
info.start,
info.__end,
delta,
(prot and VM_RW));
if (r<>0) then
begin
Writeln('failed vm_nt_map_insert:0x',HexStr(r,8));
Assert(false,'pmap_enter_object');
end;
//fill zero if needed
vm_nt_map_madvise(@pmap^.nt_map,
info.start,
info.__end,
MADV_NORMAL);
info.start :=info.start+delta;
info.__end :=__end;
end;
end;
OBJT_DEVICE:
begin
if (obj^.un_pager.map_base=nil) then
begin
goto _default;
end;
Assert((prot and VM_PROT_COPY)=0);
if ((obj^.flags and OBJ_DMEM_EXT)<>0) then
begin
//transform by base addr
offset:=offset + (QWORD(obj^.un_pager.map_base) - VM_MIN_GPU_ADDRESS);
if (p_print_pmap) then
begin
Writeln('pmap_enter_gpuobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(offset,11),':',HexStr(prot,2));
end;
info.start:=start;
info.__end:=__end;
info.offset:=offset;
while (info.start<>info.__end) do
begin
get_dmem_fd(info);
delta:=(info.__end-info.start);
if (delta=0) then Break;
if (p_print_pmap) then
begin
Writeln('vm_nt_map_insert:',HexStr(info.start,11),':',HexStr(info.__end,11),':',HexStr(info.offset,11));
end;
r:=vm_nt_map_insert(@pmap^.nt_map,
info.obj,
info.offset and PMAPP_BLK_MASK, //block local offset
info.start,
info.__end,
delta,
(prot and VM_RW));
if (r<>0) then
begin
Writeln('failed vm_nt_map_insert:0x',HexStr(r,8));
Assert(false,'pmap_enter_object');
end;
info.start :=info.start +delta;
info.__end :=__end;
info.offset:=info.offset+delta;
end;
end else
begin
Assert(false,'non dmem OBJT_DEVICE');
end;
end;
OBJT_VNODE:
begin
delta:=0;
paddi:=0;
md:=0;
VM_OBJECT_LOCK(obj);
fd:=get_vnode_handle(obj);
if (fd<>0) then
begin
delta:=(__end-start);
//max unaligned size
size:=offset+delta;
if (size>obj^.un_pager.vnp.vnp_size) then
begin
size:=obj^.un_pager.vnp.vnp_size;
end;
size:=size-offset;
max:=VM_PROT_RW;
r:=md_memfd_open(md,fd,max);
if (DWORD(r)=STATUS_ACCESS_DENIED) then
begin
max:=VM_PROT_READ;
r:=md_memfd_open(md,fd,max);
end;
end;
VM_OBJECT_UNLOCK(obj);
if (r<>0) then
begin
Writeln('failed md_memfd_open:0x',HexStr(r,8));
Assert(false,'pmap_enter_object');
end;
if (md=0) then
begin
Writeln('zero file fd');
Assert(false,'pmap_enter_object');
end;
//align host page
paddi:=(size+(MD_PAGE_SIZE-1)) and (not (MD_PAGE_SIZE-1));
if ((prot and VM_PROT_COPY)<>0) then
begin
if (p_print_pmap) then
begin
Writeln('pmap_enter_cowobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
end;
cow:=vm_nt_file_obj_allocate(md,VM_PROT_READ);
info.offset:=offset;
info.start :=start;
info.__end :=start+paddi;
while (info.start<>info.__end) do
begin
get_priv_fd(info);
delta:=(info.__end-info.start);
if (delta=0) then Break;
r:=vm_nt_map_insert(@pmap^.nt_map,
info.obj,
info.start and PMAPP_BLK_MASK, //block local offset
info.start,
info.__end,
delta,
(prot and VM_RW));
if (r<>0) then
begin
Writeln('failed vm_nt_map_insert:0x',HexStr(r,8));
Assert(false,'pmap_enter_object');
end;
//restore
vm_nt_map_madvise(@pmap^.nt_map,
info.start,
info.__end,
MADV_WILLNEED);
//copy
pmap_copy(cow,
info.offset,
info.obj,
info.start and PMAPP_BLK_MASK, //block local offset
delta,
size);
info.start :=info.start +delta;
info.__end :=start+paddi;
info.offset:=info.offset+delta;
size:=size-delta; //unaligned size
end;
vm_nt_file_obj_destroy(cow);
end else
begin
info.obj :=vm_nt_file_obj_allocate(md,max);
info.offset:=offset;
info.start :=start;
info.__end :=start+paddi;
r:=vm_nt_map_insert(@pmap^.nt_map,
info.obj,
info.offset, //offset in file
info.start,
info.__end,
size,
(prot and VM_RW));
if (r<>0) then
begin
Writeln('failed vm_nt_map_insert:0x',HexStr(r,8));
Assert(false,'pmap_enter_object');
end;
end;
ppmap_mark_rwx(info.start,info.__end,prot);
//upper pages
delta:=(paddi and PAGE_MASK);
if (delta<>0) then
begin
offset:=0;
start:=start+paddi;
prot:=prot and (not VM_PROT_COPY);
goto _default;
end;
end;
else
begin
Writeln('TODO:',vm_object_type(obj));
Assert(False);
end;
end;
pmap_unlock(pmap,lock);
end;
procedure pmap_protect(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
var
lock:Pointer;
label
_default;
begin
if (p_print_pmap) then
begin
Writeln('pmap_protect:',HexStr(start,11),':',HexStr(__end,11),':prot:',HexStr(prot,2));
end;
lock:=pmap_rlock(pmap,start,__end);
ppmap_mark_rwx(start,__end,prot);
case vm_object_type(obj) of
OBJT_SELF , // same?
OBJT_DEFAULT:
begin
_default:
vm_nt_map_prot_fix(@pmap^.nt_map,
start,
__end,
TRACK_PROT or REMAP_PROT);
//vm_nt_map_protect(@pmap^.nt_map,
// start,
// __end,
// (prot and VM_RW));
end;
OBJT_DEVICE:
begin
if (obj^.un_pager.map_base=nil) then
begin
goto _default;
end;
if (p_print_pmap) then
begin
if ((obj^.flags and OBJ_DMEM_EXT)<>0) then
begin
Writeln('pmap_protect_gpuobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
end else
begin
Writeln('pmap_protect_devobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
end;
end;
goto _default;
end;
OBJT_VNODE:
begin
goto _default;
end;
else
begin
Writeln('TODO:',vm_object_type(obj));
Assert(False);
end;
end;
pmap_unlock(pmap,lock);
end;
procedure _pmap_prot_fix(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
mode :Integer);
begin
start:=start and (not PMAPP_MASK);
__end:=(__end+PMAPP_MASK) and (not PMAPP_MASK);
vm_nt_map_prot_fix(@pmap^.nt_map,
start,
__end,
mode);
end;
procedure _pmap_prot_int(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
prot :vm_prot_t);
begin
start:=start and (not PMAPP_MASK);
__end:=(__end+PMAPP_MASK) and (not PMAPP_MASK);
vm_nt_map_protect(@pmap^.nt_map,
start,
__end,
(prot and VM_RW));
end;
procedure pmap_prot_track(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
prots:Byte); public;
begin
start:=start and (not PMAPP_MASK);
__end:=(__end+PMAPP_MASK) and (not PMAPP_MASK);
ppmap_track(start,__end,prots);
vm_nt_map_prot_fix(@pmap^.nt_map,
start,
__end,
TRACK_PROT or REMAP_PROT);
end;
procedure pmap_madvise(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
advise:Integer);
label
_default;
var
lock:Pointer;
r:Integer;
begin
if (p_print_pmap) then
begin
Writeln('pmap_madv_free:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(advise,2));
end;
lock:=pmap_wlock(pmap,start,__end);
r:=0;
case vm_object_type(obj) of
OBJT_SELF , // same?
OBJT_DEFAULT:
begin
_default:
vm_nt_map_madvise(@pmap^.nt_map,
start,
__end,
advise);
end;
OBJT_DEVICE:
begin
if (obj^.un_pager.map_base=nil) then
begin
goto _default;
end;
//ignore
end;
OBJT_PHYSHM:
begin
//ignore
end;
OBJT_VNODE:
begin
//ignore
end;
else
begin
Writeln('TODO:',vm_object_type(obj));
Assert(False);
end;
end;
if (r<>0) then
begin
Writeln('failed md_reset:0x',HexStr(r,8));
Assert(false,'pmap_madv_free');
end;
pmap_unlock(pmap,lock);
end;
procedure pmap_remove(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t);
label
_default;
var
lock:Pointer;
r:Integer;
begin
if (p_print_pmap) then
begin
Writeln('pmap_remove:',HexStr(start,11),':',HexStr(__end,11));
end;
lock:=pmap_wlock(pmap,start,__end);
ppmap_unmark(start,__end);
vm_track_map_remove_memory(@pmap^.tr_map,start,__end);
r:=0;
case vm_object_type(obj) of
OBJT_SELF , // same?
OBJT_DEFAULT:
begin
vm_nt_map_madvise(@pmap^.nt_map,
start,
__end,
MADV_FREE);
_default:
r:=vm_nt_map_delete(@pmap^.nt_map,
start,
__end);
end;
OBJT_DEVICE:
begin
if (obj^.un_pager.map_base=nil) then
begin
goto _default;
end;
if (p_print_pmap) then
begin
if ((obj^.flags and OBJ_DMEM_EXT)<>0) then
begin
Writeln('pmap_remove_gpuobj:',HexStr(start,11),':',HexStr(__end,11));
end else
begin
Writeln('pmap_remove_devobj:',HexStr(start,11),':',HexStr(__end,11));
end;
end;
goto _default;
end;
OBJT_VNODE:
begin
goto _default;
end;
else
begin
Writeln('TODO:',vm_object_type(obj));
Assert(False);
end;
end;
if (r<>0) then
begin
Writeln('failed vm_nt_map_delete:0x',HexStr(r,8));
Assert(false,'pmap_remove');
end;
pmap_unlock(pmap,lock);
end;
function pmap_mirror_map(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
var
lock:Pointer;
begin
lock:=pmap_rlock(pmap,start,__end);
Result:=vm_nt_map_mirror(@pmap^.nt_map,
start,
__end);
pmap_unlock(pmap,lock);
end;
procedure pmap_mirror_unmap(pmap:pmap_t;
base:Pointer;
size:QWORD);
var
r:Integer;
begin
r:=md_unmap_ex(base,size);
if (r<>0) then
begin
Writeln('failed md_unmap_ex:0x',HexStr(r,8));
Assert(false,'pmap_mirror_unmap');
end;
end;
function pmap_danger_zone(pmap:pmap_t;
addr:vm_offset_t;
size:vm_offset_t):Boolean;
begin
Result:=False;
while (pmap^.nt_map.danger_zone.in_range(addr,size)) do
begin
Result:=True;
pmap^.nt_map.danger_zone.d_wait(addr,size);
end;
end;
end.