X86: Remove enforcement of APIC register access alignment. Panic if more than one...
[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/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
73 #if FULL_SYSTEM
74 #include "arch/x86/pagetable_walker.hh"
75 #endif
76
77 namespace X86ISA {
78
79 TLB::TLB(const Params *p) : BaseTLB(p), configAddress(0), size(p->size)
80 {
81 tlb = new TlbEntry[size];
82 std::memset(tlb, 0, sizeof(TlbEntry) * size);
83
84 for (int x = 0; x < size; x++)
85 freeList.push_back(&tlb[x]);
86
87 #if FULL_SYSTEM
88 walker = p->walker;
89 walker->setTLB(this);
90 #endif
91 }
92
93 void
94 TLB::insert(Addr vpn, TlbEntry &entry)
95 {
96 //TODO Deal with conflicting entries
97
98 TlbEntry *newEntry = NULL;
99 if (!freeList.empty()) {
100 newEntry = freeList.front();
101 freeList.pop_front();
102 } else {
103 newEntry = entryList.back();
104 entryList.pop_back();
105 }
106 *newEntry = entry;
107 newEntry->vaddr = vpn;
108 entryList.push_front(newEntry);
109 }
110
111 TLB::EntryList::iterator
112 TLB::lookupIt(Addr va, bool update_lru)
113 {
114 //TODO make this smarter at some point
115 EntryList::iterator entry;
116 for (entry = entryList.begin(); entry != entryList.end(); entry++) {
117 if ((*entry)->vaddr <= va && (*entry)->vaddr + (*entry)->size > va) {
118 DPRINTF(TLB, "Matched vaddr %#x to entry starting at %#x "
119 "with size %#x.\n", va, (*entry)->vaddr, (*entry)->size);
120 if (update_lru) {
121 entryList.push_front(*entry);
122 entryList.erase(entry);
123 entry = entryList.begin();
124 }
125 break;
126 }
127 }
128 return entry;
129 }
130
131 TlbEntry *
132 TLB::lookup(Addr va, bool update_lru)
133 {
134 EntryList::iterator entry = lookupIt(va, update_lru);
135 if (entry == entryList.end())
136 return NULL;
137 else
138 return *entry;
139 }
140
141 #if FULL_SYSTEM
142 void
143 TLB::walk(ThreadContext * _tc, Addr vaddr)
144 {
145 walker->start(_tc, vaddr);
146 }
147 #endif
148
149 void
150 TLB::invalidateAll()
151 {
152 DPRINTF(TLB, "Invalidating all entries.\n");
153 while (!entryList.empty()) {
154 TlbEntry *entry = entryList.front();
155 entryList.pop_front();
156 freeList.push_back(entry);
157 }
158 }
159
160 void
161 TLB::setConfigAddress(uint32_t addr)
162 {
163 configAddress = addr;
164 }
165
166 void
167 TLB::invalidateNonGlobal()
168 {
169 DPRINTF(TLB, "Invalidating all non global entries.\n");
170 EntryList::iterator entryIt;
171 for (entryIt = entryList.begin(); entryIt != entryList.end();) {
172 if (!(*entryIt)->global) {
173 freeList.push_back(*entryIt);
174 entryList.erase(entryIt++);
175 } else {
176 entryIt++;
177 }
178 }
179 }
180
181 void
182 TLB::demapPage(Addr va, uint64_t asn)
183 {
184 EntryList::iterator entry = lookupIt(va, false);
185 if (entry != entryList.end()) {
186 freeList.push_back(*entry);
187 entryList.erase(entry);
188 }
189 }
190
191 template<class TlbFault>
192 Fault
193 TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
194 {
195 Addr vaddr = req->getVaddr();
196 DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
197 uint32_t flags = req->getFlags();
198 bool storeCheck = flags & StoreCheck;
199
200 int seg = flags & mask(4);
201
202 //XXX Junk code to surpress the warning
203 if (storeCheck);
204
205 // If this is true, we're dealing with a request to read an internal
206 // value.
207 if (seg == SEGMENT_REG_MS) {
208 DPRINTF(TLB, "Addresses references internal memory.\n");
209 Addr prefix = vaddr & IntAddrPrefixMask;
210 if (prefix == IntAddrPrefixCPUID) {
211 panic("CPUID memory space not yet implemented!\n");
212 } else if (prefix == IntAddrPrefixMSR) {
213 req->setMmapedIpr(true);
214 Addr regNum = 0;
215 switch (vaddr & ~IntAddrPrefixMask) {
216 case 0x10:
217 regNum = MISCREG_TSC;
218 break;
219 case 0x1B:
220 regNum = MISCREG_APIC_BASE;
221 break;
222 case 0xFE:
223 regNum = MISCREG_MTRRCAP;
224 break;
225 case 0x174:
226 regNum = MISCREG_SYSENTER_CS;
227 break;
228 case 0x175:
229 regNum = MISCREG_SYSENTER_ESP;
230 break;
231 case 0x176:
232 regNum = MISCREG_SYSENTER_EIP;
233 break;
234 case 0x179:
235 regNum = MISCREG_MCG_CAP;
236 break;
237 case 0x17A:
238 regNum = MISCREG_MCG_STATUS;
239 break;
240 case 0x17B:
241 regNum = MISCREG_MCG_CTL;
242 break;
243 case 0x1D9:
244 regNum = MISCREG_DEBUG_CTL_MSR;
245 break;
246 case 0x1DB:
247 regNum = MISCREG_LAST_BRANCH_FROM_IP;
248 break;
249 case 0x1DC:
250 regNum = MISCREG_LAST_BRANCH_TO_IP;
251 break;
252 case 0x1DD:
253 regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
254 break;
255 case 0x1DE:
256 regNum = MISCREG_LAST_EXCEPTION_TO_IP;
257 break;
258 case 0x200:
259 regNum = MISCREG_MTRR_PHYS_BASE_0;
260 break;
261 case 0x201:
262 regNum = MISCREG_MTRR_PHYS_MASK_0;
263 break;
264 case 0x202:
265 regNum = MISCREG_MTRR_PHYS_BASE_1;
266 break;
267 case 0x203:
268 regNum = MISCREG_MTRR_PHYS_MASK_1;
269 break;
270 case 0x204:
271 regNum = MISCREG_MTRR_PHYS_BASE_2;
272 break;
273 case 0x205:
274 regNum = MISCREG_MTRR_PHYS_MASK_2;
275 break;
276 case 0x206:
277 regNum = MISCREG_MTRR_PHYS_BASE_3;
278 break;
279 case 0x207:
280 regNum = MISCREG_MTRR_PHYS_MASK_3;
281 break;
282 case 0x208:
283 regNum = MISCREG_MTRR_PHYS_BASE_4;
284 break;
285 case 0x209:
286 regNum = MISCREG_MTRR_PHYS_MASK_4;
287 break;
288 case 0x20A:
289 regNum = MISCREG_MTRR_PHYS_BASE_5;
290 break;
291 case 0x20B:
292 regNum = MISCREG_MTRR_PHYS_MASK_5;
293 break;
294 case 0x20C:
295 regNum = MISCREG_MTRR_PHYS_BASE_6;
296 break;
297 case 0x20D:
298 regNum = MISCREG_MTRR_PHYS_MASK_6;
299 break;
300 case 0x20E:
301 regNum = MISCREG_MTRR_PHYS_BASE_7;
302 break;
303 case 0x20F:
304 regNum = MISCREG_MTRR_PHYS_MASK_7;
305 break;
306 case 0x250:
307 regNum = MISCREG_MTRR_FIX_64K_00000;
308 break;
309 case 0x258:
310 regNum = MISCREG_MTRR_FIX_16K_80000;
311 break;
312 case 0x259:
313 regNum = MISCREG_MTRR_FIX_16K_A0000;
314 break;
315 case 0x268:
316 regNum = MISCREG_MTRR_FIX_4K_C0000;
317 break;
318 case 0x269:
319 regNum = MISCREG_MTRR_FIX_4K_C8000;
320 break;
321 case 0x26A:
322 regNum = MISCREG_MTRR_FIX_4K_D0000;
323 break;
324 case 0x26B:
325 regNum = MISCREG_MTRR_FIX_4K_D8000;
326 break;
327 case 0x26C:
328 regNum = MISCREG_MTRR_FIX_4K_E0000;
329 break;
330 case 0x26D:
331 regNum = MISCREG_MTRR_FIX_4K_E8000;
332 break;
333 case 0x26E:
334 regNum = MISCREG_MTRR_FIX_4K_F0000;
335 break;
336 case 0x26F:
337 regNum = MISCREG_MTRR_FIX_4K_F8000;
338 break;
339 case 0x277:
340 regNum = MISCREG_PAT;
341 break;
342 case 0x2FF:
343 regNum = MISCREG_DEF_TYPE;
344 break;
345 case 0x400:
346 regNum = MISCREG_MC0_CTL;
347 break;
348 case 0x404:
349 regNum = MISCREG_MC1_CTL;
350 break;
351 case 0x408:
352 regNum = MISCREG_MC2_CTL;
353 break;
354 case 0x40C:
355 regNum = MISCREG_MC3_CTL;
356 break;
357 case 0x410:
358 regNum = MISCREG_MC4_CTL;
359 break;
360 case 0x401:
361 regNum = MISCREG_MC0_STATUS;
362 break;
363 case 0x405:
364 regNum = MISCREG_MC1_STATUS;
365 break;
366 case 0x409:
367 regNum = MISCREG_MC2_STATUS;
368 break;
369 case 0x40D:
370 regNum = MISCREG_MC3_STATUS;
371 break;
372 case 0x411:
373 regNum = MISCREG_MC4_STATUS;
374 break;
375 case 0x402:
376 regNum = MISCREG_MC0_ADDR;
377 break;
378 case 0x406:
379 regNum = MISCREG_MC1_ADDR;
380 break;
381 case 0x40A:
382 regNum = MISCREG_MC2_ADDR;
383 break;
384 case 0x40E:
385 regNum = MISCREG_MC3_ADDR;
386 break;
387 case 0x412:
388 regNum = MISCREG_MC4_ADDR;
389 break;
390 case 0x403:
391 regNum = MISCREG_MC0_MISC;
392 break;
393 case 0x407:
394 regNum = MISCREG_MC1_MISC;
395 break;
396 case 0x40B:
397 regNum = MISCREG_MC2_MISC;
398 break;
399 case 0x40F:
400 regNum = MISCREG_MC3_MISC;
401 break;
402 case 0x413:
403 regNum = MISCREG_MC4_MISC;
404 break;
405 case 0xC0000080:
406 regNum = MISCREG_EFER;
407 break;
408 case 0xC0000081:
409 regNum = MISCREG_STAR;
410 break;
411 case 0xC0000082:
412 regNum = MISCREG_LSTAR;
413 break;
414 case 0xC0000083:
415 regNum = MISCREG_CSTAR;
416 break;
417 case 0xC0000084:
418 regNum = MISCREG_SF_MASK;
419 break;
420 case 0xC0000100:
421 regNum = MISCREG_FS_BASE;
422 break;
423 case 0xC0000101:
424 regNum = MISCREG_GS_BASE;
425 break;
426 case 0xC0000102:
427 regNum = MISCREG_KERNEL_GS_BASE;
428 break;
429 case 0xC0000103:
430 regNum = MISCREG_TSC_AUX;
431 break;
432 case 0xC0010000:
433 regNum = MISCREG_PERF_EVT_SEL0;
434 break;
435 case 0xC0010001:
436 regNum = MISCREG_PERF_EVT_SEL1;
437 break;
438 case 0xC0010002:
439 regNum = MISCREG_PERF_EVT_SEL2;
440 break;
441 case 0xC0010003:
442 regNum = MISCREG_PERF_EVT_SEL3;
443 break;
444 case 0xC0010004:
445 regNum = MISCREG_PERF_EVT_CTR0;
446 break;
447 case 0xC0010005:
448 regNum = MISCREG_PERF_EVT_CTR1;
449 break;
450 case 0xC0010006:
451 regNum = MISCREG_PERF_EVT_CTR2;
452 break;
453 case 0xC0010007:
454 regNum = MISCREG_PERF_EVT_CTR3;
455 break;
456 case 0xC0010010:
457 regNum = MISCREG_SYSCFG;
458 break;
459 case 0xC0010016:
460 regNum = MISCREG_IORR_BASE0;
461 break;
462 case 0xC0010017:
463 regNum = MISCREG_IORR_BASE1;
464 break;
465 case 0xC0010018:
466 regNum = MISCREG_IORR_MASK0;
467 break;
468 case 0xC0010019:
469 regNum = MISCREG_IORR_MASK1;
470 break;
471 case 0xC001001A:
472 regNum = MISCREG_TOP_MEM;
473 break;
474 case 0xC001001D:
475 regNum = MISCREG_TOP_MEM2;
476 break;
477 case 0xC0010114:
478 regNum = MISCREG_VM_CR;
479 break;
480 case 0xC0010115:
481 regNum = MISCREG_IGNNE;
482 break;
483 case 0xC0010116:
484 regNum = MISCREG_SMM_CTL;
485 break;
486 case 0xC0010117:
487 regNum = MISCREG_VM_HSAVE_PA;
488 break;
489 default:
490 return new GeneralProtection(0);
491 }
492 //The index is multiplied by the size of a MiscReg so that
493 //any memory dependence calculations will not see these as
494 //overlapping.
495 req->setPaddr(regNum * sizeof(MiscReg));
496 return NoFault;
497 } else if (prefix == IntAddrPrefixIO) {
498 // TODO If CPL > IOPL or in virtual mode, check the I/O permission
499 // bitmap in the TSS.
500
501 Addr IOPort = vaddr & ~IntAddrPrefixMask;
502 // Make sure the address fits in the expected 16 bit IO address
503 // space.
504 assert(!(IOPort & ~0xFFFF));
505 if (IOPort == 0xCF8 && req->getSize() == 4) {
506 req->setMmapedIpr(true);
507 req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg));
508 } else if ((IOPort & ~mask(2)) == 0xCFC) {
509 Addr configAddress =
510 tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
511 if (bits(configAddress, 31, 31)) {
512 req->setPaddr(PhysAddrPrefixPciConfig |
513 bits(configAddress, 30, 0));
514 }
515 } else {
516 req->setPaddr(PhysAddrPrefixIO | IOPort);
517 }
518 return NoFault;
519 } else {
520 panic("Access to unrecognized internal address space %#x.\n",
521 prefix);
522 }
523 }
524
525 // Get cr0. This will tell us how to do translation. We'll assume it was
526 // verified to be correct and consistent when set.
527 CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
528
529 // If protected mode has been enabled...
530 if (cr0.pe) {
531 DPRINTF(TLB, "In protected mode.\n");
532 Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
533 SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
534 // If we're not in 64-bit mode, do protection/limit checks
535 if (!efer.lma || !csAttr.longMode) {
536 DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
537 SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
538 if (!attr.writable && write)
539 return new GeneralProtection(0);
540 if (!attr.readable && !write && !execute)
541 return new GeneralProtection(0);
542 Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
543 Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
544 if (!attr.expandDown) {
545 DPRINTF(TLB, "Checking an expand down segment.\n");
546 // We don't have to worry about the access going around the
547 // end of memory because accesses will be broken up into
548 // pieces at boundaries aligned on sizes smaller than an
549 // entire address space. We do have to worry about the limit
550 // being less than the base.
551 if (limit < base) {
552 if (limit < vaddr + req->getSize() && vaddr < base)
553 return new GeneralProtection(0);
554 } else {
555 if (limit < vaddr + req->getSize())
556 return new GeneralProtection(0);
557 }
558 } else {
559 if (limit < base) {
560 if (vaddr <= limit || vaddr + req->getSize() >= base)
561 return new GeneralProtection(0);
562 } else {
563 if (vaddr <= limit && vaddr + req->getSize() >= base)
564 return new GeneralProtection(0);
565 }
566 }
567 }
568 // If paging is enabled, do the translation.
569 if (cr0.pg) {
570 DPRINTF(TLB, "Paging enabled.\n");
571 // The vaddr already has the segment base applied.
572 TlbEntry *entry = lookup(vaddr);
573 if (!entry) {
574 return new TlbFault(vaddr);
575 } else {
576 // Do paging protection checks.
577 DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr);
578 Addr paddr = entry->paddr | (vaddr & (entry->size-1));
579 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
580 req->setPaddr(paddr);
581 }
582 } else {
583 //Use the address which already has segmentation applied.
584 DPRINTF(TLB, "Paging disabled.\n");
585 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
586 req->setPaddr(vaddr);
587 }
588 } else {
589 // Real mode
590 DPRINTF(TLB, "In real mode.\n");
591 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
592 req->setPaddr(vaddr);
593 }
594 // Check for an access to the local APIC
595 #if FULL_SYSTEM
596 LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE);
597 Addr baseAddr = localApicBase.base << 12;
598 Addr paddr = req->getPaddr();
599 if (baseAddr <= paddr && baseAddr + (1 << 12) > paddr) {
600 req->setMmapedIpr(true);
601 // The Intel developer's manuals say the below restrictions apply,
602 // but the linux kernel, because of a compiler optimization, breaks
603 // them.
604 /*
605 // Check alignment
606 if (paddr & ((32/8) - 1))
607 return new GeneralProtection(0);
608 // Check access size
609 if (req->getSize() != (32/8))
610 return new GeneralProtection(0);
611 */
612
613 //Make sure we're at least only accessing one register.
614 if ((paddr & ~mask(3)) != ((paddr + req->getSize()) & ~mask(3)))
615 panic("Accessed more than one register at a time in the APIC!\n");
616 MiscReg regNum;
617 Addr offset = paddr & mask(3);
618 paddr &= ~mask(3);
619 switch (paddr - baseAddr)
620 {
621 case 0x20:
622 regNum = MISCREG_APIC_ID;
623 break;
624 case 0x30:
625 regNum = MISCREG_APIC_VERSION;
626 break;
627 case 0x80:
628 regNum = MISCREG_APIC_TASK_PRIORITY;
629 break;
630 case 0x90:
631 regNum = MISCREG_APIC_ARBITRATION_PRIORITY;
632 break;
633 case 0xA0:
634 regNum = MISCREG_APIC_PROCESSOR_PRIORITY;
635 break;
636 case 0xB0:
637 regNum = MISCREG_APIC_EOI;
638 break;
639 case 0xD0:
640 regNum = MISCREG_APIC_LOGICAL_DESTINATION;
641 break;
642 case 0xE0:
643 regNum = MISCREG_APIC_DESTINATION_FORMAT;
644 break;
645 case 0xF0:
646 regNum = MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR;
647 break;
648 case 0x100:
649 case 0x108:
650 case 0x110:
651 case 0x118:
652 case 0x120:
653 case 0x128:
654 case 0x130:
655 case 0x138:
656 case 0x140:
657 case 0x148:
658 case 0x150:
659 case 0x158:
660 case 0x160:
661 case 0x168:
662 case 0x170:
663 case 0x178:
664 regNum = MISCREG_APIC_IN_SERVICE(
665 (paddr - baseAddr - 0x100) / 0x8);
666 break;
667 case 0x180:
668 case 0x188:
669 case 0x190:
670 case 0x198:
671 case 0x1A0:
672 case 0x1A8:
673 case 0x1B0:
674 case 0x1B8:
675 case 0x1C0:
676 case 0x1C8:
677 case 0x1D0:
678 case 0x1D8:
679 case 0x1E0:
680 case 0x1E8:
681 case 0x1F0:
682 case 0x1F8:
683 regNum = MISCREG_APIC_TRIGGER_MODE(
684 (paddr - baseAddr - 0x180) / 0x8);
685 break;
686 case 0x200:
687 case 0x208:
688 case 0x210:
689 case 0x218:
690 case 0x220:
691 case 0x228:
692 case 0x230:
693 case 0x238:
694 case 0x240:
695 case 0x248:
696 case 0x250:
697 case 0x258:
698 case 0x260:
699 case 0x268:
700 case 0x270:
701 case 0x278:
702 regNum = MISCREG_APIC_INTERRUPT_REQUEST(
703 (paddr - baseAddr - 0x200) / 0x8);
704 break;
705 case 0x280:
706 regNum = MISCREG_APIC_ERROR_STATUS;
707 break;
708 case 0x300:
709 regNum = MISCREG_APIC_INTERRUPT_COMMAND_LOW;
710 break;
711 case 0x310:
712 regNum = MISCREG_APIC_INTERRUPT_COMMAND_HIGH;
713 break;
714 case 0x320:
715 regNum = MISCREG_APIC_LVT_TIMER;
716 break;
717 case 0x330:
718 regNum = MISCREG_APIC_LVT_THERMAL_SENSOR;
719 break;
720 case 0x340:
721 regNum = MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS;
722 break;
723 case 0x350:
724 regNum = MISCREG_APIC_LVT_LINT0;
725 break;
726 case 0x360:
727 regNum = MISCREG_APIC_LVT_LINT1;
728 break;
729 case 0x370:
730 regNum = MISCREG_APIC_LVT_ERROR;
731 break;
732 case 0x380:
733 regNum = MISCREG_APIC_INITIAL_COUNT;
734 break;
735 case 0x390:
736 regNum = MISCREG_APIC_CURRENT_COUNT;
737 break;
738 case 0x3E0:
739 regNum = MISCREG_APIC_DIVIDE_COUNT;
740 break;
741 default:
742 // A reserved register field.
743 return new GeneralProtection(0);
744 break;
745 }
746 req->setPaddr(regNum * sizeof(MiscReg) + offset);
747 }
748 #endif
749 return NoFault;
750 };
751
752 Fault
753 DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
754 {
755 return TLB::translate<FakeDTLBFault>(req, tc, write, false);
756 }
757
758 Fault
759 ITB::translate(RequestPtr &req, ThreadContext *tc)
760 {
761 return TLB::translate<FakeITLBFault>(req, tc, false, true);
762 }
763
764 #if FULL_SYSTEM
765
766 Tick
767 DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
768 {
769 return tc->getCpuPtr()->ticks(1);
770 }
771
772 Tick
773 DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
774 {
775 return tc->getCpuPtr()->ticks(1);
776 }
777
778 #endif
779
780 void
781 TLB::serialize(std::ostream &os)
782 {
783 }
784
785 void
786 TLB::unserialize(Checkpoint *cp, const std::string &section)
787 {
788 }
789
790 void
791 DTB::serialize(std::ostream &os)
792 {
793 TLB::serialize(os);
794 }
795
796 void
797 DTB::unserialize(Checkpoint *cp, const std::string &section)
798 {
799 TLB::unserialize(cp, section);
800 }
801
802 /* end namespace X86ISA */ }
803
804 X86ISA::ITB *
805 X86ITBParams::create()
806 {
807 return new X86ISA::ITB(this);
808 }
809
810 X86ISA::DTB *
811 X86DTBParams::create()
812 {
813 return new X86ISA::DTB(this);
814 }