* [Qemu-devel] [PATCH v5 01/10] target-arm: Add HCR_EL2
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-19 14:58 ` Peter Maydell
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 02/10] target-arm: Add SCR_EL3 Edgar E. Iglesias
` (9 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/cpu.h | 36 ++++++++++++++++++++++++++++++++++++
target-arm/helper.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 79205ba..8859b94 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -184,6 +184,7 @@ typedef struct CPUARMState {
MPU write buffer control. */
uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
+ uint64_t hcr_el2; /* Hypervisor configuration register */
uint32_t ifsr_el2; /* Fault status registers. */
uint64_t esr_el[4];
uint32_t c6_region[8]; /* MPU base/size registers. */
@@ -542,6 +543,41 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
}
}
+#define HCR_VM (1ULL << 0)
+#define HCR_SWIO (1ULL << 1)
+#define HCR_PTW (1ULL << 2)
+#define HCR_FMO (1ULL << 3)
+#define HCR_IMO (1ULL << 4)
+#define HCR_AMO (1ULL << 5)
+#define HCR_VF (1ULL << 6)
+#define HCR_VI (1ULL << 7)
+#define HCR_VSE (1ULL << 8)
+#define HCR_FB (1ULL << 9)
+#define HCR_BSU_MASK (3ULL << 10)
+#define HCR_DC (1ULL << 12)
+#define HCR_TWI (1ULL << 13)
+#define HCR_TWE (1ULL << 14)
+#define HCR_TID0 (1ULL << 15)
+#define HCR_TID1 (1ULL << 16)
+#define HCR_TID2 (1ULL << 17)
+#define HCR_TID3 (1ULL << 18)
+#define HCR_TSC (1ULL << 19)
+#define HCR_TIDCP (1ULL << 20)
+#define HCR_TACR (1ULL << 21)
+#define HCR_TSW (1ULL << 22)
+#define HCR_TPC (1ULL << 23)
+#define HCR_TPU (1ULL << 24)
+#define HCR_TTLB (1ULL << 25)
+#define HCR_TVM (1ULL << 26)
+#define HCR_TGE (1ULL << 27)
+#define HCR_TDZ (1ULL << 28)
+#define HCR_HCD (1ULL << 29)
+#define HCR_TRVM (1ULL << 30)
+#define HCR_RW (1ULL << 31)
+#define HCR_CD (1ULL << 32)
+#define HCR_ID (1ULL << 33)
+#define HCR_MASK ((1ULL << 34) - 1)
+
/* Return the current FPSCR value. */
uint32_t vfp_get_fpscr(CPUARMState *env);
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index f630d96..1021812 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2124,10 +2124,44 @@ static const ARMCPRegInfo v8_el3_no_el2_cp_reginfo[] = {
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
.access = PL2_RW,
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
+ { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
+ .type = ARM_CP_NO_MIGRATE,
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
+ .access = PL2_RW,
+ .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
REGINFO_SENTINEL
};
+static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ ARMCPU *cpu = arm_env_get_cpu(env);
+ uint64_t valid_mask = HCR_MASK;
+
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
+ valid_mask &= ~HCR_HCD;
+ } else {
+ valid_mask &= ~HCR_TSC;
+ }
+
+ /* Clear RES0 bits. */
+ value &= valid_mask;
+
+ /* These bits change the MMU setup:
+ * HCR_VM enables stage 2 translation
+ * HCR_PTW forbids certain page-table setups
+ * HCR_DC Disables stage1 and enables stage2 translation
+ */
+ if ((raw_read(env, ri) ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
+ tlb_flush(CPU(cpu), 1);
+ }
+ raw_write(env, ri, value);
+}
+
static const ARMCPRegInfo v8_el2_cp_reginfo[] = {
+ { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
+ .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
+ .writefn = hcr_write },
{ .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_NO_MIGRATE,
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 01/10] target-arm: Add HCR_EL2
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 01/10] target-arm: Add HCR_EL2 Edgar E. Iglesias
@ 2014-08-19 14:58 ` Peter Maydell
0 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2014-08-19 14:58 UTC (permalink / raw)
To: Edgar E. Iglesias
Cc: Rob Herring, Peter Crosthwaite, Fabian Aggeler, QEMU Developers,
Alexander Graf, Blue Swirl, Greg Bellows, Paolo Bonzini,
Alex Bennée, Christoffer Dall, Richard Henderson
On 18 August 2014 10:40, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
-- PMM
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 02/10] target-arm: Add SCR_EL3
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 01/10] target-arm: Add HCR_EL2 Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-19 15:13 ` Peter Maydell
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 03/10] target-arm: A64: Refactor aarch64_cpu_do_interrupt Edgar E. Iglesias
` (8 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/cpu.h | 17 ++++++++++++++++-
target-arm/helper.c | 35 +++++++++++++++++++++++++++++++++--
2 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8859b94..524eb90 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -172,7 +172,6 @@ typedef struct CPUARMState {
uint64_t c1_sys; /* System control register. */
uint64_t c1_coproc; /* Coprocessor access register. */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
- uint32_t c1_scr; /* secure config register. */
uint64_t ttbr0_el1; /* MMU translation table base 0. */
uint64_t ttbr1_el1; /* MMU translation table base 1. */
uint64_t c2_control; /* MMU translation table base control. */
@@ -185,6 +184,7 @@ typedef struct CPUARMState {
uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
uint64_t hcr_el2; /* Hypervisor configuration register */
+ uint32_t scr_el3; /* Secure configuration register. */
uint32_t ifsr_el2; /* Fault status registers. */
uint64_t esr_el[4];
uint32_t c6_region[8]; /* MPU base/size registers. */
@@ -578,6 +578,21 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define HCR_ID (1ULL << 33)
#define HCR_MASK ((1ULL << 34) - 1)
+#define SCR_NS (1U << 0)
+#define SCR_IRQ (1U << 1)
+#define SCR_FIQ (1U << 2)
+#define SCR_EA (1U << 3)
+#define SCR_SMD (1U << 7)
+#define SCR_HCE (1U << 8)
+#define SCR_SIF (1U << 9)
+#define SCR_RW (1U << 10)
+#define SCR_ST (1U << 11)
+#define SCR_TWI (1U << 12)
+#define SCR_TWE (1U << 13)
+#define SCR_AARCH64_RES1_MASK (3U << 4)
+#define SCR_AARCH32_MASK (0x3fff & ~(3U << 10))
+#define SCR_AARCH64_MASK (0x3fff & ~(1U << 6))
+
/* Return the current FPSCR value. */
uint32_t vfp_get_fpscr(CPUARMState *env);
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1021812..59144cd 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -684,6 +684,32 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
raw_write(env, ri, value & ~0x1FULL);
}
+static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ uint32_t valid_mask = is_a64(env) ? SCR_AARCH64_MASK : SCR_AARCH32_MASK;
+ uint32_t res1_mask = is_a64(env) ? SCR_AARCH64_RES1_MASK : 0;
+
+ if (!arm_feature(env, ARM_FEATURE_EL2)) {
+ valid_mask &= ~SCR_HCE;
+
+ /* On ARMv7, SMD (or SCD as it is called in v7) is only
+ * supported if EL2 exists. The bit is UNK/SBZP when
+ * EL2 is unavailable. In QEMU ARMv7, we force it to always zero
+ * when EL2 is unavailable.
+ */
+ if (arm_feature(env, ARM_FEATURE_V7)) {
+ valid_mask &= ~SCR_SMD;
+ }
+ }
+
+ /* Set RES1 bits. */
+ value |= res1_mask;
+
+ /* Clear RES0 bits. */
+ value &= valid_mask;
+ raw_write(env, ri, value);
+}
+
static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
ARMCPU *cpu = arm_env_get_cpu(env);
@@ -793,8 +819,8 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, cp15.vbar_el[1]),
.resetvalue = 0 },
{ .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_scr),
- .resetvalue = 0, },
+ .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
+ .resetvalue = 0, .writefn = scr_write },
{ .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
.access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE },
@@ -2208,6 +2234,11 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
.access = PL3_RW, .writefn = vbar_write,
.fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]),
.resetvalue = 0 },
+ { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64,
+ .type = ARM_CP_NO_MIGRATE,
+ .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0,
+ .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
+ .writefn = scr_write },
REGINFO_SENTINEL
};
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 02/10] target-arm: Add SCR_EL3
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 02/10] target-arm: Add SCR_EL3 Edgar E. Iglesias
@ 2014-08-19 15:13 ` Peter Maydell
0 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2014-08-19 15:13 UTC (permalink / raw)
To: Edgar E. Iglesias
Cc: Rob Herring, Peter Crosthwaite, Fabian Aggeler, QEMU Developers,
Alexander Graf, Blue Swirl, Greg Bellows, Paolo Bonzini,
Alex Bennée, Christoffer Dall, Richard Henderson
On 18 August 2014 10:40, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
> target-arm/cpu.h | 17 ++++++++++++++++-
> target-arm/helper.c | 35 +++++++++++++++++++++++++++++++++--
> 2 files changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 8859b94..524eb90 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -172,7 +172,6 @@ typedef struct CPUARMState {
> uint64_t c1_sys; /* System control register. */
> uint64_t c1_coproc; /* Coprocessor access register. */
> uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
> - uint32_t c1_scr; /* secure config register. */
> uint64_t ttbr0_el1; /* MMU translation table base 0. */
> uint64_t ttbr1_el1; /* MMU translation table base 1. */
> uint64_t c2_control; /* MMU translation table base control. */
> @@ -185,6 +184,7 @@ typedef struct CPUARMState {
> uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
> uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
> uint64_t hcr_el2; /* Hypervisor configuration register */
> + uint32_t scr_el3; /* Secure configuration register. */
This is a uint32_t but you refer to it below with fieldoffset() in
an AArch64 reginfo -- it has to be a uint64_t for that.
> uint32_t ifsr_el2; /* Fault status registers. */
> uint64_t esr_el[4];
> uint32_t c6_region[8]; /* MPU base/size registers. */
> @@ -578,6 +578,21 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
> #define HCR_ID (1ULL << 33)
> #define HCR_MASK ((1ULL << 34) - 1)
>
> +#define SCR_NS (1U << 0)
> +#define SCR_IRQ (1U << 1)
> +#define SCR_FIQ (1U << 2)
> +#define SCR_EA (1U << 3)
> +#define SCR_SMD (1U << 7)
> +#define SCR_HCE (1U << 8)
> +#define SCR_SIF (1U << 9)
> +#define SCR_RW (1U << 10)
> +#define SCR_ST (1U << 11)
> +#define SCR_TWI (1U << 12)
> +#define SCR_TWE (1U << 13)
> +#define SCR_AARCH64_RES1_MASK (3U << 4)
> +#define SCR_AARCH32_MASK (0x3fff & ~(3U << 10))
> +#define SCR_AARCH64_MASK (0x3fff & ~(1U << 6))
I find these masks rather confusing to read...
> +
> /* Return the current FPSCR value. */
> uint32_t vfp_get_fpscr(CPUARMState *env);
> void vfp_set_fpscr(CPUARMState *env, uint32_t val);
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 1021812..59144cd 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -684,6 +684,32 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
> raw_write(env, ri, value & ~0x1FULL);
> }
>
> +static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
> +{
> + uint32_t valid_mask = is_a64(env) ? SCR_AARCH64_MASK : SCR_AARCH32_MASK;
> + uint32_t res1_mask = is_a64(env) ? SCR_AARCH64_RES1_MASK : 0;
I don't think this is valid by the definition of RES0/RES1.
We're basically implementing SCR and SCR_EL3 as
aliased to each other. That means that bit 6 is RES0
for AArch64 but has a meaning in AArch32, which puts
it into the "RES0 only in some contexts" category.
That says "a direct write to the bit must update a storage
location associated with the bit" -- we can't mask it out
here.
thanks
-- PMM
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 03/10] target-arm: A64: Refactor aarch64_cpu_do_interrupt
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 01/10] target-arm: Add HCR_EL2 Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 02/10] target-arm: Add SCR_EL3 Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 04/10] target-arm: Break out exception masking to a separate func Edgar E. Iglesias
` (7 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Introduce new_el and new_mode in preparation for future patches
that add support for taking exceptions to and from EL2 and 3.
No functional change.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/cpu.h | 7 +++++++
target-arm/helper-a64.c | 24 +++++++++++++-----------
target-arm/helper.c | 13 +++++++++++++
3 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 524eb90..48efe23 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -476,6 +476,12 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
#define PSTATE_MODE_EL1t 4
#define PSTATE_MODE_EL0t 0
+/* Map EL and handler into a PSTATE_MODE. */
+static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
+{
+ return (el << 2) | handler;
+}
+
/* Return the current PSTATE value. For the moment we don't support 32<->64 bit
* interprocessing, so we don't attempt to sync with the cpsr state used by
* the 32 bit decoder.
@@ -729,6 +735,7 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
}
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);
/* Interface between CPU and Interrupt controller. */
void armv7m_nvic_set_pending(void *opaque, int irq);
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 2e9ef64..4be0784 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -443,10 +443,12 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
- target_ulong addr = env->cp15.vbar_el[1];
+ unsigned int new_el = arm_excp_target_el(cs, cs->exception_index);
+ target_ulong addr = env->cp15.vbar_el[new_el];
+ unsigned int new_mode = aarch64_pstate_mode(new_el, true);
int i;
- if (arm_current_pl(env) == 0) {
+ if (arm_current_pl(env) < new_el) {
if (env->aarch64) {
addr += 0x400;
} else {
@@ -464,14 +466,14 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
env->exception.syndrome);
}
- env->cp15.esr_el[1] = env->exception.syndrome;
- env->cp15.far_el[1] = env->exception.vaddress;
+ env->cp15.esr_el[new_el] = env->exception.syndrome;
+ env->cp15.far_el[new_el] = 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_el[1]);
+ env->cp15.far_el[new_el]);
break;
case EXCP_BKPT:
case EXCP_UDEF:
@@ -488,15 +490,15 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
}
if (is_a64(env)) {
- env->banked_spsr[aarch64_banked_spsr_index(1)] = pstate_read(env);
+ env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
aarch64_save_sp(env, arm_current_pl(env));
- env->elr_el[1] = env->pc;
+ env->elr_el[new_el] = env->pc;
} else {
env->banked_spsr[0] = cpsr_read(env);
if (!env->thumb) {
- env->cp15.esr_el[1] |= 1 << 25;
+ env->cp15.esr_el[new_el] |= 1 << 25;
}
- env->elr_el[1] = env->regs[15];
+ env->elr_el[new_el] = env->regs[15];
for (i = 0; i < 15; i++) {
env->xregs[i] = env->regs[i];
@@ -505,9 +507,9 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
env->condexec_bits = 0;
}
- pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
+ pstate_write(env, PSTATE_DAIF | new_mode);
env->aarch64 = 1;
- aarch64_restore_sp(env, 1);
+ aarch64_restore_sp(env, new_el);
env->pc = addr;
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 59144cd..a763f18 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3243,6 +3243,11 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
return 0;
}
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
+{
+ return 1;
+}
+
#else
/* Map CPU modes onto saved register banks. */
@@ -3298,6 +3303,14 @@ void switch_mode(CPUARMState *env, int mode)
env->spsr = env->banked_spsr[i];
}
+/*
+ * Determine the target EL for a given exception type.
+ */
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
+{
+ return 1;
+}
+
static void v7m_push(CPUARMState *env, uint32_t val)
{
CPUState *cs = CPU(arm_env_get_cpu(env));
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 04/10] target-arm: Break out exception masking to a separate func
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (2 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 03/10] target-arm: A64: Refactor aarch64_cpu_do_interrupt Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 05/10] target-arm: Don't take interrupts targeting lower ELs Edgar E. Iglesias
` (6 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
cpu-exec.c | 5 ++---
target-arm/cpu.h | 15 +++++++++++++++
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index c6aad74..f9c0ebc 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -595,7 +595,7 @@ int cpu_exec(CPUArchState *env)
}
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
- && !(env->daif & PSTATE_F)) {
+ && arm_excp_unmasked(cpu, EXCP_FIQ)) {
cpu->exception_index = EXCP_FIQ;
cc->do_interrupt(cpu);
next_tb = 0;
@@ -610,8 +610,7 @@ int cpu_exec(CPUArchState *env)
We avoid this by disabling interrupts when
pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD
- && ((IS_M(env) && env->regs[15] < 0xfffffff0)
- || !(env->daif & PSTATE_I))) {
+ && arm_excp_unmasked(cpu, EXCP_IRQ)) {
cpu->exception_index = EXCP_IRQ;
cc->do_interrupt(cpu);
next_tb = 0;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 48efe23..ffcfb10 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1146,6 +1146,21 @@ bool write_cpustate_to_list(ARMCPU *cpu);
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
+static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
+{
+ CPUARMState *env = cs->env_ptr;
+
+ switch (excp_idx) {
+ case EXCP_FIQ:
+ return !(env->daif & PSTATE_F);
+ case EXCP_IRQ:
+ return ((IS_M(env) && env->regs[15] < 0xfffffff0)
+ || !(env->daif & PSTATE_I));
+ default:
+ g_assert_not_reached();
+ }
+}
+
static inline CPUARMState *cpu_init(const char *cpu_model)
{
ARMCPU *cpu = cpu_arm_init(cpu_model);
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 05/10] target-arm: Don't take interrupts targeting lower ELs
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (3 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 04/10] target-arm: Break out exception masking to a separate func Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 06/10] target-arm: A64: Correct updates to FAR and ESR on exceptions Edgar E. Iglesias
` (5 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/cpu.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ffcfb10..dd39642 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1149,6 +1149,13 @@ bool write_cpustate_to_list(ARMCPU *cpu);
static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
{
CPUARMState *env = cs->env_ptr;
+ unsigned int cur_el = arm_current_pl(env);
+ unsigned int target_el = arm_excp_target_el(cs, excp_idx);
+
+ /* Don't take exceptions if they target a lower EL. */
+ if (cur_el > target_el) {
+ return false;
+ }
switch (excp_idx) {
case EXCP_FIQ:
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 06/10] target-arm: A64: Correct updates to FAR and ESR on exceptions
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (4 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 05/10] target-arm: Don't take interrupts targeting lower ELs Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 07/10] target-arm: A64: Emulate the HVC insn Edgar E. Iglesias
` (4 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Not all exception types update both FAR and ESR.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/helper-a64.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 4be0784..c6ef8e9 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -466,18 +466,17 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
env->exception.syndrome);
}
- env->cp15.esr_el[new_el] = env->exception.syndrome;
- env->cp15.far_el[new_el] = env->exception.vaddress;
-
switch (cs->exception_index) {
case EXCP_PREFETCH_ABORT:
case EXCP_DATA_ABORT:
+ env->cp15.far_el[new_el] = env->exception.vaddress;
qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
env->cp15.far_el[new_el]);
- break;
+ /* fall through */
case EXCP_BKPT:
case EXCP_UDEF:
case EXCP_SWI:
+ env->cp15.esr_el[new_el] = env->exception.syndrome;
break;
case EXCP_IRQ:
addr += 0x80;
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 07/10] target-arm: A64: Emulate the HVC insn
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (5 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 06/10] target-arm: A64: Correct updates to FAR and ESR on exceptions Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 08/10] target-arm: A64: Emulate the SMC insn Edgar E. Iglesias
` (3 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/cpu.h | 1 +
target-arm/helper-a64.c | 1 +
target-arm/helper.c | 28 +++++++++++++++++++++++++++-
target-arm/helper.h | 1 +
target-arm/internals.h | 6 ++++++
target-arm/op_helper.c | 35 +++++++++++++++++++++++++++++++++++
target-arm/translate-a64.c | 21 ++++++++++++++++-----
7 files changed, 87 insertions(+), 6 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index dd39642..2c185a1 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -51,6 +51,7 @@
#define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */
#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
#define EXCP_STREX 10
+#define EXCP_HVC 11 /* HyperVisor Call */
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index c6ef8e9..4e6ca26 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -476,6 +476,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
case EXCP_BKPT:
case EXCP_UDEF:
case EXCP_SWI:
+ case EXCP_HVC:
env->cp15.esr_el[new_el] = env->exception.syndrome;
break;
case EXCP_IRQ:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a763f18..a8f7e24 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3308,7 +3308,33 @@ void switch_mode(CPUARMState *env, int mode)
*/
unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
{
- return 1;
+ CPUARMState *env = cs->env_ptr;
+ unsigned int cur_el = arm_current_pl(env);
+ unsigned int target_el = 1;
+ bool route_to_el2 = false;
+ /* FIXME: Use actual secure state. */
+ bool secure = false;
+
+ if (!env->aarch64) {
+ /* TODO: Add EL2 and 3 exception handling for AArch32. */
+ return 1;
+ }
+
+ if (!secure
+ && arm_feature(env, ARM_FEATURE_EL2)
+ && cur_el < 2
+ && (env->cp15.hcr_el2 & HCR_TGE)) {
+ route_to_el2 = true;
+ }
+
+ target_el = MAX(cur_el, route_to_el2 ? 2 : 1);
+
+ switch (excp_idx) {
+ case EXCP_HVC:
+ target_el = MAX(target_el, 2);
+ break;
+ }
+ return target_el;
}
static void v7m_push(CPUARMState *env, uint32_t val)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index facfcd2..70cfd28 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -50,6 +50,7 @@ DEF_HELPER_2(exception_internal, void, env, i32)
DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(wfe, void, env)
+DEF_HELPER_2(hvc, void, env, i32)
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
DEF_HELPER_1(cpsr_read, i32, env)
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 08fa697..b08381c 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -53,6 +53,7 @@ static const char * const excnames[] = {
[EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
[EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
[EXCP_STREX] = "QEMU intercept of STREX",
+ [EXCP_HVC] = "Hypervisor Call",
};
static inline void arm_log_exception(int idx)
@@ -204,6 +205,11 @@ static inline uint32_t syn_aa64_svc(uint32_t imm16)
return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
}
+static inline uint32_t syn_aa64_hvc(uint32_t imm16)
+{
+ return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
{
return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 25ad902..d08c6a7 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -369,6 +369,41 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
}
}
+void HELPER(hvc)(CPUARMState *env, uint32_t syndrome)
+{
+ int cur_el = arm_current_pl(env);
+ /* FIXME: Use actual secure state. */
+ bool secure = false;
+ bool udef;
+
+ /* We've already checked that EL2 exists at translation time.
+ * EL3.HCE has priority over EL2.HCD.
+ */
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
+ udef = !(env->cp15.scr_el3 & SCR_HCE);
+ } else {
+ udef = env->cp15.hcr_el2 & HCR_HCD;
+ }
+
+ /* In ARMv7 and ARMv8/AArch32, HVC is udef in secure state.
+ * For ARMv8/AArch64, HVC is allowed in EL3.
+ * Note that we've already trapped HVC from EL0 at translation
+ * time.
+ */
+ if (secure && (!is_a64(env) || cur_el == 1)) {
+ udef = true;
+ }
+
+ if (udef) {
+ /* UDEFs trap on the HVC, roll back to the PC to the HVC insn. */
+ env->pc -= 4;
+ env->exception.syndrome = syn_uncategorized();
+ raise_exception(env, EXCP_UDEF);
+ }
+ env->exception.syndrome = syndrome;
+ raise_exception(env, EXCP_HVC);
+}
+
void HELPER(exception_return)(CPUARMState *env)
{
int cur_el = arm_current_pl(env);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index f04ca49..a2851ad 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1438,17 +1438,28 @@ static void disas_exc(DisasContext *s, uint32_t insn)
int opc = extract32(insn, 21, 3);
int op2_ll = extract32(insn, 0, 5);
int imm16 = extract32(insn, 5, 16);
+ TCGv_i32 tmp;
switch (opc) {
case 0:
- /* SVC, HVC, SMC; since we don't support the Virtualization
- * or TrustZone extensions these all UNDEF except SVC.
- */
- if (op2_ll != 1) {
+ switch (op2_ll) {
+ case 1:
+ gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
+ break;
+ case 2:
+ if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_pl == 0) {
+ unallocated_encoding(s);
+ break;
+ }
+ tmp = tcg_const_i32(syn_aa64_hvc(imm16));
+ gen_a64_set_pc_im(s->pc);
+ gen_helper_hvc(cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
+ break;
+ default:
unallocated_encoding(s);
break;
}
- gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
break;
case 1:
if (op2_ll != 0) {
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 08/10] target-arm: A64: Emulate the SMC insn
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (6 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 07/10] target-arm: A64: Emulate the HVC insn Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 09/10] target-arm: Add IRQ and FIQ routing to EL2 and 3 Edgar E. Iglesias
` (2 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/cpu.h | 1 +
target-arm/helper-a64.c | 1 +
target-arm/helper.c | 6 ++++++
target-arm/helper.h | 1 +
target-arm/internals.h | 6 ++++++
target-arm/op_helper.c | 31 +++++++++++++++++++++++++++++++
target-arm/translate-a64.c | 10 ++++++++++
7 files changed, 56 insertions(+)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2c185a1..683fd44 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -52,6 +52,7 @@
#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
#define EXCP_STREX 10
#define EXCP_HVC 11 /* HyperVisor Call */
+#define EXCP_SMC 12 /* Secure Monitor Call */
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 4e6ca26..996dfea 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -477,6 +477,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
case EXCP_UDEF:
case EXCP_SWI:
case EXCP_HVC:
+ case EXCP_SMC:
env->cp15.esr_el[new_el] = env->exception.syndrome;
break;
case EXCP_IRQ:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a8f7e24..a2205d1 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3333,6 +3333,12 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
case EXCP_HVC:
target_el = MAX(target_el, 2);
break;
+ case EXCP_SMC:
+ target_el = 3;
+ if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+ target_el = 2;
+ }
+ break;
}
return target_el;
}
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 70cfd28..4293453 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -51,6 +51,7 @@ DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(wfe, void, env)
DEF_HELPER_2(hvc, void, env, i32)
+DEF_HELPER_2(smc, void, env, i32)
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
DEF_HELPER_1(cpsr_read, i32, env)
diff --git a/target-arm/internals.h b/target-arm/internals.h
index b08381c..e50a68e 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -54,6 +54,7 @@ static const char * const excnames[] = {
[EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
[EXCP_STREX] = "QEMU intercept of STREX",
[EXCP_HVC] = "Hypervisor Call",
+ [EXCP_SMC] = "Secure Monitor Call",
};
static inline void arm_log_exception(int idx)
@@ -210,6 +211,11 @@ static inline uint32_t syn_aa64_hvc(uint32_t imm16)
return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
}
+static inline uint32_t syn_aa64_smc(uint32_t imm16)
+{
+ return (EC_AA64_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
{
return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index d08c6a7..afd1dba 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -404,6 +404,37 @@ void HELPER(hvc)(CPUARMState *env, uint32_t syndrome)
raise_exception(env, EXCP_HVC);
}
+void HELPER(smc)(CPUARMState *env, uint32_t syndrome)
+{
+ int cur_el = arm_current_pl(env);
+ /* FIXME: Use real secure state. */
+ bool secure = false;
+ bool smd = env->cp15.scr_el3 & SCR_SMD;
+ /* On ARMv8 AArch32, SMD only applies to NS mode.
+ * On ARMv7 SMD only applies to NS mode and only if EL2 is available.
+ * For ARMv7 non EL2, we force SMD to zero so we don't need to re-check
+ * the EL2 condition here.
+ */
+ bool udef = is_a64(env) ? smd : !secure && smd;
+
+ /* In NS EL1, HCR controlled routing to EL2 has priority over SMD. */
+ if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+ /* When routing SMCs to EL2, the trap is taken at the SMC insn. */
+ env->pc -= 4;
+ udef = false;
+ }
+
+ /* We've already checked that EL3 exists at translation time. */
+ if (udef) {
+ /* UDEFs trap on the SMC, roll back to the PC to the SMC insn. */
+ env->pc -= 4;
+ env->exception.syndrome = syn_uncategorized();
+ raise_exception(env, EXCP_UDEF);
+ }
+ env->exception.syndrome = syndrome;
+ raise_exception(env, EXCP_SMC);
+}
+
void HELPER(exception_return)(CPUARMState *env)
{
int cur_el = arm_current_pl(env);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index a2851ad..731b9aa 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1456,6 +1456,16 @@ static void disas_exc(DisasContext *s, uint32_t insn)
gen_helper_hvc(cpu_env, tmp);
tcg_temp_free_i32(tmp);
break;
+ case 3:
+ if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->current_pl == 0) {
+ unallocated_encoding(s);
+ break;
+ }
+ tmp = tcg_const_i32(syn_aa64_smc(imm16));
+ gen_a64_set_pc_im(s->pc);
+ gen_helper_smc(cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
+ break;
default:
unallocated_encoding(s);
break;
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 09/10] target-arm: Add IRQ and FIQ routing to EL2 and 3
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (7 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 08/10] target-arm: A64: Emulate the SMC insn Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 10/10] target-arm: Add support for VIRQ and VFIQ Edgar E. Iglesias
2014-09-09 19:16 ` [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Peter Maydell
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
target-arm/cpu.h | 12 ++++++++++++
target-arm/helper.c | 14 ++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 683fd44..8ad23fa 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1153,6 +1153,12 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
CPUARMState *env = cs->env_ptr;
unsigned int cur_el = arm_current_pl(env);
unsigned int target_el = arm_excp_target_el(cs, excp_idx);
+ /* FIXME: Use actual secure state. */
+ bool secure = false;
+ /* Interrupts can only be hypervised and routed to
+ * EL2 if we are in NS EL0/1.
+ */
+ bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
/* Don't take exceptions if they target a lower EL. */
if (cur_el > target_el) {
@@ -1161,8 +1167,14 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
switch (excp_idx) {
case EXCP_FIQ:
+ if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
+ return true;
+ }
return !(env->daif & PSTATE_F);
case EXCP_IRQ:
+ if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
+ return true;
+ }
return ((IS_M(env) && env->regs[15] < 0xfffffff0)
|| !(env->daif & PSTATE_I));
default:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a2205d1..976fd89 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3339,6 +3339,20 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
target_el = 2;
}
break;
+ case EXCP_FIQ:
+ case EXCP_IRQ:
+ {
+ const uint64_t hcr_mask = excp_idx == EXCP_FIQ ? HCR_FMO : HCR_IMO;
+ const uint32_t scr_mask = excp_idx == EXCP_FIQ ? SCR_FIQ : SCR_IRQ;
+
+ if (!secure && (env->cp15.hcr_el2 & hcr_mask)) {
+ target_el = 2;
+ }
+ if (env->cp15.scr_el3 & scr_mask) {
+ target_el = 3;
+ }
+ break;
+ }
}
return target_el;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 10/10] target-arm: Add support for VIRQ and VFIQ
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (8 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 09/10] target-arm: Add IRQ and FIQ routing to EL2 and 3 Edgar E. Iglesias
@ 2014-08-18 9:40 ` Edgar E. Iglesias
2014-09-09 19:16 ` [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Peter Maydell
10 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-08-18 9:40 UTC (permalink / raw)
To: qemu-devel, peter.maydell
Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Acked-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
cpu-exec.c | 12 ++++++++++++
target-arm/cpu.c | 25 +++++++++++++++----------
target-arm/cpu.h | 36 +++++++++++++++++++++++++++++++++---
target-arm/helper-a64.c | 2 ++
target-arm/helper.c | 4 ++++
target-arm/internals.h | 2 ++
6 files changed, 68 insertions(+), 13 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index f9c0ebc..190b0d9 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -615,6 +615,18 @@ int cpu_exec(CPUArchState *env)
cc->do_interrupt(cpu);
next_tb = 0;
}
+ if (interrupt_request & CPU_INTERRUPT_VIRQ
+ && arm_excp_unmasked(cpu, EXCP_VIRQ)) {
+ cpu->exception_index = EXCP_VIRQ;
+ cc->do_interrupt(cpu);
+ next_tb = 0;
+ }
+ if (interrupt_request & CPU_INTERRUPT_VFIQ
+ && arm_excp_unmasked(cpu, EXCP_VFIQ)) {
+ cpu->exception_index = EXCP_VFIQ;
+ cc->do_interrupt(cpu);
+ next_tb = 0;
+ }
#elif defined(TARGET_UNICORE32)
if (interrupt_request & CPU_INTERRUPT_HARD
&& !(env->uncached_asr & ASR_I)) {
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 7cebb76..3d7e0bb 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -179,20 +179,22 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
{
ARMCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
+ static const int mask[] = {
+ [ARM_CPU_IRQ] = CPU_INTERRUPT_HARD,
+ [ARM_CPU_FIQ] = CPU_INTERRUPT_FIQ,
+ [ARM_CPU_VIRQ] = CPU_INTERRUPT_VIRQ,
+ [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
+ };
switch (irq) {
case ARM_CPU_IRQ:
- if (level) {
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
- }
- break;
case ARM_CPU_FIQ:
+ case ARM_CPU_VIRQ:
+ case ARM_CPU_VFIQ:
if (level) {
- cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
+ cpu_interrupt(cs, mask[irq]);
} else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
+ cpu_reset_interrupt(cs, mask[irq]);
}
break;
default:
@@ -242,9 +244,12 @@ static void arm_cpu_initfn(Object *obj)
#ifndef CONFIG_USER_ONLY
/* Our inbound IRQ and FIQ lines */
if (kvm_enabled()) {
- qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 2);
+ /* VIRQ and VFIQ are unused with KVM but we add them to maintain
+ * the same interface as non-KVM CPUs.
+ */
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 4);
} else {
- qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2);
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4);
}
cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8ad23fa..b72608e 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -53,6 +53,8 @@
#define EXCP_STREX 10
#define EXCP_HVC 11 /* HyperVisor Call */
#define EXCP_SMC 12 /* Secure Monitor Call */
+#define EXCP_VIRQ 13
+#define EXCP_VFIQ 14
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
@@ -67,6 +69,8 @@
/* ARM-specific interrupt pending bits. */
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
+#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2
+#define CPU_INTERRUPT_VFIQ CPU_INTERRUPT_TGT_EXT_3
/* The usual mapping for an AArch64 system register to its AArch32
* counterpart is for the 32 bit world to have access to the lower
@@ -82,9 +86,12 @@
#define offsetofhigh32(S, M) (offsetof(S, M) + sizeof(uint32_t))
#endif
-/* Meanings of the ARMCPU object's two inbound GPIO lines */
+/* Meanings of the ARMCPU object's four inbound GPIO lines */
#define ARM_CPU_IRQ 0
#define ARM_CPU_FIQ 1
+#define ARM_CPU_VIRQ 2
+#define ARM_CPU_VFIQ 3
+
typedef void ARMWriteCPFunc(void *opaque, int cp_info,
int srcreg, int operand, uint32_t value);
@@ -1159,6 +1166,18 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
* EL2 if we are in NS EL0/1.
*/
bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
+ /* ARMv7-M interrupt return works by loading a magic value
+ * into the PC. On real hardware the load causes the
+ * return to occur. The qemu implementation performs the
+ * jump normally, then does the exception return when the
+ * CPU tries to execute code at the magic address.
+ * This will cause the magic PC value to be pushed to
+ * the stack if an interrupt occurred at the wrong time.
+ * We avoid this by disabling interrupts when
+ * pc contains a magic address.
+ */
+ bool irq_unmasked = ((IS_M(env) && env->regs[15] < 0xfffffff0)
+ || !(env->daif & PSTATE_I));
/* Don't take exceptions if they target a lower EL. */
if (cur_el > target_el) {
@@ -1175,8 +1194,19 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
return true;
}
- return ((IS_M(env) && env->regs[15] < 0xfffffff0)
- || !(env->daif & PSTATE_I));
+ return irq_unmasked;
+ case EXCP_VFIQ:
+ if (!secure && !(env->cp15.hcr_el2 & HCR_FMO)) {
+ /* VFIQs are only taken when hypervized and non-secure. */
+ return false;
+ }
+ return !(env->daif & PSTATE_F);
+ case EXCP_VIRQ:
+ if (!secure && !(env->cp15.hcr_el2 & HCR_IMO)) {
+ /* VIRQs are only taken when hypervized and non-secure. */
+ return false;
+ }
+ return irq_unmasked;
default:
g_assert_not_reached();
}
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 996dfea..bd16fe3 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -481,9 +481,11 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
env->cp15.esr_el[new_el] = env->exception.syndrome;
break;
case EXCP_IRQ:
+ case EXCP_VIRQ:
addr += 0x80;
break;
case EXCP_FIQ:
+ case EXCP_VFIQ:
addr += 0x100;
break;
default:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 976fd89..fd34660 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3353,6 +3353,10 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
}
break;
}
+ case EXCP_VIRQ:
+ case EXCP_VFIQ:
+ target_el = 1;
+ break;
}
return target_el;
}
diff --git a/target-arm/internals.h b/target-arm/internals.h
index e50a68e..b1d2d4e 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -55,6 +55,8 @@ static const char * const excnames[] = {
[EXCP_STREX] = "QEMU intercept of STREX",
[EXCP_HVC] = "Hypervisor Call",
[EXCP_SMC] = "Secure Monitor Call",
+ [EXCP_VIRQ] = "Virtual IRQ",
+ [EXCP_VFIQ] = "Virtual FIQ",
};
static inline void arm_log_exception(int idx)
--
1.9.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model
2014-08-18 9:40 [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
` (9 preceding siblings ...)
2014-08-18 9:40 ` [Qemu-devel] [PATCH v5 10/10] target-arm: Add support for VIRQ and VFIQ Edgar E. Iglesias
@ 2014-09-09 19:16 ` Peter Maydell
2014-09-09 22:33 ` Edgar E. Iglesias
10 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2014-09-09 19:16 UTC (permalink / raw)
To: Edgar E. Iglesias
Cc: Rob Herring, Peter Crosthwaite, Fabian Aggeler, QEMU Developers,
Alexander Graf, Blue Swirl, Greg Bellows, Paolo Bonzini,
Alex Bennée, Christoffer Dall, Richard Henderson
On 18 August 2014 10:40, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>
> Hi,
>
> This is a second round of AArch64 EL2/3 patches working on the exception
> model. Among other things adding HVC/SMC, interrupt routing to EL2/3 and
> Virtual IRQs/FIQs. The VIRQ/VFIQ support only adds the external signal
> delivery method.
>
> Patch 8 fails checkpatch, seems like a bug in checkpatch, CC:d Blue.
>
> This conflicts slightly with the PSCI emulation patches that Rob posted.
> A rebase should be trivial, hooking in the PSCI emulation calls in the
> HVC/SMC helpers.
Ping? I was expecting to see a v6 of this...
thanks
-- PMM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model
2014-09-09 19:16 ` [Qemu-devel] [PATCH v5 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Peter Maydell
@ 2014-09-09 22:33 ` Edgar E. Iglesias
0 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2014-09-09 22:33 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Peter Crosthwaite, Fabian Aggeler, QEMU Developers,
Alexander Graf, Blue Swirl, Greg Bellows, Paolo Bonzini,
Alex Bennée, Christoffer Dall, Richard Henderson
On Tue, Sep 09, 2014 at 08:16:47PM +0100, Peter Maydell wrote:
> On 18 August 2014 10:40, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> > From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> >
> > Hi,
> >
> > This is a second round of AArch64 EL2/3 patches working on the exception
> > model. Among other things adding HVC/SMC, interrupt routing to EL2/3 and
> > Virtual IRQs/FIQs. The VIRQ/VFIQ support only adds the external signal
> > delivery method.
> >
> > Patch 8 fails checkpatch, seems like a bug in checkpatch, CC:d Blue.
> >
> > This conflicts slightly with the PSCI emulation patches that Rob posted.
> > A rebase should be trivial, hooking in the PSCI emulation calls in the
> > HVC/SMC helpers.
>
> Ping? I was expecting to see a v6 of this...
Hi,
Yes, it's just been busy times on my side. I will send a v6 out this week.
What I was planning todo:
1. Another shot at the RES0/1
2. Rebase the SMC/HVC code with the single step implementation in upstream.
3. Add virtual IRQ/FIQs to the list of events that signal that a CPU
has work todo.
If you have any further comments on the patches that still lack Reviewed-By,
it would be great to get them soon. Maybe we can avoid some of the slow
round-trips.
Cheers,
Edgar
^ permalink raw reply [flat|nested] 15+ messages in thread