arch-power: Refactor process initialization
[gem5.git] / src / mem / page_table.cc
1 /*
2 * Copyright (c) 2014 Advanced Micro Devices, Inc.
3 * Copyright (c) 2003 The Regents of The University of Michigan
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /**
31 * @file
32 * Definitions of functional page table.
33 */
34 #include "mem/page_table.hh"
35
36 #include <string>
37
38 #include "base/compiler.hh"
39 #include "base/trace.hh"
40 #include "debug/MMU.hh"
41 #include "sim/faults.hh"
42 #include "sim/serialize.hh"
43
44 void
45 EmulationPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
46 {
47 bool clobber = flags & Clobber;
48 // starting address must be page aligned
49 assert(pageOffset(vaddr) == 0);
50
51 DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr + size);
52
53 while (size > 0) {
54 auto it = pTable.find(vaddr);
55 if (it != pTable.end()) {
56 // already mapped
57 panic_if(!clobber,
58 "EmulationPageTable::allocate: addr %#x already mapped",
59 vaddr);
60 it->second = Entry(paddr, flags);
61 } else {
62 pTable.emplace(vaddr, Entry(paddr, flags));
63 }
64
65 size -= _pageSize;
66 vaddr += _pageSize;
67 paddr += _pageSize;
68 }
69 }
70
71 void
72 EmulationPageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
73 {
74 assert(pageOffset(vaddr) == 0);
75 assert(pageOffset(new_vaddr) == 0);
76
77 DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
78 new_vaddr, size);
79
80 while (size > 0) {
81 M5_VAR_USED auto new_it = pTable.find(new_vaddr);
82 auto old_it = pTable.find(vaddr);
83 assert(old_it != pTable.end() && new_it == pTable.end());
84
85 pTable.emplace(new_vaddr, old_it->second);
86 pTable.erase(old_it);
87 size -= _pageSize;
88 vaddr += _pageSize;
89 new_vaddr += _pageSize;
90 }
91 }
92
93 void
94 EmulationPageTable::getMappings(std::vector<std::pair<Addr, Addr>> *addr_maps)
95 {
96 for (auto &iter : pTable)
97 addr_maps->push_back(std::make_pair(iter.first, iter.second.paddr));
98 }
99
100 void
101 EmulationPageTable::unmap(Addr vaddr, int64_t size)
102 {
103 assert(pageOffset(vaddr) == 0);
104
105 DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr + size);
106
107 while (size > 0) {
108 auto it = pTable.find(vaddr);
109 assert(it != pTable.end());
110 pTable.erase(it);
111 size -= _pageSize;
112 vaddr += _pageSize;
113 }
114 }
115
116 bool
117 EmulationPageTable::isUnmapped(Addr vaddr, int64_t size)
118 {
119 // starting address must be page aligned
120 assert(pageOffset(vaddr) == 0);
121
122 for (int64_t offset = 0; offset < size; offset += _pageSize)
123 if (pTable.find(vaddr + offset) != pTable.end())
124 return false;
125
126 return true;
127 }
128
129 const EmulationPageTable::Entry *
130 EmulationPageTable::lookup(Addr vaddr)
131 {
132 Addr page_addr = pageAlign(vaddr);
133 PTableItr iter = pTable.find(page_addr);
134 if (iter == pTable.end())
135 return nullptr;
136 return &(iter->second);
137 }
138
139 bool
140 EmulationPageTable::translate(Addr vaddr, Addr &paddr)
141 {
142 const Entry *entry = lookup(vaddr);
143 if (!entry) {
144 DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr);
145 return false;
146 }
147 paddr = pageOffset(vaddr) + entry->paddr;
148 DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr);
149 return true;
150 }
151
152 Fault
153 EmulationPageTable::translate(const RequestPtr &req)
154 {
155 Addr paddr;
156 assert(pageAlign(req->getVaddr() + req->getSize() - 1) ==
157 pageAlign(req->getVaddr()));
158 if (!translate(req->getVaddr(), paddr))
159 return Fault(new GenericPageTableFault(req->getVaddr()));
160 req->setPaddr(paddr);
161 if ((paddr & (_pageSize - 1)) + req->getSize() > _pageSize) {
162 panic("Request spans page boundaries!\n");
163 return NoFault;
164 }
165 return NoFault;
166 }
167
168 void
169 EmulationPageTable::serialize(CheckpointOut &cp) const
170 {
171 ScopedCheckpointSection sec(cp, "ptable");
172 paramOut(cp, "size", pTable.size());
173
174 PTable::size_type count = 0;
175 for (auto &pte : pTable) {
176 ScopedCheckpointSection sec(cp, csprintf("Entry%d", count++));
177
178 paramOut(cp, "vaddr", pte.first);
179 paramOut(cp, "paddr", pte.second.paddr);
180 paramOut(cp, "flags", pte.second.flags);
181 }
182 assert(count == pTable.size());
183 }
184
185 void
186 EmulationPageTable::unserialize(CheckpointIn &cp)
187 {
188 int count;
189 ScopedCheckpointSection sec(cp, "ptable");
190 paramIn(cp, "size", count);
191
192 for (int i = 0; i < count; ++i) {
193 ScopedCheckpointSection sec(cp, csprintf("Entry%d", i));
194
195 Addr vaddr;
196 UNSERIALIZE_SCALAR(vaddr);
197 Addr paddr;
198 uint64_t flags;
199 UNSERIALIZE_SCALAR(paddr);
200 UNSERIALIZE_SCALAR(flags);
201
202 pTable.emplace(vaddr, Entry(paddr, flags));
203 }
204 }
205