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
) : MemObject(p
), walker(name(), this), 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::Walker::doNext(uint64_t data
, PacketPtr
&write
)
87 assert(state
!= Ready
&& state
!= Waiting
);
119 panic("Unknown page table walker state %d!\n");
125 TLB::Walker::buildReadPacket(Addr addr
)
127 readRequest
.setPhys(addr
, size
, PHYSICAL
| uncachable
? UNCACHEABLE
: 0);
128 readPacket
.reinitFromRequest();
131 TLB::walker::buildWritePacket(Addr addr
)
133 writeRequest
.setPhys(addr
, size
, PHYSICAL
| uncachable
? UNCACHEABLE
: 0);
134 writePacket
.reinitFromRequest();
137 TLB::Walker::WalkerPort::recvTiming(PacketPtr pkt
)
139 if (pkt
->isResponse() && !pkt
->wasNacked()) {
142 assert(walker
->state
== Waiting
);
144 walker
->state
= walker
->nextState
;
145 walker
->nextState
= Ready
;
147 if (walker
->doNext(pkt
, write
)) {
148 packet
= &walker
->packet
;
149 port
->sendTiming(packet
);
152 writes
.push_back(write
);
154 while (!port
->blocked() && writes
.size()) {
155 if (port
->sendTiming(writes
.front())) {
163 } else if (pkt
->wasNacked()) {
165 if (!sendTiming(pkt
)) {
166 if (pkt
->isWrite()) {
167 writes
.push_front(pkt
);
175 TLB::Walker::WalkerPort::recvAtomic(PacketPtr pkt
)
181 TLB::Walker::WalkerPort::recvFunctional(PacketPtr pkt
)
187 TLB::Walker::WalkerPort::recvStatusChange(Status status
)
189 if (status
== RangeChange
) {
190 if (!snoopRangeSent
) {
191 snoopRangeSent
= true;
192 sendStatusChange(Port::RangeChange
);
197 panic("Unexpected recvStatusChange.\n");
201 TLB::Walker::WalkerPort::recvRetry()
204 if (!sendTiming(packet
)) {
210 TLB::getPort(const std::string
&if_name
, int idx
)
212 if (if_name
== "walker_port")
215 panic("No tlb port named %s!\n", if_name
);
219 TLB::insert(Addr vpn
, TlbEntry
&entry
)
221 //TODO Deal with conflicting entries
223 TlbEntry
*newEntry
= NULL
;
224 if (!freeList
.empty()) {
225 newEntry
= freeList
.front();
226 freeList
.pop_front();
228 newEntry
= entryList
.back();
229 entryList
.pop_back();
232 newEntry
->vaddr
= vpn
;
233 entryList
.push_front(newEntry
);
237 TLB::lookup(Addr va
, bool update_lru
)
239 //TODO make this smarter at some point
240 EntryList::iterator entry
;
241 for (entry
= entryList
.begin(); entry
!= entryList
.end(); entry
++) {
242 if ((*entry
)->vaddr
<= va
&& (*entry
)->vaddr
+ (*entry
)->size
> va
) {
243 DPRINTF(TLB
, "Matched vaddr %#x to entry starting at %#x "
244 "with size %#x.\n", va
, (*entry
)->vaddr
, (*entry
)->size
);
245 TlbEntry
*e
= *entry
;
247 entryList
.erase(entry
);
248 entryList
.push_front(e
);
262 TLB::invalidateNonGlobal()
267 TLB::demapPage(Addr va
)
271 template<class TlbFault
>
273 TLB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
, bool execute
)
275 Addr vaddr
= req
->getVaddr();
276 DPRINTF(TLB
, "Translating vaddr %#x.\n", vaddr
);
277 uint32_t flags
= req
->getFlags();
278 bool storeCheck
= flags
& StoreCheck
;
280 int seg
= flags
& mask(3);
282 //XXX Junk code to surpress the warning
285 // If this is true, we're dealing with a request to read an internal
287 if (seg
== SEGMENT_REG_INT
) {
288 Addr prefix
= vaddr
& IntAddrPrefixMask
;
289 if (prefix
== IntAddrPrefixCPUID
) {
290 panic("CPUID memory space not yet implemented!\n");
291 } else if (prefix
== IntAddrPrefixMSR
) {
292 req
->setMmapedIpr(true);
294 switch (vaddr
& ~IntAddrPrefixMask
) {
296 regNum
= MISCREG_TSC
;
299 regNum
= MISCREG_MTRRCAP
;
302 regNum
= MISCREG_SYSENTER_CS
;
305 regNum
= MISCREG_SYSENTER_ESP
;
308 regNum
= MISCREG_SYSENTER_EIP
;
311 regNum
= MISCREG_MCG_CAP
;
314 regNum
= MISCREG_MCG_STATUS
;
317 regNum
= MISCREG_MCG_CTL
;
320 regNum
= MISCREG_DEBUG_CTL_MSR
;
323 regNum
= MISCREG_LAST_BRANCH_FROM_IP
;
326 regNum
= MISCREG_LAST_BRANCH_TO_IP
;
329 regNum
= MISCREG_LAST_EXCEPTION_FROM_IP
;
332 regNum
= MISCREG_LAST_EXCEPTION_TO_IP
;
335 regNum
= MISCREG_MTRR_PHYS_BASE_0
;
338 regNum
= MISCREG_MTRR_PHYS_MASK_0
;
341 regNum
= MISCREG_MTRR_PHYS_BASE_1
;
344 regNum
= MISCREG_MTRR_PHYS_MASK_1
;
347 regNum
= MISCREG_MTRR_PHYS_BASE_2
;
350 regNum
= MISCREG_MTRR_PHYS_MASK_2
;
353 regNum
= MISCREG_MTRR_PHYS_BASE_3
;
356 regNum
= MISCREG_MTRR_PHYS_MASK_3
;
359 regNum
= MISCREG_MTRR_PHYS_BASE_4
;
362 regNum
= MISCREG_MTRR_PHYS_MASK_4
;
365 regNum
= MISCREG_MTRR_PHYS_BASE_5
;
368 regNum
= MISCREG_MTRR_PHYS_MASK_5
;
371 regNum
= MISCREG_MTRR_PHYS_BASE_6
;
374 regNum
= MISCREG_MTRR_PHYS_MASK_6
;
377 regNum
= MISCREG_MTRR_PHYS_BASE_7
;
380 regNum
= MISCREG_MTRR_PHYS_MASK_7
;
383 regNum
= MISCREG_MTRR_FIX_64K_00000
;
386 regNum
= MISCREG_MTRR_FIX_16K_80000
;
389 regNum
= MISCREG_MTRR_FIX_16K_A0000
;
392 regNum
= MISCREG_MTRR_FIX_4K_C0000
;
395 regNum
= MISCREG_MTRR_FIX_4K_C8000
;
398 regNum
= MISCREG_MTRR_FIX_4K_D0000
;
401 regNum
= MISCREG_MTRR_FIX_4K_D8000
;
404 regNum
= MISCREG_MTRR_FIX_4K_E0000
;
407 regNum
= MISCREG_MTRR_FIX_4K_E8000
;
410 regNum
= MISCREG_MTRR_FIX_4K_F0000
;
413 regNum
= MISCREG_MTRR_FIX_4K_F8000
;
416 regNum
= MISCREG_PAT
;
419 regNum
= MISCREG_DEF_TYPE
;
422 regNum
= MISCREG_MC0_CTL
;
425 regNum
= MISCREG_MC1_CTL
;
428 regNum
= MISCREG_MC2_CTL
;
431 regNum
= MISCREG_MC3_CTL
;
434 regNum
= MISCREG_MC4_CTL
;
437 regNum
= MISCREG_MC0_STATUS
;
440 regNum
= MISCREG_MC1_STATUS
;
443 regNum
= MISCREG_MC2_STATUS
;
446 regNum
= MISCREG_MC3_STATUS
;
449 regNum
= MISCREG_MC4_STATUS
;
452 regNum
= MISCREG_MC0_ADDR
;
455 regNum
= MISCREG_MC1_ADDR
;
458 regNum
= MISCREG_MC2_ADDR
;
461 regNum
= MISCREG_MC3_ADDR
;
464 regNum
= MISCREG_MC4_ADDR
;
467 regNum
= MISCREG_MC0_MISC
;
470 regNum
= MISCREG_MC1_MISC
;
473 regNum
= MISCREG_MC2_MISC
;
476 regNum
= MISCREG_MC3_MISC
;
479 regNum
= MISCREG_MC4_MISC
;
482 regNum
= MISCREG_EFER
;
485 regNum
= MISCREG_STAR
;
488 regNum
= MISCREG_LSTAR
;
491 regNum
= MISCREG_CSTAR
;
494 regNum
= MISCREG_SF_MASK
;
497 regNum
= MISCREG_FS_BASE
;
500 regNum
= MISCREG_GS_BASE
;
503 regNum
= MISCREG_KERNEL_GS_BASE
;
506 regNum
= MISCREG_TSC_AUX
;
509 regNum
= MISCREG_PERF_EVT_SEL0
;
512 regNum
= MISCREG_PERF_EVT_SEL1
;
515 regNum
= MISCREG_PERF_EVT_SEL2
;
518 regNum
= MISCREG_PERF_EVT_SEL3
;
521 regNum
= MISCREG_PERF_EVT_CTR0
;
524 regNum
= MISCREG_PERF_EVT_CTR1
;
527 regNum
= MISCREG_PERF_EVT_CTR2
;
530 regNum
= MISCREG_PERF_EVT_CTR3
;
533 regNum
= MISCREG_SYSCFG
;
536 regNum
= MISCREG_IORR_BASE0
;
539 regNum
= MISCREG_IORR_BASE1
;
542 regNum
= MISCREG_IORR_MASK0
;
545 regNum
= MISCREG_IORR_MASK1
;
548 regNum
= MISCREG_TOP_MEM
;
551 regNum
= MISCREG_TOP_MEM2
;
554 regNum
= MISCREG_VM_CR
;
557 regNum
= MISCREG_IGNNE
;
560 regNum
= MISCREG_SMM_CTL
;
563 regNum
= MISCREG_VM_HSAVE_PA
;
566 return new GeneralProtection(0);
568 //The index is multiplied by the size of a MiscReg so that
569 //any memory dependence calculations will not see these as
571 req
->setPaddr(regNum
* sizeof(MiscReg
));
574 panic("Access to unrecognized internal address space %#x.\n",
579 // Get cr0. This will tell us how to do translation. We'll assume it was
580 // verified to be correct and consistent when set.
581 CR0 cr0
= tc
->readMiscRegNoEffect(MISCREG_CR0
);
583 // If protected mode has been enabled...
585 Efer efer
= tc
->readMiscRegNoEffect(MISCREG_EFER
);
586 SegAttr csAttr
= tc
->readMiscRegNoEffect(MISCREG_CS_ATTR
);
587 // If we're not in 64-bit mode, do protection/limit checks
588 if (!efer
.lma
|| !csAttr
.longMode
) {
589 SegAttr attr
= tc
->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg
));
590 if (!attr
.writable
&& write
)
591 return new GeneralProtection(0);
592 if (!attr
.readable
&& !write
&& !execute
)
593 return new GeneralProtection(0);
594 Addr base
= tc
->readMiscRegNoEffect(MISCREG_SEG_BASE(seg
));
595 Addr limit
= tc
->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg
));
596 if (!attr
.expandDown
) {
597 // We don't have to worry about the access going around the
598 // end of memory because accesses will be broken up into
599 // pieces at boundaries aligned on sizes smaller than an
600 // entire address space. We do have to worry about the limit
601 // being less than the base.
603 if (limit
< vaddr
+ req
->getSize() && vaddr
< base
)
604 return new GeneralProtection(0);
606 if (limit
< vaddr
+ req
->getSize())
607 return new GeneralProtection(0);
611 if (vaddr
<= limit
|| vaddr
+ req
->getSize() >= base
)
612 return new GeneralProtection(0);
614 if (vaddr
<= limit
&& vaddr
+ req
->getSize() >= base
)
615 return new GeneralProtection(0);
619 // If paging is enabled, do the translation.
621 // The vaddr already has the segment base applied.
622 TlbEntry
*entry
= lookup(vaddr
);
625 return new TlbFault();
627 return new TlbFault(vaddr
);
630 // Do paging protection checks.
631 Addr paddr
= entry
->paddr
| (vaddr
& mask(12));
632 req
->setPaddr(paddr
);
635 //Use the address which already has segmentation applied.
636 req
->setPaddr(vaddr
);
640 req
->setPaddr(vaddr
);
646 DTB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
)
648 return TLB::translate
<FakeDTLBFault
>(req
, tc
, write
, false);
652 ITB::translate(RequestPtr
&req
, ThreadContext
*tc
)
654 return TLB::translate
<FakeITLBFault
>(req
, tc
, false, true);
660 DTB::doMmuRegRead(ThreadContext
*tc
, Packet
*pkt
)
662 return tc
->getCpuPtr()->ticks(1);
666 DTB::doMmuRegWrite(ThreadContext
*tc
, Packet
*pkt
)
668 return tc
->getCpuPtr()->ticks(1);
674 TLB::serialize(std::ostream
&os
)
679 TLB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
684 DTB::serialize(std::ostream
&os
)
690 DTB::unserialize(Checkpoint
*cp
, const std::string
§ion
)
692 TLB::unserialize(cp
, section
);
695 /* end namespace X86ISA */ }
698 X86ITBParams::create()
700 return new X86ISA::ITB(this);
704 X86DTBParams::create()
706 return new X86ISA::DTB(this);