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
) : SimObject(p
), 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::invalidateNonGlobal()
153 DPRINTF(TLB
, "Invalidating all non global entries.\n");
154 EntryList::iterator entryIt
;
155 for (entryIt
= entryList
.begin(); entryIt
!= entryList
.end();) {
156 if (!(*entryIt
)->global
) {
157 freeList
.push_back(*entryIt
);
158 entryList
.erase(entryIt
++);
166 TLB::demapPage(Addr va
)
170 template<class TlbFault
>
172 TLB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
, bool execute
)
174 Addr vaddr
= req
->getVaddr();
175 DPRINTF(TLB
, "Translating vaddr %#x.\n", vaddr
);
176 uint32_t flags
= req
->getFlags();
177 bool storeCheck
= flags
& StoreCheck
;
179 int seg
= flags
& mask(4);
181 //XXX Junk code to surpress the warning
184 // If this is true, we're dealing with a request to read an internal
186 if (seg
== SEGMENT_REG_MS
) {
187 DPRINTF(TLB
, "Addresses references internal memory.\n");
188 Addr prefix
= vaddr
& IntAddrPrefixMask
;
189 if (prefix
== IntAddrPrefixCPUID
) {
190 panic("CPUID memory space not yet implemented!\n");
191 } else if (prefix
== IntAddrPrefixMSR
) {
192 req
->setMmapedIpr(true);
194 switch (vaddr
& ~IntAddrPrefixMask
) {
196 regNum
= MISCREG_TSC
;
199 regNum
= MISCREG_MTRRCAP
;
202 regNum
= MISCREG_SYSENTER_CS
;
205 regNum
= MISCREG_SYSENTER_ESP
;
208 regNum
= MISCREG_SYSENTER_EIP
;
211 regNum
= MISCREG_MCG_CAP
;
214 regNum
= MISCREG_MCG_STATUS
;
217 regNum
= MISCREG_MCG_CTL
;
220 regNum
= MISCREG_DEBUG_CTL_MSR
;
223 regNum
= MISCREG_LAST_BRANCH_FROM_IP
;
226 regNum
= MISCREG_LAST_BRANCH_TO_IP
;
229 regNum
= MISCREG_LAST_EXCEPTION_FROM_IP
;
232 regNum
= MISCREG_LAST_EXCEPTION_TO_IP
;
235 regNum
= MISCREG_MTRR_PHYS_BASE_0
;
238 regNum
= MISCREG_MTRR_PHYS_MASK_0
;
241 regNum
= MISCREG_MTRR_PHYS_BASE_1
;
244 regNum
= MISCREG_MTRR_PHYS_MASK_1
;
247 regNum
= MISCREG_MTRR_PHYS_BASE_2
;
250 regNum
= MISCREG_MTRR_PHYS_MASK_2
;
253 regNum
= MISCREG_MTRR_PHYS_BASE_3
;
256 regNum
= MISCREG_MTRR_PHYS_MASK_3
;
259 regNum
= MISCREG_MTRR_PHYS_BASE_4
;
262 regNum
= MISCREG_MTRR_PHYS_MASK_4
;
265 regNum
= MISCREG_MTRR_PHYS_BASE_5
;
268 regNum
= MISCREG_MTRR_PHYS_MASK_5
;
271 regNum
= MISCREG_MTRR_PHYS_BASE_6
;
274 regNum
= MISCREG_MTRR_PHYS_MASK_6
;
277 regNum
= MISCREG_MTRR_PHYS_BASE_7
;
280 regNum
= MISCREG_MTRR_PHYS_MASK_7
;
283 regNum
= MISCREG_MTRR_FIX_64K_00000
;
286 regNum
= MISCREG_MTRR_FIX_16K_80000
;
289 regNum
= MISCREG_MTRR_FIX_16K_A0000
;
292 regNum
= MISCREG_MTRR_FIX_4K_C0000
;
295 regNum
= MISCREG_MTRR_FIX_4K_C8000
;
298 regNum
= MISCREG_MTRR_FIX_4K_D0000
;
301 regNum
= MISCREG_MTRR_FIX_4K_D8000
;
304 regNum
= MISCREG_MTRR_FIX_4K_E0000
;
307 regNum
= MISCREG_MTRR_FIX_4K_E8000
;
310 regNum
= MISCREG_MTRR_FIX_4K_F0000
;
313 regNum
= MISCREG_MTRR_FIX_4K_F8000
;
316 regNum
= MISCREG_PAT
;
319 regNum
= MISCREG_DEF_TYPE
;
322 regNum
= MISCREG_MC0_CTL
;
325 regNum
= MISCREG_MC1_CTL
;
328 regNum
= MISCREG_MC2_CTL
;
331 regNum
= MISCREG_MC3_CTL
;
334 regNum
= MISCREG_MC4_CTL
;
337 regNum
= MISCREG_MC0_STATUS
;
340 regNum
= MISCREG_MC1_STATUS
;
343 regNum
= MISCREG_MC2_STATUS
;
346 regNum
= MISCREG_MC3_STATUS
;
349 regNum
= MISCREG_MC4_STATUS
;
352 regNum
= MISCREG_MC0_ADDR
;
355 regNum
= MISCREG_MC1_ADDR
;
358 regNum
= MISCREG_MC2_ADDR
;
361 regNum
= MISCREG_MC3_ADDR
;
364 regNum
= MISCREG_MC4_ADDR
;
367 regNum
= MISCREG_MC0_MISC
;
370 regNum
= MISCREG_MC1_MISC
;
373 regNum
= MISCREG_MC2_MISC
;
376 regNum
= MISCREG_MC3_MISC
;
379 regNum
= MISCREG_MC4_MISC
;
382 regNum
= MISCREG_EFER
;
385 regNum
= MISCREG_STAR
;
388 regNum
= MISCREG_LSTAR
;
391 regNum
= MISCREG_CSTAR
;
394 regNum
= MISCREG_SF_MASK
;
397 regNum
= MISCREG_FS_BASE
;
400 regNum
= MISCREG_GS_BASE
;
403 regNum
= MISCREG_KERNEL_GS_BASE
;
406 regNum
= MISCREG_TSC_AUX
;
409 regNum
= MISCREG_PERF_EVT_SEL0
;
412 regNum
= MISCREG_PERF_EVT_SEL1
;
415 regNum
= MISCREG_PERF_EVT_SEL2
;
418 regNum
= MISCREG_PERF_EVT_SEL3
;
421 regNum
= MISCREG_PERF_EVT_CTR0
;
424 regNum
= MISCREG_PERF_EVT_CTR1
;
427 regNum
= MISCREG_PERF_EVT_CTR2
;
430 regNum
= MISCREG_PERF_EVT_CTR3
;
433 regNum
= MISCREG_SYSCFG
;
436 regNum
= MISCREG_IORR_BASE0
;
439 regNum
= MISCREG_IORR_BASE1
;
442 regNum
= MISCREG_IORR_MASK0
;
445 regNum
= MISCREG_IORR_MASK1
;
448 regNum
= MISCREG_TOP_MEM
;
451 regNum
= MISCREG_TOP_MEM2
;
454 regNum
= MISCREG_VM_CR
;
457 regNum
= MISCREG_IGNNE
;
460 regNum
= MISCREG_SMM_CTL
;
463 regNum
= MISCREG_VM_HSAVE_PA
;
466 return new GeneralProtection(0);
468 //The index is multiplied by the size of a MiscReg so that
469 //any memory dependence calculations will not see these as
471 req
->setPaddr(regNum
* sizeof(MiscReg
));
474 panic("Access to unrecognized internal address space %#x.\n",
479 // Get cr0. This will tell us how to do translation. We'll assume it was
480 // verified to be correct and consistent when set.
481 CR0 cr0
= tc
->readMiscRegNoEffect(MISCREG_CR0
);
483 // If protected mode has been enabled...
485 DPRINTF(TLB
, "In protected mode.\n");
486 Efer efer
= tc
->readMiscRegNoEffect(MISCREG_EFER
);
487 SegAttr csAttr
= tc
->readMiscRegNoEffect(MISCREG_CS_ATTR
);
488 // If we're not in 64-bit mode, do protection/limit checks
489 if (!efer
.lma
|| !csAttr
.longMode
) {
490 DPRINTF(TLB
, "Not in long mode. Checking segment protection.\n");
491 SegAttr attr
= tc
->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg
));
492 if (!attr
.writable
&& write
)
493 return new GeneralProtection(0);
494 if (!attr
.readable
&& !write
&& !execute
)
495 return new GeneralProtection(0);
496 Addr base
= tc
->readMiscRegNoEffect(MISCREG_SEG_BASE(seg
));
497 Addr limit
= tc
->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg
));
498 if (!attr
.expandDown
) {
499 DPRINTF(TLB
, "Checking an expand down segment.\n");
500 // We don't have to worry about the access going around the
501 // end of memory because accesses will be broken up into
502 // pieces at boundaries aligned on sizes smaller than an
503 // entire address space. We do have to worry about the limit
504 // being less than the base.
506 if (limit
< vaddr
+ req
->getSize() && vaddr
< base
)
507 return new GeneralProtection(0);
509 if (limit
< vaddr
+ req
->getSize())
510 return new GeneralProtection(0);
514 if (vaddr
<= limit
|| vaddr
+ req
->getSize() >= base
)
515 return new GeneralProtection(0);
517 if (vaddr
<= limit
&& vaddr
+ req
->getSize() >= base
)
518 return new GeneralProtection(0);
522 // If paging is enabled, do the translation.
524 DPRINTF(TLB
, "Paging enabled.\n");
525 // The vaddr already has the segment base applied.
526 TlbEntry
*entry
= lookup(vaddr
);
528 return new TlbFault(vaddr
);
530 // Do paging protection checks.
531 DPRINTF(TLB
, "Entry found with paddr %#x, doing protection checks.\n", entry
->paddr
);
532 Addr paddr
= entry
->paddr
| (vaddr
& (entry
->size
-1));
533 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, paddr
);
534 req
->setPaddr(paddr
);
537 //Use the address which already has segmentation applied.
538 DPRINTF(TLB
, "Paging disabled.\n");
539 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, vaddr
);
540 req
->setPaddr(vaddr
);
544 DPRINTF(TLB
, "In real mode.\n");
545 DPRINTF(TLB
, "Translated %#x -> %#x.\n", vaddr
, vaddr
);
546 req
->setPaddr(vaddr
);
552 DTB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
)
554 return TLB::translate
<FakeDTLBFault
>(req
, tc
, write
, false);
558 ITB::translate(RequestPtr
&req
, ThreadContext
*tc
)
560 return TLB::translate
<FakeITLBFault
>(req
, tc
, false, true);
566 DTB::doMmuRegRead(ThreadContext
*tc
, Packet
*pkt
)
568 return tc
->getCpuPtr()->ticks(1);
572 DTB::doMmuRegWrite(ThreadContext
*tc
, Packet
*pkt
)
574 return tc
->getCpuPtr()->ticks(1);
580 TLB::serialize(std::ostream
&os
)
585 TLB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
590 DTB::serialize(std::ostream
&os
)
596 DTB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
598 TLB::unserialize(cp
, section
);
601 /* end namespace X86ISA */ }
604 X86ITBParams::create()
606 return new X86ISA::ITB(this);
610 X86DTBParams::create()
612 return new X86ISA::DTB(this);