From patchwork Thu Jul 12 13:36:48 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 170660 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A49352C0208 for ; Thu, 12 Jul 2012 23:37:36 +1000 (EST) Received: from localhost ([::1]:35944 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SpJaI-0002iw-KI for incoming@patchwork.ozlabs.org; Thu, 12 Jul 2012 09:37:34 -0400 Received: from eggs.gnu.org ([208.118.235.92]:43624) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SpJZz-0002ib-4q for qemu-devel@nongnu.org; Thu, 12 Jul 2012 09:37:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SpJZr-0006oy-LW for qemu-devel@nongnu.org; Thu, 12 Jul 2012 09:37:15 -0400 Received: from mnementh.archaic.org.uk ([81.2.115.146]:41606) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SpJZr-0006no-De for qemu-devel@nongnu.org; Thu, 12 Jul 2012 09:37:07 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1SpJZg-0000UD-Hu; Thu, 12 Jul 2012 14:36:56 +0100 From: Peter Maydell To: Blue Swirl Date: Thu, 12 Jul 2012 14:36:48 +0100 Message-Id: <1342100216-1832-8-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1342100216-1832-1-git-send-email-peter.maydell@linaro.org> References: <1342100216-1832-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 81.2.115.146 Cc: qemu-devel@nongnu.org, Anthony Liguori , Paul Brook Subject: [Qemu-devel] [PATCH 07/15] target-arm: Implement privileged-execute-never (PXN) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Implement the privileged-execute-never (PXN) translation table bit. It is implementation-defined whether this is implemented, so we give it its own ARM_FEATURE_ flag. LPAE requires PXN, so add also an LPAE feature flag and the implication logic, as a placeholder for actually implementing LPAE at a later date. Signed-off-by: Peter Maydell --- target-arm/cpu.c | 4 ++++ target-arm/cpu.h | 2 ++ target-arm/helper.c | 32 ++++++++++++++++++++------------ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index ae57953..526e725 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -192,6 +192,9 @@ void arm_cpu_realize(ARMCPU *cpu) if (arm_feature(env, ARM_FEATURE_VFP3)) { set_feature(env, ARM_FEATURE_VFP); } + if (arm_feature(env, ARM_FEATURE_LPAE)) { + set_feature(env, ARM_FEATURE_PXN); + } register_cp_regs_for_features(cpu); } @@ -532,6 +535,7 @@ static void cortex_a15_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_V7MP); set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + set_feature(&cpu->env, ARM_FEATURE_LPAE); cpu->midr = 0x412fc0f1; cpu->reset_fpsid = 0x410430f0; cpu->mvfr0 = 0x10110222; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index aadfca0..82cad4b 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -386,6 +386,8 @@ enum arm_features { ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */ ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */ ARM_FEATURE_MPIDR, /* has cp15 MPIDR */ + ARM_FEATURE_PXN, /* has Privileged Execute Never bit */ + ARM_FEATURE_LPAE, /* has Large Physical Address Extension */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/helper.c b/target-arm/helper.c index 0015bee..e51b038 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1935,9 +1935,10 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, uint32_t table; uint32_t desc; uint32_t xn; + uint32_t pxn = 0; int type; int ap; - int domain; + int domain = 0; int domain_prot; uint32_t phys_addr; @@ -1946,27 +1947,27 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, table = get_level1_table_address(env, address); desc = ldl_phys(table); type = (desc & 3); - if (type == 0) { - /* Section translation fault. */ + if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) { + /* Section translation fault, or attempt to use the encoding + * which is Reserved on implementations without PXN. + */ code = 5; - domain = 0; goto do_fault; - } else if (type == 2 && (desc & (1 << 18))) { - /* Supersection. */ - domain = 0; - } else { - /* Section or page. */ + } + if ((type == 1) || !(desc & (1 << 18))) { + /* Page or Section. */ domain = (desc >> 5) & 0x0f; } domain_prot = (env->cp15.c3 >> (domain * 2)) & 3; if (domain_prot == 0 || domain_prot == 2) { - if (type == 2) + if (type != 1) { code = 9; /* Section domain fault. */ - else + } else { code = 11; /* Page domain fault. */ + } goto do_fault; } - if (type == 2) { + if (type != 1) { if (desc & (1 << 18)) { /* Supersection. */ phys_addr = (desc & 0xff000000) | (address & 0x00ffffff); @@ -1978,8 +1979,12 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, } ap = ((desc >> 10) & 3) | ((desc >> 13) & 4); xn = desc & (1 << 4); + pxn = desc & 1; code = 13; } else { + if (arm_feature(env, ARM_FEATURE_PXN)) { + pxn = (desc >> 2) & 1; + } /* Lookup l2 entry. */ table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc); desc = ldl_phys(table); @@ -2007,6 +2012,9 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, if (domain_prot == 3) { *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; } else { + if (pxn && !is_user) { + xn = 1; + } if (xn && access_type == 2) goto do_fault;