diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/ppc/excp_helper.c | 1 | ||||
-rw-r--r-- | target/ppc/kvm.c | 5 | ||||
-rw-r--r-- | target/ppc/mmu-radix64.c | 67 | ||||
-rw-r--r-- | target/ppc/mmu-radix64.h | 1 | ||||
-rw-r--r-- | target/ppc/mmu_helper.c | 3 |
5 files changed, 61 insertions, 16 deletions
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 3a9f086..e6009e7 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -283,6 +283,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) * precise in the MSR. */ msr |= 0x00100000; + env->spr[SPR_BOOKE_ESR] = ESR_FP; break; case POWERPC_EXCP_INVAL: LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index f2f7c53..f7a7ea5 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -2445,6 +2445,7 @@ static int kvm_ppc_register_host_cpu_type(void) .class_init = kvmppc_host_cpu_class_init, }; PowerPCCPUClass *pvr_pcc; + ObjectClass *oc; DeviceClass *dc; int i; @@ -2455,6 +2456,9 @@ static int kvm_ppc_register_host_cpu_type(void) type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); type_register(&type_info); + oc = object_class_by_name(type_info.name); + g_assert(oc); + #if defined(TARGET_PPC64) type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host"); type_info.parent = TYPE_SPAPR_CPU_CORE, @@ -2474,7 +2478,6 @@ static int kvm_ppc_register_host_cpu_type(void) dc = DEVICE_CLASS(ppc_cpu_get_family_class(pvr_pcc)); for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { if (strcmp(ppc_cpu_aliases[i].alias, dc->desc) == 0) { - ObjectClass *oc = OBJECT_CLASS(pvr_pcc); char *suffix; ppc_cpu_aliases[i].model = g_strdup(object_class_get_name(oc)); diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 69fde65..bbd37e3 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -147,11 +147,10 @@ static void ppc_radix64_set_rc(PowerPCCPU *cpu, int rwx, uint64_t pte, } } -static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, int rwx, vaddr eaddr, +static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, vaddr eaddr, uint64_t base_addr, uint64_t nls, hwaddr *raddr, int *psize, - int *fault_cause, int *prot, - hwaddr *pte_addr) + int *fault_cause, hwaddr *pte_addr) { CPUState *cs = CPU(cpu); uint64_t index, pde; @@ -177,10 +176,6 @@ static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, int rwx, vaddr eaddr, uint64_t rpn = pde & R_PTE_RPN; uint64_t mask = (1UL << *psize) - 1; - if (ppc_radix64_check_prot(cpu, rwx, pde, fault_cause, prot)) { - return 0; /* Protection Denied Access */ - } - /* Or high bits of rpn and low bits to ea to form whole real addr */ *raddr = (rpn & ~mask) | (eaddr & mask); *pte_addr = base_addr + (index * sizeof(pde)); @@ -188,9 +183,8 @@ static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, int rwx, vaddr eaddr, } /* Next Level of Radix Tree */ - return ppc_radix64_walk_tree(cpu, rwx, eaddr, pde & R_PDE_NLB, - pde & R_PDE_NLS, raddr, psize, - fault_cause, prot, pte_addr); + return ppc_radix64_walk_tree(cpu, eaddr, pde & R_PDE_NLB, pde & R_PDE_NLS, + raddr, psize, fault_cause, pte_addr); } int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, @@ -241,11 +235,11 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ page_size = PRTBE_R_GET_RTS(prtbe0); - pte = ppc_radix64_walk_tree(cpu, rwx, eaddr & R_EADDR_MASK, + pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, - &raddr, &page_size, &fault_cause, &prot, - &pte_addr); - if (!pte) { + &raddr, &page_size, &fault_cause, &pte_addr); + if (!pte || ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, &prot)) { + /* Couldn't get pte or access denied due to protection */ ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); return 1; } @@ -257,3 +251,48 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, prot, mmu_idx, 1UL << page_size); return 0; } + +hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + hwaddr raddr, pte_addr; + uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte; + int page_size, fault_cause = 0; + + /* Handle Real Mode */ + if (msr_dr == 0) { + /* In real mode top 4 effective addr bits (mostly) ignored */ + return eaddr & 0x0FFFFFFFFFFFFFFFULL; + } + + /* Virtual Mode Access - get the fully qualified address */ + if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) { + return -1; + } + + /* Get Process Table */ + patbe = vhc->get_patbe(cpu->vhyp); + + /* Index Process Table by PID to Find Corresponding Process Table Entry */ + offset = pid * sizeof(struct prtb_entry); + size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12); + if (offset >= size) { + /* offset exceeds size of the process table */ + return -1; + } + prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset); + + /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ + page_size = PRTBE_R_GET_RTS(prtbe0); + pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, + prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, + &raddr, &page_size, &fault_cause, &pte_addr); + if (!pte) { + return -1; + } + + return raddr & TARGET_PAGE_MASK; +} diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index 1d5c7cf..0ecf063 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -46,6 +46,7 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); +hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); static inline int ppc_radix64_get_prot_eaa(uint64_t pte) { diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 65d1c86..b7b9088 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -30,6 +30,7 @@ #include "helper_regs.h" #include "qemu/error-report.h" #include "mmu-book3s-v3.h" +#include "mmu-radix64.h" //#define DEBUG_MMU //#define DEBUG_BATS @@ -1432,7 +1433,7 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return ppc_hash64_get_phys_page_debug(cpu, addr); case POWERPC_MMU_VER_3_00: if (ppc64_radix_guest(ppc_env_get_cpu(env))) { - /* TODO - Unsupported */ + return ppc_radix64_get_phys_page_debug(cpu, addr); } else { return ppc_hash64_get_phys_page_debug(cpu, addr); } |