ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
MMU.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
21#include "etiss/mm/MMU.h"
22#include "etiss/CPUCore.h"
23#include "etiss/jit/ReturnCode.h"
24
25namespace etiss
26{
27namespace mm
28{
29
30MMU::MMU(bool hw_ptw, std::string name, bool pid_enabled)
31 : mmu_enabled_(false)
32 , mmu_control_reg_val_(0)
33 , pid_(0)
34 , name_(name)
35 , pid_enabled_(pid_enabled)
36 , hw_page_table_walker_(hw_ptw)
37{
38 tlb_ = std::shared_ptr<etiss::mm::TLB<0>>(new TLB<0>());
39
41 // REGISTER_PAGE_FAULT_HANDLER(TLBISFULL, tlb_full_handler);
42}
43
44int32_t MMU::Translate(const uint64_t vma, uint64_t *const pma_buf, MM_ACCESS access, uint64_t data)
45{
46
47 if (!mmu_enabled_)
48 {
49 *pma_buf = vma;
50 return NOERROR;
51 }
52
53 if (!this->CheckPrivilegedMode())
54 {
55 *pma_buf = vma;
56 return NOERROR;
57 }
58
59 if (PTEFormat::Instance().GetFormatMap().find(std::string("PPN")) == PTEFormat::Instance().GetFormatMap().end())
60 etiss::log(etiss::FATALERROR, "PPN not defined in PTE format");
61
62 if (PTEFormat::Instance().GetFormatMap().find(std::string("PAGEOFFSET")) ==
63 PTEFormat::Instance().GetFormatMap().end())
64 etiss::log(etiss::FATALERROR, "Page size offset not defined in PTE format");
65
66 std::pair<uint32_t, uint32_t> page_offset_bitfield =
67 PTEFormat::Instance().GetFormatMap().find(std::string("PAGEOFFSET"))->second;
68
69 std::pair<uint32_t, uint32_t> ppn_bitfield = PTEFormat::Instance().GetFormatMap().find(std::string("PPN"))->second;
70
71 uint32_t page_offset_msb_pos = page_offset_bitfield.first;
72
73 uint32_t ppn_msb_pos = ppn_bitfield.first;
74
75 // Add PID as part of TLB tag to reduce flush possibility.
76 uint64_t vpn = vma >> (page_offset_msb_pos + 1);
77
78 if (pid_enabled_)
79 {
80 vpn |= pid_ << (ppn_msb_pos + 1);
81 }
82
83 PTE pte_buf = PTE(0);
84 int32_t fault = tlb_->Lookup(vpn, &pte_buf);
85 if (fault)
86 {
87 fault = HANDLE_PAGE_FAULT(fault, this, vma, access);
88 if (fault != 0)
89 return fault;
90
91 fault = tlb_->Lookup(vpn, &pte_buf);
92 if (fault != 0)
93 {
94 Dump();
95 etiss::log(etiss::FATALERROR, "TLB MISS is not correctly handled");
96 }
97 }
98
99 if ((fault = CheckProtection(pte_buf, access)))
100 return fault;
101
102 uint64_t offset_mask = (1 << (page_offset_msb_pos + 1)) - 1;
103 *pma_buf = (pte_buf.GetPPN() << (page_offset_msb_pos + 1)) | (vma & offset_mask);
104
105 UpdatePTEFlags(pte_buf, access);
106
107 // Check whether vma is trying to write the data cached in TLB, if so
108 // evict the PTE entry in the TLB
109 if (W_ACCESS == access)
110 {
111 std::map<uint64_t, PTE *>::iterator itr = tlb_entry_map_.find(*pma_buf);
112 if (itr != tlb_entry_map_.end())
113 tlb_entry_map_.erase(itr);
114 }
115
116 return NOERROR;
117}
118
119int32_t MMU::AddTLBEntry(const uint64_t vpn, const PTE &pte)
120{
121 uint32_t fault = tlb_->AddPTE(vpn, pte);
122 if (fault)
123 {
124 if ((fault = HANDLE_PAGE_FAULT(fault, this, 0, R_ACCESS)))
125 return fault;
126 tlb_->AddPTE(vpn, pte);
127 }
128 return NOERROR;
129}
130
131void MMU::SignalMMU(uint64_t control_reg_val_)
132{
133 if (0 == control_reg_val_)
134 mmu_enabled_ = false;
135 else if (control_reg_val_ && (!mmu_enabled_))
136 {
137 mmu_enabled_ = true;
138 etiss::log(etiss::VERBOSE, GetName() + " : MMU is enabled.");
139 }
140 if (control_reg_val_ != mmu_control_reg_val_)
141 {
142 cache_flush_pending = true;
143 tlb_->Flush();
144 tlb_entry_map_.clear();
145 etiss::log(etiss::VERBOSE, GetName() + " : TLB flushed due to page directory update.");
146 mmu_control_reg_val_ = control_reg_val_;
147 if (pid_enabled_)
148 UpdatePid(GetPid(control_reg_val_));
149 }
150 else
151 etiss::log(etiss::WARNING, "Redundant MMU control register write");
152}
153
155{
156 using std::cout;
157 using std::endl;
158 cout << "------------MMU Details-----------" << endl;
159 cout << "MMU name : " << name_ << endl;
160 cout << "MMU enabled: " << std::boolalpha << mmu_enabled_ << endl;
161 cout << "PID enabled: " << std::boolalpha << pid_enabled_ << endl;
162 if (pid_enabled_)
163 cout << "Current PID : 0x" << std::hex << pid_ << endl;
164 cout << "Current control register value : 0x" << std::hex << mmu_control_reg_val_ << endl;
165
166 tlb_->Dump();
167}
168
170{
171 cpu_ = cpu;
172 system_ = system;
174 // Page table walker probe
176 etiss::log(etiss::FATALERROR, "No hardware page table walker, software page table walker is required ");
177}
178
179void MMU::AddTLBEntryMap(uint64_t phy_addr_, PTE &pte)
180{
181 if (tlb_entry_map_.find(phy_addr_) != tlb_entry_map_.end())
183 tlb_entry_map_[phy_addr_] = &pte;
184}
185
186int32_t tlb_miss_handler(int32_t fault, MMU *mmu, uint64_t vma, MM_ACCESS access)
187{
188 if (mmu->HasPageTableWalker())
189 {
190 int32_t handled_fault = NOERROR;
191 if ((handled_fault = mmu->WalkPageTable(vma, access)))
192 return handled_fault;
193 return NOERROR;
194 }
195
196 switch (access)
197 {
198 case R_ACCESS:
199 return etiss::RETURNCODE::LOAD_PAGEFAULT;
200 case W_ACCESS:
201 return etiss::RETURNCODE::STORE_PAGEFAULT;
202 case X_ACCESS:
203 return etiss::RETURNCODE::INSTR_PAGEFAULT;
204 default:
205 abort();
206 }
207}
208
209void DUMP_MMU(MMU *mmu)
210{
211 mmu->Dump();
212}
213
214} // namespace mm
215} // namespace etiss
216
217using namespace etiss;
218
219extern "C"
220{
222 {
223 CPUCore *core = (CPUCore *)cpu->_etiss_private_handle_;
224 if (!core)
225 {
226 etiss::log(etiss::ERROR, "CPUArchRegListenerInterface::signalChangedRegisterValue() called from outside "
227 "etiss::CPUCore::execute(). this should not happen and indicates a faultiy "
228 "CPUArch (or Plugin) implementation. This function may have been called "
229 "indirectly from ETISS_signalChangedRegisterValue()");
230 return;
231 }
232 auto mmu = core->getMMU();
233 if (mmu)
234 mmu->SignalMMU(mmu_signal_);
235 }
236}
defines main cpu core interface
void ETISS_SIGNAL_MMU(ETISS_CPU *cpu, etiss_uint64 mmu_signal_)
Definition MMU.cpp:221
Modeling hardware memory management for virtual memory -> physical memory translation and protection.
#define DEFAULT_PAGE_TABLE_WALKER
Definition MMU.h:40
#define REGISTER_PAGE_FAULT_HANDLER(fault, handler)
#define HANDLE_PAGE_FAULT(fault, mmu, vma, access)
static __inline__ uint32_t
Definition arm_cde.h:25
static __inline__ uint64_t
Definition arm_cde.h:31
static __inline__ int32_t
Definition arm_mve.h:51
uint64_t etiss_uint64
Definition types.h:58
CPUCore is responsible for the simulation of a CPU core in ETISS.
Definition CPUCore.h:64
virtual std::shared_ptr< etiss::mm::MMU > getMMU()
Get the Memory Management Unit(MMU) of this CPUCore instance.
Definition CPUCore.h:133
int32_t AddTLBEntry(const uint64_t vfn, const PTE &pte)
Definition MMU.cpp:119
virtual int32_t GetPid(uint64_t control_reg_val_)
Definition MMU.h:137
virtual bool CheckPrivilegedMode()=0
MMU is enabled in certain mode.
std::string GetName() const
Definition MMU.h:135
bool mmu_enabled_
Definition MMU.h:144
MMU(bool hw_ptw, std::string name, bool pid_enabled)
MMU ctor.
Definition MMU.cpp:30
virtual int32_t WalkPageTable(uint64_t, MM_ACCESS)
Page table walking is required to translate virtual address to physical address if TLB miss occurs.
Definition MMU.h:109
const bool hw_page_table_walker_
Definition MMU.h:160
void SignalMMU(uint64_t control_reg_val_)
Whenever the MMU control register changes, the MMU has to be notified with the updated control regist...
Definition MMU.cpp:131
uint32_t pid_
Definition MMU.h:156
void UpdatePid(uint32_t new_pid)
Definition MMU.h:125
bool cache_flush_pending
Definition MMU.h:139
std::shared_ptr< etiss::mm::TLB< 0 > > tlb_
Definition MMU.h:148
const bool pid_enabled_
Definition MMU.h:159
virtual int32_t CheckProtection(const PTE &, MM_ACCESS access)=0
Memory protection is architecture-dependent, which should be implemented with architecture model.
virtual void UpdatePTEFlags(PTE &, MM_ACCESS)
Reserved for some MMU that might update PTE when translating.
Definition MMU.h:115
ETISS_System * system_
Definition MMU.h:143
void AddTLBEntryMap(uint64_t phy_addr_, PTE &pte)
Keep a record of mapping between cached PTE with its physical address.
Definition MMU.cpp:179
uint64_t mmu_control_reg_val_
Definition MMU.h:155
bool HasPageTableWalker()
Definition MMU.h:121
virtual int32_t Translate(const uint64_t vma, uint64_t *const pma_buf, MM_ACCESS access, uint64_t data=0)
Conduct the actual translation according to the format set by PTEFormatBuilder.
Definition MMU.cpp:44
std::string name_
Definition MMU.h:157
void Init(ETISS_CPU *cpu, ETISS_System *system)
Initialize the MMU, when DMMUWrapper is wrapping the MMU.
Definition MMU.cpp:169
void Dump()
Dump the details of the MMU, when page fault cannot be handled.
Definition MMU.cpp:154
std::map< uint64_t, PTE * > tlb_entry_map_
Definition MMU.h:153
ETISS_CPU * cpu_
Definition MMU.h:142
static PTEFormat & Instance()
Get the singleton instance.
Definition PTEFormat.h:34
PTEFormatMap & GetFormatMap()
Definition PTEFormat.h:59
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition PTE.h:31
uint64_t GetPPN() const
Definition PTE.h:81
void DUMP_MMU(MMU *mmu)
Definition MMU.cpp:209
int32_t tlb_miss_handler(int32_t fault, MMU *mmu, uint64_t vma, MM_ACCESS access)
Definition MMU.cpp:186
MM_EXPORT const int32_t TLBMISS
MM_EXPORT const int32_t NOERROR
MM_EXPORT const int32_t PTEOVERLAP
forwards: include/jit/*
Definition Benchmark.h:17
@ VERBOSE
Definition Misc.h:88
@ WARNING
Definition Misc.h:86
@ ERROR
Definition Misc.h:85
@ FATALERROR
Definition Misc.h:84
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
#define false
Definition stdbool.h:17
basic cpu state structure needed for execution of any cpu architecture.
Definition CPU.h:51
void * _etiss_private_handle_
private helper handle for plugins
Definition CPU.h:69
memory access and time synchronization functions.
Definition System.h:40