ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
MMU.cpp
Go to the documentation of this file.
1
59#include "etiss/mm/MMU.h"
60#include "etiss/CPUCore.h"
61#include "etiss/jit/ReturnCode.h"
62
63namespace etiss
64{
65namespace mm
66{
67
68MMU::MMU(bool hw_ptw, std::string name, bool pid_enabled)
69 : mmu_enabled_(false)
70 , mmu_control_reg_val_(0)
71 , pid_(0)
72 , name_(name)
73 , pid_enabled_(pid_enabled)
74 , hw_page_table_walker_(hw_ptw)
75{
76 tlb_ = std::shared_ptr<etiss::mm::TLB<0>>(new TLB<0>());
77
79 // REGISTER_PAGE_FAULT_HANDLER(TLBISFULL, tlb_full_handler);
80}
81
82int32_t MMU::Translate(const uint64_t vma, uint64_t *const pma_buf, MM_ACCESS access, uint64_t data)
83{
84
85 if (!mmu_enabled_)
86 {
87 *pma_buf = vma;
88 return NOERROR;
89 }
90
91 if (!this->CheckPrivilegedMode())
92 {
93 *pma_buf = vma;
94 return NOERROR;
95 }
96
97 if (PTEFormat::Instance().GetFormatMap().find(std::string("PPN")) == PTEFormat::Instance().GetFormatMap().end())
98 etiss::log(etiss::FATALERROR, "PPN not defined in PTE format");
99
100 if (PTEFormat::Instance().GetFormatMap().find(std::string("PAGEOFFSET")) ==
101 PTEFormat::Instance().GetFormatMap().end())
102 etiss::log(etiss::FATALERROR, "Page size offset not defined in PTE format");
103
104 std::pair<uint32_t, uint32_t> page_offset_bitfield =
105 PTEFormat::Instance().GetFormatMap().find(std::string("PAGEOFFSET"))->second;
106
107 std::pair<uint32_t, uint32_t> ppn_bitfield = PTEFormat::Instance().GetFormatMap().find(std::string("PPN"))->second;
108
109 uint32_t page_offset_msb_pos = page_offset_bitfield.first;
110
111 uint32_t ppn_msb_pos = ppn_bitfield.first;
112
113 // Add PID as part of TLB tag to reduce flush possibility.
114 uint64_t vpn = vma >> (page_offset_msb_pos + 1);
115
116 if (pid_enabled_)
117 {
118 vpn |= pid_ << (ppn_msb_pos + 1);
119 }
120
121 PTE pte_buf = PTE(0);
122 int32_t fault = tlb_->Lookup(vpn, &pte_buf);
123 if (fault)
124 {
125 if ((fault = HANDLE_PAGE_FAULT(fault, this, vma, access)))
126 return fault;
127 if ((fault = tlb_->Lookup(vpn, &pte_buf)))
128 {
129 Dump();
130 etiss::log(etiss::FATALERROR, "TLB MISS is not correctly handled");
131 }
132 }
133
134 if ((fault = CheckProtection(pte_buf, access)))
135 return fault;
136
137 uint64_t offset_mask = (1 << (page_offset_msb_pos + 1)) - 1;
138 *pma_buf = (pte_buf.GetPPN() << (page_offset_msb_pos + 1)) | (vma & offset_mask);
139
140 UpdatePTEFlags(pte_buf, access);
141
142 // Check whether vma is trying to write the data cached in TLB, if so
143 // evict the PTE entry in the TLB
144 if (W_ACCESS == access)
145 {
146 std::map<uint64_t, PTE *>::iterator itr = tlb_entry_map_.find(*pma_buf);
147 if (itr != tlb_entry_map_.end())
148 tlb_entry_map_.erase(itr);
149 }
150
151 return NOERROR;
152}
153
154int32_t MMU::AddTLBEntry(const uint64_t vpn, const PTE &pte)
155{
156 uint32_t fault = tlb_->AddPTE(vpn, pte);
157 if (fault)
158 {
159 if ((fault = HANDLE_PAGE_FAULT(fault, this, 0, R_ACCESS)))
160 return fault;
161 tlb_->AddPTE(vpn, pte);
162 }
163 return NOERROR;
164}
165
166void MMU::SignalMMU(uint64_t control_reg_val_)
167{
168 if (0 == control_reg_val_)
169 mmu_enabled_ = false;
170 else if (control_reg_val_ && (!mmu_enabled_))
171 {
172 mmu_enabled_ = true;
173 etiss::log(etiss::VERBOSE, GetName() + " : MMU is enabled.");
174 }
175 if (control_reg_val_ != mmu_control_reg_val_)
176 {
177 cache_flush_pending = true;
178 tlb_->Flush();
179 tlb_entry_map_.clear();
180 etiss::log(etiss::VERBOSE, GetName() + " : TLB flushed due to page directory update.");
181 mmu_control_reg_val_ = control_reg_val_;
182 if (pid_enabled_)
183 UpdatePid(GetPid(control_reg_val_));
184 }
185 else
186 etiss::log(etiss::WARNING, "Redundant MMU control register write");
187}
188
190{
191 using std::cout;
192 using std::endl;
193 cout << "------------MMU Details-----------" << endl;
194 cout << "MMU name : " << name_ << endl;
195 cout << "MMU enabled: " << std::boolalpha << mmu_enabled_ << endl;
196 cout << "PID enabled: " << std::boolalpha << pid_enabled_ << endl;
197 if (pid_enabled_)
198 cout << "Current PID : 0x" << std::hex << pid_ << endl;
199 cout << "Current control register value : 0x" << std::hex << mmu_control_reg_val_ << endl;
200
201 tlb_->Dump();
202}
203
205{
206 cpu_ = cpu;
207 system_ = system;
209 // Page table walker probe
211 etiss::log(etiss::FATALERROR, "No hardware page table walker, software page table walker is required ");
212}
213
214void MMU::AddTLBEntryMap(uint64_t phy_addr_, PTE &pte)
215{
216 if (tlb_entry_map_.find(phy_addr_) != tlb_entry_map_.end())
218 tlb_entry_map_[phy_addr_] = &pte;
219}
220
221int32_t tlb_miss_handler(int32_t fault, MMU *mmu, uint64_t vma, MM_ACCESS access)
222{
223 if (mmu->HasPageTableWalker())
224 {
225 int32_t handled_fault = NOERROR;
226 if ((handled_fault = mmu->WalkPageTable(vma, access)))
227 return handled_fault;
228 return NOERROR;
229 }
230
231 switch (access)
232 {
233 case R_ACCESS:
234 return etiss::RETURNCODE::LOAD_PAGEFAULT;
235 case W_ACCESS:
236 return etiss::RETURNCODE::STORE_PAGEFAULT;
237 case X_ACCESS:
238 return etiss::RETURNCODE::INSTR_PAGEFAULT;
239 default:
240 abort();
241 }
242}
243
244void DUMP_MMU(MMU *mmu)
245{
246 mmu->Dump();
247}
248
249} // namespace mm
250} // namespace etiss
251
252using namespace etiss;
253
254extern "C"
255{
257 {
258 CPUCore *core = (CPUCore *)cpu->_etiss_private_handle_;
259 if (!core)
260 {
261 etiss::log(etiss::ERROR, "CPUArchRegListenerInterface::signalChangedRegisterValue() called from outside "
262 "etiss::CPUCore::execute(). this should not happen and indicates a faultiy "
263 "CPUArch (or Plugin) implementation. This function may have been called "
264 "indirectly from ETISS_signalChangedRegisterValue()");
265 return;
266 }
267 auto mmu = core->getMMU();
268 if (mmu)
269 mmu->SignalMMU(mmu_signal_);
270 }
271}
defines main cpu core interface
void ETISS_SIGNAL_MMU(ETISS_CPU *cpu, etiss_uint64 mmu_signal_)
Definition MMU.cpp:256
Modeling hardware memory management for virtual memory -> physical memory translation and protection.
#define DEFAULT_PAGE_TABLE_WALKER
Definition MMU.h:78
#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:96
CPUCore is responsible for the simulation of a CPU core in ETISS.
Definition CPUCore.h:113
virtual std::shared_ptr< etiss::mm::MMU > getMMU()
Get the Memory Management Unit(MMU) of this CPUCore instance.
Definition CPUCore.h:181
int32_t AddTLBEntry(const uint64_t vfn, const PTE &pte)
Definition MMU.cpp:154
virtual int32_t GetPid(uint64_t control_reg_val_)
Definition MMU.h:175
virtual bool CheckPrivilegedMode()=0
MMU is enabled in certain mode.
std::string GetName() const
Definition MMU.h:173
bool mmu_enabled_
Definition MMU.h:182
MMU(bool hw_ptw, std::string name, bool pid_enabled)
MMU ctor.
Definition MMU.cpp:68
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:147
const bool hw_page_table_walker_
Definition MMU.h:198
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:166
uint32_t pid_
Definition MMU.h:194
void UpdatePid(uint32_t new_pid)
Definition MMU.h:163
bool cache_flush_pending
Definition MMU.h:177
std::shared_ptr< etiss::mm::TLB< 0 > > tlb_
Definition MMU.h:186
const bool pid_enabled_
Definition MMU.h:197
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:153
ETISS_System * system_
Definition MMU.h:181
void AddTLBEntryMap(uint64_t phy_addr_, PTE &pte)
Keep a record of mapping between cached PTE with its physical address.
Definition MMU.cpp:214
uint64_t mmu_control_reg_val_
Definition MMU.h:193
bool HasPageTableWalker()
Definition MMU.h:159
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:82
std::string name_
Definition MMU.h:195
void Init(ETISS_CPU *cpu, ETISS_System *system)
Initialize the MMU, when DMMUWrapper is wrapping the MMU.
Definition MMU.cpp:204
void Dump()
Dump the details of the MMU, when page fault cannot be handled.
Definition MMU.cpp:189
std::map< uint64_t, PTE * > tlb_entry_map_
Definition MMU.h:191
ETISS_CPU * cpu_
Definition MMU.h:180
static PTEFormat & Instance()
Get the singleton instance.
Definition PTEFormat.h:70
PTEFormatMap & GetFormatMap()
Definition PTEFormat.h:95
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition PTE.h:69
uint64_t GetPPN() const
Definition PTE.h:119
void DUMP_MMU(MMU *mmu)
Definition MMU.cpp:244
int32_t tlb_miss_handler(int32_t fault, MMU *mmu, uint64_t vma, MM_ACCESS access)
Definition MMU.cpp:221
MM_EXPORT const int32_t TLBMISS
MM_EXPORT const int32_t NOERROR
MM_EXPORT const int32_t PTEOVERLAP
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition Benchmark.h:53
@ VERBOSE
Definition Misc.h:130
@ WARNING
Definition Misc.h:128
@ ERROR
Definition Misc.h:127
@ FATALERROR
Definition Misc.h:126
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:125
#define false
Definition stdbool.h:17
basic cpu state structure needed for execution of any cpu architecture.
Definition CPU.h:89
void * _etiss_private_handle_
private helper handle for plugins
Definition CPU.h:107
memory access and time synchronization functions.
Definition System.h:78