merge
[gem5.git] / src / arch / x86 / tlb.cc
1 /*
2 * Copyright (c) 2007-2008 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/faults.hh"
63 #include "arch/x86/insts/microldstop.hh"
64 #include "arch/x86/miscregs.hh"
65 #include "arch/x86/pagetable.hh"
66 #include "arch/x86/tlb.hh"
67 #include "arch/x86/x86_traits.hh"
68 #include "base/bitfield.hh"
69 #include "base/trace.hh"
70 #include "config/full_system.hh"
71 #include "cpu/thread_context.hh"
72 #include "cpu/base.hh"
73 #include "mem/packet_access.hh"
74 #include "mem/request.hh"
75
76 #if FULL_SYSTEM
77 #include "arch/x86/pagetable_walker.hh"
78 #else
79 #include "mem/page_table.hh"
80 #include "sim/process.hh"
81 #endif
82
83 namespace X86ISA {
84
85 TLB::TLB(const Params *p) : BaseTLB(p), configAddress(0), size(p->size)
86 {
87 tlb = new TlbEntry[size];
88 std::memset(tlb, 0, sizeof(TlbEntry) * size);
89
90 for (int x = 0; x < size; x++)
91 freeList.push_back(&tlb[x]);
92
93 #if FULL_SYSTEM
94 walker = p->walker;
95 walker->setTLB(this);
96 #endif
97 }
98
99 TlbEntry *
100 TLB::insert(Addr vpn, TlbEntry &entry)
101 {
102 //TODO Deal with conflicting entries
103
104 TlbEntry *newEntry = NULL;
105 if (!freeList.empty()) {
106 newEntry = freeList.front();
107 freeList.pop_front();
108 } else {
109 newEntry = entryList.back();
110 entryList.pop_back();
111 }
112 *newEntry = entry;
113 newEntry->vaddr = vpn;
114 entryList.push_front(newEntry);
115 return newEntry;
116 }
117
118 TLB::EntryList::iterator
119 TLB::lookupIt(Addr va, bool update_lru)
120 {
121 //TODO make this smarter at some point
122 EntryList::iterator entry;
123 for (entry = entryList.begin(); entry != entryList.end(); entry++) {
124 if ((*entry)->vaddr <= va && (*entry)->vaddr + (*entry)->size > va) {
125 DPRINTF(TLB, "Matched vaddr %#x to entry starting at %#x "
126 "with size %#x.\n", va, (*entry)->vaddr, (*entry)->size);
127 if (update_lru) {
128 entryList.push_front(*entry);
129 entryList.erase(entry);
130 entry = entryList.begin();
131 }
132 break;
133 }
134 }
135 return entry;
136 }
137
138 TlbEntry *
139 TLB::lookup(Addr va, bool update_lru)
140 {
141 EntryList::iterator entry = lookupIt(va, update_lru);
142 if (entry == entryList.end())
143 return NULL;
144 else
145 return *entry;
146 }
147
148 void
149 TLB::invalidateAll()
150 {
151 DPRINTF(TLB, "Invalidating all entries.\n");
152 while (!entryList.empty()) {
153 TlbEntry *entry = entryList.front();
154 entryList.pop_front();
155 freeList.push_back(entry);
156 }
157 }
158
159 void
160 TLB::setConfigAddress(uint32_t addr)
161 {
162 configAddress = addr;
163 }
164
165 void
166 TLB::invalidateNonGlobal()
167 {
168 DPRINTF(TLB, "Invalidating all non global entries.\n");
169 EntryList::iterator entryIt;
170 for (entryIt = entryList.begin(); entryIt != entryList.end();) {
171 if (!(*entryIt)->global) {
172 freeList.push_back(*entryIt);
173 entryList.erase(entryIt++);
174 } else {
175 entryIt++;
176 }
177 }
178 }
179
180 void
181 TLB::demapPage(Addr va, uint64_t asn)
182 {
183 EntryList::iterator entry = lookupIt(va, false);
184 if (entry != entryList.end()) {
185 freeList.push_back(*entry);
186 entryList.erase(entry);
187 }
188 }
189
190 Fault
191 TLB::translateInt(RequestPtr req, ThreadContext *tc)
192 {
193 DPRINTF(TLB, "Addresses references internal memory.\n");
194 Addr vaddr = req->getVaddr();
195 Addr prefix = (vaddr >> 3) & IntAddrPrefixMask;
196 if (prefix == IntAddrPrefixCPUID) {
197 panic("CPUID memory space not yet implemented!\n");
198 } else if (prefix == IntAddrPrefixMSR) {
199 vaddr = vaddr >> 3;
200 req->setFlags(Request::MMAPED_IPR);
201 Addr regNum = 0;
202 switch (vaddr & ~IntAddrPrefixMask) {
203 case 0x10:
204 regNum = MISCREG_TSC;
205 break;
206 case 0x1B:
207 regNum = MISCREG_APIC_BASE;
208 break;
209 case 0xFE:
210 regNum = MISCREG_MTRRCAP;
211 break;
212 case 0x174:
213 regNum = MISCREG_SYSENTER_CS;
214 break;
215 case 0x175:
216 regNum = MISCREG_SYSENTER_ESP;
217 break;
218 case 0x176:
219 regNum = MISCREG_SYSENTER_EIP;
220 break;
221 case 0x179:
222 regNum = MISCREG_MCG_CAP;
223 break;
224 case 0x17A:
225 regNum = MISCREG_MCG_STATUS;
226 break;
227 case 0x17B:
228 regNum = MISCREG_MCG_CTL;
229 break;
230 case 0x1D9:
231 regNum = MISCREG_DEBUG_CTL_MSR;
232 break;
233 case 0x1DB:
234 regNum = MISCREG_LAST_BRANCH_FROM_IP;
235 break;
236 case 0x1DC:
237 regNum = MISCREG_LAST_BRANCH_TO_IP;
238 break;
239 case 0x1DD:
240 regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
241 break;
242 case 0x1DE:
243 regNum = MISCREG_LAST_EXCEPTION_TO_IP;
244 break;
245 case 0x200:
246 regNum = MISCREG_MTRR_PHYS_BASE_0;
247 break;
248 case 0x201:
249 regNum = MISCREG_MTRR_PHYS_MASK_0;
250 break;
251 case 0x202:
252 regNum = MISCREG_MTRR_PHYS_BASE_1;
253 break;
254 case 0x203:
255 regNum = MISCREG_MTRR_PHYS_MASK_1;
256 break;
257 case 0x204:
258 regNum = MISCREG_MTRR_PHYS_BASE_2;
259 break;
260 case 0x205:
261 regNum = MISCREG_MTRR_PHYS_MASK_2;
262 break;
263 case 0x206:
264 regNum = MISCREG_MTRR_PHYS_BASE_3;
265 break;
266 case 0x207:
267 regNum = MISCREG_MTRR_PHYS_MASK_3;
268 break;
269 case 0x208:
270 regNum = MISCREG_MTRR_PHYS_BASE_4;
271 break;
272 case 0x209:
273 regNum = MISCREG_MTRR_PHYS_MASK_4;
274 break;
275 case 0x20A:
276 regNum = MISCREG_MTRR_PHYS_BASE_5;
277 break;
278 case 0x20B:
279 regNum = MISCREG_MTRR_PHYS_MASK_5;
280 break;
281 case 0x20C:
282 regNum = MISCREG_MTRR_PHYS_BASE_6;
283 break;
284 case 0x20D:
285 regNum = MISCREG_MTRR_PHYS_MASK_6;
286 break;
287 case 0x20E:
288 regNum = MISCREG_MTRR_PHYS_BASE_7;
289 break;
290 case 0x20F:
291 regNum = MISCREG_MTRR_PHYS_MASK_7;
292 break;
293 case 0x250:
294 regNum = MISCREG_MTRR_FIX_64K_00000;
295 break;
296 case 0x258:
297 regNum = MISCREG_MTRR_FIX_16K_80000;
298 break;
299 case 0x259:
300 regNum = MISCREG_MTRR_FIX_16K_A0000;
301 break;
302 case 0x268:
303 regNum = MISCREG_MTRR_FIX_4K_C0000;
304 break;
305 case 0x269:
306 regNum = MISCREG_MTRR_FIX_4K_C8000;
307 break;
308 case 0x26A:
309 regNum = MISCREG_MTRR_FIX_4K_D0000;
310 break;
311 case 0x26B:
312 regNum = MISCREG_MTRR_FIX_4K_D8000;
313 break;
314 case 0x26C:
315 regNum = MISCREG_MTRR_FIX_4K_E0000;
316 break;
317 case 0x26D:
318 regNum = MISCREG_MTRR_FIX_4K_E8000;
319 break;
320 case 0x26E:
321 regNum = MISCREG_MTRR_FIX_4K_F0000;
322 break;
323 case 0x26F:
324 regNum = MISCREG_MTRR_FIX_4K_F8000;
325 break;
326 case 0x277:
327 regNum = MISCREG_PAT;
328 break;
329 case 0x2FF:
330 regNum = MISCREG_DEF_TYPE;
331 break;
332 case 0x400:
333 regNum = MISCREG_MC0_CTL;
334 break;
335 case 0x404:
336 regNum = MISCREG_MC1_CTL;
337 break;
338 case 0x408:
339 regNum = MISCREG_MC2_CTL;
340 break;
341 case 0x40C:
342 regNum = MISCREG_MC3_CTL;
343 break;
344 case 0x410:
345 regNum = MISCREG_MC4_CTL;
346 break;
347 case 0x414:
348 regNum = MISCREG_MC5_CTL;
349 break;
350 case 0x418:
351 regNum = MISCREG_MC6_CTL;
352 break;
353 case 0x41C:
354 regNum = MISCREG_MC7_CTL;
355 break;
356 case 0x401:
357 regNum = MISCREG_MC0_STATUS;
358 break;
359 case 0x405:
360 regNum = MISCREG_MC1_STATUS;
361 break;
362 case 0x409:
363 regNum = MISCREG_MC2_STATUS;
364 break;
365 case 0x40D:
366 regNum = MISCREG_MC3_STATUS;
367 break;
368 case 0x411:
369 regNum = MISCREG_MC4_STATUS;
370 break;
371 case 0x415:
372 regNum = MISCREG_MC5_STATUS;
373 break;
374 case 0x419:
375 regNum = MISCREG_MC6_STATUS;
376 break;
377 case 0x41D:
378 regNum = MISCREG_MC7_STATUS;
379 break;
380 case 0x402:
381 regNum = MISCREG_MC0_ADDR;
382 break;
383 case 0x406:
384 regNum = MISCREG_MC1_ADDR;
385 break;
386 case 0x40A:
387 regNum = MISCREG_MC2_ADDR;
388 break;
389 case 0x40E:
390 regNum = MISCREG_MC3_ADDR;
391 break;
392 case 0x412:
393 regNum = MISCREG_MC4_ADDR;
394 break;
395 case 0x416:
396 regNum = MISCREG_MC5_ADDR;
397 break;
398 case 0x41A:
399 regNum = MISCREG_MC6_ADDR;
400 break;
401 case 0x41E:
402 regNum = MISCREG_MC7_ADDR;
403 break;
404 case 0x403:
405 regNum = MISCREG_MC0_MISC;
406 break;
407 case 0x407:
408 regNum = MISCREG_MC1_MISC;
409 break;
410 case 0x40B:
411 regNum = MISCREG_MC2_MISC;
412 break;
413 case 0x40F:
414 regNum = MISCREG_MC3_MISC;
415 break;
416 case 0x413:
417 regNum = MISCREG_MC4_MISC;
418 break;
419 case 0x417:
420 regNum = MISCREG_MC5_MISC;
421 break;
422 case 0x41B:
423 regNum = MISCREG_MC6_MISC;
424 break;
425 case 0x41F:
426 regNum = MISCREG_MC7_MISC;
427 break;
428 case 0xC0000080:
429 regNum = MISCREG_EFER;
430 break;
431 case 0xC0000081:
432 regNum = MISCREG_STAR;
433 break;
434 case 0xC0000082:
435 regNum = MISCREG_LSTAR;
436 break;
437 case 0xC0000083:
438 regNum = MISCREG_CSTAR;
439 break;
440 case 0xC0000084:
441 regNum = MISCREG_SF_MASK;
442 break;
443 case 0xC0000100:
444 regNum = MISCREG_FS_BASE;
445 break;
446 case 0xC0000101:
447 regNum = MISCREG_GS_BASE;
448 break;
449 case 0xC0000102:
450 regNum = MISCREG_KERNEL_GS_BASE;
451 break;
452 case 0xC0000103:
453 regNum = MISCREG_TSC_AUX;
454 break;
455 case 0xC0010000:
456 regNum = MISCREG_PERF_EVT_SEL0;
457 break;
458 case 0xC0010001:
459 regNum = MISCREG_PERF_EVT_SEL1;
460 break;
461 case 0xC0010002:
462 regNum = MISCREG_PERF_EVT_SEL2;
463 break;
464 case 0xC0010003:
465 regNum = MISCREG_PERF_EVT_SEL3;
466 break;
467 case 0xC0010004:
468 regNum = MISCREG_PERF_EVT_CTR0;
469 break;
470 case 0xC0010005:
471 regNum = MISCREG_PERF_EVT_CTR1;
472 break;
473 case 0xC0010006:
474 regNum = MISCREG_PERF_EVT_CTR2;
475 break;
476 case 0xC0010007:
477 regNum = MISCREG_PERF_EVT_CTR3;
478 break;
479 case 0xC0010010:
480 regNum = MISCREG_SYSCFG;
481 break;
482 case 0xC0010016:
483 regNum = MISCREG_IORR_BASE0;
484 break;
485 case 0xC0010017:
486 regNum = MISCREG_IORR_BASE1;
487 break;
488 case 0xC0010018:
489 regNum = MISCREG_IORR_MASK0;
490 break;
491 case 0xC0010019:
492 regNum = MISCREG_IORR_MASK1;
493 break;
494 case 0xC001001A:
495 regNum = MISCREG_TOP_MEM;
496 break;
497 case 0xC001001D:
498 regNum = MISCREG_TOP_MEM2;
499 break;
500 case 0xC0010114:
501 regNum = MISCREG_VM_CR;
502 break;
503 case 0xC0010115:
504 regNum = MISCREG_IGNNE;
505 break;
506 case 0xC0010116:
507 regNum = MISCREG_SMM_CTL;
508 break;
509 case 0xC0010117:
510 regNum = MISCREG_VM_HSAVE_PA;
511 break;
512 default:
513 return new GeneralProtection(0);
514 }
515 //The index is multiplied by the size of a MiscReg so that
516 //any memory dependence calculations will not see these as
517 //overlapping.
518 req->setPaddr(regNum * sizeof(MiscReg));
519 return NoFault;
520 } else if (prefix == IntAddrPrefixIO) {
521 // TODO If CPL > IOPL or in virtual mode, check the I/O permission
522 // bitmap in the TSS.
523
524 Addr IOPort = vaddr & ~IntAddrPrefixMask;
525 // Make sure the address fits in the expected 16 bit IO address
526 // space.
527 assert(!(IOPort & ~0xFFFF));
528 if (IOPort == 0xCF8 && req->getSize() == 4) {
529 req->setFlags(Request::MMAPED_IPR);
530 req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg));
531 } else if ((IOPort & ~mask(2)) == 0xCFC) {
532 Addr configAddress =
533 tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
534 if (bits(configAddress, 31, 31)) {
535 req->setPaddr(PhysAddrPrefixPciConfig |
536 mbits(configAddress, 30, 2) |
537 (IOPort & mask(2)));
538 }
539 } else {
540 req->setPaddr(PhysAddrPrefixIO | IOPort);
541 }
542 return NoFault;
543 } else {
544 panic("Access to unrecognized internal address space %#x.\n",
545 prefix);
546 }
547 }
548
549 Fault
550 TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
551 Mode mode, bool &delayedResponse, bool timing)
552 {
553 uint32_t flags = req->getFlags();
554 int seg = flags & SegmentFlagMask;
555 bool storeCheck = flags & (StoreCheck << FlagShift);
556
557 // If this is true, we're dealing with a request to a non-memory address
558 // space.
559 if (seg == SEGMENT_REG_MS) {
560 return translateInt(req, tc);
561 }
562
563 delayedResponse = false;
564 Addr vaddr = req->getVaddr();
565 DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
566
567 HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
568
569 // If protected mode has been enabled...
570 if (m5Reg.prot) {
571 DPRINTF(TLB, "In protected mode.\n");
572 // If we're not in 64-bit mode, do protection/limit checks
573 if (m5Reg.mode != LongMode) {
574 DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
575 // Check for a NULL segment selector.
576 if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR ||
577 seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS)
578 && !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
579 return new GeneralProtection(0);
580 bool expandDown = false;
581 SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
582 if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) {
583 if (!attr.writable && (mode == Write || storeCheck))
584 return new GeneralProtection(0);
585 if (!attr.readable && mode == Read)
586 return new GeneralProtection(0);
587 expandDown = attr.expandDown;
588
589 }
590 Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
591 Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
592 // This assumes we're not in 64 bit mode. If we were, the default
593 // address size is 64 bits, overridable to 32.
594 int size = 32;
595 bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift));
596 SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
597 if ((csAttr.defaultSize && sizeOverride) ||
598 (!csAttr.defaultSize && !sizeOverride))
599 size = 16;
600 Addr offset = bits(vaddr - base, size-1, 0);
601 Addr endOffset = offset + req->getSize() - 1;
602 if (expandDown) {
603 DPRINTF(TLB, "Checking an expand down segment.\n");
604 warn_once("Expand down segments are untested.\n");
605 if (offset <= limit || endOffset <= limit)
606 return new GeneralProtection(0);
607 } else {
608 if (offset > limit || endOffset > limit)
609 return new GeneralProtection(0);
610 }
611 }
612 // If paging is enabled, do the translation.
613 if (m5Reg.paging) {
614 DPRINTF(TLB, "Paging enabled.\n");
615 // The vaddr already has the segment base applied.
616 TlbEntry *entry = lookup(vaddr);
617 if (!entry) {
618 #if FULL_SYSTEM
619 Fault fault = walker->start(tc, translation, req, mode);
620 if (timing || fault != NoFault) {
621 // This gets ignored in atomic mode.
622 delayedResponse = true;
623 return fault;
624 }
625 entry = lookup(vaddr);
626 assert(entry);
627 #else
628 DPRINTF(TLB, "Handling a TLB miss for "
629 "address %#x at pc %#x.\n",
630 vaddr, tc->readPC());
631
632 Process *p = tc->getProcessPtr();
633 TlbEntry newEntry;
634 bool success = p->pTable->lookup(vaddr, newEntry);
635 if (!success && mode != Execute) {
636 p->checkAndAllocNextPage(vaddr);
637 success = p->pTable->lookup(vaddr, newEntry);
638 }
639 if (!success) {
640 if (req->isPrefetch()) {
641 return new PageFault(vaddr, true, mode, true, false);
642 } else {
643 const char *modeStr = "";
644 if (mode == Execute)
645 modeStr = "execute";
646 else if (mode == Read)
647 modeStr = "read";
648 else if (mode == Write)
649 modeStr = "write";
650 else
651 modeStr = "?";
652 panic("Tried to %s unmapped address %#x.\n",
653 modeStr, vaddr);
654 }
655 } else {
656 Addr alignedVaddr = p->pTable->pageAlign(vaddr);
657 DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
658 newEntry.pageStart());
659 entry = insert(alignedVaddr, newEntry);
660 }
661 DPRINTF(TLB, "Miss was serviced.\n");
662 #endif
663 }
664 // Do paging protection checks.
665 bool inUser = (m5Reg.cpl == 3 &&
666 !(flags & (CPL0FlagBit << FlagShift)));
667 if ((inUser && !entry->user) ||
668 (mode == Write && !entry->writable)) {
669 // The page must have been present to get into the TLB in
670 // the first place. We'll assume the reserved bits are
671 // fine even though we're not checking them.
672 return new PageFault(vaddr, true, mode, inUser, false);
673 }
674 if (storeCheck && !entry->writable) {
675 // This would fault if this were a write, so return a page
676 // fault that reflects that happening.
677 return new PageFault(vaddr, true, Write, inUser, false);
678 }
679
680
681 DPRINTF(TLB, "Entry found with paddr %#x, "
682 "doing protection checks.\n", entry->paddr);
683 Addr paddr = entry->paddr | (vaddr & (entry->size-1));
684 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
685 req->setPaddr(paddr);
686 } else {
687 //Use the address which already has segmentation applied.
688 DPRINTF(TLB, "Paging disabled.\n");
689 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
690 req->setPaddr(vaddr);
691 }
692 } else {
693 // Real mode
694 DPRINTF(TLB, "In real mode.\n");
695 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
696 req->setPaddr(vaddr);
697 }
698 // Check for an access to the local APIC
699 #if FULL_SYSTEM
700 LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE);
701 Addr baseAddr = localApicBase.base * PageBytes;
702 Addr paddr = req->getPaddr();
703 if (baseAddr <= paddr && baseAddr + PageBytes > paddr) {
704 // The Intel developer's manuals say the below restrictions apply,
705 // but the linux kernel, because of a compiler optimization, breaks
706 // them.
707 /*
708 // Check alignment
709 if (paddr & ((32/8) - 1))
710 return new GeneralProtection(0);
711 // Check access size
712 if (req->getSize() != (32/8))
713 return new GeneralProtection(0);
714 */
715 // Force the access to be uncacheable.
716 req->setFlags(Request::UNCACHEABLE);
717 req->setPaddr(x86LocalAPICAddress(tc->contextId(), paddr - baseAddr));
718 }
719 #endif
720 return NoFault;
721 };
722
723 Fault
724 TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
725 {
726 bool delayedResponse;
727 return TLB::translate(req, tc, NULL, mode, delayedResponse, false);
728 }
729
730 void
731 TLB::translateTiming(RequestPtr req, ThreadContext *tc,
732 Translation *translation, Mode mode)
733 {
734 bool delayedResponse;
735 assert(translation);
736 Fault fault =
737 TLB::translate(req, tc, translation, mode, delayedResponse, true);
738 if (!delayedResponse)
739 translation->finish(fault, req, tc, mode);
740 }
741
742 #if FULL_SYSTEM
743
744 Tick
745 TLB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
746 {
747 return tc->getCpuPtr()->ticks(1);
748 }
749
750 Tick
751 TLB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
752 {
753 return tc->getCpuPtr()->ticks(1);
754 }
755
756 #endif
757
758 void
759 TLB::serialize(std::ostream &os)
760 {
761 }
762
763 void
764 TLB::unserialize(Checkpoint *cp, const std::string &section)
765 {
766 }
767
768 /* end namespace X86ISA */ }
769
770 X86ISA::TLB *
771 X86TLBParams::create()
772 {
773 return new X86ISA::TLB(this);
774 }