From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56178) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCKNX-0001Bn-Bo for qemu-devel@nongnu.org; Mon, 13 Jun 2016 01:25:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bCKNR-0001zs-Af for qemu-devel@nongnu.org; Mon, 13 Jun 2016 01:25:38 -0400 Received: from 8.mo178.mail-out.ovh.net ([46.105.74.227]:33252) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCKNQ-0001zh-VA for qemu-devel@nongnu.org; Mon, 13 Jun 2016 01:25:33 -0400 Received: from player791.ha.ovh.net (b9.ovh.net [213.186.33.59]) by mo178.mail-out.ovh.net (Postfix) with ESMTP id 706E91000BB1 for ; Mon, 13 Jun 2016 07:25:32 +0200 (CEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 13 Jun 2016 07:24:51 +0200 Message-Id: <1465795496-15071-6-git-send-email-clg@kaod.org> In-Reply-To: <1465795496-15071-1-git-send-email-clg@kaod.org> References: <1465795496-15071-1-git-send-email-clg@kaod.org> Subject: [Qemu-devel] [PATCH 05/10] ppc: Fix generation if ISI/DSI vs. HV mode List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: David Gibson Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Benjamin Herrenschmidt , Cedric Le Goater From: Benjamin Herrenschmidt Under some circumstances, we need to direct ISI and DSI interrupts at the hypervisor, turning them into HISI/HDSI, and using different SPRs (HDSISR and HDAR) depending on the combination of MSR_DR and the corresponding VPM bits in LPCR. This moves part of the code into helpers that are fixed to select the right exception type and registers. On pre-P7 processors, LPCR is 0 which provides the old behaviour of directing the interrupts at the supervisor. Thanks to Andrei Warkentin for finding a bug when HV=1 Signed-off-by: Benjamin Herrenschmidt Reviewed-by: David Gibson --- target-ppc/mmu-hash64.c | 69 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 668da5e22653..072a952c8bd5 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -613,6 +613,47 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, return 0; } +static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env, + uint64_t error_code) +{ + bool vpm; + + if (msr_ir) { + vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1); + } else { + vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM0); + } + if (vpm && !msr_hv) { + cs->exception_index = POWERPC_EXCP_HISI; + } else { + cs->exception_index = POWERPC_EXCP_ISI; + } + env->error_code = error_code; +} + +static void ppc_hash64_set_dsi(CPUState *cs, CPUPPCState *env, uint64_t dar, + uint64_t dsisr) +{ + bool vpm; + + if (msr_dr) { + vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1); + } else { + vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM0); + } + if (vpm && msr_hv) { + cs->exception_index = POWERPC_EXCP_HDSI; + env->spr[SPR_HDAR] = dar; + env->spr[SPR_HDSISR] = dsisr; + } else { + cs->exception_index = POWERPC_EXCP_DSI; + env->spr[SPR_DAR] = dar; + env->spr[SPR_DSISR] = dsisr; + } + env->error_code = 0; +} + + int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx) { @@ -623,7 +664,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, hwaddr pte_offset; ppc_hash_pte64_t pte; int pp_prot, amr_prot, prot; - uint64_t new_pte1; + uint64_t new_pte1, dsisr; const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC}; hwaddr raddr; @@ -657,26 +698,21 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, /* 3. Check for segment level no-execute violation */ if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) { - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x10000000; + ppc_hash64_set_isi(cs, env, 0x10000000); return 1; } /* 4. Locate the PTE in the hash table */ pte_offset = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte); if (pte_offset == -1) { + dsisr = 0x40000000; if (rwx == 2) { - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x40000000; + ppc_hash64_set_isi(cs, env, dsisr); } else { - cs->exception_index = POWERPC_EXCP_DSI; - env->error_code = 0; - env->spr[SPR_DAR] = eaddr; if (rwx == 1) { - env->spr[SPR_DSISR] = 0x42000000; - } else { - env->spr[SPR_DSISR] = 0x40000000; + dsisr |= 0x02000000; } + ppc_hash64_set_dsi(cs, env, eaddr, dsisr); } return 1; } @@ -705,14 +741,9 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, /* Access right violation */ qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n"); if (rwx == 2) { - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x08000000; + ppc_hash64_set_isi(cs, env, 0x08000000); } else { - target_ulong dsisr = 0; - - cs->exception_index = POWERPC_EXCP_DSI; - env->error_code = 0; - env->spr[SPR_DAR] = eaddr; + dsisr = 0; if (need_prot[rwx] & ~pp_prot) { dsisr |= 0x08000000; } @@ -722,7 +753,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, if (need_prot[rwx] & ~amr_prot) { dsisr |= 0x00200000; } - env->spr[SPR_DSISR] = dsisr; + ppc_hash64_set_dsi(cs, env, eaddr, dsisr); } return 1; } -- 2.1.4