diff options
Diffstat (limited to 'src/arch/x86')
-rw-r--r-- | src/arch/x86/tlb.cc | 61 | ||||
-rw-r--r-- | src/arch/x86/tlb.hh | 16 |
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 |