Welcome to the Linux Foundation Forum!

RISCV initialization / writing an emulator mmu



I'm trying to add a SV39 MMU to a RISCV64 emulator. The emulator is able to boot a linux kernel compiled without mmu-support. It looks like it should work with the MMU, but it doesn't, and right now, reading the source code, I can not figure out how it could ever work! So, here it goes:

Initialization starts in https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/head.S which first calls setup_vm() in https://github.com/torvalds/linux/blob/master/arch/riscv/mm/init.c#L1041 that sets up a page table, and then calls relocate_enable_mmu. relocate_enable_mmu enables SV39 by setting satp.mode = 8 at https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/head.S#L106.

  • The page table used at this point is trampoline_pg_dir. This page table only maps the kernel to high addresses ffffffffxxxxxxxx. But we are currently executing at a low address, 8xxxxxxx.
  • When satp.mode = 8 is set, priv is still set to machine mode.
  • Having priv=3 (machine mode) at the same time as satp.mode != 0 is undefined!

  • If I make it so that this is interpreted as mmu enabled, I get an immediat page fault, as pc isn't mapped by the new page table.

  • If I instead make it so that this means mmu is disabled, execution continues, and ends with a jump to ffffffff80001084, which /is/ mapped. But at that point, priv is still = 3, and that address isn't a physical addtess, so it fails to fetch.

How is this supposed to work?


Upcoming Training