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 "cpu/thread_context.hh"
68 #include "cpu/base.hh"
69 #include "mem/packet_access.hh"
70 #include "mem/request.hh"
71 #include "sim/system.hh"
75 TLB::TLB(const Params
*p
) : SimObject(p
), size(p
->size
)
77 tlb
= new TlbEntry
[size
];
78 std::memset(tlb
, 0, sizeof(TlbEntry
) * size
);
80 for (int x
= 0; x
< size
; x
++)
81 freeList
.push_back(&tlb
[x
]);
85 TLB::insert(Addr vpn
, TlbEntry
&entry
)
87 //TODO Deal with conflicting entries
89 TlbEntry
*newEntry
= NULL
;
90 if (!freeList
.empty()) {
91 newEntry
= freeList
.front();
94 newEntry
= entryList
.back();
98 newEntry
->vaddr
= vpn
;
99 entryList
.push_front(newEntry
);
103 TLB::lookup(Addr va
, bool update_lru
)
105 //TODO make this smarter at some point
106 EntryList::iterator entry
;
107 for (entry
= entryList
.begin(); entry
!= entryList
.end(); entry
++) {
108 if ((*entry
)->vaddr
<= va
&& (*entry
)->vaddr
+ (*entry
)->size
> va
) {
109 DPRINTF(TLB
, "Matched vaddr %#x to entry starting at %#x "
110 "with size %#x.\n", va
, (*entry
)->vaddr
, (*entry
)->size
);
111 TlbEntry
*e
= *entry
;
113 entryList
.erase(entry
);
114 entryList
.push_front(e
);
128 TLB::invalidateNonGlobal()
133 TLB::demapPage(Addr va
)
137 template<class TlbFault
>
139 TLB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
, bool execute
)
141 Addr vaddr
= req
->getVaddr();
142 DPRINTF(TLB
, "Translating vaddr %#x.\n", vaddr
);
143 uint32_t flags
= req
->getFlags();
144 bool storeCheck
= flags
& StoreCheck
;
146 int seg
= flags
& mask(3);
148 //XXX Junk code to surpress the warning
151 // If this is true, we're dealing with a request to read an internal
153 if (seg
== NUM_SEGMENTREGS
) {
154 Addr prefix
= vaddr
& IntAddrPrefixMask
;
155 if (prefix
== IntAddrPrefixCPUID
) {
156 panic("CPUID memory space not yet implemented!\n");
157 } else if (prefix
== IntAddrPrefixMSR
) {
158 req
->setMmapedIpr(true);
160 switch (vaddr
& ~IntAddrPrefixMask
) {
162 regNum
= MISCREG_TSC
;
165 regNum
= MISCREG_MTRRCAP
;
168 regNum
= MISCREG_SYSENTER_CS
;
171 regNum
= MISCREG_SYSENTER_ESP
;
174 regNum
= MISCREG_SYSENTER_EIP
;
177 regNum
= MISCREG_MCG_CAP
;
180 regNum
= MISCREG_MCG_STATUS
;
183 regNum
= MISCREG_MCG_CTL
;
186 regNum
= MISCREG_DEBUG_CTL_MSR
;
189 regNum
= MISCREG_LAST_BRANCH_FROM_IP
;
192 regNum
= MISCREG_LAST_BRANCH_TO_IP
;
195 regNum
= MISCREG_LAST_EXCEPTION_FROM_IP
;
198 regNum
= MISCREG_LAST_EXCEPTION_TO_IP
;
201 regNum
= MISCREG_MTRR_PHYS_BASE_0
;
204 regNum
= MISCREG_MTRR_PHYS_MASK_0
;
207 regNum
= MISCREG_MTRR_PHYS_BASE_1
;
210 regNum
= MISCREG_MTRR_PHYS_MASK_1
;
213 regNum
= MISCREG_MTRR_PHYS_BASE_2
;
216 regNum
= MISCREG_MTRR_PHYS_MASK_2
;
219 regNum
= MISCREG_MTRR_PHYS_BASE_3
;
222 regNum
= MISCREG_MTRR_PHYS_MASK_3
;
225 regNum
= MISCREG_MTRR_PHYS_BASE_4
;
228 regNum
= MISCREG_MTRR_PHYS_MASK_4
;
231 regNum
= MISCREG_MTRR_PHYS_BASE_5
;
234 regNum
= MISCREG_MTRR_PHYS_MASK_5
;
237 regNum
= MISCREG_MTRR_PHYS_BASE_6
;
240 regNum
= MISCREG_MTRR_PHYS_MASK_6
;
243 regNum
= MISCREG_MTRR_PHYS_BASE_7
;
246 regNum
= MISCREG_MTRR_PHYS_MASK_7
;
249 regNum
= MISCREG_MTRR_FIX_64K_00000
;
252 regNum
= MISCREG_MTRR_FIX_16K_80000
;
255 regNum
= MISCREG_MTRR_FIX_16K_A0000
;
258 regNum
= MISCREG_MTRR_FIX_4K_C0000
;
261 regNum
= MISCREG_MTRR_FIX_4K_C8000
;
264 regNum
= MISCREG_MTRR_FIX_4K_D0000
;
267 regNum
= MISCREG_MTRR_FIX_4K_D8000
;
270 regNum
= MISCREG_MTRR_FIX_4K_E0000
;
273 regNum
= MISCREG_MTRR_FIX_4K_E8000
;
276 regNum
= MISCREG_MTRR_FIX_4K_F0000
;
279 regNum
= MISCREG_MTRR_FIX_4K_F8000
;
282 regNum
= MISCREG_PAT
;
285 regNum
= MISCREG_DEF_TYPE
;
288 regNum
= MISCREG_MC0_CTL
;
291 regNum
= MISCREG_MC1_CTL
;
294 regNum
= MISCREG_MC2_CTL
;
297 regNum
= MISCREG_MC3_CTL
;
300 regNum
= MISCREG_MC4_CTL
;
303 regNum
= MISCREG_MC0_STATUS
;
306 regNum
= MISCREG_MC1_STATUS
;
309 regNum
= MISCREG_MC2_STATUS
;
312 regNum
= MISCREG_MC3_STATUS
;
315 regNum
= MISCREG_MC4_STATUS
;
318 regNum
= MISCREG_MC0_ADDR
;
321 regNum
= MISCREG_MC1_ADDR
;
324 regNum
= MISCREG_MC2_ADDR
;
327 regNum
= MISCREG_MC3_ADDR
;
330 regNum
= MISCREG_MC4_ADDR
;
333 regNum
= MISCREG_MC0_MISC
;
336 regNum
= MISCREG_MC1_MISC
;
339 regNum
= MISCREG_MC2_MISC
;
342 regNum
= MISCREG_MC3_MISC
;
345 regNum
= MISCREG_MC4_MISC
;
348 regNum
= MISCREG_EFER
;
351 regNum
= MISCREG_STAR
;
354 regNum
= MISCREG_LSTAR
;
357 regNum
= MISCREG_CSTAR
;
360 regNum
= MISCREG_SF_MASK
;
363 regNum
= MISCREG_FS_BASE
;
366 regNum
= MISCREG_GS_BASE
;
369 regNum
= MISCREG_KERNEL_GS_BASE
;
372 regNum
= MISCREG_TSC_AUX
;
375 regNum
= MISCREG_PERF_EVT_SEL0
;
378 regNum
= MISCREG_PERF_EVT_SEL1
;
381 regNum
= MISCREG_PERF_EVT_SEL2
;
384 regNum
= MISCREG_PERF_EVT_SEL3
;
387 regNum
= MISCREG_PERF_EVT_CTR0
;
390 regNum
= MISCREG_PERF_EVT_CTR1
;
393 regNum
= MISCREG_PERF_EVT_CTR2
;
396 regNum
= MISCREG_PERF_EVT_CTR3
;
399 regNum
= MISCREG_SYSCFG
;
402 regNum
= MISCREG_IORR_BASE0
;
405 regNum
= MISCREG_IORR_BASE1
;
408 regNum
= MISCREG_IORR_MASK0
;
411 regNum
= MISCREG_IORR_MASK1
;
414 regNum
= MISCREG_TOP_MEM
;
417 regNum
= MISCREG_TOP_MEM2
;
420 regNum
= MISCREG_VM_CR
;
423 regNum
= MISCREG_IGNNE
;
426 regNum
= MISCREG_SMM_CTL
;
429 regNum
= MISCREG_VM_HSAVE_PA
;
432 return new GeneralProtection(0);
434 //The index is multiplied by the size of a MiscReg so that
435 //any memory dependence calculations will not see these as
437 req
->setPaddr(regNum
* sizeof(MiscReg
));
440 panic("Access to unrecognized internal address space %#x.\n",
445 // Get cr0. This will tell us how to do translation. We'll assume it was
446 // verified to be correct and consistent when set.
447 CR0 cr0
= tc
->readMiscRegNoEffect(MISCREG_CR0
);
449 // If protected mode has been enabled...
451 Efer efer
= tc
->readMiscRegNoEffect(MISCREG_EFER
);
452 SegAttr csAttr
= tc
->readMiscRegNoEffect(MISCREG_CS_ATTR
);
453 // If we're not in 64-bit mode, do protection/limit checks
454 if (!efer
.lma
|| !csAttr
.longMode
) {
455 SegAttr attr
= tc
->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg
));
456 if (!attr
.writable
&& write
)
457 return new GeneralProtection(0);
458 if (!attr
.readable
&& !write
&& !execute
)
459 return new GeneralProtection(0);
460 Addr base
= tc
->readMiscRegNoEffect(MISCREG_SEG_BASE(seg
));
461 Addr limit
= tc
->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg
));
462 if (!attr
.expandDown
) {
463 // We don't have to worry about the access going around the
464 // end of memory because accesses will be broken up into
465 // pieces at boundaries aligned on sizes smaller than an
466 // entire address space. We do have to worry about the limit
467 // being less than the base.
469 if (limit
< vaddr
+ req
->getSize() && vaddr
< base
)
470 return new GeneralProtection(0);
472 if (limit
< vaddr
+ req
->getSize())
473 return new GeneralProtection(0);
477 if (vaddr
<= limit
|| vaddr
+ req
->getSize() >= base
)
478 return new GeneralProtection(0);
480 if (vaddr
<= limit
&& vaddr
+ req
->getSize() >= base
)
481 return new GeneralProtection(0);
485 // If paging is enabled, do the translation.
487 // The vaddr already has the segment base applied.
488 TlbEntry
*entry
= lookup(vaddr
);
491 return new TlbFault();
493 return new TlbFault(vaddr
);
496 // Do paging protection checks.
497 Addr paddr
= entry
->paddr
| (vaddr
& mask(12));
498 req
->setPaddr(paddr
);
501 //Use the address which already has segmentation applied.
502 req
->setPaddr(vaddr
);
506 req
->setPaddr(vaddr
);
512 DTB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
)
514 return TLB::translate
<FakeDTLBFault
>(req
, tc
, write
, false);
518 ITB::translate(RequestPtr
&req
, ThreadContext
*tc
)
520 return TLB::translate
<FakeITLBFault
>(req
, tc
, false, true);
526 DTB::doMmuRegRead(ThreadContext
*tc
, Packet
*pkt
)
528 return tc
->getCpuPtr()->ticks(1);
532 DTB::doMmuRegWrite(ThreadContext
*tc
, Packet
*pkt
)
534 return tc
->getCpuPtr()->ticks(1);
540 TLB::serialize(std::ostream
&os
)
545 TLB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
550 DTB::serialize(std::ostream
&os
)
556 DTB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
558 TLB::unserialize(cp
, section
);
561 /* end namespace X86ISA */ }
564 X86ITBParams::create()
566 return new X86ISA::ITB(this);
570 X86DTBParams::create()
572 return new X86ISA::DTB(this);