[Vm-dev] [OpenSmalltalk/opensmalltalk-vm] 28630b: The extra +1 in size parameter passed to mprotect(...
Ben Coman
btc at openinworld.com
Sat Dec 24 04:03:19 UTC 2016
On Sat, Dec 24, 2016 at 2:33 AM, Holger Freyther <holger at freyther.de> wrote:
>
>
>
> > On 23 Dec 2016, at 01:46, Ben Coman <btc at openinworld.com> wrote:
> >
> > Just curious about the behaviour and performance of mprotect and VirtualProtect. Would it be feasible to use on each FFI callout so that aberrant memory access from C code cannot corrupt the Smalltalk Image, but generate an exception that could be handled in-Image?
>
> Hi Ben,
>
> * syscall overhead (e.g. mprotect is not part of the VDSO)
> * lock/unlock of Page Table Entries (PTEs)
> * walking page table entries
> * modifying page table entries
> * merging/combining virtual memory areas now (allocation)
> * cache/tlb being invalidated
>
>
> E.g. for FreeBSD the chain is like this with a lot of details on the way
>
> * sys_mprotect[1] the syscall after the dispatch
> * vm_map_protect[2] for the VM subsystem
> * AMD64's pmap_protect[3] implementation various ways to invalidate the TLB in it
>
> holger
>
>
>
> [1] https://github.com/freebsd/freebsd/blob/releng/10.3/sys/vm/vm_mmap.c#L657
> [2] https://github.com/freebsd/freebsd/blob/releng/10.3/sys/vm/vm_map.c#L1924
> [3] https://github.com/freebsd/freebsd/blob/releng/10.3/sys/amd64/amd64/pmap.c#L3906
Thanks Holger. A bit hard to soak up in a first sitting, but
interesting to get a feel for how it works under the covers.
I summarised the loops, so it seems it needs to modify every page table entry.
sys_mprotect()
vm_map_protect()
/* Make a first pass to check for protection violations.*/
while ((current != &map->header) && (current->start < end))
{... current = current->next; ...}
/* Do an accounting pass for private read-only mappings that now
will do cow due to allowed write (e.g. debugger sets breakpoint on
text segment) */
for (current = entry; (current != &map->header) &&
(current->start < end); current = current->next)
{...}
/* Go back and fix up protections. [Note that clipping is not
necessary the second time.] */
current = entry;
while ((current != &map->header) && (current->start < end))
{
...
pmap_protect()
for (; sva < eva; sva = va_next) {
va_next = (sva + NBPDR) & ~PDRMASK;
for (pte = pmap_pde_to_pte(pde, sva); sva != va_next;
pte++, sva += PAGE_SIZE)
{...flip page table bits...}
current = current->next;
}
The documentation of variables in the code there is not great. I'm
guessing at variable purposes...
sva = start virtual address
eva = end virtual address
pte = page table entry
NBPDR=number bytes / page directory
So maybe useful for debugging, but not practical for every FFI call (??)
cheers -ben
More information about the Vm-dev
mailing list