2 * Copyright (c) 2007 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/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"
74 #include "arch/x86/pagetable_walker.hh"
79 TLB::TLB(const Params
*p
) : BaseTLB(p
), configAddress(0), size(p
->size
)
81 tlb
= new TlbEntry
[size
];
82 std::memset(tlb
, 0, sizeof(TlbEntry
) * size
);
84 for (int x
= 0; x
< size
; x
++)
85 freeList
.push_back(&tlb
[x
]);
94 TLB::insert(Addr vpn
, TlbEntry
&entry
)
96 //TODO Deal with conflicting entries
98 TlbEntry
*newEntry
= NULL
;
99 if (!freeList
.empty()) {
100 newEntry
= freeList
.front();
101 freeList
.pop_front();
103 newEntry
= entryList
.back();
104 entryList
.pop_back();
107 newEntry
->vaddr
= vpn
;
108 entryList
.push_front(newEntry
);
112 TLB::lookup(Addr va
, bool update_lru
)
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 TlbEntry
*e
= *entry
;
122 entryList
.erase(entry
);
123 entryList
.push_front(e
);
133 TLB::walk(ThreadContext
* _tc
, Addr vaddr
)
135 walker
->start(_tc
, vaddr
);
142 DPRINTF(TLB
, "Invalidating all entries.\n");
143 while (!entryList
.empty()) {
144 TlbEntry
*entry
= entryList
.front();
145 entryList
.pop_front();
146 freeList
.push_back(entry
);
151 TLB::setConfigAddress(uint32_t addr
)
153 configAddress
= addr
;
157 TLB::invalidateNonGlobal()
159 DPRINTF(TLB
, "Invalidating all non global entries.\n");
160 EntryList::iterator entryIt
;
161 for (entryIt
= entryList
.begin(); entryIt
!= entryList
.end();) {
162 if (!(*entryIt
)->global
) {
163 freeList
.push_back(*entryIt
);
164 entryList
.erase(entryIt
++);
172 TLB::demapPage(Addr va
, uint64_t asn
)
174 EntryList::iterator entry
= lookupIt(va
, false);
175 if (entry
!= entryList
.end()) {
176 freeList
.push_back(*entry
);
177 entryList
.erase(entry
);
181 template<class TlbFault
>
183 TLB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
, bool execute
)
185 Addr vaddr
= req
->getVaddr();
186 DPRINTF(TLB
, "Translating vaddr %#x.\n", vaddr
);
187 uint32_t flags
= req
->getFlags();
188 bool storeCheck
= flags
& StoreCheck
;
190 int seg
= flags
& mask(4);
192 //XXX Junk code to surpress the warning
195 // If this is true, we're dealing with a request to read an internal
197 if (seg
== SEGMENT_REG_MS
) {
198 DPRINTF(TLB
, "Addresses references internal memory.\n");
199 Addr prefix
= vaddr
& IntAddrPrefixMask
;
200 if (prefix
== IntAddrPrefixCPUID
) {
201 panic("CPUID memory space not yet implemented!\n");
202 } else if (prefix
== IntAddrPrefixMSR
) {
203 req
->setMmapedIpr(true);
205 switch (vaddr
& ~IntAddrPrefixMask
) {
207 regNum
= MISCREG_TSC
;
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_MC0_STATUS
;
351 regNum
= MISCREG_MC1_STATUS
;
354 regNum
= MISCREG_MC2_STATUS
;
357 regNum
= MISCREG_MC3_STATUS
;
360 regNum
= MISCREG_MC4_STATUS
;
363 regNum
= MISCREG_MC0_ADDR
;
366 regNum
= MISCREG_MC1_ADDR
;
369 regNum
= MISCREG_MC2_ADDR
;
372 regNum
= MISCREG_MC3_ADDR
;
375 regNum
= MISCREG_MC4_ADDR
;
378 regNum
= MISCREG_MC0_MISC
;
381 regNum
= MISCREG_MC1_MISC
;
384 regNum
= MISCREG_MC2_MISC
;
387 regNum
= MISCREG_MC3_MISC
;
390 regNum
= MISCREG_MC4_MISC
;
393 regNum
= MISCREG_EFER
;
396 regNum
= MISCREG_STAR
;
399 regNum
= MISCREG_LSTAR
;
402 regNum
= MISCREG_CSTAR
;
405 regNum
= MISCREG_SF_MASK
;
408 regNum
= MISCREG_FS_BASE
;
411 regNum
= MISCREG_GS_BASE
;
414 regNum
= MISCREG_KERNEL_GS_BASE
;
417 regNum
= MISCREG_TSC_AUX
;
420 regNum
= MISCREG_PERF_EVT_SEL0
;
423 regNum
= MISCREG_PERF_EVT_SEL1
;
426 regNum
= MISCREG_PERF_EVT_SEL2
;
429 regNum
= MISCREG_PERF_EVT_SEL3
;
432 regNum
= MISCREG_PERF_EVT_CTR0
;
435 regNum
= MISCREG_PERF_EVT_CTR1
;
438 regNum
= MISCREG_PERF_EVT_CTR2
;
441 regNum
= MISCREG_PERF_EVT_CTR3
;
444 regNum
= MISCREG_SYSCFG
;
447 regNum
= MISCREG_IORR_BASE0
;
450 regNum
= MISCREG_IORR_BASE1
;
453 regNum
= MISCREG_IORR_MASK0
;
456 regNum
= MISCREG_IORR_MASK1
;
459 regNum
= MISCREG_TOP_MEM
;
462 regNum
= MISCREG_TOP_MEM2
;
465 regNum
= MISCREG_VM_CR
;
468 regNum
= MISCREG_IGNNE
;
471 regNum
= MISCREG_SMM_CTL
;
474 regNum
= MISCREG_VM_HSAVE_PA
;
477 return new GeneralProtection(0);
479 //The index is multiplied by the size of a MiscReg so that
480 //any memory dependence calculations will not see these as
482 req
->setPaddr(regNum
* sizeof(MiscReg
));
484 } else if (prefix
== IntAddrPrefixIO
) {
485 // TODO If CPL > IOPL or in virtual mode, check the I/O permission
486 // bitmap in the TSS.
488 Addr IOPort
= vaddr
& ~IntAddrPrefixMask
;
489 // Make sure the address fits in the expected 16 bit IO address
491 assert(!(IOPort
& ~0xFFFF));
492 if (IOPort
== 0xCF8 && req
->getSize() == 4) {
493 req
->setMmapedIpr(true);
494 req
->setPaddr(MISCREG_PCI_CONFIG_ADDRESS
* sizeof(MiscReg
));
495 } else if ((IOPort
& ~mask(2)) == 0xCFC) {
497 tc
->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS
);
498 if (bits(configAddress
, 31, 31)) {
499 req
->setPaddr(PhysAddrPrefixPciConfig
|
500 bits(configAddress
, 30, 0));
503 req
->setPaddr(PhysAddrPrefixIO
| IOPort
);
507 panic("Access to unrecognized internal address space %#x.\n",
512 // Get cr0. This will tell us how to do translation. We'll assume it was
513 // verified to be correct and consistent when set.
514 CR0 cr0
= tc
->readMiscRegNoEffect(MISCREG_CR0
);
516 // If protected mode has been enabled...
518 DPRINTF(TLB
, "In protected mode.\n");
519 Efer efer
= tc
->readMiscRegNoEffect(MISCREG_EFER
);
520 SegAttr csAttr
= tc
->readMiscRegNoEffect(MISCREG_CS_ATTR
);
521 // If we're not in 64-bit mode, do protection/limit checks
522 if (!efer
.lma
|| !csAttr
.longMode
) {
523 DPRINTF(TLB
, "Not in long mode. Checking segment protection.\n");
524 SegAttr attr
= tc
->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg
));
525 if (!attr
.writable
&& write
)
526 return new GeneralProtection(0);
527 if (!attr
.readable
&& !write
&& !execute
)
528 return new GeneralProtection(0);
529 Addr base
= tc
->readMiscRegNoEffect(MISCREG_SEG_BASE(seg
));
530 Addr limit
= tc
->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg
));
531 if (!attr
.expandDown
) {
532 DPRINTF(TLB
, "Checking an expand down segment.\n");
533 // We don't have to worry about the access going around the
534 // end of memory because accesses will be broken up into
535 // pieces at boundaries aligned on sizes smaller than an
536 // entire address space. We do have to worry about the limit
537 // being less than the base.
539 if (limit
< vaddr
+ req
->getSize() && vaddr
< base
)
540 return new GeneralProtection(0);
542 if (limit
< vaddr
+ req
->getSize())
543 return new GeneralProtection(0);
547 if (vaddr
<= limit
|| vaddr
+ req
->getSize() >= base
)
548 return new GeneralProtection(0);
550 if (vaddr
<= limit
&& vaddr
+ req
->getSize() >= base
)
551 return new GeneralProtection(0);
555 // If paging is enabled, do the translation.
557 DPRINTF(TLB
, "Paging enabled.\n");
558 // The vaddr already has the segment base applied.
559 TlbEntry
*entry
= lookup(vaddr
);
561 return new TlbFault(vaddr
);
563 // Do paging protection checks.
564 DPRINTF(TLB
, "Entry found with paddr %#x, doing protection checks.\n", entry
->paddr
);
565 Addr paddr
= entry
->paddr
| (vaddr
& (entry
->size
-1));
566 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, paddr
);
567 req
->setPaddr(paddr
);
570 //Use the address which already has segmentation applied.
571 DPRINTF(TLB
, "Paging disabled.\n");
572 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, vaddr
);
573 req
->setPaddr(vaddr
);
577 DPRINTF(TLB
, "In real mode.\n");
578 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, vaddr
);
579 req
->setPaddr(vaddr
);
585 DTB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
)
587 return TLB::translate
<FakeDTLBFault
>(req
, tc
, write
, false);
591 ITB::translate(RequestPtr
&req
, ThreadContext
*tc
)
593 return TLB::translate
<FakeITLBFault
>(req
, tc
, false, true);
599 DTB::doMmuRegRead(ThreadContext
*tc
, Packet
*pkt
)
601 return tc
->getCpuPtr()->ticks(1);
605 DTB::doMmuRegWrite(ThreadContext
*tc
, Packet
*pkt
)
607 return tc
->getCpuPtr()->ticks(1);
613 TLB::serialize(std::ostream
&os
)
618 TLB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
623 DTB::serialize(std::ostream
&os
)
629 DTB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
631 TLB::unserialize(cp
, section
);
634 /* end namespace X86ISA */ }
637 X86ITBParams::create()
639 return new X86ISA::ITB(this);
643 X86DTBParams::create()
645 return new X86ISA::DTB(this);