tlb.cc (5237:6c819dbe8045) tlb.cc (5242:280a99136427)
1/*
2 * Copyright (c) 2007 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * Redistribution and use of this software in source and binary forms,
6 * with or without modification, are permitted provided that the
7 * following conditions are met:
8 *
9 * The software must be used only for Non-Commercial Use which means any
10 * use which is NOT directed to receiving any direct monetary
11 * compensation for, or commercial advantage from such use. Illustrative
12 * examples of non-commercial use are academic research, personal study,
13 * teaching, education and corporate research & development.
14 * Illustrative examples of commercial use are distributing products for
15 * commercial advantage and providing services using the software for
16 * commercial advantage.
17 *
18 * If you wish to use this software or functionality therein that may be
19 * covered by patents for commercial use, please contact:
20 * Director of Intellectual Property Licensing
21 * Office of Strategy and Technology
22 * Hewlett-Packard Company
23 * 1501 Page Mill Road
24 * Palo Alto, California 94304
25 *
26 * Redistributions of source code must retain the above copyright notice,
27 * this list of conditions and the following disclaimer. Redistributions
28 * in binary form must reproduce the above copyright notice, this list of
29 * conditions and the following disclaimer in the documentation and/or
30 * other materials provided with the distribution. Neither the name of
31 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
32 * contributors may be used to endorse or promote products derived from
33 * this software without specific prior written permission. No right of
34 * sublicense is granted herewith. Derivatives of the software and
35 * output created using the software may be prepared, but only for
36 * Non-Commercial Uses. Derivatives of the software may be shared with
37 * others provided: (i) the others agree to abide by the list of
38 * conditions herein which includes the Non-Commercial Use restrictions;
39 * and (ii) such Derivatives of the software include the above copyright
40 * notice to acknowledge the contribution from this software where
41 * applicable, this list of conditions and the disclaimer below.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
58#include <cstring>
59
60#include "config/full_system.hh"
61
62#include "arch/x86/pagetable.hh"
63#include "arch/x86/tlb.hh"
64#include "arch/x86/x86_traits.hh"
65#include "base/bitfield.hh"
66#include "base/trace.hh"
67#include "config/full_system.hh"
68#include "cpu/thread_context.hh"
69#include "cpu/base.hh"
70#include "mem/packet_access.hh"
71#include "mem/request.hh"
72#include "sim/system.hh"
73
74namespace X86ISA {
75
76#if FULL_SYSTEM
77TLB::TLB(const Params *p) : MemObject(p), walker(name(), this), size(p->size)
78#else
79TLB::TLB(const Params *p) : MemObject(p), size(p->size)
80#endif
81{
82 tlb = new TlbEntry[size];
83 std::memset(tlb, 0, sizeof(TlbEntry) * size);
84
85 for (int x = 0; x < size; x++)
86 freeList.push_back(&tlb[x]);
87}
88
89#if FULL_SYSTEM
90
91// Unfortunately, the placement of the base field in a page table entry is
92// very erratic and would make a mess here. It might be moved here at some
93// point in the future.
94BitUnion64(PageTableEntry)
95 Bitfield<63> nx;
96 Bitfield<11, 9> avl;
97 Bitfield<8> g;
98 Bitfield<7> ps;
99 Bitfield<6> d;
100 Bitfield<5> a;
101 Bitfield<4> pcd;
102 Bitfield<3> pwt;
103 Bitfield<2> u;
104 Bitfield<1> w;
105 Bitfield<0> p;
106EndBitUnion(PageTableEntry)
107
108void
109TLB::Walker::doNext(PacketPtr &read, PacketPtr &write)
110{
111 assert(state != Ready && state != Waiting);
112 write = NULL;
113 PageTableEntry pte;
114 if (size == 8)
115 pte = read->get<uint64_t>();
116 else
117 pte = read->get<uint32_t>();
118 VAddr vaddr = entry.vaddr;
119 bool uncacheable = pte.pcd;
120 Addr nextRead = 0;
121 bool doWrite = false;
122 bool badNX = pte.nx && (!tlb->allowNX || !enableNX);
123 switch(state) {
124 case LongPML4:
125 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl3 * size;
126 doWrite = !pte.a;
127 pte.a = 1;
128 entry.writable = pte.w;
129 entry.user = pte.u;
130 if (badNX)
131 panic("NX violation!\n");
132 entry.noExec = pte.nx;
133 if (!pte.p)
134 panic("Page not present!\n");
135 nextState = LongPDP;
136 break;
137 case LongPDP:
138 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl2 * size;
139 doWrite = !pte.a;
140 pte.a = 1;
141 entry.writable = entry.writable && pte.w;
142 entry.user = entry.user && pte.u;
143 if (badNX)
144 panic("NX violation!\n");
145 if (!pte.p)
146 panic("Page not present!\n");
147 nextState = LongPD;
148 break;
149 case LongPD:
150 doWrite = !pte.a;
151 pte.a = 1;
152 entry.writable = entry.writable && pte.w;
153 entry.user = entry.user && pte.u;
154 if (badNX)
155 panic("NX violation!\n");
156 if (!pte.p)
157 panic("Page not present!\n");
158 if (!pte.ps) {
159 // 4 KB page
160 entry.size = 4 * (1 << 10);
161 nextRead =
162 ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl1 * size;
163 nextState = LongPTE;
164 break;
165 } else {
166 // 2 MB page
167 entry.size = 2 * (1 << 20);
168 entry.paddr = (uint64_t)pte & (mask(31) << 21);
169 entry.uncacheable = uncacheable;
170 entry.global = pte.g;
171 entry.patBit = bits(pte, 12);
172 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
173 tlb->insert(entry.vaddr, entry);
174 nextState = Ready;
175 delete read->req;
176 delete read;
177 read = NULL;
178 return;
179 }
180 case LongPTE:
181 doWrite = !pte.a;
182 pte.a = 1;
183 entry.writable = entry.writable && pte.w;
184 entry.user = entry.user && pte.u;
185 if (badNX)
186 panic("NX violation!\n");
187 if (!pte.p)
188 panic("Page not present!\n");
189 entry.paddr = (uint64_t)pte & (mask(40) << 12);
190 entry.uncacheable = uncacheable;
191 entry.global = pte.g;
192 entry.patBit = bits(pte, 12);
193 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
194 tlb->insert(entry.vaddr, entry);
195 nextState = Ready;
196 delete read->req;
197 delete read;
198 read = NULL;
199 return;
200 case PAEPDP:
201 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size;
202 if (!pte.p)
203 panic("Page not present!\n");
204 nextState = PAEPD;
205 break;
206 case PAEPD:
207 doWrite = !pte.a;
208 pte.a = 1;
209 entry.writable = pte.w;
210 entry.user = pte.u;
211 if (badNX)
212 panic("NX violation!\n");
213 if (!pte.p)
214 panic("Page not present!\n");
215 if (!pte.ps) {
216 // 4 KB page
217 entry.size = 4 * (1 << 10);
218 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael1 * size;
219 nextState = PAEPTE;
220 break;
221 } else {
222 // 2 MB page
223 entry.size = 2 * (1 << 20);
224 entry.paddr = (uint64_t)pte & (mask(31) << 21);
225 entry.uncacheable = uncacheable;
226 entry.global = pte.g;
227 entry.patBit = bits(pte, 12);
228 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
229 tlb->insert(entry.vaddr, entry);
230 nextState = Ready;
231 delete read->req;
232 delete read;
233 read = NULL;
234 return;
235 }
236 case PAEPTE:
237 doWrite = !pte.a;
238 pte.a = 1;
239 entry.writable = entry.writable && pte.w;
240 entry.user = entry.user && pte.u;
241 if (badNX)
242 panic("NX violation!\n");
243 if (!pte.p)
244 panic("Page not present!\n");
245 entry.paddr = (uint64_t)pte & (mask(40) << 12);
246 entry.uncacheable = uncacheable;
247 entry.global = pte.g;
248 entry.patBit = bits(pte, 7);
249 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
250 tlb->insert(entry.vaddr, entry);
251 nextState = Ready;
252 delete read->req;
253 delete read;
254 read = NULL;
255 return;
256 case PSEPD:
257 doWrite = !pte.a;
258 pte.a = 1;
259 entry.writable = pte.w;
260 entry.user = pte.u;
261 if (!pte.p)
262 panic("Page not present!\n");
263 if (!pte.ps) {
264 // 4 KB page
265 entry.size = 4 * (1 << 10);
266 nextRead =
267 ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
268 nextState = PTE;
269 break;
270 } else {
271 // 4 MB page
272 entry.size = 4 * (1 << 20);
273 entry.paddr = bits(pte, 20, 13) << 32 | bits(pte, 31, 22) << 22;
274 entry.uncacheable = uncacheable;
275 entry.global = pte.g;
276 entry.patBit = bits(pte, 12);
277 entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1);
278 tlb->insert(entry.vaddr, entry);
279 nextState = Ready;
280 delete read->req;
281 delete read;
282 read = NULL;
283 return;
284 }
285 case PD:
286 doWrite = !pte.a;
287 pte.a = 1;
288 entry.writable = pte.w;
289 entry.user = pte.u;
290 if (!pte.p)
291 panic("Page not present!\n");
292 // 4 KB page
293 entry.size = 4 * (1 << 10);
294 nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
295 nextState = PTE;
296 break;
297 nextState = PTE;
298 break;
299 case PTE:
300 doWrite = !pte.a;
301 pte.a = 1;
302 entry.writable = pte.w;
303 entry.user = pte.u;
304 if (!pte.p)
305 panic("Page not present!\n");
306 entry.paddr = (uint64_t)pte & (mask(20) << 12);
307 entry.uncacheable = uncacheable;
308 entry.global = pte.g;
309 entry.patBit = bits(pte, 7);
310 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
311 tlb->insert(entry.vaddr, entry);
312 nextState = Ready;
313 delete read->req;
314 delete read;
315 read = NULL;
316 return;
317 default:
318 panic("Unknown page table walker state %d!\n");
319 }
320 PacketPtr oldRead = read;
321 //If we didn't return, we're setting up another read.
322 uint32_t flags = oldRead->req->getFlags();
323 if (uncacheable)
324 flags |= UNCACHEABLE;
325 else
326 flags &= ~UNCACHEABLE;
327 RequestPtr request =
328 new Request(nextRead, oldRead->getSize(), flags);
329 read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast);
330 read->allocate();
331 //If we need to write, adjust the read packet to write the modified value
332 //back to memory.
333 if (doWrite) {
334 write = oldRead;
335 write->set<uint64_t>(pte);
336 write->cmd = MemCmd::WriteReq;
337 write->setDest(Packet::Broadcast);
338 } else {
339 write = NULL;
340 delete oldRead->req;
341 delete oldRead;
342 }
343}
344
345void
346TLB::Walker::start(ThreadContext * _tc, Addr vaddr)
347{
348 assert(state == Ready);
349 assert(!tc);
350 tc = _tc;
351
352 VAddr addr = vaddr;
353
354 //Figure out what we're doing.
355 CR3 cr3 = tc->readMiscRegNoEffect(MISCREG_CR3);
356 Addr top = 0;
357 // Check if we're in long mode or not
358 Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
359 size = 8;
360 if (efer.lma) {
361 // Do long mode.
362 state = LongPML4;
363 top = (cr3.longPdtb << 12) + addr.longl4 * size;
364 } else {
365 // We're in some flavor of legacy mode.
366 CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
367 if (cr4.pae) {
368 // Do legacy PAE.
369 state = PAEPDP;
370 top = (cr3.paePdtb << 5) + addr.pael3 * size;
371 } else {
372 size = 4;
373 top = (cr3.pdtb << 12) + addr.norml2 * size;
374 if (cr4.pse) {
375 // Do legacy PSE.
376 state = PSEPD;
377 } else {
378 // Do legacy non PSE.
379 state = PD;
380 }
381 }
382 }
1/*
2 * Copyright (c) 2007 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * Redistribution and use of this software in source and binary forms,
6 * with or without modification, are permitted provided that the
7 * following conditions are met:
8 *
9 * The software must be used only for Non-Commercial Use which means any
10 * use which is NOT directed to receiving any direct monetary
11 * compensation for, or commercial advantage from such use. Illustrative
12 * examples of non-commercial use are academic research, personal study,
13 * teaching, education and corporate research & development.
14 * Illustrative examples of commercial use are distributing products for
15 * commercial advantage and providing services using the software for
16 * commercial advantage.
17 *
18 * If you wish to use this software or functionality therein that may be
19 * covered by patents for commercial use, please contact:
20 * Director of Intellectual Property Licensing
21 * Office of Strategy and Technology
22 * Hewlett-Packard Company
23 * 1501 Page Mill Road
24 * Palo Alto, California 94304
25 *
26 * Redistributions of source code must retain the above copyright notice,
27 * this list of conditions and the following disclaimer. Redistributions
28 * in binary form must reproduce the above copyright notice, this list of
29 * conditions and the following disclaimer in the documentation and/or
30 * other materials provided with the distribution. Neither the name of
31 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
32 * contributors may be used to endorse or promote products derived from
33 * this software without specific prior written permission. No right of
34 * sublicense is granted herewith. Derivatives of the software and
35 * output created using the software may be prepared, but only for
36 * Non-Commercial Uses. Derivatives of the software may be shared with
37 * others provided: (i) the others agree to abide by the list of
38 * conditions herein which includes the Non-Commercial Use restrictions;
39 * and (ii) such Derivatives of the software include the above copyright
40 * notice to acknowledge the contribution from this software where
41 * applicable, this list of conditions and the disclaimer below.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
58#include <cstring>
59
60#include "config/full_system.hh"
61
62#include "arch/x86/pagetable.hh"
63#include "arch/x86/tlb.hh"
64#include "arch/x86/x86_traits.hh"
65#include "base/bitfield.hh"
66#include "base/trace.hh"
67#include "config/full_system.hh"
68#include "cpu/thread_context.hh"
69#include "cpu/base.hh"
70#include "mem/packet_access.hh"
71#include "mem/request.hh"
72#include "sim/system.hh"
73
74namespace X86ISA {
75
76#if FULL_SYSTEM
77TLB::TLB(const Params *p) : MemObject(p), walker(name(), this), size(p->size)
78#else
79TLB::TLB(const Params *p) : MemObject(p), size(p->size)
80#endif
81{
82 tlb = new TlbEntry[size];
83 std::memset(tlb, 0, sizeof(TlbEntry) * size);
84
85 for (int x = 0; x < size; x++)
86 freeList.push_back(&tlb[x]);
87}
88
89#if FULL_SYSTEM
90
91// Unfortunately, the placement of the base field in a page table entry is
92// very erratic and would make a mess here. It might be moved here at some
93// point in the future.
94BitUnion64(PageTableEntry)
95 Bitfield<63> nx;
96 Bitfield<11, 9> avl;
97 Bitfield<8> g;
98 Bitfield<7> ps;
99 Bitfield<6> d;
100 Bitfield<5> a;
101 Bitfield<4> pcd;
102 Bitfield<3> pwt;
103 Bitfield<2> u;
104 Bitfield<1> w;
105 Bitfield<0> p;
106EndBitUnion(PageTableEntry)
107
108void
109TLB::Walker::doNext(PacketPtr &read, PacketPtr &write)
110{
111 assert(state != Ready && state != Waiting);
112 write = NULL;
113 PageTableEntry pte;
114 if (size == 8)
115 pte = read->get<uint64_t>();
116 else
117 pte = read->get<uint32_t>();
118 VAddr vaddr = entry.vaddr;
119 bool uncacheable = pte.pcd;
120 Addr nextRead = 0;
121 bool doWrite = false;
122 bool badNX = pte.nx && (!tlb->allowNX || !enableNX);
123 switch(state) {
124 case LongPML4:
125 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl3 * size;
126 doWrite = !pte.a;
127 pte.a = 1;
128 entry.writable = pte.w;
129 entry.user = pte.u;
130 if (badNX)
131 panic("NX violation!\n");
132 entry.noExec = pte.nx;
133 if (!pte.p)
134 panic("Page not present!\n");
135 nextState = LongPDP;
136 break;
137 case LongPDP:
138 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl2 * size;
139 doWrite = !pte.a;
140 pte.a = 1;
141 entry.writable = entry.writable && pte.w;
142 entry.user = entry.user && pte.u;
143 if (badNX)
144 panic("NX violation!\n");
145 if (!pte.p)
146 panic("Page not present!\n");
147 nextState = LongPD;
148 break;
149 case LongPD:
150 doWrite = !pte.a;
151 pte.a = 1;
152 entry.writable = entry.writable && pte.w;
153 entry.user = entry.user && pte.u;
154 if (badNX)
155 panic("NX violation!\n");
156 if (!pte.p)
157 panic("Page not present!\n");
158 if (!pte.ps) {
159 // 4 KB page
160 entry.size = 4 * (1 << 10);
161 nextRead =
162 ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl1 * size;
163 nextState = LongPTE;
164 break;
165 } else {
166 // 2 MB page
167 entry.size = 2 * (1 << 20);
168 entry.paddr = (uint64_t)pte & (mask(31) << 21);
169 entry.uncacheable = uncacheable;
170 entry.global = pte.g;
171 entry.patBit = bits(pte, 12);
172 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
173 tlb->insert(entry.vaddr, entry);
174 nextState = Ready;
175 delete read->req;
176 delete read;
177 read = NULL;
178 return;
179 }
180 case LongPTE:
181 doWrite = !pte.a;
182 pte.a = 1;
183 entry.writable = entry.writable && pte.w;
184 entry.user = entry.user && pte.u;
185 if (badNX)
186 panic("NX violation!\n");
187 if (!pte.p)
188 panic("Page not present!\n");
189 entry.paddr = (uint64_t)pte & (mask(40) << 12);
190 entry.uncacheable = uncacheable;
191 entry.global = pte.g;
192 entry.patBit = bits(pte, 12);
193 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
194 tlb->insert(entry.vaddr, entry);
195 nextState = Ready;
196 delete read->req;
197 delete read;
198 read = NULL;
199 return;
200 case PAEPDP:
201 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size;
202 if (!pte.p)
203 panic("Page not present!\n");
204 nextState = PAEPD;
205 break;
206 case PAEPD:
207 doWrite = !pte.a;
208 pte.a = 1;
209 entry.writable = pte.w;
210 entry.user = pte.u;
211 if (badNX)
212 panic("NX violation!\n");
213 if (!pte.p)
214 panic("Page not present!\n");
215 if (!pte.ps) {
216 // 4 KB page
217 entry.size = 4 * (1 << 10);
218 nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael1 * size;
219 nextState = PAEPTE;
220 break;
221 } else {
222 // 2 MB page
223 entry.size = 2 * (1 << 20);
224 entry.paddr = (uint64_t)pte & (mask(31) << 21);
225 entry.uncacheable = uncacheable;
226 entry.global = pte.g;
227 entry.patBit = bits(pte, 12);
228 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
229 tlb->insert(entry.vaddr, entry);
230 nextState = Ready;
231 delete read->req;
232 delete read;
233 read = NULL;
234 return;
235 }
236 case PAEPTE:
237 doWrite = !pte.a;
238 pte.a = 1;
239 entry.writable = entry.writable && pte.w;
240 entry.user = entry.user && pte.u;
241 if (badNX)
242 panic("NX violation!\n");
243 if (!pte.p)
244 panic("Page not present!\n");
245 entry.paddr = (uint64_t)pte & (mask(40) << 12);
246 entry.uncacheable = uncacheable;
247 entry.global = pte.g;
248 entry.patBit = bits(pte, 7);
249 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
250 tlb->insert(entry.vaddr, entry);
251 nextState = Ready;
252 delete read->req;
253 delete read;
254 read = NULL;
255 return;
256 case PSEPD:
257 doWrite = !pte.a;
258 pte.a = 1;
259 entry.writable = pte.w;
260 entry.user = pte.u;
261 if (!pte.p)
262 panic("Page not present!\n");
263 if (!pte.ps) {
264 // 4 KB page
265 entry.size = 4 * (1 << 10);
266 nextRead =
267 ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
268 nextState = PTE;
269 break;
270 } else {
271 // 4 MB page
272 entry.size = 4 * (1 << 20);
273 entry.paddr = bits(pte, 20, 13) << 32 | bits(pte, 31, 22) << 22;
274 entry.uncacheable = uncacheable;
275 entry.global = pte.g;
276 entry.patBit = bits(pte, 12);
277 entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1);
278 tlb->insert(entry.vaddr, entry);
279 nextState = Ready;
280 delete read->req;
281 delete read;
282 read = NULL;
283 return;
284 }
285 case PD:
286 doWrite = !pte.a;
287 pte.a = 1;
288 entry.writable = pte.w;
289 entry.user = pte.u;
290 if (!pte.p)
291 panic("Page not present!\n");
292 // 4 KB page
293 entry.size = 4 * (1 << 10);
294 nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
295 nextState = PTE;
296 break;
297 nextState = PTE;
298 break;
299 case PTE:
300 doWrite = !pte.a;
301 pte.a = 1;
302 entry.writable = pte.w;
303 entry.user = pte.u;
304 if (!pte.p)
305 panic("Page not present!\n");
306 entry.paddr = (uint64_t)pte & (mask(20) << 12);
307 entry.uncacheable = uncacheable;
308 entry.global = pte.g;
309 entry.patBit = bits(pte, 7);
310 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
311 tlb->insert(entry.vaddr, entry);
312 nextState = Ready;
313 delete read->req;
314 delete read;
315 read = NULL;
316 return;
317 default:
318 panic("Unknown page table walker state %d!\n");
319 }
320 PacketPtr oldRead = read;
321 //If we didn't return, we're setting up another read.
322 uint32_t flags = oldRead->req->getFlags();
323 if (uncacheable)
324 flags |= UNCACHEABLE;
325 else
326 flags &= ~UNCACHEABLE;
327 RequestPtr request =
328 new Request(nextRead, oldRead->getSize(), flags);
329 read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast);
330 read->allocate();
331 //If we need to write, adjust the read packet to write the modified value
332 //back to memory.
333 if (doWrite) {
334 write = oldRead;
335 write->set<uint64_t>(pte);
336 write->cmd = MemCmd::WriteReq;
337 write->setDest(Packet::Broadcast);
338 } else {
339 write = NULL;
340 delete oldRead->req;
341 delete oldRead;
342 }
343}
344
345void
346TLB::Walker::start(ThreadContext * _tc, Addr vaddr)
347{
348 assert(state == Ready);
349 assert(!tc);
350 tc = _tc;
351
352 VAddr addr = vaddr;
353
354 //Figure out what we're doing.
355 CR3 cr3 = tc->readMiscRegNoEffect(MISCREG_CR3);
356 Addr top = 0;
357 // Check if we're in long mode or not
358 Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
359 size = 8;
360 if (efer.lma) {
361 // Do long mode.
362 state = LongPML4;
363 top = (cr3.longPdtb << 12) + addr.longl4 * size;
364 } else {
365 // We're in some flavor of legacy mode.
366 CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
367 if (cr4.pae) {
368 // Do legacy PAE.
369 state = PAEPDP;
370 top = (cr3.paePdtb << 5) + addr.pael3 * size;
371 } else {
372 size = 4;
373 top = (cr3.pdtb << 12) + addr.norml2 * size;
374 if (cr4.pse) {
375 // Do legacy PSE.
376 state = PSEPD;
377 } else {
378 // Do legacy non PSE.
379 state = PD;
380 }
381 }
382 }
383
383 nextState = Ready;
384 entry.vaddr = vaddr;
385
386 enableNX = efer.nxe;
387
388 RequestPtr request =
389 new Request(top, size, PHYSICAL | cr3.pcd ? UNCACHEABLE : 0);
390 read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast);
391 read->allocate();
392 Enums::MemoryMode memMode = tlb->sys->getMemoryMode();
393 if (memMode == Enums::timing) {
394 tc->suspend();
395 port.sendTiming(read);
396 } else if (memMode == Enums::atomic) {
397 do {
398 port.sendAtomic(read);
399 PacketPtr write = NULL;
400 doNext(read, write);
401 state = nextState;
402 nextState = Ready;
403 if (write)
404 port.sendAtomic(write);
405 } while(read);
406 tc = NULL;
407 state = Ready;
408 nextState = Waiting;
409 } else {
410 panic("Unrecognized memory system mode.\n");
411 }
412}
413
414bool
415TLB::Walker::WalkerPort::recvTiming(PacketPtr pkt)
416{
417 return walker->recvTiming(pkt);
418}
419
420bool
421TLB::Walker::recvTiming(PacketPtr pkt)
422{
423 inflight--;
424 if (pkt->isResponse() && !pkt->wasNacked()) {
425 if (pkt->isRead()) {
426 assert(inflight);
427 assert(state == Waiting);
428 assert(!read);
429 state = nextState;
430 nextState = Ready;
431 PacketPtr write = NULL;
432 doNext(pkt, write);
433 state = Waiting;
434 read = pkt;
435 if (write) {
436 writes.push_back(write);
437 }
438 sendPackets();
439 } else {
440 sendPackets();
441 }
442 if (inflight == 0 && read == NULL && writes.size() == 0) {
443 tc->activate(0);
444 tc = NULL;
445 state = Ready;
446 nextState = Waiting;
447 }
448 } else if (pkt->wasNacked()) {
449 pkt->reinitNacked();
450 if (!port.sendTiming(pkt)) {
451 retrying = true;
452 if (pkt->isWrite()) {
453 writes.push_back(pkt);
454 } else {
455 assert(!read);
456 read = pkt;
457 }
458 } else {
459 inflight++;
460 }
461 }
462 return true;
463}
464
465Tick
466TLB::Walker::WalkerPort::recvAtomic(PacketPtr pkt)
467{
468 return 0;
469}
470
471void
472TLB::Walker::WalkerPort::recvFunctional(PacketPtr pkt)
473{
474 return;
475}
476
477void
478TLB::Walker::WalkerPort::recvStatusChange(Status status)
479{
480 if (status == RangeChange) {
481 if (!snoopRangeSent) {
482 snoopRangeSent = true;
483 sendStatusChange(Port::RangeChange);
484 }
485 return;
486 }
487
488 panic("Unexpected recvStatusChange.\n");
489}
490
491void
492TLB::Walker::WalkerPort::recvRetry()
493{
494 walker->recvRetry();
495}
496
497void
498TLB::Walker::recvRetry()
499{
500 retrying = false;
501 sendPackets();
502}
503
504void
505TLB::Walker::sendPackets()
506{
507 //If we're already waiting for the port to become available, just return.
508 if (retrying)
509 return;
510
511 //Reads always have priority
512 if (read) {
513 if (!port.sendTiming(read)) {
514 retrying = true;
515 return;
516 } else {
517 inflight++;
518 delete read->req;
519 delete read;
520 read = NULL;
521 }
522 }
523 //Send off as many of the writes as we can.
524 while (writes.size()) {
525 PacketPtr write = writes.back();
526 if (!port.sendTiming(write)) {
527 retrying = true;
528 return;
529 } else {
530 inflight++;
531 delete write->req;
532 delete write;
533 writes.pop_back();
534 }
535 }
536}
537
538Port *
539TLB::getPort(const std::string &if_name, int idx)
540{
541 if (if_name == "walker_port")
542 return &walker.port;
543 else
544 panic("No tlb port named %s!\n", if_name);
545}
546
547#else
548
549Port *
550TLB::getPort(const std::string &if_name, int idx)
551{
552 panic("No tlb ports in se!\n", if_name);
553}
554
555#endif
556
557void
558TLB::insert(Addr vpn, TlbEntry &entry)
559{
560 //TODO Deal with conflicting entries
561
562 TlbEntry *newEntry = NULL;
563 if (!freeList.empty()) {
564 newEntry = freeList.front();
565 freeList.pop_front();
566 } else {
567 newEntry = entryList.back();
568 entryList.pop_back();
569 }
570 *newEntry = entry;
571 newEntry->vaddr = vpn;
572 entryList.push_front(newEntry);
573}
574
575TlbEntry *
576TLB::lookup(Addr va, bool update_lru)
577{
578 //TODO make this smarter at some point
579 EntryList::iterator entry;
580 for (entry = entryList.begin(); entry != entryList.end(); entry++) {
581 if ((*entry)->vaddr <= va && (*entry)->vaddr + (*entry)->size > va) {
582 DPRINTF(TLB, "Matched vaddr %#x to entry starting at %#x "
583 "with size %#x.\n", va, (*entry)->vaddr, (*entry)->size);
584 TlbEntry *e = *entry;
585 if (update_lru) {
586 entryList.erase(entry);
587 entryList.push_front(e);
588 }
589 return e;
590 }
591 }
592 return NULL;
593}
594
595void
596TLB::invalidateAll()
597{
384 nextState = Ready;
385 entry.vaddr = vaddr;
386
387 enableNX = efer.nxe;
388
389 RequestPtr request =
390 new Request(top, size, PHYSICAL | cr3.pcd ? UNCACHEABLE : 0);
391 read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast);
392 read->allocate();
393 Enums::MemoryMode memMode = tlb->sys->getMemoryMode();
394 if (memMode == Enums::timing) {
395 tc->suspend();
396 port.sendTiming(read);
397 } else if (memMode == Enums::atomic) {
398 do {
399 port.sendAtomic(read);
400 PacketPtr write = NULL;
401 doNext(read, write);
402 state = nextState;
403 nextState = Ready;
404 if (write)
405 port.sendAtomic(write);
406 } while(read);
407 tc = NULL;
408 state = Ready;
409 nextState = Waiting;
410 } else {
411 panic("Unrecognized memory system mode.\n");
412 }
413}
414
415bool
416TLB::Walker::WalkerPort::recvTiming(PacketPtr pkt)
417{
418 return walker->recvTiming(pkt);
419}
420
421bool
422TLB::Walker::recvTiming(PacketPtr pkt)
423{
424 inflight--;
425 if (pkt->isResponse() && !pkt->wasNacked()) {
426 if (pkt->isRead()) {
427 assert(inflight);
428 assert(state == Waiting);
429 assert(!read);
430 state = nextState;
431 nextState = Ready;
432 PacketPtr write = NULL;
433 doNext(pkt, write);
434 state = Waiting;
435 read = pkt;
436 if (write) {
437 writes.push_back(write);
438 }
439 sendPackets();
440 } else {
441 sendPackets();
442 }
443 if (inflight == 0 && read == NULL && writes.size() == 0) {
444 tc->activate(0);
445 tc = NULL;
446 state = Ready;
447 nextState = Waiting;
448 }
449 } else if (pkt->wasNacked()) {
450 pkt->reinitNacked();
451 if (!port.sendTiming(pkt)) {
452 retrying = true;
453 if (pkt->isWrite()) {
454 writes.push_back(pkt);
455 } else {
456 assert(!read);
457 read = pkt;
458 }
459 } else {
460 inflight++;
461 }
462 }
463 return true;
464}
465
466Tick
467TLB::Walker::WalkerPort::recvAtomic(PacketPtr pkt)
468{
469 return 0;
470}
471
472void
473TLB::Walker::WalkerPort::recvFunctional(PacketPtr pkt)
474{
475 return;
476}
477
478void
479TLB::Walker::WalkerPort::recvStatusChange(Status status)
480{
481 if (status == RangeChange) {
482 if (!snoopRangeSent) {
483 snoopRangeSent = true;
484 sendStatusChange(Port::RangeChange);
485 }
486 return;
487 }
488
489 panic("Unexpected recvStatusChange.\n");
490}
491
492void
493TLB::Walker::WalkerPort::recvRetry()
494{
495 walker->recvRetry();
496}
497
498void
499TLB::Walker::recvRetry()
500{
501 retrying = false;
502 sendPackets();
503}
504
505void
506TLB::Walker::sendPackets()
507{
508 //If we're already waiting for the port to become available, just return.
509 if (retrying)
510 return;
511
512 //Reads always have priority
513 if (read) {
514 if (!port.sendTiming(read)) {
515 retrying = true;
516 return;
517 } else {
518 inflight++;
519 delete read->req;
520 delete read;
521 read = NULL;
522 }
523 }
524 //Send off as many of the writes as we can.
525 while (writes.size()) {
526 PacketPtr write = writes.back();
527 if (!port.sendTiming(write)) {
528 retrying = true;
529 return;
530 } else {
531 inflight++;
532 delete write->req;
533 delete write;
534 writes.pop_back();
535 }
536 }
537}
538
539Port *
540TLB::getPort(const std::string &if_name, int idx)
541{
542 if (if_name == "walker_port")
543 return &walker.port;
544 else
545 panic("No tlb port named %s!\n", if_name);
546}
547
548#else
549
550Port *
551TLB::getPort(const std::string &if_name, int idx)
552{
553 panic("No tlb ports in se!\n", if_name);
554}
555
556#endif
557
558void
559TLB::insert(Addr vpn, TlbEntry &entry)
560{
561 //TODO Deal with conflicting entries
562
563 TlbEntry *newEntry = NULL;
564 if (!freeList.empty()) {
565 newEntry = freeList.front();
566 freeList.pop_front();
567 } else {
568 newEntry = entryList.back();
569 entryList.pop_back();
570 }
571 *newEntry = entry;
572 newEntry->vaddr = vpn;
573 entryList.push_front(newEntry);
574}
575
576TlbEntry *
577TLB::lookup(Addr va, bool update_lru)
578{
579 //TODO make this smarter at some point
580 EntryList::iterator entry;
581 for (entry = entryList.begin(); entry != entryList.end(); entry++) {
582 if ((*entry)->vaddr <= va && (*entry)->vaddr + (*entry)->size > va) {
583 DPRINTF(TLB, "Matched vaddr %#x to entry starting at %#x "
584 "with size %#x.\n", va, (*entry)->vaddr, (*entry)->size);
585 TlbEntry *e = *entry;
586 if (update_lru) {
587 entryList.erase(entry);
588 entryList.push_front(e);
589 }
590 return e;
591 }
592 }
593 return NULL;
594}
595
596void
597TLB::invalidateAll()
598{
599 DPRINTF(TLB, "Invalidating all entries.\n");
600 while (!entryList.empty()) {
601 TlbEntry *entry = entryList.front();
602 entryList.pop_front();
603 freeList.push_back(entry);
604 }
598}
599
600void
601TLB::invalidateNonGlobal()
602{
605}
606
607void
608TLB::invalidateNonGlobal()
609{
610 DPRINTF(TLB, "Invalidating all non global entries.\n");
611 EntryList::iterator entryIt;
612 for (entryIt = entryList.begin(); entryIt != entryList.end();) {
613 if (!(*entryIt)->global) {
614 freeList.push_back(*entryIt);
615 entryList.erase(entryIt++);
616 } else {
617 entryIt++;
618 }
619 }
603}
604
605void
606TLB::demapPage(Addr va)
607{
608}
609
610template<class TlbFault>
611Fault
612TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
613{
614 Addr vaddr = req->getVaddr();
615 DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
616 uint32_t flags = req->getFlags();
617 bool storeCheck = flags & StoreCheck;
618
619 int seg = flags & mask(3);
620
621 //XXX Junk code to surpress the warning
622 if (storeCheck);
623
624 // If this is true, we're dealing with a request to read an internal
625 // value.
626 if (seg == SEGMENT_REG_INT) {
627 Addr prefix = vaddr & IntAddrPrefixMask;
628 if (prefix == IntAddrPrefixCPUID) {
629 panic("CPUID memory space not yet implemented!\n");
630 } else if (prefix == IntAddrPrefixMSR) {
631 req->setMmapedIpr(true);
632 Addr regNum = 0;
633 switch (vaddr & ~IntAddrPrefixMask) {
634 case 0x10:
635 regNum = MISCREG_TSC;
636 break;
637 case 0xFE:
638 regNum = MISCREG_MTRRCAP;
639 break;
640 case 0x174:
641 regNum = MISCREG_SYSENTER_CS;
642 break;
643 case 0x175:
644 regNum = MISCREG_SYSENTER_ESP;
645 break;
646 case 0x176:
647 regNum = MISCREG_SYSENTER_EIP;
648 break;
649 case 0x179:
650 regNum = MISCREG_MCG_CAP;
651 break;
652 case 0x17A:
653 regNum = MISCREG_MCG_STATUS;
654 break;
655 case 0x17B:
656 regNum = MISCREG_MCG_CTL;
657 break;
658 case 0x1D9:
659 regNum = MISCREG_DEBUG_CTL_MSR;
660 break;
661 case 0x1DB:
662 regNum = MISCREG_LAST_BRANCH_FROM_IP;
663 break;
664 case 0x1DC:
665 regNum = MISCREG_LAST_BRANCH_TO_IP;
666 break;
667 case 0x1DD:
668 regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
669 break;
670 case 0x1DE:
671 regNum = MISCREG_LAST_EXCEPTION_TO_IP;
672 break;
673 case 0x200:
674 regNum = MISCREG_MTRR_PHYS_BASE_0;
675 break;
676 case 0x201:
677 regNum = MISCREG_MTRR_PHYS_MASK_0;
678 break;
679 case 0x202:
680 regNum = MISCREG_MTRR_PHYS_BASE_1;
681 break;
682 case 0x203:
683 regNum = MISCREG_MTRR_PHYS_MASK_1;
684 break;
685 case 0x204:
686 regNum = MISCREG_MTRR_PHYS_BASE_2;
687 break;
688 case 0x205:
689 regNum = MISCREG_MTRR_PHYS_MASK_2;
690 break;
691 case 0x206:
692 regNum = MISCREG_MTRR_PHYS_BASE_3;
693 break;
694 case 0x207:
695 regNum = MISCREG_MTRR_PHYS_MASK_3;
696 break;
697 case 0x208:
698 regNum = MISCREG_MTRR_PHYS_BASE_4;
699 break;
700 case 0x209:
701 regNum = MISCREG_MTRR_PHYS_MASK_4;
702 break;
703 case 0x20A:
704 regNum = MISCREG_MTRR_PHYS_BASE_5;
705 break;
706 case 0x20B:
707 regNum = MISCREG_MTRR_PHYS_MASK_5;
708 break;
709 case 0x20C:
710 regNum = MISCREG_MTRR_PHYS_BASE_6;
711 break;
712 case 0x20D:
713 regNum = MISCREG_MTRR_PHYS_MASK_6;
714 break;
715 case 0x20E:
716 regNum = MISCREG_MTRR_PHYS_BASE_7;
717 break;
718 case 0x20F:
719 regNum = MISCREG_MTRR_PHYS_MASK_7;
720 break;
721 case 0x250:
722 regNum = MISCREG_MTRR_FIX_64K_00000;
723 break;
724 case 0x258:
725 regNum = MISCREG_MTRR_FIX_16K_80000;
726 break;
727 case 0x259:
728 regNum = MISCREG_MTRR_FIX_16K_A0000;
729 break;
730 case 0x268:
731 regNum = MISCREG_MTRR_FIX_4K_C0000;
732 break;
733 case 0x269:
734 regNum = MISCREG_MTRR_FIX_4K_C8000;
735 break;
736 case 0x26A:
737 regNum = MISCREG_MTRR_FIX_4K_D0000;
738 break;
739 case 0x26B:
740 regNum = MISCREG_MTRR_FIX_4K_D8000;
741 break;
742 case 0x26C:
743 regNum = MISCREG_MTRR_FIX_4K_E0000;
744 break;
745 case 0x26D:
746 regNum = MISCREG_MTRR_FIX_4K_E8000;
747 break;
748 case 0x26E:
749 regNum = MISCREG_MTRR_FIX_4K_F0000;
750 break;
751 case 0x26F:
752 regNum = MISCREG_MTRR_FIX_4K_F8000;
753 break;
754 case 0x277:
755 regNum = MISCREG_PAT;
756 break;
757 case 0x2FF:
758 regNum = MISCREG_DEF_TYPE;
759 break;
760 case 0x400:
761 regNum = MISCREG_MC0_CTL;
762 break;
763 case 0x404:
764 regNum = MISCREG_MC1_CTL;
765 break;
766 case 0x408:
767 regNum = MISCREG_MC2_CTL;
768 break;
769 case 0x40C:
770 regNum = MISCREG_MC3_CTL;
771 break;
772 case 0x410:
773 regNum = MISCREG_MC4_CTL;
774 break;
775 case 0x401:
776 regNum = MISCREG_MC0_STATUS;
777 break;
778 case 0x405:
779 regNum = MISCREG_MC1_STATUS;
780 break;
781 case 0x409:
782 regNum = MISCREG_MC2_STATUS;
783 break;
784 case 0x40D:
785 regNum = MISCREG_MC3_STATUS;
786 break;
787 case 0x411:
788 regNum = MISCREG_MC4_STATUS;
789 break;
790 case 0x402:
791 regNum = MISCREG_MC0_ADDR;
792 break;
793 case 0x406:
794 regNum = MISCREG_MC1_ADDR;
795 break;
796 case 0x40A:
797 regNum = MISCREG_MC2_ADDR;
798 break;
799 case 0x40E:
800 regNum = MISCREG_MC3_ADDR;
801 break;
802 case 0x412:
803 regNum = MISCREG_MC4_ADDR;
804 break;
805 case 0x403:
806 regNum = MISCREG_MC0_MISC;
807 break;
808 case 0x407:
809 regNum = MISCREG_MC1_MISC;
810 break;
811 case 0x40B:
812 regNum = MISCREG_MC2_MISC;
813 break;
814 case 0x40F:
815 regNum = MISCREG_MC3_MISC;
816 break;
817 case 0x413:
818 regNum = MISCREG_MC4_MISC;
819 break;
820 case 0xC0000080:
821 regNum = MISCREG_EFER;
822 break;
823 case 0xC0000081:
824 regNum = MISCREG_STAR;
825 break;
826 case 0xC0000082:
827 regNum = MISCREG_LSTAR;
828 break;
829 case 0xC0000083:
830 regNum = MISCREG_CSTAR;
831 break;
832 case 0xC0000084:
833 regNum = MISCREG_SF_MASK;
834 break;
835 case 0xC0000100:
836 regNum = MISCREG_FS_BASE;
837 break;
838 case 0xC0000101:
839 regNum = MISCREG_GS_BASE;
840 break;
841 case 0xC0000102:
842 regNum = MISCREG_KERNEL_GS_BASE;
843 break;
844 case 0xC0000103:
845 regNum = MISCREG_TSC_AUX;
846 break;
847 case 0xC0010000:
848 regNum = MISCREG_PERF_EVT_SEL0;
849 break;
850 case 0xC0010001:
851 regNum = MISCREG_PERF_EVT_SEL1;
852 break;
853 case 0xC0010002:
854 regNum = MISCREG_PERF_EVT_SEL2;
855 break;
856 case 0xC0010003:
857 regNum = MISCREG_PERF_EVT_SEL3;
858 break;
859 case 0xC0010004:
860 regNum = MISCREG_PERF_EVT_CTR0;
861 break;
862 case 0xC0010005:
863 regNum = MISCREG_PERF_EVT_CTR1;
864 break;
865 case 0xC0010006:
866 regNum = MISCREG_PERF_EVT_CTR2;
867 break;
868 case 0xC0010007:
869 regNum = MISCREG_PERF_EVT_CTR3;
870 break;
871 case 0xC0010010:
872 regNum = MISCREG_SYSCFG;
873 break;
874 case 0xC0010016:
875 regNum = MISCREG_IORR_BASE0;
876 break;
877 case 0xC0010017:
878 regNum = MISCREG_IORR_BASE1;
879 break;
880 case 0xC0010018:
881 regNum = MISCREG_IORR_MASK0;
882 break;
883 case 0xC0010019:
884 regNum = MISCREG_IORR_MASK1;
885 break;
886 case 0xC001001A:
887 regNum = MISCREG_TOP_MEM;
888 break;
889 case 0xC001001D:
890 regNum = MISCREG_TOP_MEM2;
891 break;
892 case 0xC0010114:
893 regNum = MISCREG_VM_CR;
894 break;
895 case 0xC0010115:
896 regNum = MISCREG_IGNNE;
897 break;
898 case 0xC0010116:
899 regNum = MISCREG_SMM_CTL;
900 break;
901 case 0xC0010117:
902 regNum = MISCREG_VM_HSAVE_PA;
903 break;
904 default:
905 return new GeneralProtection(0);
906 }
907 //The index is multiplied by the size of a MiscReg so that
908 //any memory dependence calculations will not see these as
909 //overlapping.
910 req->setPaddr(regNum * sizeof(MiscReg));
911 return NoFault;
912 } else {
913 panic("Access to unrecognized internal address space %#x.\n",
914 prefix);
915 }
916 }
917
918 // Get cr0. This will tell us how to do translation. We'll assume it was
919 // verified to be correct and consistent when set.
920 CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
921
922 // If protected mode has been enabled...
923 if (cr0.pe) {
924 DPRINTF(TLB, "In protected mode.\n");
925 Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
926 SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
927 // If we're not in 64-bit mode, do protection/limit checks
928 if (!efer.lma || !csAttr.longMode) {
929 DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
930 SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
931 if (!attr.writable && write)
932 return new GeneralProtection(0);
933 if (!attr.readable && !write && !execute)
934 return new GeneralProtection(0);
935 Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
936 Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
937 if (!attr.expandDown) {
938 DPRINTF(TLB, "Checking an expand down segment.\n");
939 // We don't have to worry about the access going around the
940 // end of memory because accesses will be broken up into
941 // pieces at boundaries aligned on sizes smaller than an
942 // entire address space. We do have to worry about the limit
943 // being less than the base.
944 if (limit < base) {
945 if (limit < vaddr + req->getSize() && vaddr < base)
946 return new GeneralProtection(0);
947 } else {
948 if (limit < vaddr + req->getSize())
949 return new GeneralProtection(0);
950 }
951 } else {
952 if (limit < base) {
953 if (vaddr <= limit || vaddr + req->getSize() >= base)
954 return new GeneralProtection(0);
955 } else {
956 if (vaddr <= limit && vaddr + req->getSize() >= base)
957 return new GeneralProtection(0);
958 }
959 }
960 }
961 // If paging is enabled, do the translation.
962 if (cr0.pg) {
963 DPRINTF(TLB, "Paging enabled.\n");
964 // The vaddr already has the segment base applied.
965 TlbEntry *entry = lookup(vaddr);
966 if (!entry) {
967 return new TlbFault(vaddr);
968 } else {
969 // Do paging protection checks.
970 DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr);
971 Addr paddr = entry->paddr | (vaddr & (entry->size-1));
972 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
973 req->setPaddr(paddr);
974 }
975 } else {
976 //Use the address which already has segmentation applied.
977 DPRINTF(TLB, "Paging disabled.\n");
978 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
979 req->setPaddr(vaddr);
980 }
981 } else {
982 // Real mode
983 DPRINTF(TLB, "In real mode.\n");
984 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
985 req->setPaddr(vaddr);
986 }
987 return NoFault;
988};
989
990Fault
991DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
992{
993 return TLB::translate<FakeDTLBFault>(req, tc, write, false);
994}
995
996Fault
997ITB::translate(RequestPtr &req, ThreadContext *tc)
998{
999 return TLB::translate<FakeITLBFault>(req, tc, false, true);
1000}
1001
1002#if FULL_SYSTEM
1003
1004Tick
1005DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
1006{
1007 return tc->getCpuPtr()->ticks(1);
1008}
1009
1010Tick
1011DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
1012{
1013 return tc->getCpuPtr()->ticks(1);
1014}
1015
1016#endif
1017
1018void
1019TLB::serialize(std::ostream &os)
1020{
1021}
1022
1023void
1024TLB::unserialize(Checkpoint *cp, const std::string &section)
1025{
1026}
1027
1028void
1029DTB::serialize(std::ostream &os)
1030{
1031 TLB::serialize(os);
1032}
1033
1034void
1035DTB::unserialize(Checkpoint *cp, const std::string &section)
1036{
1037 TLB::unserialize(cp, section);
1038}
1039
1040/* end namespace X86ISA */ }
1041
1042X86ISA::ITB *
1043X86ITBParams::create()
1044{
1045 return new X86ISA::ITB(this);
1046}
1047
1048X86ISA::DTB *
1049X86DTBParams::create()
1050{
1051 return new X86ISA::DTB(this);
1052}
620}
621
622void
623TLB::demapPage(Addr va)
624{
625}
626
627template<class TlbFault>
628Fault
629TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
630{
631 Addr vaddr = req->getVaddr();
632 DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
633 uint32_t flags = req->getFlags();
634 bool storeCheck = flags & StoreCheck;
635
636 int seg = flags & mask(3);
637
638 //XXX Junk code to surpress the warning
639 if (storeCheck);
640
641 // If this is true, we're dealing with a request to read an internal
642 // value.
643 if (seg == SEGMENT_REG_INT) {
644 Addr prefix = vaddr & IntAddrPrefixMask;
645 if (prefix == IntAddrPrefixCPUID) {
646 panic("CPUID memory space not yet implemented!\n");
647 } else if (prefix == IntAddrPrefixMSR) {
648 req->setMmapedIpr(true);
649 Addr regNum = 0;
650 switch (vaddr & ~IntAddrPrefixMask) {
651 case 0x10:
652 regNum = MISCREG_TSC;
653 break;
654 case 0xFE:
655 regNum = MISCREG_MTRRCAP;
656 break;
657 case 0x174:
658 regNum = MISCREG_SYSENTER_CS;
659 break;
660 case 0x175:
661 regNum = MISCREG_SYSENTER_ESP;
662 break;
663 case 0x176:
664 regNum = MISCREG_SYSENTER_EIP;
665 break;
666 case 0x179:
667 regNum = MISCREG_MCG_CAP;
668 break;
669 case 0x17A:
670 regNum = MISCREG_MCG_STATUS;
671 break;
672 case 0x17B:
673 regNum = MISCREG_MCG_CTL;
674 break;
675 case 0x1D9:
676 regNum = MISCREG_DEBUG_CTL_MSR;
677 break;
678 case 0x1DB:
679 regNum = MISCREG_LAST_BRANCH_FROM_IP;
680 break;
681 case 0x1DC:
682 regNum = MISCREG_LAST_BRANCH_TO_IP;
683 break;
684 case 0x1DD:
685 regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
686 break;
687 case 0x1DE:
688 regNum = MISCREG_LAST_EXCEPTION_TO_IP;
689 break;
690 case 0x200:
691 regNum = MISCREG_MTRR_PHYS_BASE_0;
692 break;
693 case 0x201:
694 regNum = MISCREG_MTRR_PHYS_MASK_0;
695 break;
696 case 0x202:
697 regNum = MISCREG_MTRR_PHYS_BASE_1;
698 break;
699 case 0x203:
700 regNum = MISCREG_MTRR_PHYS_MASK_1;
701 break;
702 case 0x204:
703 regNum = MISCREG_MTRR_PHYS_BASE_2;
704 break;
705 case 0x205:
706 regNum = MISCREG_MTRR_PHYS_MASK_2;
707 break;
708 case 0x206:
709 regNum = MISCREG_MTRR_PHYS_BASE_3;
710 break;
711 case 0x207:
712 regNum = MISCREG_MTRR_PHYS_MASK_3;
713 break;
714 case 0x208:
715 regNum = MISCREG_MTRR_PHYS_BASE_4;
716 break;
717 case 0x209:
718 regNum = MISCREG_MTRR_PHYS_MASK_4;
719 break;
720 case 0x20A:
721 regNum = MISCREG_MTRR_PHYS_BASE_5;
722 break;
723 case 0x20B:
724 regNum = MISCREG_MTRR_PHYS_MASK_5;
725 break;
726 case 0x20C:
727 regNum = MISCREG_MTRR_PHYS_BASE_6;
728 break;
729 case 0x20D:
730 regNum = MISCREG_MTRR_PHYS_MASK_6;
731 break;
732 case 0x20E:
733 regNum = MISCREG_MTRR_PHYS_BASE_7;
734 break;
735 case 0x20F:
736 regNum = MISCREG_MTRR_PHYS_MASK_7;
737 break;
738 case 0x250:
739 regNum = MISCREG_MTRR_FIX_64K_00000;
740 break;
741 case 0x258:
742 regNum = MISCREG_MTRR_FIX_16K_80000;
743 break;
744 case 0x259:
745 regNum = MISCREG_MTRR_FIX_16K_A0000;
746 break;
747 case 0x268:
748 regNum = MISCREG_MTRR_FIX_4K_C0000;
749 break;
750 case 0x269:
751 regNum = MISCREG_MTRR_FIX_4K_C8000;
752 break;
753 case 0x26A:
754 regNum = MISCREG_MTRR_FIX_4K_D0000;
755 break;
756 case 0x26B:
757 regNum = MISCREG_MTRR_FIX_4K_D8000;
758 break;
759 case 0x26C:
760 regNum = MISCREG_MTRR_FIX_4K_E0000;
761 break;
762 case 0x26D:
763 regNum = MISCREG_MTRR_FIX_4K_E8000;
764 break;
765 case 0x26E:
766 regNum = MISCREG_MTRR_FIX_4K_F0000;
767 break;
768 case 0x26F:
769 regNum = MISCREG_MTRR_FIX_4K_F8000;
770 break;
771 case 0x277:
772 regNum = MISCREG_PAT;
773 break;
774 case 0x2FF:
775 regNum = MISCREG_DEF_TYPE;
776 break;
777 case 0x400:
778 regNum = MISCREG_MC0_CTL;
779 break;
780 case 0x404:
781 regNum = MISCREG_MC1_CTL;
782 break;
783 case 0x408:
784 regNum = MISCREG_MC2_CTL;
785 break;
786 case 0x40C:
787 regNum = MISCREG_MC3_CTL;
788 break;
789 case 0x410:
790 regNum = MISCREG_MC4_CTL;
791 break;
792 case 0x401:
793 regNum = MISCREG_MC0_STATUS;
794 break;
795 case 0x405:
796 regNum = MISCREG_MC1_STATUS;
797 break;
798 case 0x409:
799 regNum = MISCREG_MC2_STATUS;
800 break;
801 case 0x40D:
802 regNum = MISCREG_MC3_STATUS;
803 break;
804 case 0x411:
805 regNum = MISCREG_MC4_STATUS;
806 break;
807 case 0x402:
808 regNum = MISCREG_MC0_ADDR;
809 break;
810 case 0x406:
811 regNum = MISCREG_MC1_ADDR;
812 break;
813 case 0x40A:
814 regNum = MISCREG_MC2_ADDR;
815 break;
816 case 0x40E:
817 regNum = MISCREG_MC3_ADDR;
818 break;
819 case 0x412:
820 regNum = MISCREG_MC4_ADDR;
821 break;
822 case 0x403:
823 regNum = MISCREG_MC0_MISC;
824 break;
825 case 0x407:
826 regNum = MISCREG_MC1_MISC;
827 break;
828 case 0x40B:
829 regNum = MISCREG_MC2_MISC;
830 break;
831 case 0x40F:
832 regNum = MISCREG_MC3_MISC;
833 break;
834 case 0x413:
835 regNum = MISCREG_MC4_MISC;
836 break;
837 case 0xC0000080:
838 regNum = MISCREG_EFER;
839 break;
840 case 0xC0000081:
841 regNum = MISCREG_STAR;
842 break;
843 case 0xC0000082:
844 regNum = MISCREG_LSTAR;
845 break;
846 case 0xC0000083:
847 regNum = MISCREG_CSTAR;
848 break;
849 case 0xC0000084:
850 regNum = MISCREG_SF_MASK;
851 break;
852 case 0xC0000100:
853 regNum = MISCREG_FS_BASE;
854 break;
855 case 0xC0000101:
856 regNum = MISCREG_GS_BASE;
857 break;
858 case 0xC0000102:
859 regNum = MISCREG_KERNEL_GS_BASE;
860 break;
861 case 0xC0000103:
862 regNum = MISCREG_TSC_AUX;
863 break;
864 case 0xC0010000:
865 regNum = MISCREG_PERF_EVT_SEL0;
866 break;
867 case 0xC0010001:
868 regNum = MISCREG_PERF_EVT_SEL1;
869 break;
870 case 0xC0010002:
871 regNum = MISCREG_PERF_EVT_SEL2;
872 break;
873 case 0xC0010003:
874 regNum = MISCREG_PERF_EVT_SEL3;
875 break;
876 case 0xC0010004:
877 regNum = MISCREG_PERF_EVT_CTR0;
878 break;
879 case 0xC0010005:
880 regNum = MISCREG_PERF_EVT_CTR1;
881 break;
882 case 0xC0010006:
883 regNum = MISCREG_PERF_EVT_CTR2;
884 break;
885 case 0xC0010007:
886 regNum = MISCREG_PERF_EVT_CTR3;
887 break;
888 case 0xC0010010:
889 regNum = MISCREG_SYSCFG;
890 break;
891 case 0xC0010016:
892 regNum = MISCREG_IORR_BASE0;
893 break;
894 case 0xC0010017:
895 regNum = MISCREG_IORR_BASE1;
896 break;
897 case 0xC0010018:
898 regNum = MISCREG_IORR_MASK0;
899 break;
900 case 0xC0010019:
901 regNum = MISCREG_IORR_MASK1;
902 break;
903 case 0xC001001A:
904 regNum = MISCREG_TOP_MEM;
905 break;
906 case 0xC001001D:
907 regNum = MISCREG_TOP_MEM2;
908 break;
909 case 0xC0010114:
910 regNum = MISCREG_VM_CR;
911 break;
912 case 0xC0010115:
913 regNum = MISCREG_IGNNE;
914 break;
915 case 0xC0010116:
916 regNum = MISCREG_SMM_CTL;
917 break;
918 case 0xC0010117:
919 regNum = MISCREG_VM_HSAVE_PA;
920 break;
921 default:
922 return new GeneralProtection(0);
923 }
924 //The index is multiplied by the size of a MiscReg so that
925 //any memory dependence calculations will not see these as
926 //overlapping.
927 req->setPaddr(regNum * sizeof(MiscReg));
928 return NoFault;
929 } else {
930 panic("Access to unrecognized internal address space %#x.\n",
931 prefix);
932 }
933 }
934
935 // Get cr0. This will tell us how to do translation. We'll assume it was
936 // verified to be correct and consistent when set.
937 CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
938
939 // If protected mode has been enabled...
940 if (cr0.pe) {
941 DPRINTF(TLB, "In protected mode.\n");
942 Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
943 SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
944 // If we're not in 64-bit mode, do protection/limit checks
945 if (!efer.lma || !csAttr.longMode) {
946 DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
947 SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
948 if (!attr.writable && write)
949 return new GeneralProtection(0);
950 if (!attr.readable && !write && !execute)
951 return new GeneralProtection(0);
952 Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
953 Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
954 if (!attr.expandDown) {
955 DPRINTF(TLB, "Checking an expand down segment.\n");
956 // We don't have to worry about the access going around the
957 // end of memory because accesses will be broken up into
958 // pieces at boundaries aligned on sizes smaller than an
959 // entire address space. We do have to worry about the limit
960 // being less than the base.
961 if (limit < base) {
962 if (limit < vaddr + req->getSize() && vaddr < base)
963 return new GeneralProtection(0);
964 } else {
965 if (limit < vaddr + req->getSize())
966 return new GeneralProtection(0);
967 }
968 } else {
969 if (limit < base) {
970 if (vaddr <= limit || vaddr + req->getSize() >= base)
971 return new GeneralProtection(0);
972 } else {
973 if (vaddr <= limit && vaddr + req->getSize() >= base)
974 return new GeneralProtection(0);
975 }
976 }
977 }
978 // If paging is enabled, do the translation.
979 if (cr0.pg) {
980 DPRINTF(TLB, "Paging enabled.\n");
981 // The vaddr already has the segment base applied.
982 TlbEntry *entry = lookup(vaddr);
983 if (!entry) {
984 return new TlbFault(vaddr);
985 } else {
986 // Do paging protection checks.
987 DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr);
988 Addr paddr = entry->paddr | (vaddr & (entry->size-1));
989 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
990 req->setPaddr(paddr);
991 }
992 } else {
993 //Use the address which already has segmentation applied.
994 DPRINTF(TLB, "Paging disabled.\n");
995 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
996 req->setPaddr(vaddr);
997 }
998 } else {
999 // Real mode
1000 DPRINTF(TLB, "In real mode.\n");
1001 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
1002 req->setPaddr(vaddr);
1003 }
1004 return NoFault;
1005};
1006
1007Fault
1008DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
1009{
1010 return TLB::translate<FakeDTLBFault>(req, tc, write, false);
1011}
1012
1013Fault
1014ITB::translate(RequestPtr &req, ThreadContext *tc)
1015{
1016 return TLB::translate<FakeITLBFault>(req, tc, false, true);
1017}
1018
1019#if FULL_SYSTEM
1020
1021Tick
1022DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
1023{
1024 return tc->getCpuPtr()->ticks(1);
1025}
1026
1027Tick
1028DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
1029{
1030 return tc->getCpuPtr()->ticks(1);
1031}
1032
1033#endif
1034
1035void
1036TLB::serialize(std::ostream &os)
1037{
1038}
1039
1040void
1041TLB::unserialize(Checkpoint *cp, const std::string &section)
1042{
1043}
1044
1045void
1046DTB::serialize(std::ostream &os)
1047{
1048 TLB::serialize(os);
1049}
1050
1051void
1052DTB::unserialize(Checkpoint *cp, const std::string &section)
1053{
1054 TLB::unserialize(cp, section);
1055}
1056
1057/* end namespace X86ISA */ }
1058
1059X86ISA::ITB *
1060X86ITBParams::create()
1061{
1062 return new X86ISA::ITB(this);
1063}
1064
1065X86ISA::DTB *
1066X86DTBParams::create()
1067{
1068 return new X86ISA::DTB(this);
1069}