diff options
Diffstat (limited to 'src/arch/sparc/faults.cc')
-rw-r--r-- | src/arch/sparc/faults.cc | 232 |
1 files changed, 112 insertions, 120 deletions
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 5466115d0..0b6a28927 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -629,49 +629,46 @@ FastInstructionAccessMMUMiss::invoke(ThreadContext *tc, } Process *p = tc->getProcessPtr(); - TlbEntry entry; - bool success = p->pTable->lookup(vaddr, entry); - if (!success) { - panic("Tried to execute unmapped address %#x.\n", vaddr); - } else { - Addr alignedvaddr = p->pTable->pageAlign(vaddr); - - // Grab fields used during instruction translation to figure out - // which context to use. - uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); - - // Inside a VM, a real address is the address that guest OS would - // interpret to be a physical address. To map to the physical address, - // it still needs to undergo a translation. The instruction - // translation code in the SPARC ITLB code assumes that the context is - // zero (kernel-level) if real addressing is being used. - bool is_real_address = !bits(tlbdata, 4); - - // The SPARC ITLB code assumes that traps are executed in context - // zero so we carry that assumption through here. - bool trapped = bits(tlbdata, 18, 16) > 0; - - // The primary context acts as a PASID. It allows the MMU to - // distinguish between virtual addresses that would alias to the - // same physical address (if two or more processes shared the same - // virtual address mapping). - int primary_context = bits(tlbdata, 47, 32); - - // The partition id distinguishes between virtualized environments. - int const partition_id = 0; - - // Given the assumptions in the translateInst code in the SPARC ITLB, - // the logic works out to the following for the context. - int context_id = (is_real_address || trapped) ? 0 : primary_context; - - // Insert the TLB entry. - // The entry specifying whether the address is "real" is set to - // false for syscall emulation mode regardless of whether the - // address is real in preceding code. Not sure sure that this is - // correct, but also not sure if it matters at all. - dynamic_cast<TLB *>(tc->getITBPtr())-> - insert(alignedvaddr, partition_id, context_id, false, entry.pte); - } + TlbEntry *entry = p->pTable->lookup(vaddr); + panic_if(!entry, "Tried to execute unmapped address %#x.\n", vaddr); + + Addr alignedvaddr = p->pTable->pageAlign(vaddr); + + // Grab fields used during instruction translation to figure out + // which context to use. + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); + + // Inside a VM, a real address is the address that guest OS would + // interpret to be a physical address. To map to the physical address, + // it still needs to undergo a translation. The instruction + // translation code in the SPARC ITLB code assumes that the context is + // zero (kernel-level) if real addressing is being used. + bool is_real_address = !bits(tlbdata, 4); + + // The SPARC ITLB code assumes that traps are executed in context + // zero so we carry that assumption through here. + bool trapped = bits(tlbdata, 18, 16) > 0; + + // The primary context acts as a PASID. It allows the MMU to + // distinguish between virtual addresses that would alias to the + // same physical address (if two or more processes shared the same + // virtual address mapping). + int primary_context = bits(tlbdata, 47, 32); + + // The partition id distinguishes between virtualized environments. + int const partition_id = 0; + + // Given the assumptions in the translateInst code in the SPARC ITLB, + // the logic works out to the following for the context. + int context_id = (is_real_address || trapped) ? 0 : primary_context; + + // Insert the TLB entry. + // The entry specifying whether the address is "real" is set to + // false for syscall emulation mode regardless of whether the + // address is real in preceding code. Not sure sure that this is + // correct, but also not sure if it matters at all. + dynamic_cast<TLB *>(tc->getITBPtr())-> + insert(alignedvaddr, partition_id, context_id, false, entry->pte); } void @@ -683,83 +680,78 @@ FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst) } Process *p = tc->getProcessPtr(); - TlbEntry entry; - bool success = p->pTable->lookup(vaddr, entry); - if (!success) { - if (p->fixupStackFault(vaddr)) - success = p->pTable->lookup(vaddr, entry); - } - if (!success) { - panic("Tried to access unmapped address %#x.\n", vaddr); - } else { - Addr alignedvaddr = p->pTable->pageAlign(vaddr); - - // Grab fields used during data translation to figure out - // which context to use. - uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); - - // The primary context acts as a PASID. It allows the MMU to - // distinguish between virtual addresses that would alias to the - // same physical address (if two or more processes shared the same - // virtual address mapping). There's a secondary context used in the - // DTLB translation code, but it should __probably__ be zero for - // syscall emulation code. (The secondary context is used by Solaris - // to allow kernel privilege code to access user space code: - // [ISBN 0-13-022496-0]:PG199.) - int primary_context = bits(tlbdata, 47, 32); - - // "Hyper-Privileged Mode" is in use. There are three main modes of - // operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and - // User Mode. - int hpriv = bits(tlbdata, 0); - - // Reset, Error and Debug state is in use. Something horrible has - // happened or the system is operating in Reset Mode. - int red = bits(tlbdata, 1); - - // Inside a VM, a real address is the address that guest OS would - // interpret to be a physical address. To map to the physical address, - // it still needs to undergo a translation. The instruction - // translation code in the SPARC ITLB code assumes that the context is - // zero (kernel-level) if real addressing is being used. - int is_real_address = !bits(tlbdata, 5); - - // Grab the address space identifier register from the thread context. - // XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for - // MISCREG_ASI causes me to think that the ASI register implementation - // might be bugged. The NoEffect variant changes the ASI register - // value in the architectural state while the normal variant changes - // the context field in the thread context's currently decoded request - // but does not directly affect the ASI register value in the - // architectural state. The ASI values and the context field in the - // request packet seem to have completely different uses. - MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI); - ASI asi = static_cast<ASI>(reg_asi); - - // The SPARC DTLB code assumes that traps are executed in context - // zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also - // an assumption that the nucleus address space is being used, but - // the context is the relevant issue since we need to pass it to TLB. - bool trapped = bits(tlbdata, 18, 16) > 0; - - // Given the assumptions in the translateData code in the SPARC DTLB, - // the logic works out to the following for the context. - int context_id = ((!hpriv && !red && is_real_address) || - asiIsReal(asi) || - (trapped && asi == ASI_IMPLICIT)) - ? 0 : primary_context; - - // The partition id distinguishes between virtualized environments. - int const partition_id = 0; - - // Insert the TLB entry. - // The entry specifying whether the address is "real" is set to - // false for syscall emulation mode regardless of whether the - // address is real in preceding code. Not sure sure that this is - // correct, but also not sure if it matters at all. - dynamic_cast<TLB *>(tc->getDTBPtr())-> - insert(alignedvaddr, partition_id, context_id, false, entry.pte); - } + TlbEntry *entry = p->pTable->lookup(vaddr); + if (!entry && p->fixupStackFault(vaddr)) + entry = p->pTable->lookup(vaddr); + panic_if(!entry, "Tried to access unmapped address %#x.\n", vaddr); + + Addr alignedvaddr = p->pTable->pageAlign(vaddr); + + // Grab fields used during data translation to figure out + // which context to use. + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); + + // The primary context acts as a PASID. It allows the MMU to + // distinguish between virtual addresses that would alias to the + // same physical address (if two or more processes shared the same + // virtual address mapping). There's a secondary context used in the + // DTLB translation code, but it should __probably__ be zero for + // syscall emulation code. (The secondary context is used by Solaris + // to allow kernel privilege code to access user space code: + // [ISBN 0-13-022496-0]:PG199.) + int primary_context = bits(tlbdata, 47, 32); + + // "Hyper-Privileged Mode" is in use. There are three main modes of + // operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and + // User Mode. + int hpriv = bits(tlbdata, 0); + + // Reset, Error and Debug state is in use. Something horrible has + // happened or the system is operating in Reset Mode. + int red = bits(tlbdata, 1); + + // Inside a VM, a real address is the address that guest OS would + // interpret to be a physical address. To map to the physical address, + // it still needs to undergo a translation. The instruction + // translation code in the SPARC ITLB code assumes that the context is + // zero (kernel-level) if real addressing is being used. + int is_real_address = !bits(tlbdata, 5); + + // Grab the address space identifier register from the thread context. + // XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for + // MISCREG_ASI causes me to think that the ASI register implementation + // might be bugged. The NoEffect variant changes the ASI register + // value in the architectural state while the normal variant changes + // the context field in the thread context's currently decoded request + // but does not directly affect the ASI register value in the + // architectural state. The ASI values and the context field in the + // request packet seem to have completely different uses. + MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI); + ASI asi = static_cast<ASI>(reg_asi); + + // The SPARC DTLB code assumes that traps are executed in context + // zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also + // an assumption that the nucleus address space is being used, but + // the context is the relevant issue since we need to pass it to TLB. + bool trapped = bits(tlbdata, 18, 16) > 0; + + // Given the assumptions in the translateData code in the SPARC DTLB, + // the logic works out to the following for the context. + int context_id = ((!hpriv && !red && is_real_address) || + asiIsReal(asi) || + (trapped && asi == ASI_IMPLICIT)) + ? 0 : primary_context; + + // The partition id distinguishes between virtualized environments. + int const partition_id = 0; + + // Insert the TLB entry. + // The entry specifying whether the address is "real" is set to + // false for syscall emulation mode regardless of whether the + // address is real in preceding code. Not sure sure that this is + // correct, but also not sure if it matters at all. + dynamic_cast<TLB *>(tc->getDTBPtr())-> + insert(alignedvaddr, partition_id, context_id, false, entry->pte); } void |