diff --git a/fpPS4.lpi b/fpPS4.lpi index dc5f1657..88687a9b 100644 --- a/fpPS4.lpi +++ b/fpPS4.lpi @@ -1558,6 +1558,10 @@ + + + + diff --git a/sys/md/md_map.pas b/sys/md/md_map.pas index 5b6b04c9..29b1ec8c 100644 --- a/sys/md/md_map.pas +++ b/sys/md/md_map.pas @@ -14,7 +14,7 @@ const MD_PAGE_SHIFT = 12; MD_PAGE_SIZE = 4*1024; MD_PAGE_MASK = MD_PAGE_SIZE-1; - MD_ALLOC_GRANULARITY=64*1024; + MD_ALLOC_GRANULARITY= 64*1024; const VM_RW =VM_PROT_READ or VM_PROT_WRITE; diff --git a/sys/md/vm_pmap.pas b/sys/md/vm_pmap.pas index 09986bb4..61a099ea 100644 --- a/sys/md/vm_pmap.pas +++ b/sys/md/vm_pmap.pas @@ -98,22 +98,10 @@ procedure pmap_protect(pmap :pmap_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); + prot :Byte); procedure pmap_prot_restore(pmap :pmap_t; start:vm_offset_t; @@ -1009,15 +997,10 @@ begin 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)); + vm_nt_map_protect(@pmap^.nt_map, + start, + __end, + (prot and VM_RW)); end; OBJT_DEVICE: @@ -1054,58 +1037,34 @@ begin 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; + prot :Byte); public; begin if (p_print_pmap) then begin - Writeln('pmap_prot_track:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prots,2)); + Writeln('pmap_prot_track:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2)); end; start:=start and (not PMAPP_MASK); __end:=(__end+PMAPP_MASK) and (not PMAPP_MASK); - ppmap_track(start,__end,prots); + //Don't do range lock here! - vm_nt_map_prot_fix(@pmap^.nt_map, + ppmap_track(start,__end,prot); + + vm_nt_map_tracking(@pmap^.nt_map, start, __end, - TRACK_PROT or REMAP_PROT); + prot); end; procedure pmap_prot_restore(pmap :pmap_t; start:vm_offset_t; __end:vm_offset_t); +var + lock:Pointer; begin if (p_print_pmap) then begin @@ -1115,10 +1074,14 @@ begin start:=start and (not PMAPP_MASK); __end:=(__end+PMAPP_MASK) and (not PMAPP_MASK); + lock:=pmap_wlock(pmap,start,__end); + vm_nt_map_prot_fix(@pmap^.nt_map, start, __end, REMAP_PROT); + + pmap_unlock(pmap,lock); end; procedure pmap_madvise(pmap :pmap_t; diff --git a/sys/vm/vm_nt_map.pas b/sys/vm/vm_nt_map.pas index 562d2f95..9837c873 100644 --- a/sys/vm/vm_nt_map.pas +++ b/sys/vm/vm_nt_map.pas @@ -9,7 +9,8 @@ uses sysutils, vm, kern_mtx, - vm_pmap_prot; + vm_pmap_prot, + vm_nt_sub_map; const NT_FILE_FREE=1; @@ -44,30 +45,31 @@ type maxp :Byte; end; + /// + pp_vm_nt_entry=^p_vm_nt_entry; p_vm_nt_entry=^vm_nt_entry; - vm_nt_entry=packed record - prev :p_vm_nt_entry; // previous entry - next :p_vm_nt_entry; // next entry - left :p_vm_nt_entry; // left child in binary search tree - right :p_vm_nt_entry; // right child in binary search tree - start :vm_offset_t; // start address - __end :vm_offset_t; // end address - size :vm_offset_t; // unaligned size - obj :p_vm_nt_file_obj; // object I point to - offset :vm_ooffset_t; // offset into object + vm_nt_entry=packed object + prev :p_vm_nt_entry; // previous entry + next :p_vm_nt_entry; // next entry + left :p_vm_nt_entry; // left child in binary search tree + right :p_vm_nt_entry; // right child in binary search tree + usize :vm_offset_t; // unaligned size + offset:vm_ooffset_t; // offset into object + obj :p_vm_nt_file_obj; // object I point to + sub :t_vm_nt_sub_map; + property start:vm_offset_t read sub.header.start write sub.header.start; // start address + property __end:vm_offset_t read sub.header.__end write sub.header.__end; // end address end; p_vm_nt_map=^t_vm_nt_map; t_vm_nt_map=object header :vm_nt_entry; // List of entries - size :vm_size_t; // virtual size - nentries :Integer; // Number of entries + lock :mtx; // Lock for map data root :p_vm_nt_entry; // Root of a binary search tree danger_zone:t_danger_zone; - lock :mtx; - property min_offset:vm_offset_t read header.start write header.start; - property max_offset:vm_offset_t read header.__end write header.__end; + property min_offset:vm_offset_t read header.sub.header.start write header.sub.header.start; + property max_offset:vm_offset_t read header.sub.header.__end write header.sub.header.__end; end; function vm_nt_file_obj_allocate (hfile:THandle;maxp:Byte):p_vm_nt_file_obj; @@ -86,27 +88,36 @@ function vm_nt_map_insert( offset:vm_ooffset_t; start :vm_offset_t; __end :vm_offset_t; - size :vm_offset_t; + usize :vm_offset_t; prot :Integer):Integer; function vm_nt_map_delete(map:p_vm_nt_map;start:vm_offset_t;__end:vm_offset_t):Integer; -procedure vm_nt_map_protect(map:p_vm_nt_map; +//Change protection taking into account tracking +procedure vm_nt_map_protect(map :p_vm_nt_map; start:vm_offset_t; __end:vm_offset_t; - prot :Integer); + prot :Integer); -procedure vm_nt_map_prot_fix(map:p_vm_nt_map; +//Change protection tracking +procedure vm_nt_map_tracking(map :p_vm_nt_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Integer); + +//Update page protection by mode +procedure vm_nt_map_prot_fix(map :p_vm_nt_map; start:vm_offset_t; __end:vm_offset_t; mode :Integer); -procedure vm_nt_map_madvise(map:p_vm_nt_map; - start:vm_offset_t; - __end:vm_offset_t; +procedure vm_nt_map_madvise(map :p_vm_nt_map; + start :vm_offset_t; + __end :vm_offset_t; advise:Integer); -function vm_nt_map_mirror(map:p_vm_nt_map; +//Create a memory mirror of the current state of the pages +function vm_nt_map_mirror(map :p_vm_nt_map; start:vm_offset_t; __end:vm_offset_t):Pointer; @@ -191,60 +202,6 @@ end; // -procedure vm_prot_fixup(map:p_vm_nt_map; - start:vm_offset_t; - __end:vm_offset_t; - max :Integer; - mode :Integer); -var - next:vm_offset_t; - base,size:vm_size_t; - prot:Integer; - mask:Integer; - r:Integer; -begin - if (PAGE_PROT=nil) then Exit; - if (start=__end) then Exit; - - while (start<__end) do - begin - if ((mode and TRACK_PROT)=0) then - begin - next:=ppmap_scan_rwx(start,__end); - - prot:=ppmap_get_prot(start); - - prot:=(prot and VM_RW); - end else - begin - next:=ppmap_scan(start,__end); - - prot:=ppmap_get_prot(start); - - mask:=not (prot shr PAGE_TRACK_SHIFT); - - prot:=(prot and VM_RW) and mask; - end; - - base:=start; - size:=next-start; - - if ((mode and REMAP_PROT)<>0) or (prot<>(max and VM_RW)) then - begin - r:=md_protect(Pointer(base),size,prot); - if (r<>0) then - begin - Writeln('failed md_protect(',HexStr(base,11),',',HexStr(base+size,11),'):0x',HexStr(r,8)); - Assert(false,'vm_prot_fixup'); - end; - end; - - start:=next; - end; -end; - -// - procedure vm_init_stat(var stat:t_range_stat;entry:p_vm_nt_entry); inline; begin stat:=Default(t_range_stat); @@ -313,7 +270,7 @@ begin r:=md_file_mmap_ex(entry^.obj^.hfile, Pointer(entry^.start), entry^.offset, - entry^.size, //unaligned size + entry^.usize, //unaligned size (max and VM_RW)); if (r<>0) then begin @@ -562,7 +519,7 @@ begin r:=md_file_mmap_ex(stat.obj^.hfile, Pointer(ets[i]^.start), ets[i]^.offset, - ets[i]^.size, //unaligned size + ets[i]^.usize, //unaligned size (max and VM_RW)); if (r<>0) then begin @@ -584,12 +541,11 @@ begin if (ets[i]^.obj<>nil) then if (stat.obj^.hfile<>0) then begin - vm_prot_fixup(map, - ets[i]^.start, - ets[i]^.__end, - max, - TRACK_PROT or REMAP_PROT //untrack trigger or restore track? - ); + vm_nt_sub_map_prot_fixup(@ets[i]^.sub, + ets[i]^.start, + ets[i]^.__end, + TRACK_PROT or REMAP_PROT //untrack trigger or restore track? + ); end; end; end; @@ -690,6 +646,13 @@ begin FreeMem(entry); end; +procedure vm_nt_entry_deallocate(map:p_vm_nt_map;entry:p_vm_nt_entry); inline; +begin + vm_nt_sub_map_free (@entry^.sub); + vm_nt_file_obj_deallocate(entry^.obj); + vm_nt_entry_dispose (map,entry); +end; + function vm_nt_entry_create(map:p_vm_nt_map):p_vm_nt_entry; var new_entry:p_vm_nt_entry; @@ -779,7 +742,6 @@ procedure vm_nt_entry_link( after_where:p_vm_nt_entry; entry :p_vm_nt_entry); begin - Inc(map^.nentries); entry^.prev:=after_where; entry^.next:=after_where^.next; entry^.next^.prev:=entry; @@ -826,7 +788,6 @@ begin next:=entry^.next; next^.prev:=prev; prev^.next:=next; - Dec(map^.nentries); end; function vm_nt_map_lookup_entry( @@ -874,7 +835,7 @@ function _vm_nt_map_insert( offset:vm_ooffset_t; start :vm_offset_t; __end :vm_offset_t; - size :vm_offset_t; //unaligned size + usize :vm_offset_t; //unaligned size prot :Integer):Integer; var new_entry :p_vm_nt_entry; @@ -903,12 +864,16 @@ begin new_entry:=vm_nt_entry_create(map); new_entry^.start :=start; new_entry^.__end :=__end; - new_entry^.size :=size; //unaligned size + new_entry^.usize :=usize; //unaligned size new_entry^.obj :=obj; new_entry^.offset:=offset; + vm_nt_sub_map_init (@new_entry^.sub,start,__end); + + //fill full map + vm_nt_sub_map_insert(@new_entry^.sub,start,__end,prot); + vm_nt_entry_link(map, prev_entry, new_entry); - map^.size:=map^.size+(new_entry^.__end - new_entry^.start); vm_map(map,new_entry,prot); @@ -925,7 +890,7 @@ function vm_nt_map_insert( offset:vm_ooffset_t; start :vm_offset_t; __end :vm_offset_t; - size :vm_offset_t; //unaligned size + usize :vm_offset_t; //unaligned size prot :Integer):Integer; begin if (start=__end) then @@ -941,7 +906,7 @@ begin offset, start , __end , - size , + usize , prot ); vm_nt_map_unlock(map); @@ -985,10 +950,15 @@ begin entry^.start :=prev^.start; entry^.offset:=prev^.offset; - entry^.size :=entry^.size+prev^.size; //unaligned size + entry^.usize :=entry^.usize+prev^.usize; //unaligned size - vm_nt_file_obj_deallocate(prev^.obj); - vm_nt_entry_dispose(map, prev); + //update (implicitly) + //entry^.sub.min_offset:=entry^.start; + + //move + vm_nt_sub_map_move(@entry^.sub,@prev^.sub); + + vm_nt_entry_deallocate(map,prev); end; end; @@ -1002,18 +972,21 @@ begin ((stat.obj=nil) or (entry^.offset + esize=next^.offset)) then begin - begin - vm_nt_entry_unlink(map, next); + vm_nt_entry_unlink(map, next); - stat.rnext.start:=next^.start; - stat.rnext.__end:=next^.__end; + stat.rnext.start:=next^.start; + stat.rnext.__end:=next^.__end; - entry^.__end:=next^.__end; - entry^.size :=entry^.size+next^.size; //unaligned size + entry^.__end:=next^.__end; + entry^.usize:=entry^.usize+next^.usize; //unaligned size - vm_nt_file_obj_deallocate(next^.obj); - vm_nt_entry_dispose(map, next); - end; + //update (implicitly) + //entry^.sub.max_offset:=entry^.__end; + + //move + vm_nt_sub_map_move(@entry^.sub,@next^.sub); + + vm_nt_entry_deallocate(map,next); end; end; @@ -1047,11 +1020,21 @@ begin prev^:=entry^; prev^.__end:=start; - prev^.size :=(prev^.__end-prev^.start); //unaligned size + prev^.usize:=(prev^.__end-prev^.start); //unaligned size entry^.offset:=entry^.offset + (start - entry^.start); entry^.start :=start; - entry^.size :=entry^.size-prev^.size; //unaligned size + entry^.usize :=entry^.usize-prev^.usize; //unaligned size + + //update (implicitly) + //prev ^.sub.max_offset:=start; + //entry^.sub.min_offset:=start; + + //new map + vm_nt_sub_map_init(@prev^.sub,prev^.start,prev^.__end); + + //move + vm_nt_sub_map_move(@prev^.sub,@entry^.sub); vm_nt_entry_link(map, entry^.prev, prev); vm_nt_file_obj_reference(prev^.obj); @@ -1065,10 +1048,20 @@ begin next^.start :=__end; entry^.__end:=__end; - entry^.size :=(entry^.__end-entry^.start); //unaligned size + entry^.usize:=(entry^.__end-entry^.start); //unaligned size next^.offset:=next^.offset + (__end - entry^.start); - next^.size :=next^.size-entry^.size; //unaligned size + next^.usize :=next^.usize-entry^.usize; //unaligned size + + //update (implicitly) + //next ^.sub.min_offset:=__end; + //entry^.sub.max_offset:=__end; + + //new map + vm_nt_sub_map_init(@next^.sub,next^.start,next^.__end); + + //move + vm_nt_sub_map_move(@next^.sub,@entry^.sub); vm_nt_entry_link(map, entry, next); vm_nt_file_obj_reference(next^.obj); @@ -1106,10 +1099,20 @@ begin next^.start :=__end; entry^.__end:=__end; - entry^.size :=(entry^.__end-entry^.size); //unaligned size + entry^.usize:=(entry^.__end-entry^.usize); //unaligned size next^.offset:=next^.offset + (__end - entry^.start); - next^.size :=next^.size-entry^.size; //unaligned size + next^.usize :=next^.usize-entry^.usize; //unaligned size + + //update (implicitly) + //next ^.sub.min_offset:=__end; + //entry^.sub.max_offset:=__end; + + //new map + vm_nt_sub_map_init(@next^.sub,next^.start,next^.__end); + + //move + vm_nt_sub_map_move(@next^.sub,@entry^.sub); vm_nt_entry_link(map, entry, next); vm_nt_file_obj_reference(next^.obj); @@ -1128,22 +1131,10 @@ begin end; -procedure vm_nt_entry_deallocate(entry:p_vm_nt_entry); +procedure vm_nt_entry_delete(map:p_vm_nt_map;entry:p_vm_nt_entry); inline; begin - vm_nt_file_obj_deallocate(entry^.obj); - Freemem(entry); -end; - -procedure vm_nt_entry_delete(map:p_vm_nt_map;entry:p_vm_nt_entry); -var - size:vm_ooffset_t; -begin - vm_nt_entry_unlink(map, entry); - - size:=entry^.__end - entry^.start; - map^.size:=map^.size-size; - - vm_nt_entry_deallocate(entry); + vm_nt_entry_unlink (map, entry); + vm_nt_entry_deallocate(map, entry); end; function vm_nt_map_delete(map:p_vm_nt_map;start:vm_offset_t;__end:vm_offset_t):Integer; @@ -1189,16 +1180,15 @@ begin Result:=(KERN_SUCCESS); end; -procedure vm_nt_map_protect(map:p_vm_nt_map; +procedure vm_nt_map_protect(map :p_vm_nt_map; start:vm_offset_t; __end:vm_offset_t; - prot :Integer); + prot :Integer); var entry:p_vm_nt_entry; e_start:vm_offset_t; e___end:vm_offset_t; max:Integer; - r:Integer; begin if (start=__end) then Exit; @@ -1209,7 +1199,7 @@ begin entry:=entry^.next; end else begin - entry:=entry; + // end; while (entry<>@map^.header) and (entry^.start<__end) do @@ -1238,13 +1228,7 @@ begin max:=0; end; - r:=md_protect(Pointer(e_start),e___end-e_start,(prot and max and VM_RW)); - if (r<>0) then - begin - Writeln('failed md_protect(',HexStr(e_start,11),',',HexStr(e___end,11),'):0x',HexStr(r,8)); - Assert(false,'vm_nt_map_protect'); - end; - + vm_nt_sub_map_protect(@entry^.sub,e_start,e___end,(prot and max and VM_RW)); end; entry:=entry^.next; @@ -1253,7 +1237,57 @@ begin vm_nt_map_unlock(map); end; -procedure vm_nt_map_prot_fix(map:p_vm_nt_map; +procedure vm_nt_map_tracking(map :p_vm_nt_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Integer); +var + entry:p_vm_nt_entry; + e_start:vm_offset_t; + e___end:vm_offset_t; +begin + if (start=__end) then Exit; + + vm_nt_map_lock(map); + + if (not vm_nt_map_lookup_entry(map, start, @entry)) then + begin + entry:=entry^.next; + end else + begin + // + end; + + while (entry<>@map^.header) and (entry^.start<__end) do + begin + e_start:=entry^.start; + e___end:=entry^.__end; + + if (e_start__end) then + begin + e___end:=__end; + end; + + if (e___end>e_start) then + begin + vm_nt_sub_map_tracking(@entry^.sub,e_start,e___end,prot); + end; + + entry:=entry^.next; + end; + + vm_nt_map_unlock(map); +end; + + + + +procedure vm_nt_map_prot_fix(map :p_vm_nt_map; start:vm_offset_t; __end:vm_offset_t; mode :Integer); @@ -1294,7 +1328,7 @@ begin if (e___end>e_start) then begin - vm_prot_fixup(map,e_start,e___end,entry^.obj^.maxp,mode); + vm_nt_sub_map_prot_fixup(@entry^.sub,e_start,e___end,mode); end; end; @@ -1327,9 +1361,9 @@ asm _exit: end; -procedure vm_nt_map_madvise(map:p_vm_nt_map; - start:vm_offset_t; - __end:vm_offset_t; +procedure vm_nt_map_madvise(map :p_vm_nt_map; + start :vm_offset_t; + __end :vm_offset_t; advise:Integer); var entry:p_vm_nt_entry; @@ -1379,7 +1413,7 @@ begin mirror:=vm_nt_map_mirror(map,base,base+size); if (mirror<>nil) then begin - ZeroPages(mirror,size); + ZeroPages (mirror,size); md_unmap_ex(mirror,size); end; @@ -1396,7 +1430,7 @@ begin end; -function vm_nt_map_mirror(map:p_vm_nt_map; +function vm_nt_map_mirror(map :p_vm_nt_map; start:vm_offset_t; __end:vm_offset_t):Pointer; var diff --git a/sys/vm/vm_nt_sub_map.pas b/sys/vm/vm_nt_sub_map.pas new file mode 100644 index 00000000..4eb11df3 --- /dev/null +++ b/sys/vm/vm_nt_sub_map.pas @@ -0,0 +1,653 @@ +unit vm_nt_sub_map; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +uses + sysutils, + vm, + vm_pmap_prot; + +type + pp_vm_nt_sub_entry=^p_vm_nt_sub_entry; + p_vm_nt_sub_entry=^vm_nt_sub_entry; + vm_nt_sub_entry=packed record + prev :p_vm_nt_sub_entry; // previous entry + next :p_vm_nt_sub_entry; // next entry + left :p_vm_nt_sub_entry; // left child in binary search tree + right:p_vm_nt_sub_entry; // right child in binary search tree + start:vm_offset_t; // start address + __end:vm_offset_t; // end address + // + decl_prot:Byte; // declared protection (with tracking bits) + real_prot:Byte; // real page protection + align :Word; + end; + + p_vm_nt_sub_map=^t_vm_nt_sub_map; + t_vm_nt_sub_map=object + header:vm_nt_sub_entry; // List of entries + root :p_vm_nt_sub_entry; // Root of a binary search tree + property min_offset:vm_offset_t read header.start write header.start; + property max_offset:vm_offset_t read header.__end write header.__end; + end; + +procedure vm_nt_sub_map_init(map:p_vm_nt_sub_map;min,max:vm_offset_t); + +function vm_nt_sub_map_insert( + map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Byte):Integer; + +// Move nodes from one submap to another +procedure vm_nt_sub_map_move(dst,src:p_vm_nt_sub_map); + +procedure vm_nt_sub_map_free(map:p_vm_nt_sub_map); + +//Change protection taking into account tracking +function vm_nt_sub_map_protect(map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Byte):Integer; + +//Change protection tracking +function vm_nt_sub_map_tracking(map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Byte):Integer; + +//Update page protection by mode +procedure vm_nt_sub_map_prot_fixup(map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + mode :Integer); + +implementation + +uses + md_map; + +procedure vm_nt_sub_map_init(map:p_vm_nt_sub_map;min,max:vm_offset_t); inline; +begin + map^:=Default(t_vm_nt_sub_map); + map^.header.next:=@map^.header; + map^.header.prev:=@map^.header; + map^.min_offset :=min; + map^.max_offset :=max; +end; + +function vm_nt_sub_entry_create(map:p_vm_nt_sub_map):p_vm_nt_sub_entry; +var + new_entry:p_vm_nt_sub_entry; +begin + new_entry:=AllocMem(SizeOf(vm_nt_sub_entry)); + Assert((new_entry<>nil),'vm_nt_sub_entry_create: kernel resources exhausted'); + Result:=new_entry; +end; + +procedure vm_nt_sub_entry_dispose(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry); inline; +begin + FreeMem(entry); +end; + +function vm_nt_sub_entry_splay(addr:vm_offset_t;root:p_vm_nt_sub_entry):p_vm_nt_sub_entry; +var + llist,rlist:p_vm_nt_sub_entry; + ltree,rtree:p_vm_nt_sub_entry; + y :p_vm_nt_sub_entry; +begin + if (root=nil) then Exit(root); + + llist:=nil; + rlist:=nil; + repeat + { root is never nil in here. } + if (addrnil) then + begin + { Rotate right and put y on rlist. } + root^.left:=y^.right; + y^.right:=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; + 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; + + ltree:=root^.left; + while (llist<>nil) do + begin + y:=llist^.right; + llist^.right:=ltree; + ltree:=llist; + llist:=y; + end; + rtree:=root^.right; + while (rlist<>nil) do + begin + y:=rlist^.left; + rlist^.left:=rtree; + rtree:=rlist; + rlist:=y; + end; + + root^.left :=ltree; + root^.right:=rtree; + + Result:=(root); +end; + +procedure vm_nt_sub_entry_link( + map :p_vm_nt_sub_map; + after_where:p_vm_nt_sub_entry; + entry :p_vm_nt_sub_entry); +begin + 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 + vm_nt_sub_entry_splay(after_where^.start, map^.root); + end; + entry^.right:=after_where^.right; + entry^.left :=after_where; + after_where^.right:=nil; + end else + begin + entry^.right:=map^.root; + entry^.left :=nil; + end; + map^.root:=entry; +end; + +procedure vm_nt_sub_entry_unlink( + map :p_vm_nt_sub_map; + entry:p_vm_nt_sub_entry); +var + next,prev,root:p_vm_nt_sub_entry; +begin + if (entry<>map^.root) then + begin + vm_nt_sub_entry_splay(entry^.start, map^.root); + end; + if (entry^.left=nil) then + begin + root:=entry^.right; + end else + begin + root:=vm_nt_sub_entry_splay(entry^.start, entry^.left); + root^.right:=entry^.right; + end; + map^.root:=root; + + prev:=entry^.prev; + next:=entry^.next; + next^.prev:=prev; + prev^.next:=next; +end; + +function vm_nt_sub_map_lookup_entry( + map :p_vm_nt_sub_map; + address:vm_offset_t; + entry :pp_vm_nt_sub_entry):Boolean; +var + cur:p_vm_nt_sub_entry; +begin + 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 + cur:=vm_nt_sub_entry_splay(address,cur); + map^.root:=cur; + + 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; + +procedure vm_nt_sub_simplify_entry(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry); forward; + +function vm_nt_sub_map_insert( + map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Byte):Integer; +var + new_entry :p_vm_nt_sub_entry; + prev_entry :p_vm_nt_sub_entry; + temp_entry :p_vm_nt_sub_entry; + +begin + if (startmap^.max_offset) or (start>=__end) then + begin + Exit(KERN_INVALID_ADDRESS); + end; + + if vm_nt_sub_map_lookup_entry(map,start,@temp_entry) then + begin + Exit(KERN_NO_SPACE); + end; + + prev_entry:=temp_entry; + + if (prev_entry^.next<>@map^.header) and + (prev_entry^.next^.start<__end) then + begin + Exit(KERN_NO_SPACE); + end; + + if (prev_entry<>@map^.header) and + (prev_entry^.decl_prot=prot) and + (prev_entry^.real_prot=0) and + (prev_entry^.__end=start) then + begin + prev_entry^.__end:=__end; + + vm_nt_sub_simplify_entry(map, prev_entry); + + Exit(KERN_SUCCESS); + end; + + new_entry:=vm_nt_sub_entry_create(map); + new_entry^.start:=start; + new_entry^.__end:=__end; + + new_entry^.decl_prot:=prot; + new_entry^.real_prot:=0; //do fixup + + vm_nt_sub_entry_link(map, prev_entry, new_entry); + + vm_nt_sub_simplify_entry(map, new_entry); + + Result:=KERN_SUCCESS; +end; + +procedure vm_nt_sub_map_entry_delete(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry); inline; +begin + vm_nt_sub_entry_unlink (map, entry); + vm_nt_sub_entry_dispose(map, entry); +end; + +procedure vm_nt_sub_simplify_entry(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry); +var + next,prev:p_vm_nt_sub_entry; +begin + prev:=entry^.prev; + if (prev<>@map^.header) then + begin + if (prev^.__end=entry^.start) and + (prev^.decl_prot=entry^.decl_prot) and + (prev^.real_prot=entry^.real_prot) then + begin + vm_nt_sub_entry_unlink(map, prev); + entry^.start:=prev^.start; + + vm_nt_sub_entry_dispose(map, prev); + end; + end; + + next:=entry^.next; + if (next<>@map^.header) then + begin + if (entry^.__end=next^.start) and + (next^.decl_prot=entry^.decl_prot) and + (next^.real_prot=entry^.real_prot) then + begin + vm_nt_sub_entry_unlink(map, next); + entry^.__end:=next^.__end; + + vm_nt_sub_entry_dispose(map, next); + end; + end; +end; + +procedure _vm_nt_sub_map_clip_start(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry;start:vm_offset_t); +var + new_entry:p_vm_nt_sub_entry; +begin + vm_nt_sub_simplify_entry(map, entry); + + new_entry:=vm_nt_sub_entry_create(map); + new_entry^:=entry^; + + new_entry^.__end:=start; + entry^.start :=start; + + vm_nt_sub_entry_link(map, entry^.prev, new_entry); +end; + +procedure vm_nt_sub_map_clip_start(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry;start:vm_offset_t); inline; +begin + if (start>entry^.start) then + begin + _vm_nt_sub_map_clip_start(map,entry,start); + end; +end; + +procedure _vm_nt_sub_map_clip_end(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry;__end:vm_offset_t); +var + new_entry:p_vm_nt_sub_entry; +begin + new_entry:=vm_nt_sub_entry_create(map); + new_entry^:=entry^; + + new_entry^.start:=__end; + entry^.__end :=__end; + + vm_nt_sub_entry_link(map, entry, new_entry); +end; + +procedure vm_nt_sub_map_clip_end(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry;__end:vm_offset_t); inline; +begin + if (__end@src^.header) do + begin + vm_nt_sub_map_clip_end(src, entry, dst^.max_offset); //devide src by dst + // + if (after=nil) then + begin + vm_nt_sub_map_lookup_entry(dst, entry^.__end, @after); //get first position of insert + end; + // + next:=entry^.next; + // + vm_nt_sub_entry_unlink (src,entry); + vm_nt_sub_entry_link (dst,after,entry); + vm_nt_sub_simplify_entry(dst,entry); + // + after:=entry; + // + entry:=next; + end; +end; + +procedure vm_nt_sub_map_free(map:p_vm_nt_sub_map); +var + entry,next:p_vm_nt_sub_entry; +begin + entry:=map^.header.next; + // + while (entry<>@map^.header) do + begin + next:=entry^.next; + // + vm_nt_sub_map_entry_delete(map,entry); + // + entry:=next; + end; +end; + +// + +function vm_nt_sub_map_protect(map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Byte):Integer; +var + entry:p_vm_nt_sub_entry; + + base,size:vm_size_t; + mask:Integer; + r:Integer; +begin + if (start=__end) then + begin + Exit(KERN_SUCCESS); + end; + + if (vm_nt_sub_map_lookup_entry(map, start, @entry)) then + begin + vm_nt_sub_map_clip_start(map, entry, start); + end else + begin + entry:=entry^.next; + end; + + while (entry<>@map^.header) and (entry^.start<__end) do + begin + vm_nt_sub_map_clip_end(map, entry, __end); + + //save trac, change prot + prot:=(prot and VM_RW) or (entry^.decl_prot and PAGE_TRACK_RWX); + entry^.decl_prot:=prot; + + //masking + mask:=not (prot shr PAGE_TRACK_SHIFT); + prot:=(prot and VM_RW) and mask; + + if (prot<>(entry^.real_prot and VM_RW)) then + begin + base:=entry^.start; + size:=entry^.__end-entry^.start; + + r:=md_protect(Pointer(base),size,prot); + if (r<>0) then + begin + Writeln('failed md_protect(',HexStr(base,11),',',HexStr(base+size,11),'):0x',HexStr(r,8)); + Assert(false,'vm_nt_sub_map_protect'); + end; + //save changes + entry^.real_prot:=prot; + end; + + vm_nt_sub_simplify_entry(map, entry); + entry:=entry^.next; + end; + + Result:=(KERN_SUCCESS); +end; + +function vm_nt_sub_map_tracking(map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + prot :Byte):Integer; +var + entry:p_vm_nt_sub_entry; + + base,size:vm_size_t; + mask:Integer; + r:Integer; +begin + if (start=__end) then + begin + Exit(KERN_SUCCESS); + end; + + if (vm_nt_sub_map_lookup_entry(map, start, @entry)) then + begin + vm_nt_sub_map_clip_start(map, entry, start); + end else + begin + entry:=entry^.next; + end; + + while (entry<>@map^.header) and (entry^.start<__end) do + begin + vm_nt_sub_map_clip_end(map, entry, __end); + + //save prot, change track + prot:=(prot and PAGE_TRACK_RWX) or (entry^.decl_prot and VM_RW); + entry^.decl_prot:=prot; + + //masking + mask:=not (prot shr PAGE_TRACK_SHIFT); + prot:=(prot and VM_RW) and mask; + + if (prot<>(entry^.real_prot and VM_RW)) then + begin + base:=entry^.start; + size:=entry^.__end-entry^.start; + + r:=md_protect(Pointer(base),size,prot); + if (r<>0) then + begin + Writeln('failed md_protect(',HexStr(base,11),',',HexStr(base+size,11),'):0x',HexStr(r,8)); + Assert(false,'vm_nt_sub_map_protect'); + end; + //save changes + entry^.real_prot:=prot; + end; + + vm_nt_sub_simplify_entry(map, entry); + entry:=entry^.next; + end; + + Result:=(KERN_SUCCESS); +end; + +procedure vm_nt_sub_map_prot_fixup(map :p_vm_nt_sub_map; + start:vm_offset_t; + __end:vm_offset_t; + mode :Integer); +var + entry :p_vm_nt_sub_entry; + e_start:vm_offset_t; + e___end:vm_offset_t; + + base,size:vm_size_t; + prot:Integer; + mask:Integer; + r:Integer; +begin + if (start=__end) then Exit; + + if (vm_nt_sub_map_lookup_entry(map, start, @entry)) then + begin + // + end else + begin + entry:=entry^.next; + end; + + while (entry<>@map^.header) and (entry^.start<__end) do + begin + + e_start:=entry^.start; + e___end:=entry^.__end; + + if (e_start__end) then + begin + e___end:=__end; + end; + + if (e_start<>e___end) then + begin + prot:=entry^.decl_prot; + + //TRACK_PROT Take tracking bits into account + if ((mode and TRACK_PROT)=0) then + begin + prot:=(prot and VM_RW); + end else + begin + mask:=not (prot shr PAGE_TRACK_SHIFT); + prot:=(prot and VM_RW) and mask; + end; + + //REMAP_PROT Ignore protect bit checking + if ((mode and REMAP_PROT)<>0) or (prot<>(entry^.real_prot and VM_RW)) then + begin + base:=e_start; + size:=e___end-e_start; + + r:=md_protect(Pointer(base),size,prot); + if (r<>0) then + begin + Writeln('failed md_protect(',HexStr(base,11),',',HexStr(base+size,11),'):0x',HexStr(r,8)); + Assert(false,'vm_nt_sub_map_prot_fixup'); + end; + //save changes + entry^.real_prot:=prot; + end; + + end; + + entry:=entry^.next; + end; +end; + + +end. + diff --git a/sys/vm/vm_tracking_map.pas b/sys/vm/vm_tracking_map.pas index b48a042e..17813f6b 100644 --- a/sys/vm/vm_tracking_map.pas +++ b/sys/vm/vm_tracking_map.pas @@ -153,7 +153,7 @@ implementation procedure pmap_prot_track(pmap :Pointer; start:vm_offset_t; __end:vm_offset_t; - prots:Byte); external; + prot :Byte); external; function vm_track_object_allocate(handle:Pointer;start,__end:vm_offset_t;htype:T_THANDLE_TYPE;prot:Byte):p_vm_track_object; begin