[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 3/5] target-arm: add hvc and smc exception em
From: |
Ard Biesheuvel |
Subject: |
Re: [Qemu-devel] [PATCH v2 3/5] target-arm: add hvc and smc exception emulation handling infrastructure |
Date: |
Mon, 1 Sep 2014 20:01:40 +0200 |
On 1 September 2014 13:55, Ard Biesheuvel <address@hidden> wrote:
> From: Rob Herring <address@hidden>
>
> Add the infrastructure to handle and emulate hvc and smc exceptions.
> This will enable emulation of things such as PSCI calls. This commit
> does not change the behavior and will exit with unknown exception.
>
> Signed-off-by: Rob Herring <address@hidden>
> Signed-off-by: Ard Biesheuvel <address@hidden>
> ---
> target-arm/cpu-qom.h | 3 +++
> target-arm/cpu.h | 2 ++
> target-arm/helper-a64.c | 16 ++++++++++++++++
> target-arm/helper.c | 32 ++++++++++++++++++++++++++++++++
> target-arm/internals.h | 20 ++++++++++++++++++++
> target-arm/translate-a64.c | 26 +++++++++++++++++---------
> target-arm/translate.c | 24 +++++++++++++++++-------
> 7 files changed, 107 insertions(+), 16 deletions(-)
>
> diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
> index eae0a7b9c908..104cc67e82d2 100644
> --- a/target-arm/cpu-qom.h
> +++ b/target-arm/cpu-qom.h
> @@ -192,6 +192,9 @@ extern const struct VMStateDescription vmstate_arm_cpu;
> void register_cp_regs_for_features(ARMCPU *cpu);
> void init_cpreg_list(ARMCPU *cpu);
>
> +bool arm_cpu_do_hvc(CPUState *cs);
> +bool arm_cpu_do_smc(CPUState *cs);
> +
> void arm_cpu_do_interrupt(CPUState *cpu);
> void arm_v7m_cpu_do_interrupt(CPUState *cpu);
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 51bedc826299..d235929f4c12 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -51,6 +51,8 @@
> #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
> +#define EXCP_SMC 12
>
> #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 89b913ee9396..1f8072ab141b 100644
> --- a/target-arm/helper-a64.c
> +++ b/target-arm/helper-a64.c
> @@ -485,6 +485,22 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
> case EXCP_FIQ:
> addr += 0x100;
> break;
> + case EXCP_HVC:
> + if (arm_cpu_do_hvc(cs)) {
> + return;
> + }
> + /* Treat as unallocated encoding */
> + qemu_log_mask(LOG_GUEST_ERROR, "HVC not implemented on this CPU\n");
> + env->exception.syndrome = syn_uncategorized();
> + break;
> + case EXCP_SMC:
> + if (arm_cpu_do_smc(cs)) {
> + return;
> + }
> + /* Treat as unallocated encoding */
> + qemu_log_mask(LOG_GUEST_ERROR, "SMC not implemented on this CPU\n");
> + env->exception.syndrome = syn_uncategorized();
> + break;
> default:
> cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
> }
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 2b95f33872cb..51a01a815b7b 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -3497,6 +3497,16 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
> env->thumb = addr & 1;
> }
>
> +bool arm_cpu_do_hvc(CPUState *cs)
> +{
> + return false;
> +}
> +
> +bool arm_cpu_do_smc(CPUState *cs)
> +{
> + return false;
> +}
> +
> /* Handle a CPU exception. */
> void arm_cpu_do_interrupt(CPUState *cs)
> {
> @@ -3599,6 +3609,28 @@ void arm_cpu_do_interrupt(CPUState *cs)
> mask = CPSR_A | CPSR_I | CPSR_F;
> offset = 4;
> break;
> + case EXCP_HVC:
> + if (arm_cpu_do_hvc(cs)) {
> + return;
> + }
> + qemu_log_mask(LOG_GUEST_ERROR, "HVC not implemented on this CPU\n");
> + goto hvc_unallocated;
> + case EXCP_SMC:
> + if (arm_cpu_do_smc(cs)) {
> + return;
> + }
> + qemu_log_mask(LOG_GUEST_ERROR, "SMC not implemented on this CPU\n");
> + hvc_unallocated:
> + /* Treat as unallocated encoding */
> + new_mode = ARM_CPU_MODE_UND;
> + addr = 0x04;
> + mask = CPSR_I;
> + if (env->thumb) {
> + offset = 2;
> + } else {
> + offset = 4;
> + }
> + break;
Replying to self: I guess I forgot to set the correct ESR value here, would this
env->cp15.esr_el[1] = syn_uncategorized();
be sufficient?
> default:
> cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
> return; /* Never happens. Keep compiler happy. */
> diff --git a/target-arm/internals.h b/target-arm/internals.h
> index 53c2e3cf3e7e..caab98e6b508 100644
> --- a/target-arm/internals.h
> +++ b/target-arm/internals.h
> @@ -210,6 +210,26 @@ static inline uint32_t syn_aa32_svc(uint32_t imm16, bool
> is_thumb)
> | (is_thumb ? 0 : ARM_EL_IL);
> }
>
> +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_hvc(uint32_t imm16)
> +{
> + return (EC_AA32_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_smc(void)
> +{
> + return (EC_AA32_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL;
> +}
> +
> static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
> {
> return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 8e66b6c97282..65e35e3aaec0 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -1473,20 +1473,28 @@ static void disas_exc(DisasContext *s, uint32_t insn)
>
> 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) {
> - unallocated_encoding(s);
> - break;
> - }
> /* For SVC, HVC and SMC we advance the single-step state
> * machine before taking the exception. This is architecturally
> * mandated, to ensure that single-stepping a system call
> * instruction works properly.
> */
> - gen_ss_advance(s);
> - gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
> + switch (op2_ll) {
> + case 1:
> + gen_ss_advance(s);
> + gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
> + break;
> + case 2:
> + gen_ss_advance(s);
> + gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
> + break;
> + case 3:
> + gen_ss_advance(s);
> + gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16));
> + break;
> + default:
> + unallocated_encoding(s);
> + break;
> + }
> break;
> case 1:
> if (op2_ll != 0) {
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index 2c0b1deaea81..a4545ed2bc40 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -7871,9 +7871,14 @@ static void disas_arm_insn(CPUARMState * env,
> DisasContext *s)
> case 7:
> {
> int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) <<
> 4);
> - /* SMC instruction (op1 == 3)
> - and undefined instructions (op1 == 0 || op1 == 2)
> - will trap */
> + /* HVC and SMC instructions */
> + if (op1 == 2) {
> + gen_exception_insn(s, 0, EXCP_HVC, syn_aa32_hvc(imm16));
> + break;
> + } else if (op1 == 3) {
> + gen_exception_insn(s, 0, EXCP_SMC, syn_aa32_smc());
> + break;
> + }
> if (op1 != 1) {
> goto illegal_op;
> }
> @@ -9709,10 +9714,15 @@ static int disas_thumb2_insn(CPUARMState *env,
> DisasContext *s, uint16_t insn_hw
> goto illegal_op;
>
> if (insn & (1 << 26)) {
> - /* Secure monitor call (v6Z) */
> - qemu_log_mask(LOG_UNIMP,
> - "arm: unimplemented secure monitor
> call\n");
> - goto illegal_op; /* not implemented. */
> + if (!(insn & (1 << 20))) {
> + /* Hypervisor call (v7) */
> + uint32_t imm16 = extract32(insn, 16, 4) << 12;
> + imm16 |= extract32(insn, 0, 12);
> + gen_exception_insn(s, 0, EXCP_HVC,
> syn_aa32_hvc(imm16));
> + } else {
> + /* Secure monitor call (v6+) */
> + gen_exception_insn(s, 0, EXCP_SMC, syn_aa32_smc());
> + }
> } else {
> op = (insn >> 20) & 7;
> switch (op) {
> --
> 1.8.3.2
>
- [Qemu-devel] [PATCH v2 0/5] ARM: add PSCI 0.2 support in TCG mode, Ard Biesheuvel, 2014/09/01
- [Qemu-devel] [PATCH v2 1/5] target-arm: add powered off cpu state, Ard Biesheuvel, 2014/09/01
- [Qemu-devel] [PATCH v2 2/5] target-arm: do not set do_interrupt handler for AArch64 user mode, Ard Biesheuvel, 2014/09/01
- [Qemu-devel] [PATCH v2 4/5] target-arm: add emulation of PSCI calls for system emulation, Ard Biesheuvel, 2014/09/01
- [Qemu-devel] [PATCH v2 3/5] target-arm: add hvc and smc exception emulation handling infrastructure, Ard Biesheuvel, 2014/09/01
- Re: [Qemu-devel] [PATCH v2 3/5] target-arm: add hvc and smc exception emulation handling infrastructure,
Ard Biesheuvel <=
- [Qemu-devel] [PATCH v2 5/5] arm/virt: enable PSCI emulation support for system emulation, Ard Biesheuvel, 2014/09/01
- Re: [Qemu-devel] [PATCH v2 0/5] ARM: add PSCI 0.2 support in TCG mode, Peter Maydell, 2014/09/01