summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/tlb.cc61
-rw-r--r--src/arch/x86/tlb.hh16
2 files changed, 52 insertions, 25 deletions
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 33de0129a..52cc3e0ee 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -226,6 +226,40 @@ TLB::translateInt(RequestPtr req, ThreadContext *tc)
}
Fault
+TLB::finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
+{
+ Addr paddr = req->getPaddr();
+
+ // Check for an access to the local APIC
+ if (FullSystem) {
+ LocalApicBase localApicBase =
+ tc->readMiscRegNoEffect(MISCREG_APIC_BASE);
+ AddrRange apicRange(localApicBase.base * PageBytes,
+ (localApicBase.base + 1) * PageBytes - 1);
+
+ if (apicRange.contains(paddr)) {
+ // The Intel developer's manuals say the below restrictions apply,
+ // but the linux kernel, because of a compiler optimization, breaks
+ // them.
+ /*
+ // Check alignment
+ if (paddr & ((32/8) - 1))
+ return new GeneralProtection(0);
+ // Check access size
+ if (req->getSize() != (32/8))
+ return new GeneralProtection(0);
+ */
+ // Force the access to be uncacheable.
+ req->setFlags(Request::UNCACHEABLE);
+ req->setPaddr(x86LocalAPICAddress(tc->contextId(),
+ paddr - apicRange.start()));
+ }
+ }
+
+ return NoFault;
+}
+
+Fault
TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
Mode mode, bool &delayedResponse, bool timing)
{
@@ -366,31 +400,8 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr);
req->setPaddr(vaddr);
}
- // Check for an access to the local APIC
- if (FullSystem) {
- LocalApicBase localApicBase =
- tc->readMiscRegNoEffect(MISCREG_APIC_BASE);
- Addr baseAddr = localApicBase.base * PageBytes;
- Addr paddr = req->getPaddr();
- if (baseAddr <= paddr && baseAddr + PageBytes > paddr) {
- // The Intel developer's manuals say the below restrictions apply,
- // but the linux kernel, because of a compiler optimization, breaks
- // them.
- /*
- // Check alignment
- if (paddr & ((32/8) - 1))
- return new GeneralProtection(0);
- // Check access size
- if (req->getSize() != (32/8))
- return new GeneralProtection(0);
- */
- // Force the access to be uncacheable.
- req->setFlags(Request::UNCACHEABLE);
- req->setPaddr(x86LocalAPICAddress(tc->contextId(),
- paddr - baseAddr));
- }
- }
- return NoFault;
+
+ return finalizePhysical(req, tc, mode);
}
Fault
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
index 39ae240af..4f0d58d5c 100644
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -129,6 +129,22 @@ namespace X86ISA
*/
Fault translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode);
+ /**
+ * Do post-translation physical address finalization.
+ *
+ * Some addresses, for example requests going to the APIC,
+ * need post-translation updates. Such physical addresses are
+ * remapped into a "magic" part of the physical address space
+ * by this method.
+ *
+ * @param req Request to updated in-place.
+ * @param tc Thread context that created the request.
+ * @param mode Request type (read/write/execute).
+ * @return A fault on failure, NoFault otherwise.
+ */
+ Fault finalizePhysical(RequestPtr req, ThreadContext *tc,
+ Mode mode) const;
+
TlbEntry * insert(Addr vpn, TlbEntry &entry);
// Checkpointing