From 11fad84fb19699c1333a72a615bc2f6557a6eed3 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 12 Mar 2015 20:00:09 -0700 Subject: [PATCH] Implement PTE referenced/dirty bits --- riscv/encoding.h | 2 ++ riscv/mmu.cc | 24 ++++++++++++------------ riscv/mmu.h | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/riscv/encoding.h b/riscv/encoding.h index 4b929d3..25091cf 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -72,6 +72,8 @@ #define PTE_SR 0x040 // Supervisor Read permission #define PTE_SW 0x080 // Supervisor Write permission #define PTE_SX 0x100 // Supervisor eXecute permission +#define PTE_R 0x200 // Referenced +#define PTE_D 0x400 // Dirty #define PTE_PERM (PTE_SR | PTE_SW | PTE_SX | PTE_UR | PTE_UW | PTE_UX) #ifdef __riscv diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 779383d..9bbb4e4 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -52,7 +52,7 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) pte |= PTE_UR | PTE_SR | PTE_UW | PTE_SW; } } else { - pte = walk(addr); + pte = walk(addr, store); } reg_t pte_perm = pte & PTE_PERM; @@ -79,7 +79,7 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) else { tlb_load_tag[idx] = (pte_perm & PTE_UR) ? expected_tag : -1; - tlb_store_tag[idx] = (pte_perm & PTE_UW) ? expected_tag : -1; + tlb_store_tag[idx] = (pte_perm & PTE_UW) && store ? expected_tag : -1; tlb_insn_tag[idx] = (pte_perm & PTE_UX) ? expected_tag : -1; tlb_data[idx] = mem + pgbase - (addr & ~(PGSIZE-1)); } @@ -87,14 +87,13 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) return mem + paddr; } -pte_t mmu_t::walk(reg_t addr) +pte_t mmu_t::walk(reg_t addr, bool store) { reg_t msb_mask = -(reg_t(1) << (VA_BITS-1)); if ((addr & msb_mask) != 0 && (addr & msb_mask) != msb_mask) return 0; // address isn't properly sign-extended reg_t base = proc->get_state()->sptbr; - reg_t ptd; int ptshift = (LEVELS-1)*PTIDXBITS; for (reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS) { @@ -105,23 +104,24 @@ pte_t mmu_t::walk(reg_t addr) if (pte_addr >= memsz) return 0; - ptd = *(pte_t*)(mem+pte_addr); + pte_t* ppte = (pte_t*)(mem+pte_addr); - if (!(ptd & PTE_V)) { // invalid mapping + if (!(*ppte & PTE_V)) { // invalid mapping return 0; - } else if (ptd & PTE_T) { // next level of page table - base = (ptd >> PGSHIFT) << PGSHIFT; + } else if (*ppte & PTE_T) { // next level of page table + base = (*ppte >> PGSHIFT) << PGSHIFT; } else { - // we've found the PTE. + // we've found the PTE. set referenced and possibly dirty bits. + *ppte |= PTE_R | (store ? PTE_D : 0); // for superpage mappings, make a fake leaf PTE for the TLB's benefit. reg_t vpn = addr >> PGSHIFT; - ptd |= (vpn & ((1<<(ptshift))-1)) << PGSHIFT; + reg_t pte = *ppte | ((vpn & ((1<<(ptshift))-1)) << PGSHIFT); // check that physical address is legal - if (((ptd >> PGSHIFT) << PGSHIFT) >= memsz) + if (((pte >> PGSHIFT) << PGSHIFT) >= memsz) return 0; - return ptd; + return pte; } } return 0; diff --git a/riscv/mmu.h b/riscv/mmu.h index 329f291..0803d0f 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -154,8 +154,8 @@ private: // finish translation on a TLB miss and upate the TLB void* refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch); - // perform a page table walk for a given virtual address - pte_t walk(reg_t addr); + // perform a page table walk for a given VA; set referenced/dirty bits + pte_t walk(reg_t addr, bool store); // translate a virtual address to a physical address void* translate(reg_t addr, reg_t bytes, bool store, bool fetch) -- 2.30.2