gem5  v22.1.0.0
multi_level_page_table.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
34 #ifndef __MEM_MULTI_LEVEL_PAGE_TABLE_HH__
35 #define __MEM_MULTI_LEVEL_PAGE_TABLE_HH__
36 
37 #include <string>
38 
39 #include "base/types.hh"
40 #include "debug/MMU.hh"
41 #include "mem/page_table.hh"
42 #include "sim/se_workload.hh"
43 #include "sim/system.hh"
44 
45 namespace gem5
46 {
47 
104 namespace {
105 
106 template <class First, class ...Rest>
107 Addr
108 prepTopTable(System *system, Addr pageSize)
109 {
110  auto *se_workload = dynamic_cast<SEWorkload *>(system->workload);
111  fatal_if(!se_workload, "Couldn't find an appropriate workload object.");
112  Addr addr = se_workload->allocPhysPages(First::tableSize());
113  PortProxy &p = system->physProxy;
114  p.memsetBlob(addr, 0, First::tableSize() * pageSize);
115  return addr;
116 }
117 
118 template <class ...Types>
119 struct LastType;
120 
121 template <class First, class Second, class ...Rest>
122 struct LastType<First, Second, Rest...>
123 {
124  typedef typename LastType<Second, Rest...>::type type;
125 };
126 
127 template <class Only>
128 struct LastType<Only>
129 {
130  typedef Only type;
131 };
132 
133 
134 template <class ...Types>
135 struct WalkWrapper;
136 
137 template <class Final, class Only>
138 struct WalkWrapper<Final, Only>
139 {
140  static void
141  walk(System *system, Addr pageSize, Addr table, Addr vaddr,
142  bool allocate, Final *entry)
143  {
144  entry->read(system->physProxy, table, vaddr);
145  }
146 };
147 
148 template <class Final, class First, class Second, class ...Rest>
149 struct WalkWrapper<Final, First, Second, Rest...>
150 {
151  static void
152  walk(System *system, Addr pageSize, Addr table, Addr vaddr,
153  bool allocate, Final *entry)
154  {
155  First first;
156  first.read(system->physProxy, table, vaddr);
157 
158  Addr next;
159  if (!first.present()) {
160  fatal_if(!allocate,
161  "Page fault while walking the page table.");
162  next = prepTopTable<Second>(system, pageSize);
163  first.reset(next);
164  first.write(system->physProxy);
165  } else {
166  next = first.paddr();
167  }
168  WalkWrapper<Final, Second, Rest...>::walk(
169  system, pageSize, next, vaddr, allocate, entry);
170  }
171 };
172 
173 template <class ...EntryTypes>
174 void
175 walk(System *system, Addr pageSize, Addr table, Addr vaddr,
176  bool allocate, typename LastType<EntryTypes...>::type *entry)
177 {
178  WalkWrapper<typename LastType<EntryTypes...>::type, EntryTypes...>::walk(
179  system, pageSize, table, vaddr, allocate, entry);
180 }
181 
182 }
183 
184 
185 template <class ...EntryTypes>
187 {
188  typedef typename LastType<EntryTypes...>::type Final;
189 
194 
199 
200 public:
201  MultiLevelPageTable(const std::string &__name, uint64_t _pid,
202  System *_sys, Addr _pageSize) :
203  EmulationPageTable(__name, _pid, _pageSize), system(_sys)
204  {}
205 
207 
208  void
209  initState() override
210  {
211  if (shared)
212  return;
213 
214  _basePtr = prepTopTable<EntryTypes...>(system, _pageSize);
215  }
216 
217  Addr basePtr() { return _basePtr; }
218 
219  void
220  map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags = 0) override
221  {
222  EmulationPageTable::map(vaddr, paddr, size, flags);
223 
224  Final entry;
225 
226  for (int64_t offset = 0; offset < size; offset += _pageSize) {
227  walk<EntryTypes...>(system, _pageSize, _basePtr,
228  vaddr + offset, true, &entry);
229 
230  entry.reset(paddr + offset, true, flags & Uncacheable,
231  flags & ReadOnly);
232  entry.write(system->physProxy);
233 
234  DPRINTF(MMU, "New mapping: %#x-%#x\n",
235  vaddr + offset, paddr + offset);
236  }
237  }
238 
239  void
240  remap(Addr vaddr, int64_t size, Addr new_vaddr) override
241  {
242  EmulationPageTable::remap(vaddr, size, new_vaddr);
243 
244  Final old_entry, new_entry;
245 
246  for (int64_t offset = 0; offset < size; offset += _pageSize) {
247  // Unmap the original mapping.
248  walk<EntryTypes...>(system, _pageSize, _basePtr, vaddr + offset,
249  false, &old_entry);
250  old_entry.present(false);
251  old_entry.write(system->physProxy);
252 
253  // Map the new one.
254  walk<EntryTypes...>(system, _pageSize, _basePtr,
255  new_vaddr + offset, true, &new_entry);
256  new_entry.reset(old_entry.paddr(), true, old_entry.uncacheable(),
257  old_entry.readonly());
258  new_entry.write(system->physProxy);
259  }
260  }
261 
262  void
263  unmap(Addr vaddr, int64_t size) override
264  {
266 
267  Final entry;
268 
269  for (int64_t offset = 0; offset < size; offset += _pageSize) {
270  walk<EntryTypes...>(system, _pageSize, _basePtr,
271  vaddr + offset, false, &entry);
272  fatal_if(!entry.present(),
273  "PageTable::unmap: Address %#x not mapped.", vaddr);
274  entry.present(false);
275  entry.write(system->physProxy);
276  DPRINTF(MMU, "Unmapping: %#x\n", vaddr);
277  }
278  }
279 
280  void
281  serialize(CheckpointOut &cp) const override
282  {
288  paramOut(cp, "ptable.pointer", _basePtr);
289  }
290 
291  void
292  unserialize(CheckpointIn &cp) override
293  {
295  paramIn(cp, "ptable.pointer", _basePtr);
296  }
297 };
298 
299 } // namespace gem5
300 
301 #endif // __MEM_MULTI_LEVEL_PAGE_TABLE_HH__
#define DPRINTF(x,...)
Definition: trace.hh:186
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
virtual void map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags=0)
Maps a virtual memory region to a physical memory region.
Definition: page_table.cc:48
virtual void remap(Addr vaddr, int64_t size, Addr new_vaddr)
Definition: page_table.cc:75
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: page_table.cc:186
const uint64_t _pid
Definition: page_table.hh:73
virtual void unmap(Addr vaddr, int64_t size)
Definition: page_table.cc:104
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: page_table.cc:203
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Addr _basePtr
Physical address to the last level of the page table.
void serialize(CheckpointOut &cp) const override
Serialize an object.
MultiLevelPageTable(const std::string &__name, uint64_t _pid, System *_sys, Addr _pageSize)
LastType< EntryTypes... >::type Final
void unmap(Addr vaddr, int64_t size) override
void remap(Addr vaddr, int64_t size, Addr new_vaddr) override
void map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags=0) override
Maps a virtual memory region to a physical memory region.
System * system
Pointer to System object.
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition: system.hh:326
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
uint8_t flags
Definition: helpers.cc:66
Bitfield< 23, 0 > offset
Definition: types.hh:144
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 15 > system
Definition: misc.hh:1004
Bitfield< 3 > addr
Definition: types.hh:84
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::ostream CheckpointOut
Definition: serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
Declarations of a non-full system Page Table.

Generated on Wed Dec 21 2022 10:22:37 for gem5 by doxygen 1.9.1