From 64b216f074160ffea37e34c027b893f82d9ee2b2 Mon Sep 17 00:00:00 2001 From: Bugra Eryilmaz Date: Tue, 17 Dec 2024 13:09:25 +0000 Subject: [PATCH] feat: unpriviledged memory operation support --- .../CommonQEMU/Slices/AbstractInstruction.hpp | 6 ++++++ components/Decoder/Effects.cpp | 2 +- .../SemanticActions/ExclusiveMonitorAction.cpp | 2 +- components/Decoder/SemanticActions/LDPAction.cpp | 2 +- components/Decoder/Validations.cpp | 4 ++-- components/Decoder/encodings/LoadStore.cpp | 13 +++++++++++-- components/MMU/MMUImpl.cpp | 7 ++++--- components/MMU/pageWalk.cpp | 5 +++-- components/uArch/microArch.cpp | 2 +- components/uArch/uArchImpl.cpp | 2 +- components/uFetch/uFetch.cpp | 4 ++-- core/qemu/api.h | 2 +- core/qemu/mai_api.hpp | 14 +++++++------- 13 files changed, 41 insertions(+), 24 deletions(-) diff --git a/components/CommonQEMU/Slices/AbstractInstruction.hpp b/components/CommonQEMU/Slices/AbstractInstruction.hpp index 4e5b55b4..3372503c 100644 --- a/components/CommonQEMU/Slices/AbstractInstruction.hpp +++ b/components/CommonQEMU/Slices/AbstractInstruction.hpp @@ -18,6 +18,11 @@ struct AbstractInstruction : public boost::counted_base bool theExclusive; public: + + bool theUnprivAccess; + virtual void setUnprivAccess() { theUnprivAccess = true; } + virtual bool unprivAccess() const { return theUnprivAccess; } + virtual bool isExclusive() const { return theExclusive; } virtual void setExclusive() { theExclusive = true; } virtual void describe(std::ostream& anOstream) const; @@ -32,6 +37,7 @@ struct AbstractInstruction : public boost::counted_base AbstractInstruction() : theInsnSourceLevel(eL1I) , theExclusive(false) + , theUnprivAccess(false) { } virtual ~AbstractInstruction() {} diff --git a/components/Decoder/Effects.cpp b/components/Decoder/Effects.cpp index 60d2f75e..c7a4aa3c 100644 --- a/components/Decoder/Effects.cpp +++ b/components/Decoder/Effects.cpp @@ -1250,7 +1250,7 @@ struct MarkExclusiveMonitor : public Effect uint64_t addr = anInstruction.operand(theAddressCode); Flexus::Qemu::Processor c = Flexus::Qemu::Processor::getProcessor(anInstruction.cpu()); PhysicalMemoryAddress pAddress = - PhysicalMemoryAddress(c.translate_va2pa(VirtualMemoryAddress((addr >> 6) << 6))); + PhysicalMemoryAddress(c.translate_va2pa(VirtualMemoryAddress((addr >> 6) << 6), anInstruction.unprivAccess())); anInstruction.core()->markExclusiveGlobal(pAddress, theSize, kMonitorSet); anInstruction.core()->markExclusiveLocal(pAddress, theSize, kMonitorSet); diff --git a/components/Decoder/SemanticActions/ExclusiveMonitorAction.cpp b/components/Decoder/SemanticActions/ExclusiveMonitorAction.cpp index 9b782079..819c436e 100644 --- a/components/Decoder/SemanticActions/ExclusiveMonitorAction.cpp +++ b/components/Decoder/SemanticActions/ExclusiveMonitorAction.cpp @@ -51,7 +51,7 @@ struct ExclusiveMonitorAction : public PredicatedSemanticAction uint64_t addr = theInstruction->operand(theAddressCode); Flexus::Qemu::Processor c = Flexus::Qemu::Processor::getProcessor(theInstruction->cpu()); PhysicalMemoryAddress pAddress = - PhysicalMemoryAddress(c.translate_va2pa(VirtualMemoryAddress((addr >> 6) << 6))); + PhysicalMemoryAddress(c.translate_va2pa(VirtualMemoryAddress((addr >> 6) << 6), theInstruction->unprivAccess())); // passed &= core()->isExclusiveGlobal(pAddress, theSize); // passed &= core()->isExclusiveVA(VirtualMemoryAddress(addr), theSize); diff --git a/components/Decoder/SemanticActions/LDPAction.cpp b/components/Decoder/SemanticActions/LDPAction.cpp index 10e8b8e9..d159399e 100644 --- a/components/Decoder/SemanticActions/LDPAction.cpp +++ b/components/Decoder/SemanticActions/LDPAction.cpp @@ -75,7 +75,7 @@ struct LDPAction : public PredicatedSemanticAction Flexus::Qemu::Processor c = Flexus::Qemu::Processor::getProcessor(theInstruction->cpu()); uint64_t addr = theInstruction->operand(kAddress); uint64_t addr_final = addr + (size >> 3) - 1; - bits value_new = c.read_va(VirtualMemoryAddress(addr), size >> 3); + bits value_new = c.read_va(VirtualMemoryAddress(addr), size >> 3, theInstruction->unprivAccess()); if (((addr & 0x1000) != (addr_final & 0x1000)) && value != value_new) { DBG_(Iface, (<< theInstruction->identify() << " Correcting LDP access across pages at address: " << std::hex diff --git a/components/Decoder/Validations.cpp b/components/Decoder/Validations.cpp index ed83c552..a71b1419 100644 --- a/components/Decoder/Validations.cpp +++ b/components/Decoder/Validations.cpp @@ -86,11 +86,11 @@ validateMemory::operator()() theSize_orig -= theSize_extra; vaddr_final = (VirtualMemoryAddress)(vaddr_final & ~0xFFFULL); } - PhysicalMemoryAddress paddr = c.translate_va2pa(vaddr); + PhysicalMemoryAddress paddr = c.translate_va2pa(vaddr, theInstruction->unprivAccess()); bits qemu = c.read_pa(paddr, theSize_orig); if (theSize_extra) { DBG_Assert((qemu >> (theSize_orig * 8)) == 0); - PhysicalMemoryAddress paddr_spill = c.translate_va2pa(vaddr_final); + PhysicalMemoryAddress paddr_spill = c.translate_va2pa(vaddr_final, theInstruction->unprivAccess()); qemu |= c.read_pa(paddr_spill, theSize_extra) << (theSize_orig * 8); } diff --git a/components/Decoder/encodings/LoadStore.cpp b/components/Decoder/encodings/LoadStore.cpp index 24abc5e0..23021a4f 100644 --- a/components/Decoder/encodings/LoadStore.cpp +++ b/components/Decoder/encodings/LoadStore.cpp @@ -685,8 +685,10 @@ STR(archcode const& aFetchedOpcode, uint32_t aCPU, int64_t aSequenceNo) case 0x2: { if (extract32(aFetchedOpcode.theOpcode, 21, 1) == 1) index = kRegOffset; // LDR x1, [x2, x3, LSL #2] - else + else { index = kSignedOffset; // LDTR x1, [x2, #4] + inst->setUnprivAccess(); + } break; } case 0x3: index = kPreIndex; break; @@ -786,6 +788,7 @@ LDR(archcode const& aFetchedOpcode, uint32_t aCPU, int64_t aSequenceNo) bool is_unsigned = extract32(aFetchedOpcode.theOpcode, 24, 1); uint64_t imm = 0, regsize = 0; eIndex index = kSignedOffset; + bool unprivAccess = false; if ((opc & 0x2) == 0) { regsize = (size == 0x3) ? 64 : 32; @@ -807,8 +810,10 @@ LDR(archcode const& aFetchedOpcode, uint32_t aCPU, int64_t aSequenceNo) case 0x2: { if (extract32(aFetchedOpcode.theOpcode, 21, 1) == 1) index = kRegOffset; // LDR x1, [x2, x3, LSL #2] - else + else { index = kSignedOffset; // LDTR x1, [x2, #4] + unprivAccess = true; + } break; } case 0x3: index = kPreIndex; break; @@ -829,6 +834,10 @@ LDR(archcode const& aFetchedOpcode, uint32_t aCPU, int64_t aSequenceNo) inst->setClass(clsLoad, codeLoad); eAccType acctype = kAccType_NORMAL; + if (unprivAccess) { + inst->setUnprivAccess(); + } + std::vector> rs_deps(1), rs2_deps(1); predicated_action ex, sh, wb; diff --git a/components/MMU/MMUImpl.cpp b/components/MMU/MMUImpl.cpp index a6306972..0271e475 100644 --- a/components/MMU/MMUImpl.cpp +++ b/components/MMU/MMUImpl.cpp @@ -374,7 +374,7 @@ MMUComponent::busCycle() std::pair entry = (item->isInstr() ? theInstrTLB : theDataTLB).lookUp(item); if (cfg.PerfectTLB || !mmu_is_init) { - PhysicalMemoryAddress perfectPaddr(API::qemu_api.translate_va2pa(flexusIndex(), item->theVaddr)); + PhysicalMemoryAddress perfectPaddr(API::qemu_api.translate_va2pa(flexusIndex(), item->theVaddr, (item->getInstruction() ? item->getInstruction()->unprivAccess(): false))); entry.first = true; entry.second = perfectPaddr; if (perfectPaddr == 0xFFFFFFFFFFFFFFFF) item->setPagefault(); @@ -391,7 +391,7 @@ MMUComponent::busCycle() // item exists so mark hit item->setHit(); - PhysicalMemoryAddress perfectPaddr(API::qemu_api.translate_va2pa(flexusIndex(), item->theVaddr)); + PhysicalMemoryAddress perfectPaddr(API::qemu_api.translate_va2pa(flexusIndex(), item->theVaddr, (item->getInstruction() ? item->getInstruction()->unprivAccess(): false))); // item->thePaddr = (PhysicalMemoryAddress)(entry.second | (item->theVaddr & ~(PAGEMASK))); item->thePaddr = perfectPaddr; @@ -416,7 +416,8 @@ MMUComponent::busCycle() alreadyPW.insert(pageAddr); thePageWalkEntries.push(item); } else { - PhysicalMemoryAddress perfectPaddr(API::qemu_api.translate_va2pa(flexusIndex(), item->theVaddr)); + PhysicalMemoryAddress perfectPaddr( + API::qemu_api.translate_va2pa(flexusIndex(), item->theVaddr, (item->getInstruction() ? item->getInstruction()->unprivAccess(): false))); item->setHit(); item->thePaddr = perfectPaddr; if (item->isInstr()) diff --git a/components/MMU/pageWalk.cpp b/components/MMU/pageWalk.cpp index 4c974d7b..11736ee2 100644 --- a/components/MMU/pageWalk.cpp +++ b/components/MMU/pageWalk.cpp @@ -51,7 +51,7 @@ PageWalk::preWalk(TranslationTransport& aTranslation) DBG_(VVerb, (<< "preWalking " << basicPointer->theVaddr)); if (statefulPointer->currentLookupLevel == 0) { - PhysicalMemoryAddress magicPaddr(API::qemu_api.translate_va2pa(theNode, basicPointer->theVaddr)); + PhysicalMemoryAddress magicPaddr(API::qemu_api.translate_va2pa(theNode, basicPointer->theVaddr, (basicPointer->getInstruction() ? basicPointer->getInstruction()->unprivAccess(): false))); DBG_(VVerb, (<< " QEMU Translated: " << std::hex << basicPointer->theVaddr << std::dec << ", to: " << std::hex << magicPaddr << std::dec)); @@ -335,7 +335,8 @@ PageWalk::cycle() (<< "stlb hit " << (VirtualMemoryAddress)(tr->theVaddr & (PAGEMASK)) << ":" << tr->theID << std::hex << ":" << res.second)); tr->setHit(); - PhysicalMemoryAddress perfectPaddr(API::qemu_api.translate_va2pa(mmu->flexusIndex(), tr->theVaddr)); + PhysicalMemoryAddress perfectPaddr(API::qemu_api.translate_va2pa(mmu->flexusIndex(), tr->theVaddr, (tr->getInstruction() ? tr->getInstruction()->unprivAccess(): false))); + // tr->thePaddr = (PhysicalMemoryAddress)(res.second | (tr->theVaddr & ~(PAGEMASK))); tr->thePaddr = perfectPaddr; mmu->stlb_accesses++; } else { diff --git a/components/uArch/microArch.cpp b/components/uArch/microArch.cpp index 53b556af..0442f285 100644 --- a/components/uArch/microArch.cpp +++ b/components/uArch/microArch.cpp @@ -165,7 +165,7 @@ class microArchImpl : public microArch Flexus::SharedTypes::Translation xlat; xlat.theVaddr = op->theVAddr; xlat.theType = Flexus::SharedTypes::Translation::eStore; - op->theExtendedValue = theCPU.read_va(xlat.theVaddr, op->theSize); + op->theExtendedValue = theCPU.read_va(xlat.theVaddr, op->theSize, (op->theInstruction ? op->theInstruction->unprivAccess() : false)); } else if (op->theOperation == kStoreReply && !op->theSideEffect && !op->theAtomic) { // Need to inform ValueTracker that this store is complete bits value = op->theValue; diff --git a/components/uArch/uArchImpl.cpp b/components/uArch/uArchImpl.cpp index ef76fc1b..482b077e 100644 --- a/components/uArch/uArchImpl.cpp +++ b/components/uArch/uArchImpl.cpp @@ -241,7 +241,7 @@ class FLEXUS_COMPONENT(uArch) { PhysicalMemoryAddress magicTranslation = - Flexus::Qemu::Processor::getProcessor(theMicroArch->core()).translate_va2pa(aTranslate->theVaddr); + Flexus::Qemu::Processor::getProcessor(theMicroArch->core()).translate_va2pa(aTranslate->theVaddr, (aTranslate->getInstruction() ? aTranslate->getInstruction()->unprivAccess(): false)); if (aTranslate->thePaddr == magicTranslation || magicTranslation == kUnresolved) { DBG_(Iface, diff --git a/components/uFetch/uFetch.cpp b/components/uFetch/uFetch.cpp index 42ce0d06..b960c095 100644 --- a/components/uFetch/uFetch.cpp +++ b/components/uFetch/uFetch.cpp @@ -166,7 +166,7 @@ class FLEXUS_COMPONENT(uFetch) DBG_Assert(tr->isDone() || tr->isHit()); DBG_(VVerb, Comp(*this)(<< "Updating translation response for " << tr->theVaddr << " @ cpu index " << flexusIndex())); - PhysicalMemoryAddress magicTranslation = cpu(tr->theIndex).translate_va2pa(tr->theVaddr); + PhysicalMemoryAddress magicTranslation = cpu(tr->theIndex).translate_va2pa(tr->theVaddr, (tr->getInstruction() ? tr->getInstruction()->unprivAccess(): false)); if (tr->thePaddr == magicTranslation || magicTranslation == nuArch::kUnresolved) { DBG_(VVerb, @@ -276,7 +276,7 @@ class FLEXUS_COMPONENT(uFetch) Flexus::SharedTypes::Translation xlat; xlat.theVaddr = vaddr; xlat.theType = Translation::eFetch; - xlat.thePaddr = cpu(anIndex).translate_va2pa(xlat.theVaddr); + xlat.thePaddr = cpu(anIndex).translate_va2pa(xlat.theVaddr, false); return xlat.thePaddr; } diff --git a/core/qemu/api.h b/core/qemu/api.h index 58097820..53c8abf3 100644 --- a/core/qemu/api.h +++ b/core/qemu/api.h @@ -224,7 +224,7 @@ struct cycles_opts // typedef int (*QEMU_MEM_OP_IS_DATA_t) (generic_transaction_t *mop); // typedef int (*QEMU_MEM_OP_IS_WRITE_t)(generic_transaction_t *mop); -typedef physical_address_t (*QEMU_GET_PA_t)(size_t core_index, logical_address_t va); +typedef physical_address_t (*QEMU_GET_PA_t)(size_t core_index, logical_address_t va, bool unprivileged); typedef uint64_t (*QEMU_READ_REG_t)(size_t core_index, register_type_t reg, size_t reg_info); typedef uint64_t (*QEMU_READ_SYSREG_t)(size_t core_index, uint8_t op0, diff --git a/core/qemu/mai_api.hpp b/core/qemu/mai_api.hpp index 254d22f0..da21a6eb 100644 --- a/core/qemu/mai_api.hpp +++ b/core/qemu/mai_api.hpp @@ -49,12 +49,12 @@ class Processor uint64_t advance(bool count_time = true) { return API::qemu_api.cpu_exec(core_index, count_time); } - PhysicalMemoryAddress translate_va2pa(VirtualMemoryAddress addr) + PhysicalMemoryAddress translate_va2pa(VirtualMemoryAddress addr, bool unprivileged) { - return PhysicalMemoryAddress(API::qemu_api.translate_va2pa(core_index, addr)); + return PhysicalMemoryAddress(API::qemu_api.translate_va2pa(core_index, addr, unprivileged)); } - bits read_va(VirtualMemoryAddress anAddress, size_t size) + bits read_va(VirtualMemoryAddress anAddress, size_t size, bool unprivileged) { VirtualMemoryAddress finalAddress(((uint64_t)(anAddress) + size - 1) & ~0xFFF); @@ -63,21 +63,21 @@ class Processor bits value1, value2; size_t partial = finalAddress - anAddress; // Partial is the size of the first access. value1 = read_pa( - PhysicalMemoryAddress(API::qemu_api.translate_va2pa(core_index, API::logical_address_t(anAddress))), + PhysicalMemoryAddress(API::qemu_api.translate_va2pa(core_index, API::logical_address_t(anAddress), unprivileged)), partial); value2 = read_pa( PhysicalMemoryAddress(API::qemu_api.translate_va2pa(core_index, - API::logical_address_t(finalAddress))), size - partial); + API::logical_address_t(finalAddress), unprivileged)), size - partial); // * 8 convert bytes to bits. value2 si appended to value2 value2 = (value2 << (partial * 8)) | value1; return value2; } return read_pa( - PhysicalMemoryAddress(API::qemu_api.translate_va2pa(core_index, API::logical_address_t(anAddress))), + PhysicalMemoryAddress(API::qemu_api.translate_va2pa(core_index, API::logical_address_t(anAddress), unprivileged)), size); } - uint32_t fetch_inst(VirtualMemoryAddress addr) { return static_cast(read_va(addr, 4)); } + uint32_t fetch_inst(VirtualMemoryAddress addr) { return static_cast(read_va(addr, 4, false)); } bits read_pa(PhysicalMemoryAddress anAddress, size_t aSize) const {