2519f84b683fff7e1ac219ed6d8840406d4854fb
1 // See LICENSE for license details.
7 mmu_t::mmu_t(char* _mem
, size_t _memsz
)
8 : mem(_mem
), memsz(_memsz
), proc(NULL
)
17 void mmu_t::flush_icache()
19 for (size_t i
= 0; i
< ICACHE_ENTRIES
; i
++)
23 void mmu_t::flush_tlb()
25 memset(tlb_insn_tag
, -1, sizeof(tlb_insn_tag
));
26 memset(tlb_load_tag
, -1, sizeof(tlb_load_tag
));
27 memset(tlb_store_tag
, -1, sizeof(tlb_store_tag
));
32 void* mmu_t::refill_tlb(reg_t addr
, reg_t bytes
, bool store
, bool fetch
)
34 reg_t idx
= (addr
>> PGSHIFT
) % TLB_ENTRIES
;
35 reg_t expected_tag
= addr
>> PGSHIFT
;
37 reg_t mstatus
= proc
? proc
->state
.mstatus
: 0;
39 bool vm_disabled
= get_field(mstatus
, MSTATUS_VM
) == VM_MBARE
;
40 bool mode_m
= get_field(mstatus
, MSTATUS_PRV
) == PRV_M
;
41 bool mode_s
= get_field(mstatus
, MSTATUS_PRV
) == PRV_S
;
42 bool mprv_m
= get_field(mstatus
, MSTATUS_MPRV
) == PRV_M
;
43 bool mprv_s
= get_field(mstatus
, MSTATUS_MPRV
) == PRV_S
;
46 if (vm_disabled
|| (mode_m
&& (mprv_m
|| fetch
))) {
47 pgbase
= addr
& -PGSIZE
;
48 // virtual memory is disabled. merely check legality of physical address.
52 pgbase
= walk(addr
, mode_s
|| (mode_m
&& mprv_s
), store
, fetch
);
55 reg_t pgoff
= addr
& (PGSIZE
-1);
56 reg_t paddr
= pgbase
+ pgoff
;
58 if (pgbase
== reg_t(-1)) {
59 if (fetch
) throw trap_instruction_access_fault(addr
);
60 else if (store
) throw trap_store_access_fault(addr
);
61 else throw trap_load_access_fault(addr
);
64 if (unlikely(tracer
.interested_in_range(pgbase
, pgbase
+ PGSIZE
, store
, fetch
)))
65 tracer
.trace(paddr
, bytes
, store
, fetch
);
68 if (tlb_load_tag
[idx
] != expected_tag
) tlb_load_tag
[idx
] = -1;
69 if (tlb_store_tag
[idx
] != expected_tag
) tlb_store_tag
[idx
] = -1;
70 if (tlb_insn_tag
[idx
] != expected_tag
) tlb_insn_tag
[idx
] = -1;
72 if (fetch
) tlb_insn_tag
[idx
] = expected_tag
;
73 else if (store
) tlb_store_tag
[idx
] = expected_tag
;
74 else tlb_load_tag
[idx
] = expected_tag
;
76 tlb_data
[idx
] = mem
+ pgbase
- (addr
& ~(PGSIZE
-1));
82 pte_t
mmu_t::walk(reg_t addr
, bool supervisor
, bool store
, bool fetch
)
84 reg_t msb_mask
= -(reg_t(1) << (VA_BITS
-1));
85 if ((addr
& msb_mask
) != 0 && (addr
& msb_mask
) != msb_mask
)
86 return -1; // address isn't properly sign-extended
88 reg_t base
= proc
->get_state()->sptbr
;
90 int ptshift
= (LEVELS
-1)*PTIDXBITS
;
91 for (reg_t i
= 0; i
< LEVELS
; i
++, ptshift
-= PTIDXBITS
) {
92 reg_t idx
= (addr
>> (PGSHIFT
+ptshift
)) & ((1<<PTIDXBITS
)-1);
94 // check that physical address of PTE is legal
95 reg_t pte_addr
= base
+ idx
*sizeof(pte_t
);
96 if (pte_addr
>= memsz
)
99 pte_t
* ppte
= (pte_t
*)(mem
+pte_addr
);
100 reg_t ppn
= *ppte
>> PTE_PPN_SHIFT
;
102 if ((*ppte
& PTE_TYPE
) == PTE_TYPE_TABLE
) { // next level of page table
103 base
= ppn
<< PGSHIFT
;
105 // we've found the PTE. check the permissions.
106 if (!PTE_CHECK_PERM(*ppte
, supervisor
, store
, fetch
))
108 // set referenced and possibly dirty bits.
112 // for superpage mappings, make a fake leaf PTE for the TLB's benefit.
113 reg_t vpn
= addr
>> PGSHIFT
;
114 reg_t addr
= (ppn
| (vpn
& ((reg_t(1) << ptshift
) - 1))) << PGSHIFT
;
116 // check that physical address is legal
127 void mmu_t::register_memtracer(memtracer_t
* t
)