On Mon, Oct 19, 2020 at 3:13 PM Tom Rollet <tom.rol...@epita.fr> wrote:

> Hi,
>
> I'm starting to help in the development of the dt device.
>
> I'm stuck on permission handling of memory. I'm trying to allocate a
> page in kernel with read/write protections, fill the allocated page
> with data then change the permissions to  read/exec.
>
> Snippet of my code:
>
>   addr = uvm_km_alloc(kernel_map, PAGE_SIZE);
>
>      [...] (memcpy data in allocated page)
>
>   uvm_map_protect(kernel_map, addr, addr + PAGE_SIZE, PROT_READ
>                                              | PROT_EXEC, FALSE)))
>

This is same usage as seen in the 'sti' driver...which is on hppa only, so
while it's presumably the correct usage of uvm_km_alloc() and
uvm_map_protect(), I don't think uvm_map_protect() has been used on
kernel-space on amd64 (or possibly all non-hppa archs) before in OpenBSD.
Whee?


It triggers the following error at boot time when executing
> the uvm_map_protect function.
>
> uvm_fault(0xffffffff81fb2c90, 0x7ffec0008000, 0, 2) -> e kernel: page fault
> trap, code=0 Stopped at    pmap_write_protect+0x1f5:  lock andq
> $-0x3,0(%rdi)
>
> Trace:
>
> pmap_write_protect(ffffffff82187b28,ffff80002255b000,ffff80002255c000,
>      5,50e8b70481f4f622,fffffd81b6567e70) at pmap_write_protect+0x212
> uvm_map_protect(ffffffff82129ae0,ffff80002255b000,ffff80002255c000
>      ,5,0,ffffffff82129ae0) at uvm_map_protect+0x501
> dt_alloc_kprobe(ffffffff815560e0,ffff800000173900,e7ef01a2855152cc,
>      ffffffff82395c98,0,ffffffff815560e0) at dt_alloc_kprobe+0x1ff
> dt_prov_kprobe_init(2333e28db00d3edd,0,ffffffff82121150,0,0,
>      ffffffff824d9008) at dt_prov_kprobe_init+0x1d9
> dtattach(1,ffffffff821fb384,f,1,c2ee1c3f472154e,2dda28) at dtattach+0x5d
> main(0,0,0,0,0,1) at main+0x419
>
> The problem comes from the loop in pmap_write_protect
> (sys/arch/amd64/amd64/pmap.c:2108) that is executed
> infinity in my case.
>
> Entry of function pmap_write_protect:
>      sva:  FFFF80002250A000
>      eva:  FFFF80002250B000
>
> After &= PG_FRAME (line 2098-2099)
>      sva= F80002250A000
>      eva= F80002250B000
>
>   loop:  (ligne 2108)
>
>       first iteration:
>          va           = F80002250A000
>          eva         = F80002250B000
>          blockend = 0800122400000
>
...

> Does anyone have an idea how to fix this issue?


So, blockend is clearly wrong for va and eva.  I suspect the use of
L2_FRAME here:
               blockend = (va & L2_FRAME) + NBPD_L2;

is wrong here and it should be
               blockend = (va & VA_SIGN_NEG(L2_FRAME)) + NBPD_L2;

or some equivalent expression to keep all the bits above the frame.


Philip Guenther

Reply via email to