Sv39 virtual memory translation on Milk V Duo

Hey there,

I’m trying to get Sv39 running on the Milk V Duo and I just can’t get it working.

Quick info about the setup: I used fiptool to emplace my binary into the OpenSBI slot, which means it is running completely bare metal, starts in M-mode and then I push it down to S-mode, where my minikernel runs.

I use identity mapping for the kernel (with megapages) and the user mapping uses traditional 4KiB pages (meaning the full three levels).

I know for sure the page table setup works correctly – I tested in in an emulator (MSIM) and it works there. Yes, MSIM currently only supports 32bit RV32, however, I contributed with an RV64 implementation with Sv39 support.

The problem is, when I update satp with the ASID (starts at 0) and the root of the table, the instruction after the CSR write causes fault 12, which is Instruction page fault. I don’t know what is happening since the PTEs should be correct and the kernel is identity mapped, so it should continue execution without a problem.

Has anyone tried to get Sv39 running on the CV1800B?

Cheers!

1 Like

I have to, once again, respond to myself but in case anyone has the same problem with it:

The problem wasn’t the Sv39 memory translation itself, it was that on the chip, you CANNOT DELEGATE M-MODE EXCEPTIONS TO S-MODE. It took me forever to fix this, even though it is written in the chip manual.

Also, when trying to get Sv39 working, do not forget to set the proper bits (bit 21) in mxstatus.

1 Like

Man, you are a god.
I always follow your posts because I know you’ll find a solution.

2 Likes

There is more to this, just some notes:

Access/Dirty bits in the PTE

The CPU does NOT set the A/D bits automatically because it does not implement the Svade extension. You have to do this manually on a fault (which in this case you’ll get even if it isn’t exactly a fault – the CPU just tells you to update the bits this way). Also note that you have to handle these faults in M-mode since you can’t delegate M-mode exceptions to S-mode.

Another way is to hardcode the A/D bits to one when constructing the page table and then you should not get any faults that ask you for a bit update. This, however, did not work for me, but I’ve seen some people on Reddit that solved it this way. The page fault method is IMO better though.

Extended page attributes

The C906 processor uses additional bits in the PTE to decide what to cache/buffer and what not to cache. These are described in the C906 manual, page 53 and 54.

When using the CLINT/PLIC (and maybe other MMIO? IDK yet), make sure the Strong order (SO) bit IS SET in the PTEs that map that range. Otherwise, it won’t work and weird things will happen.

Also a strange thing – I tried to set the Cacheable bit on normal PTEs (meaning those who map the heap, etc.), however, that did not work. I just ended up not setting these at all, which works fine.

1 Like