From a9047ec3f6ab56295cba5b07e0d46cded9e2a7ff Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 4 Aug 2014 14:41:53 +0100 Subject: [PATCH 01/12] hw/arm/boot: Set PC correctly when loading AArch64 ELF files The code in do_cpu_reset() correctly handled AArch64 CPUs when running Linux kernels, but was missing code in the branch of the if() that deals with loading ELF files. Correctly jump to the ELF entry point on reset rather than leaving the reset PC at zero. Reported-by: Christopher Covington Signed-off-by: Peter Maydell Tested-by: Christopher Covington Cc: qemu-stable@nongnu.org --- hw/arm/boot.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 3d1f4a255b..12417617a3 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -417,8 +417,12 @@ static void do_cpu_reset(void *opaque) if (info) { if (!info->is_linux) { /* Jump to the entry point. */ - env->regs[15] = info->entry & 0xfffffffe; - env->thumb = info->entry & 1; + if (env->aarch64) { + env->pc = info->entry; + } else { + env->regs[15] = info->entry & 0xfffffffe; + env->thumb = info->entry & 1; + } } else { if (CPU(cpu) == first_cpu) { if (env->aarch64) { From fab46932393366792b438c078b48c196e9d35a1a Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 4 Aug 2014 14:41:53 +0100 Subject: [PATCH 02/12] hw/arm/virt: formatting: memory map Add some spacing and zeros to make it easier to read and modify the map. This patch has no functional changes. The review looks ugly, but it's actually pretty easy to confirm all the addresses are as they should be - thanks to the new formatting ;-) Signed-off-by: Andrew Jones Signed-off-by: Peter Maydell --- hw/arm/virt.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 89532bd786..ba94298555 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -98,17 +98,17 @@ typedef struct VirtBoardInfo { */ static const MemMapEntry a15memmap[] = { /* Space up to 0x8000000 is reserved for a boot ROM */ - [VIRT_FLASH] = { 0, 0x8000000 }, - [VIRT_CPUPERIPHS] = { 0x8000000, 0x20000 }, + [VIRT_FLASH] = { 0, 0x08000000 }, + [VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 }, /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */ - [VIRT_GIC_DIST] = { 0x8000000, 0x10000 }, - [VIRT_GIC_CPU] = { 0x8010000, 0x10000 }, - [VIRT_UART] = { 0x9000000, 0x1000 }, - [VIRT_RTC] = { 0x9010000, 0x1000 }, - [VIRT_MMIO] = { 0xa000000, 0x200 }, + [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 }, + [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 }, + [VIRT_UART] = { 0x09000000, 0x00001000 }, + [VIRT_RTC] = { 0x09010000, 0x00001000 }, + [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ /* 0x10000000 .. 0x40000000 reserved for PCI */ - [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 }, + [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 }, }; static const int a15irqmap[] = { From 9db11cef8c557ccc6e0a3e7eca786b197eed5f59 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 4 Aug 2014 14:41:54 +0100 Subject: [PATCH 03/12] sd: sdhci: Fix ADMA dma_memory_read access This dma_memory_read was giving too big a size when begin was non-zero. This could cause segfaults in some circumstances. Fix. Signed-off-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- hw/sd/sdhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index b5a9eee3e2..f9fe700add 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -702,7 +702,8 @@ static void sdhci_do_adma(SDHCIState *s) length -= block_size - begin; } dma_memory_read(&address_space_memory, dscr.addr, - &s->fifo_buffer[begin], s->data_count); + &s->fifo_buffer[begin], + s->data_count - begin); dscr.addr += s->data_count - begin; if (s->data_count == block_size) { for (n = 0; n < block_size; n++) { From 9208b9617f18b56ba4eb32928ae8f6439ba38a24 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 4 Aug 2014 14:41:54 +0100 Subject: [PATCH 04/12] target-arm: A64: Break out aarch64_save/restore_sp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break out code to save/restore AArch64 SP into functions. Reviewed-by: Alex Bennée Signed-off-by: Edgar E. Iglesias Reviewed-by: Greg Bellows Message-id: 1402994746-8328-2-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/internals.h | 29 ++++++++++++++++++++--------- target-arm/kvm64.c | 13 +++---------- target-arm/op_helper.c | 6 +----- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/target-arm/internals.h b/target-arm/internals.h index 564b5fa602..08fa69757d 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -105,6 +105,24 @@ enum arm_fprounding { int arm_rmode_to_sf(int rmode); +static inline void aarch64_save_sp(CPUARMState *env, int el) +{ + if (env->pstate & PSTATE_SP) { + env->sp_el[el] = env->xregs[31]; + } else { + env->sp_el[0] = env->xregs[31]; + } +} + +static inline void aarch64_restore_sp(CPUARMState *env, int el) +{ + if (env->pstate & PSTATE_SP) { + env->xregs[31] = env->sp_el[el]; + } else { + env->xregs[31] = env->sp_el[0]; + } +} + static inline void update_spsel(CPUARMState *env, uint32_t imm) { unsigned int cur_el = arm_current_pl(env); @@ -114,21 +132,14 @@ static inline void update_spsel(CPUARMState *env, uint32_t imm) if (!((imm ^ env->pstate) & PSTATE_SP)) { return; } + aarch64_save_sp(env, cur_el); env->pstate = deposit32(env->pstate, 0, 1, imm); /* We rely on illegal updates to SPsel from EL0 to get trapped * at translation time. */ assert(cur_el >= 1 && cur_el <= 3); - if (env->pstate & PSTATE_SP) { - /* Switch from using SP_EL0 to using SP_ELx */ - env->sp_el[0] = env->xregs[31]; - env->xregs[31] = env->sp_el[cur_el]; - } else { - /* Switch from SP_EL0 to SP_ELx */ - env->sp_el[cur_el] = env->xregs[31]; - env->xregs[31] = env->sp_el[0]; - } + aarch64_restore_sp(env, cur_el); } /* Valid Syndrome Register EC field values */ diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c index 5d217ca2ad..c615286158 100644 --- a/target-arm/kvm64.c +++ b/target-arm/kvm64.c @@ -21,6 +21,7 @@ #include "sysemu/kvm.h" #include "kvm_arm.h" #include "cpu.h" +#include "internals.h" #include "hw/arm/arm.h" static inline void set_feature(uint64_t *features, int feature) @@ -132,11 +133,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) /* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the * QEMU side we keep the current SP in xregs[31] as well. */ - if (env->pstate & PSTATE_SP) { - env->sp_el[1] = env->xregs[31]; - } else { - env->sp_el[0] = env->xregs[31]; - } + aarch64_save_sp(env, 1); reg.id = AARCH64_CORE_REG(regs.sp); reg.addr = (uintptr_t) &env->sp_el[0]; @@ -235,11 +232,7 @@ int kvm_arch_get_registers(CPUState *cs) /* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the * QEMU side we keep the current SP in xregs[31] as well. */ - if (env->pstate & PSTATE_SP) { - env->xregs[31] = env->sp_el[1]; - } else { - env->xregs[31] = env->sp_el[0]; - } + aarch64_restore_sp(env, 1); reg.id = AARCH64_CORE_REG(regs.pc); reg.addr = (uintptr_t) &env->pc; diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 9c1ef525a3..90a946a0fd 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -376,11 +376,7 @@ void HELPER(exception_return)(CPUARMState *env) uint32_t spsr = env->banked_spsr[spsr_idx]; int new_el, i; - if (env->pstate & PSTATE_SP) { - env->sp_el[cur_el] = env->xregs[31]; - } else { - env->sp_el[0] = env->xregs[31]; - } + aarch64_save_sp(env, cur_el); env->exclusive_addr = -1; From 98ea5615ab24b21991d68b61bc91427fab273817 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 4 Aug 2014 14:41:54 +0100 Subject: [PATCH 05/12] target-arm: A64: Respect SPSEL in ERET SP restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Bennée Signed-off-by: Edgar E. Iglesias Reviewed-by: Greg Bellows Message-id: 1402994746-8328-3-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/op_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 90a946a0fd..25ad902e04 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -410,7 +410,7 @@ void HELPER(exception_return)(CPUARMState *env) } env->aarch64 = 1; pstate_write(env, spsr); - env->xregs[31] = env->sp_el[new_el]; + aarch64_restore_sp(env, new_el); env->pc = env->elr_el[cur_el]; } From f151b123a35ff36085fb765a7a16373644711df1 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 4 Aug 2014 14:41:54 +0100 Subject: [PATCH 06/12] target-arm: A64: Respect SPSEL when taking exceptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Bennée Signed-off-by: Edgar E. Iglesias Reviewed-by: Greg Bellows Message-id: 1402994746-8328-4-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/helper-a64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index 2b4ce6ac60..027434a929 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -489,8 +489,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs) if (is_a64(env)) { env->banked_spsr[aarch64_banked_spsr_index(1)] = pstate_read(env); - env->sp_el[arm_current_pl(env)] = env->xregs[31]; - env->xregs[31] = env->sp_el[1]; + aarch64_save_sp(env, arm_current_pl(env)); env->elr_el[1] = env->pc; } else { env->banked_spsr[0] = cpsr_read(env); @@ -508,6 +507,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs) pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h); env->aarch64 = 1; + aarch64_restore_sp(env, 1); env->pc = addr; cs->interrupt_request |= CPU_INTERRUPT_EXITTB; From 2f0180c51bfbd00b35d02149b831734f04c12d44 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 4 Aug 2014 14:41:54 +0100 Subject: [PATCH 07/12] target-arm: Make far_el1 an array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional change. Prepares for future additions of the EL2 and 3 versions of this reg. Reviewed-by: Greg Bellows Signed-off-by: Edgar E. Iglesias Reviewed-by: Alex Bennée Message-id: 1402994746-8328-5-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/cpu.c | 2 +- target-arm/cpu.h | 2 +- target-arm/helper-a64.c | 4 ++-- target-arm/helper.c | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 05e52e0e83..7cebb76656 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -447,7 +447,7 @@ static void arm1026_initfn(Object *obj) ARMCPRegInfo ifar = { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW, - .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1), + .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[1]), .resetvalue = 0 }; define_one_arm_cp_reg(cpu, &ifar); diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 369d4727ae..b755f99e64 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -187,7 +187,7 @@ typedef struct CPUARMState { uint32_t ifsr_el2; /* Fault status registers. */ uint64_t esr_el[2]; uint32_t c6_region[8]; /* MPU base/size registers. */ - uint64_t far_el1; /* Fault address registers. */ + uint64_t far_el[2]; /* Fault address registers. */ uint64_t par_el1; /* Translation result. */ uint32_t c9_insn; /* Cache lockdown registers. */ uint32_t c9_data; diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index 027434a929..2e9ef64786 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -465,13 +465,13 @@ void aarch64_cpu_do_interrupt(CPUState *cs) } env->cp15.esr_el[1] = env->exception.syndrome; - env->cp15.far_el1 = env->exception.vaddress; + env->cp15.far_el[1] = env->exception.vaddress; switch (cs->exception_index) { case EXCP_PREFETCH_ABORT: case EXCP_DATA_ABORT: qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n", - env->cp15.far_el1); + env->cp15.far_el[1]); break; case EXCP_BKPT: case EXCP_UDEF: diff --git a/target-arm/helper.c b/target-arm/helper.c index d3438560e6..b5f2e57f06 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -521,7 +521,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = { .access = PL0_W, .type = ARM_CP_NOP }, { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2, .access = PL1_RW, - .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1), + .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[1]), .resetvalue = 0, }, /* Watchpoint Fault Address Register : should actually only be present * for 1136, 1176, 11MPCore. @@ -1516,7 +1516,7 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = { /* 64-bit FAR; this entry also gives us the AArch32 DFAR */ { .name = "FAR_EL1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el1), + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]), .resetvalue = 0, }, REGINFO_SENTINEL }; @@ -3425,8 +3425,8 @@ void arm_cpu_do_interrupt(CPUState *cs) /* Fall through to prefetch abort. */ case EXCP_PREFETCH_ABORT: env->cp15.ifsr_el2 = env->exception.fsr; - env->cp15.far_el1 = deposit64(env->cp15.far_el1, 32, 32, - env->exception.vaddress); + env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 32, 32, + env->exception.vaddress); qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n", env->cp15.ifsr_el2, (uint32_t)env->exception.vaddress); new_mode = ARM_CPU_MODE_ABT; @@ -3436,8 +3436,8 @@ void arm_cpu_do_interrupt(CPUState *cs) break; case EXCP_DATA_ABORT: env->cp15.esr_el[1] = env->exception.fsr; - env->cp15.far_el1 = deposit64(env->cp15.far_el1, 0, 32, - env->exception.vaddress); + env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 0, 32, + env->exception.vaddress); qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n", (uint32_t)env->cp15.esr_el[1], (uint32_t)env->exception.vaddress); From f2c30f42f506ea884de22f79d9da43867a327b2a Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 4 Aug 2014 14:41:55 +0100 Subject: [PATCH 08/12] target-arm: Add ESR_EL2 and 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Greg Bellows Signed-off-by: Edgar E. Iglesias Reviewed-by: Alex Bennée Message-id: 1402994746-8328-6-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/cpu.h | 2 +- target-arm/helper.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index b755f99e64..3d9cf576f6 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -185,7 +185,7 @@ typedef struct CPUARMState { uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */ uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */ uint32_t ifsr_el2; /* Fault status registers. */ - uint64_t esr_el[2]; + uint64_t esr_el[4]; uint32_t c6_region[8]; /* MPU base/size registers. */ uint64_t far_el[2]; /* Fault address registers. */ uint64_t par_el1; /* Translation result. */ diff --git a/target-arm/helper.c b/target-arm/helper.c index b5f2e57f06..f4845b0f20 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2127,6 +2127,10 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, elr_el[2]) }, + { .name = "ESR_EL2", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_NO_MIGRATE, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0, + .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) }, { .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64, .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0, @@ -2145,6 +2149,10 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = { .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1, .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, elr_el[3]) }, + { .name = "ESR_EL3", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_NO_MIGRATE, + .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 2, .opc2 = 0, + .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[3]) }, { .name = "SPSR_EL3", .state = ARM_CP_STATE_AA64, .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 0, From 63b60551a7a4846de2f1f41dd37296fa1571d27e Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 4 Aug 2014 14:41:55 +0100 Subject: [PATCH 09/12] target-arm: Add FAR_EL2 and 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Greg Bellows Signed-off-by: Edgar E. Iglesias Reviewed-by: Alex Bennée Message-id: 1402994746-8328-7-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/cpu.h | 2 +- target-arm/helper.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 3d9cf576f6..79205ba335 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -187,7 +187,7 @@ typedef struct CPUARMState { uint32_t ifsr_el2; /* Fault status registers. */ uint64_t esr_el[4]; uint32_t c6_region[8]; /* MPU base/size registers. */ - uint64_t far_el[2]; /* Fault address registers. */ + uint64_t far_el[4]; /* Fault address registers. */ uint64_t par_el1; /* Translation result. */ uint32_t c9_insn; /* Cache lockdown registers. */ uint32_t c9_data; diff --git a/target-arm/helper.c b/target-arm/helper.c index f4845b0f20..a7f82f32fe 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2131,6 +2131,9 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = { .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) }, + { .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]) }, { .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64, .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0, @@ -2153,6 +2156,9 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = { .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 2, .opc2 = 0, .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[3]) }, + { .name = "FAR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 6, .crm = 0, .opc2 = 0, + .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[3]) }, { .name = "SPSR_EL3", .state = ARM_CP_STATE_AA64, .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 0, From cdcf14057d780cdbb1f89f8c5fc11a1a9184b5b1 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 4 Aug 2014 14:41:55 +0100 Subject: [PATCH 10/12] target-arm: Fix bit test in sp_el0_access Static code analyzers complain about a dubious & operation used for a boolean value. The code does not test the PSTATE_SP bit as it should. Cc: Peter Maydell Signed-off-by: Stefan Weil Message-id: 1406359601-25583-1-git-send-email-sw@weilnetz.de Signed-off-by: Peter Maydell --- target-arm/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index a7f82f32fe..d709285505 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1853,7 +1853,7 @@ static uint64_t aa64_dczid_read(CPUARMState *env, const ARMCPRegInfo *ri) static CPAccessResult sp_el0_access(CPUARMState *env, const ARMCPRegInfo *ri) { - if (!env->pstate & PSTATE_SP) { + if (!(env->pstate & PSTATE_SP)) { /* Access to SP_EL0 is undefined if it's being used as * the stack pointer. */ From dcd82c118c891571d2d7db5b4ec84d9cf3ea49b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 4 Aug 2014 14:41:55 +0100 Subject: [PATCH 11/12] target-arm: don't hardcode mask values in arm_cpu_handle_mmu_fault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we break quickly when we change TARGET_PAGE_SIZE. Signed-off-by: Alex Bennée Message-id: 1406733627-24255-2-git-send-email-alex.bennee@linaro.org Signed-off-by: Peter Maydell --- target-arm/helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index d709285505..35c11e7800 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -4156,8 +4156,8 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, &page_size); if (ret == 0) { /* Map a single [sub]page. */ - phys_addr &= ~(hwaddr)0x3ff; - address &= ~(target_ulong)0x3ff; + phys_addr &= TARGET_PAGE_MASK; + address &= TARGET_PAGE_MASK; tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size); return 0; } From dbb1fb277ca12acd577403575aa6a2f119ab79ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 4 Aug 2014 14:41:56 +0100 Subject: [PATCH 12/12] target-arm: A64: fix TLB flush instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the ARM ARM we weren't correctly flushing the TLB entries where bits 63:56 didn't match bit 55 of the virtual address. This exposed a problem when we switched QEMU's internal TARGET_PAGE_BITS to 12 for aarch64. Signed-off-by: Alex Bennée Reviewed-by: Peter Maydell Message-id: 1406733627-24255-3-git-send-email-alex.bennee@linaro.org Signed-off-by: Peter Maydell --- target-arm/helper.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 35c11e7800..f630d96306 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1801,12 +1801,17 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env, return CP_ACCESS_OK; } +/* See: D4.7.2 TLB maintenance requirements and the TLB maintenance instructions + * Page D4-1736 (DDI0487A.b) + */ + static void tlbi_aa64_va_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate by VA (AArch64 version) */ ARMCPU *cpu = arm_env_get_cpu(env); - uint64_t pageaddr = value << 12; + uint64_t pageaddr = sextract64(value << 12, 0, 56); + tlb_flush_page(CPU(cpu), pageaddr); } @@ -1815,7 +1820,8 @@ static void tlbi_aa64_vaa_write(CPUARMState *env, const ARMCPRegInfo *ri, { /* Invalidate by VA, all ASIDs (AArch64 version) */ ARMCPU *cpu = arm_env_get_cpu(env); - uint64_t pageaddr = value << 12; + uint64_t pageaddr = sextract64(value << 12, 0, 56); + tlb_flush_page(CPU(cpu), pageaddr); }