From 6675d719154969456e841a7e1729c0dc14113a44 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Tue, 25 Aug 2015 15:45:06 +0100 Subject: [PATCH 01/18] xlnx-zynqmp: Connect the four OCM banks The Xilinx EP108 has four separate OCM banks which are located adjacent to each other. This patch adds the four banks to the ZynqMP SoC. Signed-off-by: Alistair Francis Reviewed-by: Peter Crosthwaite Message-id: afa6ba31163a5d541a0bef4b0dc11f2597e0c495.1436813543.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell --- hw/arm/xlnx-zynqmp.c | 15 +++++++++++++++ include/hw/arm/xlnx-zynqmp.h | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 62ef4ceb32..388baef76e 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -101,6 +101,21 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) qemu_irq gic_spi[GIC_NUM_SPI_INTR]; Error *err = NULL; + /* Create the four OCM banks */ + for (i = 0; i < XLNX_ZYNQMP_NUM_OCM_BANKS; i++) { + char *ocm_name = g_strdup_printf("zynqmp.ocm_ram_bank_%d", i); + + memory_region_init_ram(&s->ocm_ram[i], NULL, ocm_name, + XLNX_ZYNQMP_OCM_RAM_SIZE, &error_abort); + vmstate_register_ram_global(&s->ocm_ram[i]); + memory_region_add_subregion(get_system_memory(), + XLNX_ZYNQMP_OCM_RAM_0_ADDRESS + + i * XLNX_ZYNQMP_OCM_RAM_SIZE, + &s->ocm_ram[i]); + + g_free(ocm_name); + } + qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32); qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2); qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS); diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index c379632f2a..6ccb57b187 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -32,6 +32,10 @@ #define XLNX_ZYNQMP_NUM_GEMS 4 #define XLNX_ZYNQMP_NUM_UARTS 2 +#define XLNX_ZYNQMP_NUM_OCM_BANKS 4 +#define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC0000 +#define XLNX_ZYNQMP_OCM_RAM_SIZE 0x10000 + #define XLNX_ZYNQMP_GIC_REGIONS 2 /* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets @@ -52,6 +56,8 @@ typedef struct XlnxZynqMPState { ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS]; GICState gic; MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES]; + MemoryRegion ocm_ram[XLNX_ZYNQMP_NUM_OCM_BANKS]; + CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; From 4b46ba6145c4c9b79641efdcc9f1aa92fdbf779c Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Tue, 25 Aug 2015 15:45:06 +0100 Subject: [PATCH 02/18] MAINTAINERS: Update Xilinx Maintainership Peter C is leaving Xilinx, so update the maintainer list to point to Alistair and Edgar from Xilinx and Peter's personal email address. Signed-off-by: Alistair Francis Reviewed-by: Peter Crosthwaite Message-id: 54b4c070452bac05aa3a9c1d75899bc097fef831.1436486024.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell --- MAINTAINERS | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a059d5de3b..d0268f9033 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -349,7 +349,8 @@ S: Maintained F: hw/*/versatile* Xilinx Zynq -M: Peter Crosthwaite +M: Alistair Francis +M: Peter Crosthwaite S: Maintained F: hw/arm/xilinx_zynq.c F: hw/misc/zynq_slcr.c @@ -405,7 +406,7 @@ S: Maintained F: hw/microblaze/petalogix_s3adsp1800_mmu.c petalogix_ml605 -M: Peter Crosthwaite +M: Edgar E. Iglesias S: Maintained F: hw/microblaze/petalogix_ml605_mmu.c @@ -685,10 +686,17 @@ S: Orphan F: hw/scsi/lsi53c895a.c SSI -M: Peter Crosthwaite +M: Peter Crosthwaite S: Maintained F: hw/ssi/* F: hw/block/m25p80.c +X: hw/ssi/xilinx_* + +Xilinx SPI +M: Alistair Francis +M: Peter Crosthwaite +S: Maintained +F: hw/ssi/xilinx_* USB M: Gerd Hoffmann @@ -777,8 +785,9 @@ F: hw/scsi/megasas.c F: hw/scsi/mfi.h Xilinx EDK -M: Peter Crosthwaite M: Edgar E. Iglesias +M: Alistair Francis +M: Peter Crosthwaite S: Maintained F: hw/*/xilinx_* F: include/hw/xilinx.h @@ -880,7 +889,7 @@ F: include/hw/cpu/icc_bus.h F: hw/cpu/icc_bus.c Device Tree -M: Peter Crosthwaite +M: Peter Crosthwaite M: Alexander Graf S: Maintained F: device_tree.[ch] From 137805f5d8504933faa4fe129cdab88f2695a8c2 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Tue, 25 Aug 2015 15:45:07 +0100 Subject: [PATCH 03/18] MAINTAINERS: Add ZynqMP to MAINTAINERS file Add the Xilinx ZynqMP SoC and EP108 machine to the maintainers file. Signed-off-by: Alistair Francis Reviewed-by: Peter Crosthwaite Message-id: fed078103a0b02cfb3adadbe8e80e4420d554505.1436486024.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d0268f9033..08f356a54c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -357,6 +357,14 @@ F: hw/misc/zynq_slcr.c F: hw/*/cadence_* F: hw/ssi/xilinx_spips.c +Xilinx ZynqMP +M: Alistair Francis +M: Peter Crosthwaite +S: Maintained +F: hw/arm/xlnx-zynqmp.c +F: hw/arm/xlnx-ep108.c +F: include/hw/arm/xlnx-zynqmp.h + ARM ACPI Subsystem M: Shannon Zhao M: Shannon Zhao From 4cfb8ad896a6f85953038bd913ce3d82d347013d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:07 +0100 Subject: [PATCH 04/18] target-arm: Add missing MAIR_EL3 and TPIDR_EL3 registers Add the AArch64 registers MAIR_EL3 and TPIDR_EL3, which are the only two which we had implemented the 32-bit Secure equivalents of but not the 64-bit Secure versions. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1438281398-18746-2-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 1568aa6617..749749ea83 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1022,6 +1022,10 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[1]), .resetvalue = 0 }, + { .name = "MAIR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 10, .crm = 2, .opc2 = 0, + .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[3]), + .resetvalue = 0 }, /* For non-long-descriptor page tables these are PRRR and NMRR; * regardless they still act as reads-as-written for QEMU. */ @@ -3089,6 +3093,10 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 2, .access = PL3_RW, .accessfn = cptr_access, .resetvalue = 0, .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[3]) }, + { .name = "TPIDR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 13, .crm = 0, .opc2 = 2, + .access = PL3_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[3]) }, REGINFO_SENTINEL }; From 2179ef958c81480b841ffa0aab5e265688ffd2b0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:07 +0100 Subject: [PATCH 05/18] target-arm: Implement missing AMAIR registers The AMAIR registers are for providing auxiliary implementation defined memory attributes. We already implemented a RAZ/WI AMAIR_EL1; add the EL2 and EL3 versions for consistency. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1438281398-18746-3-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 749749ea83..54f99aeb84 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2840,6 +2840,14 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = { { .name = "HMAIR1", .state = ARM_CP_STATE_AA32, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + { .name = "HMAIR1", .state = ARM_CP_STATE_AA32, + .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, @@ -2955,6 +2963,15 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1, .access = PL2_RW, .type = ARM_CP_ALIAS, .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el[2]) }, + { .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + /* HAMAIR1 is mapped to AMAIR_EL2[63:32] */ + { .name = "HMAIR1", .state = ARM_CP_STATE_AA32, + .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, .access = PL2_RW, .writefn = vmsa_tcr_el1_write, @@ -3097,6 +3114,10 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { .opc0 = 3, .opc1 = 6, .crn = 13, .crm = 0, .opc2 = 2, .access = PL3_RW, .resetvalue = 0, .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[3]) }, + { .name = "AMAIR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 10, .crm = 3, .opc2 = 0, + .access = PL3_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, REGINFO_SENTINEL }; From 37cd6c2478196623ca28526627ca8c69afe0d654 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:07 +0100 Subject: [PATCH 06/18] target-arm: Implement missing AFSR registers The AFSR registers are implementation dependent auxiliary fault status registers. We already implemented a RAZ/WI AFSR0_EL1 and AFSR_EL1; add the missing AFSR{0,1}_EL{2,3} for consistency. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1438281398-18746-4-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 54f99aeb84..f6119be888 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2848,6 +2848,14 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = { .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + { .name = "AFSR1_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 1, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, @@ -2972,6 +2980,14 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + { .name = "AFSR1_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 1, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, .access = PL2_RW, .writefn = vmsa_tcr_el1_write, @@ -3118,6 +3134,14 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { .opc0 = 3, .opc1 = 6, .crn = 10, .crm = 3, .opc2 = 0, .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "AFSR0_EL3", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 1, .opc2 = 0, + .access = PL3_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + { .name = "AFSR1_EL3", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 1, .opc2 = 1, + .access = PL3_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, REGINFO_SENTINEL }; From 834a6c6920316d39aaf0e68ac936c0a3ad164815 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:07 +0100 Subject: [PATCH 07/18] target-arm: Implement missing ACTLR registers We already implemented ACTLR_EL1; add the missing ACTLR_EL2 and ACTLR_EL3, for consistency. Since we don't currently have any CPUs that need the EL2/EL3 versions to reset to non-zero values, implement as RAZ/WI. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1438281398-18746-5-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index f6119be888..97ca86ad0a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3936,13 +3936,22 @@ void register_cp_regs_for_features(ARMCPU *cpu) } if (arm_feature(env, ARM_FEATURE_AUXCR)) { - ARMCPRegInfo auxcr = { - .name = "ACTLR_EL1", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 1, - .access = PL1_RW, .type = ARM_CP_CONST, - .resetvalue = cpu->reset_auxcr + ARMCPRegInfo auxcr_reginfo[] = { + { .name = "ACTLR_EL1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 1, + .access = PL1_RW, .type = ARM_CP_CONST, + .resetvalue = cpu->reset_auxcr }, + { .name = "ACTLR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 1, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + { .name = "ACTLR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 1, + .access = PL3_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + REGINFO_SENTINEL }; - define_one_arm_cp_reg(cpu, &auxcr); + define_arm_cp_regs(cpu, auxcr_reginfo); } if (arm_feature(env, ARM_FEATURE_CBAR)) { From d0a2cbceb2aa20d64d53e1c20c7d26a78ade8382 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:08 +0100 Subject: [PATCH 08/18] target-arm: there is no TTBR1 for 32-bit EL2 stage 1 translations For EL2 stage 1 translations, there is no TTBR1. We were already handling this for 64-bit EL2; add the code to take the 'no TTBR1' code path for 64-bit EL2 as well. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1437751263-21913-2-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 97ca86ad0a..86d0baf2c0 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5999,6 +5999,11 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, if (el > 1) { ttbr1_valid = false; } + } else { + /* There is no TTBR1 for EL2 */ + if (el == 2) { + ttbr1_valid = false; + } } /* Determine whether this address is in the region controlled by From 2a47df953202e1f226aa045ea974427c4540a167 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:08 +0100 Subject: [PATCH 09/18] target-arm: Wire up AArch64 EL2 and EL3 address translation ops Wire up the AArch64 EL2 and EL3 address translation operations (AT S12E1*, AT S12E0*, AT S1E2*, AT S1E3*), and correct some errors in the ats_write64() function in previously unused code that would have done the wrong kind of lookup for accesses from EL3 when SCR.NS==0. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1437751263-21913-3-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 86d0baf2c0..8603660d4f 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1844,6 +1844,14 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) A32_BANKED_CURRENT_REG_SET(env, par, par64); } +static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + if (arm_current_el(env) == 3 && !(env->cp15.scr_el3 & SCR_NS)) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -1871,10 +1879,10 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0; break; case 4: /* AT S12E1R, AT S12E1W */ - mmu_idx = ARMMMUIdx_S12NSE1; + mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S12NSE1; break; case 6: /* AT S12E0R, AT S12E0W */ - mmu_idx = ARMMMUIdx_S12NSE0; + mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S12NSE0; break; default: g_assert_not_reached(); @@ -2746,6 +2754,25 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { { .name = "AT_S1E0W", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 3, .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + { .name = "AT_S12E1R", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 4, + .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + { .name = "AT_S12E1W", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 5, + .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + { .name = "AT_S12E0R", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 6, + .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + { .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 7, + .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */ + { .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 0, + .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + { .name = "AT_S1E3W", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 1, + .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, #endif /* TLB invalidate last level of translation table walk */ { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, @@ -3021,6 +3048,18 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .type = ARM_CP_NO_RAW, .access = PL2_W, .writefn = tlbi_aa64_vaa_write }, #ifndef CONFIG_USER_ONLY + /* Unlike the other EL2-related AT operations, these must + * UNDEF from EL3 if EL2 is not implemented, which is why we + * define them here rather than with the rest of the AT ops. + */ + { .name = "AT_S1E2R", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0, + .access = PL2_W, .accessfn = at_s1e2_access, + .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + { .name = "AT_S1E2W", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1, + .access = PL2_W, .accessfn = at_s1e2_access, + .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, { .name = "CNTHCTL_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 1, .opc2 = 0, /* ARMv7 requires bit 0 and 1 to reset to 1. ARMv8 defines the From e76157264da20b85698b09fa5eb8e02e515e232c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:08 +0100 Subject: [PATCH 10/18] target-arm: Add CP_ACCESS_TRAP_UNCATEGORIZED_EL2, 3 Some coprocessor register access functions need to be able to report "trap to EL3 with an 'uncategorized' syndrome"; add the necessary CPAccessResult enum and handling for it. I don't currently know of any registers that need to trap to EL2 with the 'uncategorized' syndrome, but adding the _EL2 enum as well is trivial and fills in what would otherwise be an odd gap in the handling. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1437751263-21913-4-git-send-email-peter.maydell@linaro.org --- target-arm/cpu.h | 3 +++ target-arm/op_helper.c | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 2e680da1fc..31825d34a1 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1284,6 +1284,9 @@ typedef enum CPAccessResult { /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */ CP_ACCESS_TRAP_EL2 = 3, CP_ACCESS_TRAP_EL3 = 4, + /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */ + CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5, + CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6, } CPAccessResult; /* Access functions for coprocessor registers. These cannot fail and diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 663c05d1d2..1425a1d4bb 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -444,6 +444,14 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome) target_el = exception_target_el(env); syndrome = syn_uncategorized(); break; + case CP_ACCESS_TRAP_UNCATEGORIZED_EL2: + target_el = 2; + syndrome = syn_uncategorized(); + break; + case CP_ACCESS_TRAP_UNCATEGORIZED_EL3: + target_el = 3; + syndrome = syn_uncategorized(); + break; default: g_assert_not_reached(); } From 87562e4f4a2bdd028eef3549ce9cb4e7c83cb0bf Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:08 +0100 Subject: [PATCH 11/18] target-arm: Enable the AArch32 ATS12NSO ops Apply the correct conditions in the ats_access() function for the ATS12NSO* address translation operations: * succeed at EL2 or EL3 * normal UNDEF trap from NS EL1 * trap to EL3 from S EL1 (only possible if EL3 is AArch64) (This change means they're now available in our EL3-supporting CPUs when they would previously always UNDEF.) Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1437751263-21913-5-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 8603660d4f..4b2fc0903b 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1719,12 +1719,17 @@ static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri) { if (ri->opc2 & 4) { - /* Other states are only available with TrustZone; in - * a non-TZ implementation these registers don't exist - * at all, which is an Uncategorized trap. This underdecoding - * is safe because the reginfo is NO_RAW. + /* The ATS12NSO* operations must trap to EL3 if executed in + * Secure EL1 (which can only happen if EL3 is AArch64). + * They are simply UNDEF if executed from NS EL1. + * They function normally from EL2 or EL3. */ - return CP_ACCESS_TRAP_UNCATEGORIZED; + if (arm_current_el(env) == 1) { + if (arm_is_secure_below_el3(env)) { + return CP_ACCESS_TRAP_UNCATEGORIZED_EL3; + } + return CP_ACCESS_TRAP_UNCATEGORIZED; + } } return CP_ACCESS_OK; } @@ -1899,6 +1904,7 @@ static const ARMCPRegInfo vapa_cp_reginfo[] = { offsetoflow32(CPUARMState, cp15.par_ns) }, .writefn = par_write }, #ifndef CONFIG_USER_ONLY + /* This underdecoding is safe because the reginfo is NO_RAW. */ { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W, .accessfn = ats_access, .writefn = ats_write, .type = ARM_CP_NO_RAW }, From 14db7fe09a2c8d561ff37f98b328409906a560d7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:08 +0100 Subject: [PATCH 12/18] target-arm: Implement AArch32 ATS1H* operations Implement the AArch32 ATS1H* operations which perform Hyp mode stage 1 translations. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1437751263-21913-6-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 4b2fc0903b..6c55cc4083 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1849,6 +1849,17 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) A32_BANKED_CURRENT_REG_SET(env, par, par64); } +static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + int access_type = ri->opc2 & 1; + uint64_t par64; + + par64 = do_ats_write(env, value, access_type, ARMMMUIdx_S2NS); + + A32_BANKED_CURRENT_REG_SET(env, par, par64); +} + static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri) { if (arm_current_el(env) == 3 && !(env->cp15.scr_el3 & SCR_NS)) { @@ -3066,6 +3077,17 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1, .access = PL2_W, .accessfn = at_s1e2_access, .type = ARM_CP_NO_RAW, .writefn = ats_write64 }, + /* The AArch32 ATS1H* operations are CONSTRAINED UNPREDICTABLE + * if EL2 is not implemented; we choose to UNDEF. Behaviour at EL3 + * with SCR.NS == 0 outside Monitor mode is UNPREDICTABLE; we choose + * to behave as if SCR.NS was 1. + */ + { .name = "ATS1HR", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0, + .access = PL2_W, + .writefn = ats1h_write, .type = ARM_CP_NO_RAW }, + { .name = "ATS1HW", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1, + .access = PL2_W, + .writefn = ats1h_write, .type = ARM_CP_NO_RAW }, { .name = "CNTHCTL_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 1, .opc2 = 0, /* ARMv7 requires bit 0 and 1 to reset to 1. ARMv8 defines the From d7a74a9d4a68e27b3a8ceda17bb95cb0a23d8e4d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:09 +0100 Subject: [PATCH 13/18] cputlb: Add functions for flushing TLB for a single MMU index Guest CPU TLB maintenance operations may be sufficiently specialized to only need to flush TLB entries corresponding to a particular MMU index. Implement cputlb functions for this, to avoid the inefficiency of flushing TLB entries which we don't need to. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1439548879-1972-2-git-send-email-peter.maydell@linaro.org --- cputlb.c | 97 +++++++++++++++++++++++++++++++++++++++++ include/exec/exec-all.h | 47 ++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/cputlb.c b/cputlb.c index a50608676c..4bc6c24e11 100644 --- a/cputlb.c +++ b/cputlb.c @@ -69,6 +69,47 @@ void tlb_flush(CPUState *cpu, int flush_global) tlb_flush_count++; } +static inline void v_tlb_flush_by_mmuidx(CPUState *cpu, va_list argp) +{ + CPUArchState *env = cpu->env_ptr; + +#if defined(DEBUG_TLB) + printf("tlb_flush_by_mmuidx:"); +#endif + /* must reset current TB so that interrupts cannot modify the + links while we are modifying them */ + cpu->current_tb = NULL; + + for (;;) { + int mmu_idx = va_arg(argp, int); + + if (mmu_idx < 0) { + break; + } + +#if defined(DEBUG_TLB) + printf(" %d", mmu_idx); +#endif + + memset(env->tlb_table[mmu_idx], -1, sizeof(env->tlb_table[0])); + memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0])); + } + +#if defined(DEBUG_TLB) + printf("\n"); +#endif + + memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache)); +} + +void tlb_flush_by_mmuidx(CPUState *cpu, ...) +{ + va_list argp; + va_start(argp, cpu); + v_tlb_flush_by_mmuidx(cpu, argp); + va_end(argp); +} + static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) { if (addr == (tlb_entry->addr_read & @@ -121,6 +162,62 @@ void tlb_flush_page(CPUState *cpu, target_ulong addr) tb_flush_jmp_cache(cpu, addr); } +void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, ...) +{ + CPUArchState *env = cpu->env_ptr; + int i, k; + va_list argp; + + va_start(argp, addr); + +#if defined(DEBUG_TLB) + printf("tlb_flush_page_by_mmu_idx: " TARGET_FMT_lx, addr); +#endif + /* Check if we need to flush due to large pages. */ + if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) { +#if defined(DEBUG_TLB) + printf(" forced full flush (" + TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", + env->tlb_flush_addr, env->tlb_flush_mask); +#endif + v_tlb_flush_by_mmuidx(cpu, argp); + va_end(argp); + return; + } + /* must reset current TB so that interrupts cannot modify the + links while we are modifying them */ + cpu->current_tb = NULL; + + addr &= TARGET_PAGE_MASK; + i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); + + for (;;) { + int mmu_idx = va_arg(argp, int); + + if (mmu_idx < 0) { + break; + } + +#if defined(DEBUG_TLB) + printf(" %d", mmu_idx); +#endif + + tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr); + + /* check whether there are vltb entries that need to be flushed */ + for (k = 0; k < CPU_VTLB_SIZE; k++) { + tlb_flush_entry(&env->tlb_v_table[mmu_idx][k], addr); + } + } + va_end(argp); + +#if defined(DEBUG_TLB) + printf("\n"); +#endif + + tb_flush_jmp_cache(cpu, addr); +} + /* update the TLBs so that writes to code in the virtual page 'addr' can be detected */ void tlb_protect_code(ram_addr_t ram_addr) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 29775c012c..fbc6dcb90c 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -96,8 +96,46 @@ bool qemu_in_vcpu_thread(void); void cpu_reload_memory_map(CPUState *cpu); void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as); /* cputlb.c */ +/** + * tlb_flush_page: + * @cpu: CPU whose TLB should be flushed + * @addr: virtual address of page to be flushed + * + * Flush one page from the TLB of the specified CPU, for all + * MMU indexes. + */ void tlb_flush_page(CPUState *cpu, target_ulong addr); +/** + * tlb_flush: + * @cpu: CPU whose TLB should be flushed + * @flush_global: ignored + * + * Flush the entire TLB for the specified CPU. + * The flush_global flag is in theory an indicator of whether the whole + * TLB should be flushed, or only those entries not marked global. + * In practice QEMU does not implement any global/not global flag for + * TLB entries, and the argument is ignored. + */ void tlb_flush(CPUState *cpu, int flush_global); +/** + * tlb_flush_page_by_mmuidx: + * @cpu: CPU whose TLB should be flushed + * @addr: virtual address of page to be flushed + * @...: list of MMU indexes to flush, terminated by a negative value + * + * Flush one page from the TLB of the specified CPU, for the specified + * MMU indexes. + */ +void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, ...); +/** + * tlb_flush_by_mmuidx: + * @cpu: CPU whose TLB should be flushed + * @...: list of MMU indexes to flush, terminated by a negative value + * + * Flush all entries from the TLB of the specified CPU, for the specified + * MMU indexes. + */ +void tlb_flush_by_mmuidx(CPUState *cpu, ...); void tlb_set_page(CPUState *cpu, target_ulong vaddr, hwaddr paddr, int prot, int mmu_idx, target_ulong size); @@ -115,6 +153,15 @@ static inline void tlb_flush_page(CPUState *cpu, target_ulong addr) static inline void tlb_flush(CPUState *cpu, int flush_global) { } + +static inline void tlb_flush_page_by_mmuidx(CPUState *cpu, + target_ulong addr, ...) +{ +} + +static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...) +{ +} #endif #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ From 83ddf975777cc23337b7ef92e83b1b9c949396f3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:09 +0100 Subject: [PATCH 14/18] target-arm: Move TLBI ALLE1/ALLE1IS definitions into numeric order Move the two regdefs for TLBI ALLE1 and TLBI ALLE1IS down so that the whole set of AArch64 TLBI regdefs is arranged in numeric order. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1439548879-1972-3-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 6c55cc4083..becc6f8e14 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2701,14 +2701,6 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2, .access = PL1_W, .type = ARM_CP_NOP }, /* TLBI operations */ - { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, - .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, - .access = PL2_W, .type = ARM_CP_NO_RAW, - .writefn = tlbiall_write }, - { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, - .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, - .access = PL2_W, .type = ARM_CP_NO_RAW, - .writefn = tlbiall_is_write }, { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, .access = PL1_W, .type = ARM_CP_NO_RAW, @@ -2757,6 +2749,14 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vaa_write }, + { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbiall_is_write }, + { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbiall_write }, #ifndef CONFIG_USER_ONLY /* 64 bit address translation operations */ { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64, From fd3ed969227f54f08f87d9eb6de2d4e48e99279b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:09 +0100 Subject: [PATCH 15/18] target-arm: Restrict AArch64 TLB flushes to the MMU indexes they must touch Now we have the ability to flush the TLB only for specific MMU indexes, update the AArch64 TLB maintenance instruction implementations to only flush the parts of the TLB they need to, rather than doing full flushes. We take the opportunity to remove some duplicate functions (the per-asid tlb ops work like the non-per-asid ones because we don't support flushing a TLB only by ASID) and to bring the function names in line with the architectural TLBI operation names. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1439548879-1972-4-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 200 +++++++++++++++++++++++++++++++------------- 1 file changed, 143 insertions(+), 57 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index becc6f8e14..c8d07d9cfc 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2507,65 +2507,151 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env, * Page D4-1736 (DDI0487A.b) */ -static void tlbi_aa64_va_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { - /* Invalidate by VA (AArch64 version) */ ARMCPU *cpu = arm_env_get_cpu(env); - uint64_t pageaddr = sextract64(value << 12, 0, 56); + CPUState *cs = CPU(cpu); - tlb_flush_page(CPU(cpu), pageaddr); + if (arm_is_secure_below_el3(env)) { + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1); + } else { + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, -1); + } } -static void tlbi_aa64_vaa_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { - /* Invalidate by VA, all ASIDs (AArch64 version) */ - ARMCPU *cpu = arm_env_get_cpu(env); - uint64_t pageaddr = sextract64(value << 12, 0, 56); + bool sec = arm_is_secure_below_el3(env); + CPUState *other_cs; - tlb_flush_page(CPU(cpu), pageaddr); + CPU_FOREACH(other_cs) { + if (sec) { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1); + } else { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1, + ARMMMUIdx_S12NSE0, -1); + } + } } -static void tlbi_aa64_asid_write(CPUARMState *env, const ARMCPRegInfo *ri, +static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Note that the 'ALL' scope must invalidate both stage 1 and + * stage 2 translations, whereas most other scopes only invalidate + * stage 1 translations. + */ + ARMCPU *cpu = arm_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + if (arm_is_secure_below_el3(env)) { + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1); + } else { + if (arm_feature(env, ARM_FEATURE_EL2)) { + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, + ARMMMUIdx_S2NS, -1); + } else { + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, -1); + } + } +} + +static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E2, -1); +} + +static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Note that the 'ALL' scope must invalidate both stage 1 and + * stage 2 translations, whereas most other scopes only invalidate + * stage 1 translations. + */ + bool sec = arm_is_secure_below_el3(env); + bool has_el2 = arm_feature(env, ARM_FEATURE_EL2); + CPUState *other_cs; + + CPU_FOREACH(other_cs) { + if (sec) { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1); + } else if (has_el2) { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1, + ARMMMUIdx_S12NSE0, ARMMMUIdx_S2NS, -1); + } else { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1, + ARMMMUIdx_S12NSE0, -1); + } + } +} + +static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - /* Invalidate by ASID (AArch64 version) */ + /* Invalidate by VA, EL1&0 (AArch64 version). + * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1, + * since we don't support flush-for-specific-ASID-only or + * flush-last-level-only. + */ ARMCPU *cpu = arm_env_get_cpu(env); - int asid = extract64(value, 48, 16); - tlb_flush(CPU(cpu), asid == 0); + CPUState *cs = CPU(cpu); + uint64_t pageaddr = sextract64(value << 12, 0, 56); + + if (arm_is_secure_below_el3(env)) { + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1SE1, + ARMMMUIdx_S1SE0, -1); + } else { + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S12NSE1, + ARMMMUIdx_S12NSE0, -1); + } } -static void tlbi_aa64_va_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate by VA, EL2 + * Currently handles both VAE2 and VALE2, since we don't support + * flush-last-level-only. + */ + ARMCPU *cpu = arm_env_get_cpu(env); + CPUState *cs = CPU(cpu); + uint64_t pageaddr = sextract64(value << 12, 0, 56); + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1E2, -1); +} + +static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + bool sec = arm_is_secure_below_el3(env); + CPUState *other_cs; + uint64_t pageaddr = sextract64(value << 12, 0, 56); + + CPU_FOREACH(other_cs) { + if (sec) { + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1SE1, + ARMMMUIdx_S1SE0, -1); + } else { + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S12NSE1, + ARMMMUIdx_S12NSE0, -1); + } + } +} + +static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { CPUState *other_cs; uint64_t pageaddr = sextract64(value << 12, 0, 56); CPU_FOREACH(other_cs) { - tlb_flush_page(other_cs, pageaddr); - } -} - -static void tlbi_aa64_vaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *other_cs; - uint64_t pageaddr = sextract64(value << 12, 0, 56); - - CPU_FOREACH(other_cs) { - tlb_flush_page(other_cs, pageaddr); - } -} - -static void tlbi_aa64_asid_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *other_cs; - int asid = extract64(value, 48, 16); - - CPU_FOREACH(other_cs) { - tlb_flush(other_cs, asid == 0); + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1); } } @@ -2704,59 +2790,59 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbiall_is_write }, + .writefn = tlbi_aa64_vmalle1is_write }, { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_va_is_write }, + .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_asid_is_write }, + .writefn = tlbi_aa64_vmalle1is_write }, { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_vaa_is_write }, + .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_va_is_write }, + .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_vaa_is_write }, + .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbiall_write }, + .writefn = tlbi_aa64_vmalle1_write }, { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_va_write }, + .writefn = tlbi_aa64_vae1_write }, { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_asid_write }, + .writefn = tlbi_aa64_vmalle1_write }, { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_vaa_write }, + .writefn = tlbi_aa64_vae1_write }, { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_va_write }, + .writefn = tlbi_aa64_vae1_write }, { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, .access = PL1_W, .type = ARM_CP_NO_RAW, - .writefn = tlbi_aa64_vaa_write }, + .writefn = tlbi_aa64_vae1_write }, { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, .access = PL2_W, .type = ARM_CP_NO_RAW, - .writefn = tlbiall_is_write }, + .writefn = tlbi_aa64_alle1is_write }, { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, .access = PL2_W, .type = ARM_CP_NO_RAW, - .writefn = tlbiall_write }, + .writefn = tlbi_aa64_alle1_write }, #ifndef CONFIG_USER_ONLY /* 64 bit address translation operations */ { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64, @@ -3055,15 +3141,15 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, .type = ARM_CP_NO_RAW, .access = PL2_W, - .writefn = tlbiall_write }, + .writefn = tlbi_aa64_alle2_write }, { .name = "TLBI_VAE2", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, .type = ARM_CP_NO_RAW, .access = PL2_W, - .writefn = tlbi_aa64_vaa_write }, + .writefn = tlbi_aa64_vae2_write }, { .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, .type = ARM_CP_NO_RAW, .access = PL2_W, - .writefn = tlbi_aa64_vaa_write }, + .writefn = tlbi_aa64_vae2is_write }, #ifndef CONFIG_USER_ONLY /* Unlike the other EL2-related AT operations, these must * UNDEF from EL3 if EL2 is not implemented, which is why we From 2bfb9d75d37ceab6ef1674f54fca06c74f6978e7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:09 +0100 Subject: [PATCH 16/18] target-arm: Implement missing EL2 TLBI operations Implement the missing TLBI operations that exist only if EL2 is implemented. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1439548879-1972-5-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index c8d07d9cfc..6c38d66011 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2591,6 +2591,16 @@ static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri, } } +static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + + CPU_FOREACH(other_cs) { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E2, -1); + } +} + static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -3146,10 +3156,22 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, .type = ARM_CP_NO_RAW, .access = PL2_W, .writefn = tlbi_aa64_vae2_write }, + { .name = "TLBI_VALE2", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae2_write }, + { .name = "TLBI_ALLE2IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_alle2is_write }, { .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, .type = ARM_CP_NO_RAW, .access = PL2_W, .writefn = tlbi_aa64_vae2is_write }, + { .name = "TLBI_VALE2IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae2is_write }, #ifndef CONFIG_USER_ONLY /* Unlike the other EL2-related AT operations, these must * UNDEF from EL3 if EL2 is not implemented, which is why we From 43efaa33faa2bdaed789b9ddaa76b30880e57554 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:10 +0100 Subject: [PATCH 17/18] target-arm: Implement missing EL3 TLB invalidate operations Implement the remaining stage 1 TLB invalidate operations visible from EL3. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1439548879-1972-6-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 76 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 6c38d66011..00ecda93e4 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2567,6 +2567,15 @@ static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri, tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E2, -1); } +static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E3, -1); +} + static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -2601,6 +2610,16 @@ static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri, } } +static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + + CPU_FOREACH(other_cs) { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E3, -1); + } +} + static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -2636,6 +2655,20 @@ static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri, tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1E2, -1); } +static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate by VA, EL3 + * Currently handles both VAE3 and VALE3, since we don't support + * flush-last-level-only. + */ + ARMCPU *cpu = arm_env_get_cpu(env); + CPUState *cs = CPU(cpu); + uint64_t pageaddr = sextract64(value << 12, 0, 56); + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1E3, -1); +} + static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -2665,6 +2698,17 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri, } } +static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + uint64_t pageaddr = sextract64(value << 12, 0, 56); + + CPU_FOREACH(other_cs) { + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E3, -1); + } +} + static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri) { /* We don't implement EL2, so the only control on DC ZVA is the @@ -2849,10 +2893,18 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_alle1is_write }, + { .name = "TLBI_VMALLS12E1IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_alle1is_write }, { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_alle1_write }, + { .name = "TLBI_VMALLS12E1", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 6, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_alle1is_write }, #ifndef CONFIG_USER_ONLY /* 64 bit address translation operations */ { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64, @@ -3317,6 +3369,30 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 1, .opc2 = 1, .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "TLBI_ALLE3IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 0, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_alle3is_write }, + { .name = "TLBI_VAE3IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 1, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae3is_write }, + { .name = "TLBI_VALE3IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 5, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae3is_write }, + { .name = "TLBI_ALLE3", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 0, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_alle3_write }, + { .name = "TLBI_VAE3", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 1, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae3_write }, + { .name = "TLBI_VALE3", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae3_write }, REGINFO_SENTINEL }; From cea66e91212164e02ad1d245c2371f7e8eb59e7f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 25 Aug 2015 15:45:10 +0100 Subject: [PATCH 18/18] target-arm: Implement AArch64 TLBI operations on IPAs Implement the AArch64 TLBI operations which take an intermediate physical address and invalidate stage 2 translations. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Message-id: 1439548879-1972-7-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 00ecda93e4..7df1f0684d 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2709,6 +2709,45 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, } } +static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate by IPA. This has to invalidate any structures that + * contain only stage 2 translation information, but does not need + * to apply to structures that contain combined stage 1 and stage 2 + * translation information. + * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero. + */ + ARMCPU *cpu = arm_env_get_cpu(env); + CPUState *cs = CPU(cpu); + uint64_t pageaddr; + + if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { + return; + } + + pageaddr = sextract64(value << 12, 0, 48); + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S2NS, -1); +} + +static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + uint64_t pageaddr; + + if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { + return; + } + + pageaddr = sextract64(value << 12, 0, 48); + + CPU_FOREACH(other_cs) { + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S2NS, -1); + } +} + static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri) { /* We don't implement EL2, so the only control on DC ZVA is the @@ -2889,6 +2928,14 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vae1_write }, + { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_ipas2e1is_write }, + { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_ipas2e1is_write }, { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, .access = PL2_W, .type = ARM_CP_NO_RAW, @@ -2897,6 +2944,14 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6, .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_alle1is_write }, + { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_ipas2e1_write }, + { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_ipas2e1_write }, { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, .access = PL2_W, .type = ARM_CP_NO_RAW,