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