From 6a43e0b6e1f6bcd6b11656967422f4217258200a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 3 Feb 2016 13:46:33 +0000 Subject: target-arm: Make various system registers visible to EL3 The AArch64 system registers DACR32_EL2, IFSR32_EL2, SPSR_IRQ, SPSR_ABT, SPSR_UND and SPSR_FIQ are visible and fully functional from EL3 even if the CPU has no EL2 (unlike some others which are RES0 from EL3 in that configuration). Move them from el2_cp_reginfo[] to v8_cp_reginfo[] so they are always present. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Reviewed-by: Sergey Fedorov Message-id: 1453227802-9991-1-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'target-arm') diff --git a/target-arm/helper.c b/target-arm/helper.c index ae024869d0..b631b83089 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3167,6 +3167,35 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .type = ARM_CP_ALIAS, .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]), .access = PL2_RW, .accessfn = fpexc32_access }, + { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0, + .access = PL2_RW, .resetvalue = 0, + .writefn = dacr_write, .raw_writefn = raw_write, + .fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) }, + { .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1, + .access = PL2_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) }, + { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, + { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, + { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) }, + { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, REGINFO_SENTINEL }; @@ -3294,11 +3323,6 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2), .writefn = hcr_write }, - { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0, - .access = PL2_RW, .resetvalue = 0, - .writefn = dacr_write, .raw_writefn = raw_write, - .fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) }, { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1, @@ -3308,10 +3332,6 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) }, - { .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1, - .access = PL2_RW, .resetvalue = 0, - .fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) }, { .name = "FAR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) }, @@ -3320,26 +3340,6 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) }, - { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, - { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, - { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) }, - { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0, .access = PL2_RW, .writefn = vbar_write, -- cgit v1.2.1 From 98d68ec289750139258d9cd9ab3f6d7dd10bb762 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Wed, 3 Feb 2016 13:46:33 +0000 Subject: target-arm: Apply S2 MMU startlevel table size check to AArch64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The S2 starting level table size check applies to both AArch32 and AArch64. Move it to common code. Reviewed-by: Alex Bennée Reviewed-by: Peter Maydell Signed-off-by: Edgar E. Iglesias Message-id: 1453932970-14576-2-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/helper.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'target-arm') diff --git a/target-arm/helper.c b/target-arm/helper.c index b631b83089..f5e6fb1db5 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -6775,11 +6775,19 @@ typedef enum { static bool check_s2_startlevel(ARMCPU *cpu, bool is_aa64, int level, int inputsize, int stride) { + const int grainsize = stride + 3; + int startsizecheck; + /* Negative levels are never allowed. */ if (level < 0) { return false; } + startsizecheck = inputsize - ((3 - level) * stride + grainsize); + if (startsizecheck < 1 || startsizecheck > stride + 4) { + return false; + } + if (is_aa64) { unsigned int pamax = arm_pamax(cpu); @@ -6803,20 +6811,12 @@ static bool check_s2_startlevel(ARMCPU *cpu, bool is_aa64, int level, g_assert_not_reached(); } } else { - const int grainsize = stride + 3; - int startsizecheck; - /* AArch32 only supports 4KB pages. Assert on that. */ assert(stride == 9); if (level == 0) { return false; } - - startsizecheck = inputsize - ((3 - level) * stride + grainsize); - if (startsizecheck < 1 || startsizecheck > stride + 4) { - return false; - } } return true; } -- cgit v1.2.1 From a0e966c93a0968d29ef51447d08a6b7be6f4d757 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Wed, 3 Feb 2016 13:46:33 +0000 Subject: target-arm: Rename check_s2_startlevel to check_s2_mmu_setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename check_s2_startlevel to check_s2_mmu_setup in preparation for additional checks. Signed-off-by: Edgar E. Iglesias Reviewed-by: Alex Bennée Message-id: 1453932970-14576-3-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'target-arm') diff --git a/target-arm/helper.c b/target-arm/helper.c index f5e6fb1db5..31ff650147 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -6763,17 +6763,18 @@ typedef enum { } MMUFaultType; /* - * check_s2_startlevel + * check_s2_mmu_setup * @cpu: ARMCPU * @is_aa64: True if the translation regime is in AArch64 state * @startlevel: Suggested starting level * @inputsize: Bitsize of IPAs * @stride: Page-table stride (See the ARM ARM) * - * Returns true if the suggested starting level is OK and false otherwise. + * Returns true if the suggested S2 translation parameters are OK and + * false otherwise. */ -static bool check_s2_startlevel(ARMCPU *cpu, bool is_aa64, int level, - int inputsize, int stride) +static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, + int inputsize, int stride) { const int grainsize = stride + 3; int startsizecheck; @@ -7013,8 +7014,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, } /* Check that the starting level is valid. */ - ok = check_s2_startlevel(cpu, va_size == 64, level, - inputsize, stride); + ok = check_s2_mmu_setup(cpu, va_size == 64, level, inputsize, stride); if (!ok) { /* AArch64 reports these as level 0 faults. * AArch32 reports these as level 1 faults. -- cgit v1.2.1 From 3526423e867765568ad95b8094ae8b4042cac215 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Wed, 3 Feb 2016 13:46:33 +0000 Subject: target-arm: Implement the S2 MMU inputsize > pamax check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement the inputsize > pamax check for Stage 2 translations. This is CONSTRAINED UNPREDICTABLE and we choose to fault. Signed-off-by: Edgar E. Iglesias Reviewed-by: Alex Bennée Message-id: 1453932970-14576-4-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/helper.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'target-arm') diff --git a/target-arm/helper.c b/target-arm/helper.c index 31ff650147..5ea507f5bc 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -6790,6 +6790,7 @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, } if (is_aa64) { + CPUARMState *env = &cpu->env; unsigned int pamax = arm_pamax(cpu); switch (stride) { @@ -6811,6 +6812,13 @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, default: g_assert_not_reached(); } + + /* Inputsize checks. */ + if (inputsize > pamax && + (arm_el_is_aa64(env, 1) || inputsize > 40)) { + /* This is CONSTRAINED UNPREDICTABLE and we choose to fault. */ + return false; + } } else { /* AArch32 only supports 4KB pages. Assert on that. */ assert(stride == 9); -- cgit v1.2.1 From 3c2f7bb32b4c597925c5c7411307d51f1a56045d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 2 Feb 2016 18:20:42 +0000 Subject: target-arm: Don't report presence of EL2 if it doesn't exist We already modify the processor feature bits to not report EL3 support to the guest if EL3 isn't enabled for the CPU we're emulating. Add similar support for not reporting EL2 unless it is enabled. This is necessary because real world guest code running at EL3 (trusted firmware or bootloaders) will query the ID registers to determine whether it should start a guest Linux kernel in EL2 or EL3. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov Message-id: 1454437242-10262-1-git-send-email-peter.maydell@linaro.org --- target-arm/cpu.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'target-arm') diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 0e582c4410..7ddbf3d19b 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -650,6 +650,15 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) cpu->id_aa64pfr0 &= ~0xf000; } + if (!arm_feature(env, ARM_FEATURE_EL2)) { + /* Disable the hypervisor feature bits in the processor feature + * registers if we don't have EL2. These are id_pfr1[15:12] and + * id_aa64pfr0_el1[11:8]. + */ + cpu->id_aa64pfr0 &= ~0xf00; + cpu->id_pfr1 &= ~0xf000; + } + if (!cpu->has_mpu) { unset_feature(env, ARM_FEATURE_MPU); } -- cgit v1.2.1