From patchwork Thu Jul 12 13:36:52 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 170681 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 6F07F2C02BD for ; Fri, 13 Jul 2012 00:44:29 +1000 (EST) Received: from localhost ([::1]:36859 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SpJaU-0003EJ-BJ for incoming@patchwork.ozlabs.org; Thu, 12 Jul 2012 09:37:46 -0400 Received: from eggs.gnu.org ([208.118.235.92]:43628) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SpJZz-0002ic-A3 for qemu-devel@nongnu.org; Thu, 12 Jul 2012 09:37:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SpJZs-0006p6-7k 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-TX for qemu-devel@nongnu.org; Thu, 12 Jul 2012 09:37:08 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1SpJZg-0000UL-Q6; Thu, 12 Jul 2012 14:36:56 +0100 From: Peter Maydell To: Blue Swirl Date: Thu, 12 Jul 2012 14:36:52 +0100 Message-Id: <1342100216-1832-12-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 11/15] target-arm: Add 64 bit PAR, TTBR0, TTBR1 for LPAE 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 Under LPAE, the cp15 registers PAR, TTBR0 and TTBR1 are extended to 64 bits, with a 64 bit (MRRC/MCRR) access path to read the full width of the register. Add the state fields for the top half and the 64 bit access path. Actual use of the top half of the register will come with the addition of the long-descriptor translation table format support. For the PAR we also need to correct the masking applied for 32 bit writes (there are no bits reserved if LPAE is implemented) and clear the high half when doing a 32 bit result VA-to-PA lookup. Signed-off-by: Peter Maydell --- target-arm/cpu.h | 7 +++- target-arm/helper.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++- target-arm/machine.c | 6 ++++ 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 3c5d2be..191895c 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -113,7 +113,9 @@ typedef struct CPUARMState { uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */ uint32_t c1_scr; /* secure config register. */ uint32_t c2_base0; /* MMU translation table base 0. */ - uint32_t c2_base1; /* MMU translation table base 1. */ + uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */ + uint32_t c2_base1; /* MMU translation table base 0. */ + uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */ uint32_t c2_control; /* MMU translation table base control. */ uint32_t c2_mask; /* MMU translation table base selection mask. */ uint32_t c2_base_mask; /* MMU translation table base 0 mask. */ @@ -127,6 +129,7 @@ typedef struct CPUARMState { uint32_t c6_insn; /* Fault address registers. */ uint32_t c6_data; uint32_t c7_par; /* Translation result. */ + uint32_t c7_par_hi; /* Translation result, high 32 bits */ uint32_t c9_insn; /* Cache lockdown registers. */ uint32_t c9_data; uint32_t c9_pmcr; /* performance monitor control register */ @@ -638,7 +641,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model) #define cpu_signal_handler cpu_arm_signal_handler #define cpu_list arm_cpu_list -#define CPU_SAVE_VERSION 8 +#define CPU_SAVE_VERSION 9 /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel diff --git a/target-arm/helper.c b/target-arm/helper.c index 0cf7b8d..6bb6767 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -491,7 +491,9 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - if (arm_feature(env, ARM_FEATURE_V7)) { + if (arm_feature(env, ARM_FEATURE_LPAE)) { + env->cp15.c7_par = value; + } else if (arm_feature(env, ARM_FEATURE_V7)) { env->cp15.c7_par = value & 0xfffff6ff; } else { env->cp15.c7_par = value & 0xfffff1ff; @@ -528,6 +530,7 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) ((ret & (12 << 1)) >> 6) | ((ret & 0xf) << 1) | 1; } + env->cp15.c7_par_hi = 0; return 0; } #endif @@ -871,6 +874,69 @@ static const ARMCPRegInfo mpidr_cp_reginfo[] = { REGINFO_SENTINEL }; +static int par64_read(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value) +{ + *value = ((uint64_t)env->cp15.c7_par_hi << 32) | env->cp15.c7_par; + return 0; +} + +static int par64_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +{ + env->cp15.c7_par_hi = value >> 32; + env->cp15.c7_par = value; + return 0; +} + +static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + env->cp15.c7_par_hi = 0; + env->cp15.c7_par = 0; +} + +static int ttbr064_read(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t *value) +{ + *value = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0; + return 0; +} + +static int ttbr064_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.c2_base0_hi = value >> 32; + env->cp15.c2_base0 = value; + /* Writes to the 64 bit format TTBRs may change the ASID */ + tlb_flush(env, 1); + return 0; +} + +static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + env->cp15.c2_base0_hi = 0; + env->cp15.c2_base0 = 0; +} + +static int ttbr164_read(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t *value) +{ + *value = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1; + return 0; +} + +static int ttbr164_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.c2_base1_hi = value >> 32; + env->cp15.c2_base1 = value; + return 0; +} + +static void ttbr164_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + env->cp15.c2_base1_hi = 0; + env->cp15.c2_base1 = 0; +} + static const ARMCPRegInfo lpae_cp_reginfo[] = { /* NOP AMAIR0/1: the override is because these clash with tha rather * broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo. @@ -886,6 +952,15 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = { .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 }, { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0, .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 }, + { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0, + .access = PL1_RW, .type = ARM_CP_64BIT, + .readfn = par64_read, .writefn = par64_write, .resetfn = par64_reset }, + { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0, + .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr064_read, + .writefn = ttbr064_write, .resetfn = ttbr064_reset }, + { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1, + .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr164_read, + .writefn = ttbr164_write, .resetfn = ttbr164_reset }, REGINFO_SENTINEL }; diff --git a/target-arm/machine.c b/target-arm/machine.c index 429cbc8..68dca7f 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -27,7 +27,9 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_be32(f, env->cp15.c1_xscaleauxcr); qemu_put_be32(f, env->cp15.c1_scr); qemu_put_be32(f, env->cp15.c2_base0); + qemu_put_be32(f, env->cp15.c2_base0_hi); qemu_put_be32(f, env->cp15.c2_base1); + qemu_put_be32(f, env->cp15.c2_base1_hi); qemu_put_be32(f, env->cp15.c2_control); qemu_put_be32(f, env->cp15.c2_mask); qemu_put_be32(f, env->cp15.c2_base_mask); @@ -42,6 +44,7 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_be32(f, env->cp15.c6_insn); qemu_put_be32(f, env->cp15.c6_data); qemu_put_be32(f, env->cp15.c7_par); + qemu_put_be32(f, env->cp15.c7_par_hi); qemu_put_be32(f, env->cp15.c9_insn); qemu_put_be32(f, env->cp15.c9_data); qemu_put_be32(f, env->cp15.c9_pmcr); @@ -144,7 +147,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) env->cp15.c1_xscaleauxcr = qemu_get_be32(f); env->cp15.c1_scr = qemu_get_be32(f); env->cp15.c2_base0 = qemu_get_be32(f); + env->cp15.c2_base0_hi = qemu_get_be32(f); env->cp15.c2_base1 = qemu_get_be32(f); + env->cp15.c2_base1_hi = qemu_get_be32(f); env->cp15.c2_control = qemu_get_be32(f); env->cp15.c2_mask = qemu_get_be32(f); env->cp15.c2_base_mask = qemu_get_be32(f); @@ -159,6 +164,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) env->cp15.c6_insn = qemu_get_be32(f); env->cp15.c6_data = qemu_get_be32(f); env->cp15.c7_par = qemu_get_be32(f); + env->cp15.c7_par_hi = qemu_get_be32(f); env->cp15.c9_insn = qemu_get_be32(f); env->cp15.c9_data = qemu_get_be32(f); env->cp15.c9_pmcr = qemu_get_be32(f);