2 * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
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:
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.
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
24 * Palo Alto, California 94304
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.
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.
60 #include "config/full_system.hh"
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"
77 #include "arch/x86/pagetable_walker.hh"
79 #include "mem/page_table.hh"
80 #include "sim/process.hh"
85 TLB::TLB(const Params
*p
) : BaseTLB(p
), configAddress(0), size(p
->size
)
87 tlb
= new TlbEntry
[size
];
88 std::memset(tlb
, 0, sizeof(TlbEntry
) * size
);
90 for (int x
= 0; x
< size
; x
++)
91 freeList
.push_back(&tlb
[x
]);
100 TLB::insert(Addr vpn
, TlbEntry
&entry
)
102 //TODO Deal with conflicting entries
104 TlbEntry
*newEntry
= NULL
;
105 if (!freeList
.empty()) {
106 newEntry
= freeList
.front();
107 freeList
.pop_front();
109 newEntry
= entryList
.back();
110 entryList
.pop_back();
113 newEntry
->vaddr
= vpn
;
114 entryList
.push_front(newEntry
);
118 TLB::EntryList::iterator
119 TLB::lookupIt(Addr va
, bool update_lru
)
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
);
128 entryList
.push_front(*entry
);
129 entryList
.erase(entry
);
130 entry
= entryList
.begin();
139 TLB::lookup(Addr va
, bool update_lru
)
141 EntryList::iterator entry
= lookupIt(va
, update_lru
);
142 if (entry
== entryList
.end())
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
);
160 TLB::setConfigAddress(uint32_t addr
)
162 configAddress
= addr
;
166 TLB::invalidateNonGlobal()
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
++);
181 TLB::demapPage(Addr va
, uint64_t asn
)
183 EntryList::iterator entry
= lookupIt(va
, false);
184 if (entry
!= entryList
.end()) {
185 freeList
.push_back(*entry
);
186 entryList
.erase(entry
);
191 TLB::translateInt(RequestPtr req
, ThreadContext
*tc
)
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
) {
200 req
->setFlags(Request::MMAPED_IPR
);
202 switch (vaddr
& ~IntAddrPrefixMask
) {
204 regNum
= MISCREG_TSC
;
207 regNum
= MISCREG_APIC_BASE
;
210 regNum
= MISCREG_MTRRCAP
;
213 regNum
= MISCREG_SYSENTER_CS
;
216 regNum
= MISCREG_SYSENTER_ESP
;
219 regNum
= MISCREG_SYSENTER_EIP
;
222 regNum
= MISCREG_MCG_CAP
;
225 regNum
= MISCREG_MCG_STATUS
;
228 regNum
= MISCREG_MCG_CTL
;
231 regNum
= MISCREG_DEBUG_CTL_MSR
;
234 regNum
= MISCREG_LAST_BRANCH_FROM_IP
;
237 regNum
= MISCREG_LAST_BRANCH_TO_IP
;
240 regNum
= MISCREG_LAST_EXCEPTION_FROM_IP
;
243 regNum
= MISCREG_LAST_EXCEPTION_TO_IP
;
246 regNum
= MISCREG_MTRR_PHYS_BASE_0
;
249 regNum
= MISCREG_MTRR_PHYS_MASK_0
;
252 regNum
= MISCREG_MTRR_PHYS_BASE_1
;
255 regNum
= MISCREG_MTRR_PHYS_MASK_1
;
258 regNum
= MISCREG_MTRR_PHYS_BASE_2
;
261 regNum
= MISCREG_MTRR_PHYS_MASK_2
;
264 regNum
= MISCREG_MTRR_PHYS_BASE_3
;
267 regNum
= MISCREG_MTRR_PHYS_MASK_3
;
270 regNum
= MISCREG_MTRR_PHYS_BASE_4
;
273 regNum
= MISCREG_MTRR_PHYS_MASK_4
;
276 regNum
= MISCREG_MTRR_PHYS_BASE_5
;
279 regNum
= MISCREG_MTRR_PHYS_MASK_5
;
282 regNum
= MISCREG_MTRR_PHYS_BASE_6
;
285 regNum
= MISCREG_MTRR_PHYS_MASK_6
;
288 regNum
= MISCREG_MTRR_PHYS_BASE_7
;
291 regNum
= MISCREG_MTRR_PHYS_MASK_7
;
294 regNum
= MISCREG_MTRR_FIX_64K_00000
;
297 regNum
= MISCREG_MTRR_FIX_16K_80000
;
300 regNum
= MISCREG_MTRR_FIX_16K_A0000
;
303 regNum
= MISCREG_MTRR_FIX_4K_C0000
;
306 regNum
= MISCREG_MTRR_FIX_4K_C8000
;
309 regNum
= MISCREG_MTRR_FIX_4K_D0000
;
312 regNum
= MISCREG_MTRR_FIX_4K_D8000
;
315 regNum
= MISCREG_MTRR_FIX_4K_E0000
;
318 regNum
= MISCREG_MTRR_FIX_4K_E8000
;
321 regNum
= MISCREG_MTRR_FIX_4K_F0000
;
324 regNum
= MISCREG_MTRR_FIX_4K_F8000
;
327 regNum
= MISCREG_PAT
;
330 regNum
= MISCREG_DEF_TYPE
;
333 regNum
= MISCREG_MC0_CTL
;
336 regNum
= MISCREG_MC1_CTL
;
339 regNum
= MISCREG_MC2_CTL
;
342 regNum
= MISCREG_MC3_CTL
;
345 regNum
= MISCREG_MC4_CTL
;
348 regNum
= MISCREG_MC5_CTL
;
351 regNum
= MISCREG_MC6_CTL
;
354 regNum
= MISCREG_MC7_CTL
;
357 regNum
= MISCREG_MC0_STATUS
;
360 regNum
= MISCREG_MC1_STATUS
;
363 regNum
= MISCREG_MC2_STATUS
;
366 regNum
= MISCREG_MC3_STATUS
;
369 regNum
= MISCREG_MC4_STATUS
;
372 regNum
= MISCREG_MC5_STATUS
;
375 regNum
= MISCREG_MC6_STATUS
;
378 regNum
= MISCREG_MC7_STATUS
;
381 regNum
= MISCREG_MC0_ADDR
;
384 regNum
= MISCREG_MC1_ADDR
;
387 regNum
= MISCREG_MC2_ADDR
;
390 regNum
= MISCREG_MC3_ADDR
;
393 regNum
= MISCREG_MC4_ADDR
;
396 regNum
= MISCREG_MC5_ADDR
;
399 regNum
= MISCREG_MC6_ADDR
;
402 regNum
= MISCREG_MC7_ADDR
;
405 regNum
= MISCREG_MC0_MISC
;
408 regNum
= MISCREG_MC1_MISC
;
411 regNum
= MISCREG_MC2_MISC
;
414 regNum
= MISCREG_MC3_MISC
;
417 regNum
= MISCREG_MC4_MISC
;
420 regNum
= MISCREG_MC5_MISC
;
423 regNum
= MISCREG_MC6_MISC
;
426 regNum
= MISCREG_MC7_MISC
;
429 regNum
= MISCREG_EFER
;
432 regNum
= MISCREG_STAR
;
435 regNum
= MISCREG_LSTAR
;
438 regNum
= MISCREG_CSTAR
;
441 regNum
= MISCREG_SF_MASK
;
444 regNum
= MISCREG_FS_BASE
;
447 regNum
= MISCREG_GS_BASE
;
450 regNum
= MISCREG_KERNEL_GS_BASE
;
453 regNum
= MISCREG_TSC_AUX
;
456 regNum
= MISCREG_PERF_EVT_SEL0
;
459 regNum
= MISCREG_PERF_EVT_SEL1
;
462 regNum
= MISCREG_PERF_EVT_SEL2
;
465 regNum
= MISCREG_PERF_EVT_SEL3
;
468 regNum
= MISCREG_PERF_EVT_CTR0
;
471 regNum
= MISCREG_PERF_EVT_CTR1
;
474 regNum
= MISCREG_PERF_EVT_CTR2
;
477 regNum
= MISCREG_PERF_EVT_CTR3
;
480 regNum
= MISCREG_SYSCFG
;
483 regNum
= MISCREG_IORR_BASE0
;
486 regNum
= MISCREG_IORR_BASE1
;
489 regNum
= MISCREG_IORR_MASK0
;
492 regNum
= MISCREG_IORR_MASK1
;
495 regNum
= MISCREG_TOP_MEM
;
498 regNum
= MISCREG_TOP_MEM2
;
501 regNum
= MISCREG_VM_CR
;
504 regNum
= MISCREG_IGNNE
;
507 regNum
= MISCREG_SMM_CTL
;
510 regNum
= MISCREG_VM_HSAVE_PA
;
513 return new GeneralProtection(0);
515 //The index is multiplied by the size of a MiscReg so that
516 //any memory dependence calculations will not see these as
518 req
->setPaddr(regNum
* sizeof(MiscReg
));
520 } else if (prefix
== IntAddrPrefixIO
) {
521 // TODO If CPL > IOPL or in virtual mode, check the I/O permission
522 // bitmap in the TSS.
524 Addr IOPort
= vaddr
& ~IntAddrPrefixMask
;
525 // Make sure the address fits in the expected 16 bit IO address
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) {
533 tc
->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS
);
534 if (bits(configAddress
, 31, 31)) {
535 req
->setPaddr(PhysAddrPrefixPciConfig
|
536 mbits(configAddress
, 30, 2) |
540 req
->setPaddr(PhysAddrPrefixIO
| IOPort
);
544 panic("Access to unrecognized internal address space %#x.\n",
550 TLB::translate(RequestPtr req
, ThreadContext
*tc
, Translation
*translation
,
551 Mode mode
, bool &delayedResponse
, bool timing
)
553 uint32_t flags
= req
->getFlags();
554 int seg
= flags
& SegmentFlagMask
;
555 bool storeCheck
= flags
& (StoreCheck
<< FlagShift
);
557 // If this is true, we're dealing with a request to a non-memory address
559 if (seg
== SEGMENT_REG_MS
) {
560 return translateInt(req
, tc
);
563 delayedResponse
= false;
564 Addr vaddr
= req
->getVaddr();
565 DPRINTF(TLB
, "Translating vaddr %#x.\n", vaddr
);
567 HandyM5Reg m5Reg
= tc
->readMiscRegNoEffect(MISCREG_M5_REG
);
569 // If protected mode has been enabled...
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
;
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.
595 bool sizeOverride
= (flags
& (AddrSizeFlagBit
<< FlagShift
));
596 SegAttr csAttr
= tc
->readMiscRegNoEffect(MISCREG_CS_ATTR
);
597 if ((csAttr
.defaultSize
&& sizeOverride
) ||
598 (!csAttr
.defaultSize
&& !sizeOverride
))
600 Addr offset
= bits(vaddr
- base
, size
-1, 0);
601 Addr endOffset
= offset
+ req
->getSize() - 1;
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);
608 if (offset
> limit
|| endOffset
> limit
)
609 return new GeneralProtection(0);
612 // If paging is enabled, do the translation.
614 DPRINTF(TLB
, "Paging enabled.\n");
615 // The vaddr already has the segment base applied.
616 TlbEntry
*entry
= lookup(vaddr
);
619 Fault fault
= walker
->start(tc
, translation
, req
, mode
);
620 if (timing
|| fault
!= NoFault
) {
621 // This gets ignored in atomic mode.
622 delayedResponse
= true;
625 entry
= lookup(vaddr
);
628 DPRINTF(TLB
, "Handling a TLB miss for "
629 "address %#x at pc %#x.\n",
630 vaddr
, tc
->readPC());
632 Process
*p
= tc
->getProcessPtr();
634 bool success
= p
->pTable
->lookup(vaddr
, newEntry
);
635 if(!success
&& mode
!= Execute
) {
636 p
->checkAndAllocNextPage(vaddr
);
637 success
= p
->pTable
->lookup(vaddr
, newEntry
);
640 panic("Tried to execute unmapped address %#x.\n", vaddr
);
642 Addr alignedVaddr
= p
->pTable
->pageAlign(vaddr
);
643 DPRINTF(TLB
, "Mapping %#x to %#x\n", alignedVaddr
,
644 newEntry
.pageStart());
645 entry
= insert(alignedVaddr
, newEntry
);
647 DPRINTF(TLB
, "Miss was serviced.\n");
650 // Do paging protection checks.
651 bool inUser
= (m5Reg
.cpl
== 3 &&
652 !(flags
& (CPL0FlagBit
<< FlagShift
)));
653 if ((inUser
&& !entry
->user
) ||
654 (mode
== Write
&& !entry
->writable
)) {
655 // The page must have been present to get into the TLB in
656 // the first place. We'll assume the reserved bits are
657 // fine even though we're not checking them.
658 return new PageFault(vaddr
, true, mode
, inUser
, false);
660 if (storeCheck
&& !entry
->writable
) {
661 // This would fault if this were a write, so return a page
662 // fault that reflects that happening.
663 return new PageFault(vaddr
, true, Write
, inUser
, false);
667 DPRINTF(TLB
, "Entry found with paddr %#x, "
668 "doing protection checks.\n", entry
->paddr
);
669 Addr paddr
= entry
->paddr
| (vaddr
& (entry
->size
-1));
670 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, paddr
);
671 req
->setPaddr(paddr
);
673 //Use the address which already has segmentation applied.
674 DPRINTF(TLB
, "Paging disabled.\n");
675 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, vaddr
);
676 req
->setPaddr(vaddr
);
680 DPRINTF(TLB
, "In real mode.\n");
681 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, vaddr
);
682 req
->setPaddr(vaddr
);
684 // Check for an access to the local APIC
686 LocalApicBase localApicBase
= tc
->readMiscRegNoEffect(MISCREG_APIC_BASE
);
687 Addr baseAddr
= localApicBase
.base
* PageBytes
;
688 Addr paddr
= req
->getPaddr();
689 if (baseAddr
<= paddr
&& baseAddr
+ PageBytes
> paddr
) {
690 // The Intel developer's manuals say the below restrictions apply,
691 // but the linux kernel, because of a compiler optimization, breaks
695 if (paddr & ((32/8) - 1))
696 return new GeneralProtection(0);
698 if (req->getSize() != (32/8))
699 return new GeneralProtection(0);
701 // Force the access to be uncacheable.
702 req
->setFlags(Request::UNCACHEABLE
);
703 req
->setPaddr(x86LocalAPICAddress(tc
->contextId(), paddr
- baseAddr
));
710 TLB::translateAtomic(RequestPtr req
, ThreadContext
*tc
, Mode mode
)
712 bool delayedResponse
;
713 return TLB::translate(req
, tc
, NULL
, mode
, delayedResponse
, false);
717 TLB::translateTiming(RequestPtr req
, ThreadContext
*tc
,
718 Translation
*translation
, Mode mode
)
720 bool delayedResponse
;
723 TLB::translate(req
, tc
, translation
, mode
, delayedResponse
, true);
724 if (!delayedResponse
)
725 translation
->finish(fault
, req
, tc
, mode
);
731 TLB::doMmuRegRead(ThreadContext
*tc
, Packet
*pkt
)
733 return tc
->getCpuPtr()->ticks(1);
737 TLB::doMmuRegWrite(ThreadContext
*tc
, Packet
*pkt
)
739 return tc
->getCpuPtr()->ticks(1);
745 TLB::serialize(std::ostream
&os
)
750 TLB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
754 /* end namespace X86ISA */ }
757 X86TLBParams::create()
759 return new X86ISA::TLB(this);