Setting a new Sv39 page table

Anyone have any examples setting a new Sv39 page table on rv64? Working on jumping into Haiku’s kernel and a little stuck generating new page tables :slight_smile: I feel like it’s csr instructions, but mmu stuff is always my weakness. None of the risc-v books I have detail the process well.

my WIP is here if you’re curious:
https://review.haiku-os.org/c/haiku/+/3733

1 Like

You set up the page table in RAM. Then you set the “satp” CSR with the address of the page table you’ve made, and what MMU mode you want.

ok. think i got it…

// Generate the final satp with our new sv39 mmu
	
uint64_t
arch_mmu_generate_satp(uint64_t sv39)
{
	dprintf("%s called sv39: 0x%" B_PRIx64 "\n", __func__, sv39);

	uint64_t satp = 0;
	__asm__	__volatile__ ("csrr %0, satp" : "=r"(satp) : : );
	dprintf("  current satp: 0x%" B_PRIx64 "\n", satp);
	
	// Set sv39 mode
	satp = (satp & ~RV64_SATP_MODE_MASK)
		| ((uint64_t)RV64_SATP_MODE_SV39 << RV64_SATP_MODE_SHIFT);
	// Our new sv39 table
	satp = (satp & ~RV64_SATP_PPN_MASK)
		| (sv39 << RV64_SATP_PPN_SHIFT);
	
	// TODO: Do we need to set / change ASID?
	
	dprintf("  new satp: 0x%" B_PRIx64 "\n", satp);
	return satp;
}

then just before jumping into our kernel:

/*  status_t arch_enter_kernel(uint64 satp, struct kernel_args *kernelArgs,
        addr_t kernelEntry, addr_t kernelStackTop);
    a0  - satp
    a1  - kernelArgs
    a2  - kernelEntry
	
    a3  - kernelStackTop
*/
FUNCTION(arch_enter_kernel):
	// Set the kernel stack
	mv	sp,a3
	
	
	// Set new memory map for kernel
	sfence.vma
	csrw satp, a0

	// Setup kernel args
	mv	a0,a1	// kernelArgs
	mv	a4,a2
	li	a1,0	// currentCPU=0

	// call the kernel
	jr	a4

	// return
	li	a0,-1  // B_ERROR
	ret
FUNCTION_END(arch_enter_kernel)
Final SV39 at 0xfbff0000
arch_mmu_generate_satp called sv39: 0xfbff0000
  current satp: 0x0
  new satp: 0x80000000fbff0000
Calling ExitBootServices. So long, EFI!
2 Likes