From cc081ec813276d0d13ec8fb942df611f93c892f1 Mon Sep 17 00:00:00 2001 From: Zihao Yu Date: Fri, 11 Oct 2019 16:43:15 +0800 Subject: [PATCH] riscv64,mmu: support sv39 paging --- src/isa/riscv64/mmu.c | 65 ++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/src/isa/riscv64/mmu.c b/src/isa/riscv64/mmu.c index 30ca5011..4ab97e81 100644 --- a/src/isa/riscv64/mmu.c +++ b/src/isa/riscv64/mmu.c @@ -2,7 +2,6 @@ #include "memory/memory.h" #include "csr.h" -/* the 32bit Page Table Entry(second level page table) data structure */ typedef union PageTableEntry { struct { uint32_t valid : 1; @@ -14,57 +13,71 @@ typedef union PageTableEntry { uint32_t access : 1; uint32_t dirty : 1; uint32_t rsw : 2; - uint32_t ppn :22; + uint64_t ppn :44; + uint32_t pad :10; }; - uint32_t val; + uint64_t val; } PTE; typedef union { struct { - uint32_t pf_off :12; - uint32_t pt_idx :10; - uint32_t pdir_idx :10; + uint64_t pf_off :12; + uint64_t vpn0 : 9; + uint64_t vpn1 : 9; + uint64_t vpn2 : 9; }; - uint32_t addr; + uint64_t addr; } PageAddr; -static paddr_t page_walk(vaddr_t vaddr, bool is_write) { +// Sv39 page walk +static word_t page_walk(vaddr_t vaddr, bool is_write) { PageAddr *addr = (void *)&vaddr; - paddr_t pdir_base = satp->ppn << 12; + word_t pdir_base = satp->ppn << 12; - PTE pde; - pde.val = paddr_read(pdir_base + addr->pdir_idx * 4, 4); - if (!pde.valid) { - panic("pc = %lx, vaddr = %lx, pdir_base = %x, pde = %x", cpu.pc, vaddr, pdir_base, pde.val); + PTE pte2; + pte2.val = paddr_read(pdir_base + addr->vpn2 * 8, 8); + if (!pte2.valid) { + panic("pc = " FMT_WORD ", vaddr = " FMT_WORD ", pdir_base = " FMT_WORD ", pte2 = " FMT_WORD, + cpu.pc, vaddr, pdir_base, pte2.val); } - paddr_t pt_base = pde.ppn << 12; - PTE pte; - pte.val = paddr_read(pt_base + addr->pt_idx * 4, 4); - if (!pte.valid) { - panic("pc = %lx, vaddr = %lx, pt_base = %x, pte = %x", cpu.pc, vaddr, pt_base, pte.val); + word_t pt_base1 = pte2.ppn << 12; + PTE pte1; + pte1.val = paddr_read(pt_base1 + addr->vpn1 * 8, 8); + if (!pte1.valid) { + panic("pc = " FMT_WORD ", vaddr = " FMT_WORD ", pt_base1 = " FMT_WORD ", pte1 = " FMT_WORD, + cpu.pc, vaddr, pt_base1, pte1.val); } - if (!pte.access || (pte.dirty == 0 && is_write)) { - pte.access = 1; - pte.dirty |= is_write; - paddr_write(pt_base + addr->pt_idx * 4, pte.val, 4); + word_t pt_base0 = pte1.ppn << 12; + PTE pte0; + pte0.val = paddr_read(pt_base0 + addr->vpn0 * 8, 8); + if (!pte0.valid) { + panic("pc = " FMT_WORD ", vaddr = " FMT_WORD ", pt_base0 = " FMT_WORD ", pte0 = " FMT_WORD, + cpu.pc, vaddr, pt_base0, pte0.val); } - return pte.ppn << 12; + //if (!pte.access || (pte.dirty == 0 && is_write)) { + // pte.access = 1; + // pte.dirty |= is_write; + // paddr_write(pt_base + addr->pt_idx * 4, pte.val, 4); + //} + + return pte0.ppn << 12; } static inline paddr_t page_translate(vaddr_t addr, bool is_write) { - printf("There's page translate\n"); return page_walk(addr, is_write) | (addr & PAGE_MASK); } word_t isa_vaddr_read(vaddr_t addr, int len) { - paddr_t paddr = (satp->mode ? page_translate(addr, false) : addr); + assert(satp->mode == 0 || satp->mode == 4); + paddr_t paddr = (satp->mode == 4 ? page_translate(addr, false) : addr); return paddr_read(paddr, len); } void isa_vaddr_write(vaddr_t addr, word_t data, int len) { - paddr_t paddr = (satp->mode ? page_translate(addr, true) : addr); + assert(satp->mode == 0 || satp->mode == 4); + paddr_t paddr = (satp->mode == 4 ? page_translate(addr, true) : addr); paddr_write(paddr, data, len); } -- GitLab