From patchwork Wed Sep 10 07:02:48 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 37182 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pa0-f71.google.com (mail-pa0-f71.google.com [209.85.220.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 77A2120491 for ; Wed, 10 Sep 2014 07:04:19 +0000 (UTC) Received: by mail-pa0-f71.google.com with SMTP id rd3sf32229463pab.10 for ; Wed, 10 Sep 2014 00:04:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=MYS+7VGzqLHav96aP4gPPxI0t95EQRBKGcUpks9jdFA=; b=Dr9paG8ZXO651NRJynCAPLs3fLLuM/DtI9FYVxoaCrt0jxjmtgwn1ql0Je+neTo8AE iGIGiKXfEfxcMiuhhUTZ2nltvazveM2+w3YINjATEK8mG429oUw9Ls7RpjDT9zhDsi5W yCz0OZVVGoG/qJhwWfD3sijlHGXJ6drdgc0wLz7S4g69PDPc660UAFCr7z/vY1o7Hjs8 +M0Cvl6rovjIxrZVy3yoO6K6JaAATj8uLCaZRtZ7EbvVkjHrQrljNo3C/X/CocfJFghs 6EG3Qp8bPYWDcP6wZ/Von7sCRT4SMVXjypvmJvg1cA/ZfMhMPzJMsGwZ2cRjcE0und7y Qc7w== X-Gm-Message-State: ALoCoQmhUj/bRR5Da+u+MbQJphtyiafaPS3ADkeoCsZQvGFKsTiFdLwpRl0RggltBDjB2k078jyw X-Received: by 10.67.4.231 with SMTP id ch7mr132251pad.46.1410332658807; Wed, 10 Sep 2014 00:04:18 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.93.34 with SMTP id c31ls2432279qge.92.gmail; Wed, 10 Sep 2014 00:04:18 -0700 (PDT) X-Received: by 10.52.26.206 with SMTP id n14mr28725693vdg.0.1410332658650; Wed, 10 Sep 2014 00:04:18 -0700 (PDT) Received: from mail-vc0-f175.google.com (mail-vc0-f175.google.com [209.85.220.175]) by mx.google.com with ESMTPS id hf10si4747602vdb.57.2014.09.10.00.04.18 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Sep 2014 00:04:18 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.175 as permitted sender) client-ip=209.85.220.175; Received: by mail-vc0-f175.google.com with SMTP id hq11so1658vcb.20 for ; Wed, 10 Sep 2014 00:04:18 -0700 (PDT) X-Received: by 10.52.185.168 with SMTP id fd8mr5152615vdc.58.1410332658546; Wed, 10 Sep 2014 00:04:18 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp394613vcb; Wed, 10 Sep 2014 00:04:18 -0700 (PDT) X-Received: by 10.140.28.8 with SMTP id 8mr56204518qgy.19.1410332657966; Wed, 10 Sep 2014 00:04:17 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id w9si17887109qcj.42.2014.09.10.00.04.17 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 10 Sep 2014 00:04:17 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:53883 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XRbwv-00041J-GB for patch@linaro.org; Wed, 10 Sep 2014 03:04:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45206) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XRbvo-0002vN-5M for qemu-devel@nongnu.org; Wed, 10 Sep 2014 03:03:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XRbvg-00058X-VJ for qemu-devel@nongnu.org; Wed, 10 Sep 2014 03:03:08 -0400 Received: from mail-wg0-f43.google.com ([74.125.82.43]:38666) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XRbvg-00058N-N4 for qemu-devel@nongnu.org; Wed, 10 Sep 2014 03:03:00 -0400 Received: by mail-wg0-f43.google.com with SMTP id x12so4752882wgg.26 for ; Wed, 10 Sep 2014 00:03:00 -0700 (PDT) X-Received: by 10.194.23.167 with SMTP id n7mr12464816wjf.35.1410332579992; Wed, 10 Sep 2014 00:02:59 -0700 (PDT) Received: from ards-macbook-pro.local (cag06-7-83-153-85-71.fbx.proxad.net. [83.153.85.71]) by mx.google.com with ESMTPSA id wx3sm17405444wjc.19.2014.09.10.00.02.58 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Sep 2014 00:02:59 -0700 (PDT) From: Ard Biesheuvel To: peter.maydell@linaro.org, qemu-devel@nongnu.org Date: Wed, 10 Sep 2014 09:02:48 +0200 Message-Id: <1410332571-10544-4-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1410332571-10544-1-git-send-email-ard.biesheuvel@linaro.org> References: <1410332571-10544-1-git-send-email-ard.biesheuvel@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 74.125.82.43 Cc: Rob Herring , christoffer.dall@linaro.org, Ard Biesheuvel Subject: [Qemu-devel] [PACTH v4 3/6] target-arm: add hvc and smc exception emulation handling infrastructure X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ard.biesheuvel@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.175 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Rob Herring 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 Signed-off-by: Ard Biesheuvel --- target-arm/cpu-qom.h | 3 +++ target-arm/cpu.h | 2 ++ target-arm/helper-a64.c | 16 +++++++++++++ target-arm/helper.c | 23 ++++++++++++++++++ target-arm/internals.h | 20 ++++++++++++++++ target-arm/translate-a64.c | 35 ++++++++++++++++++++------- target-arm/translate.c | 59 +++++++++++++++++++++++++++++++++++++--------- target-arm/translate.h | 2 ++ 8 files changed, 140 insertions(+), 20 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 9c129c8b080c..64bd49ecdaf9 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3492,6 +3492,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) { @@ -3508,6 +3518,19 @@ void arm_cpu_do_interrupt(CPUState *cs) /* TODO: Vectored interrupt controller. */ switch (cs->exception_index) { + 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: + /* Fall through -- treat as unallocated encoding */ case EXCP_UDEF: new_mode = ARM_CPU_MODE_UND; addr = 0x04; 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..e5fb775c4a50 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -1473,20 +1473,37 @@ 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: + if (s->current_pl != 0 + && arm_dc_feature(s, ARM_FEATURE_EL2)) { + gen_ss_advance(s); + gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16)); + break; + } + unallocated_encoding(s); + break; + case 3: + if (s->current_pl != 0 + && arm_dc_feature(s, ARM_FEATURE_EL3)) { + gen_ss_advance(s); + gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16)); + break; + } + /* fall through */ + 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..aefe01142762 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -7871,15 +7871,33 @@ 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 */ - if (op1 != 1) { + switch (op1) { + case 1: + /* bkpt */ + ARCH(5); + gen_exception_insn(s, 4, EXCP_BKPT, + syn_aa32_bkpt(imm16, false)); + break; + case 2: + /* Hypervisor call (v7) */ + ARCH(7); + if (IS_USER(s)) + goto illegal_op; + s->svc_imm = imm16; + gen_set_pc_im(s, s->pc); + s->is_jmp = DISAS_HVC; + break; + case 3: + /* Secure monitor call (v6+) */ + ARCH(6K); + if (IS_USER(s)) + goto illegal_op; + gen_set_pc_im(s, s->pc); + s->is_jmp = DISAS_SMC; + break; + default: goto illegal_op; } - /* bkpt */ - ARCH(5); - gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false)); break; } case 0x8: /* signed multiply */ @@ -9709,10 +9727,23 @@ 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) */ + ARCH(7); + if (IS_USER(s)) + goto illegal_op; + s->svc_imm = extract32(insn, 16, 4) << 12 | + extract32(insn, 0, 12); + gen_set_pc_im(s, s->pc); + s->is_jmp = DISAS_HVC; + } else { + /* Secure monitor call (v6+) */ + ARCH(6K); + if (IS_USER(s)) + goto illegal_op; + gen_set_pc_im(s, s->pc); + s->is_jmp = DISAS_SMC; + } } else { op = (insn >> 20) & 7; switch (op) { @@ -11200,6 +11231,12 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, case DISAS_SWI: gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; + case DISAS_HVC: + gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm)); + break; + case DISAS_SMC: + gen_exception(EXCP_SMC, syn_aa32_smc()); + break; } if (dc->condjmp) { gen_set_label(dc->condlabel); diff --git a/target-arm/translate.h b/target-arm/translate.h index b90d27514d52..50c4d6ef4ab6 100644 --- a/target-arm/translate.h +++ b/target-arm/translate.h @@ -82,6 +82,8 @@ static inline int get_mem_index(DisasContext *s) #define DISAS_EXC 6 /* WFE */ #define DISAS_WFE 7 +#define DISAS_HVC 8 +#define DISAS_SMC 9 #ifdef TARGET_AARCH64 void a64_translate_init(void);