From patchwork Thu Jun 23 05:48:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 639503 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rZrNj2wJmz9t1n for ; Thu, 23 Jun 2016 15:58:13 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.b=V/QoaI4C; dkim-atps=neutral Received: from localhost ([::1]:34448 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bFxeV-00038u-23 for incoming@patchwork.ozlabs.org; Thu, 23 Jun 2016 01:58:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35953) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bFxTv-00077u-A0 for qemu-devel@nongnu.org; Thu, 23 Jun 2016 01:47:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bFxTq-0002aM-BI for qemu-devel@nongnu.org; Thu, 23 Jun 2016 01:47:14 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:33413) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bFxTp-0002Yg-Ln; Thu, 23 Jun 2016 01:47:10 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 3rZr7q1f3cz9t1h; Thu, 23 Jun 2016 15:47:02 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1466660823; bh=btYiGDgjPsHyhmJ9nU/bs5kxSIj7z4uWHnnZC64D+VQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V/QoaI4Cyx/BWqhqIAaNRj0r2pQ9jplAm6UU7zN2LwKvUeGJkg+pxqRbMiDXFZ5KN 1RbsUMhJHXfvc92Z+PcRF8zpOSt1A1OR84qQcx0QEnhgLsvxaD0AWJIUf38Ay9vlPB jVqIUuCYJs8pb3gfhg39g//IloITV57aOTl5B71Q= From: David Gibson To: peter.maydell@linaro.org Date: Thu, 23 Jun 2016 15:48:40 +1000 Message-Id: <1466660926-1544-12-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1466660926-1544-1-git-send-email-david@gibson.dropbear.id.au> References: <1466660926-1544-1-git-send-email-david@gibson.dropbear.id.au> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2401:3900:2:1::2 Subject: [Qemu-devel] [PULL 11/17] ppc: Fix generation if ISI/DSI vs. HV mode X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: agraf@suse.de, qemu-devel@nongnu.org, qemu-ppc@nongnu.org, =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , pbonzini@redhat.com, David Gibson Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 [clg: Merged a fix on POWERPC_EXCP_HDSI fixing the condition on msr_hv, from Andrei Warkentin ] Signed-off-by: Cédric Le Goater Signed-off-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 668da5e..5b7b5e9 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; }