From patchwork Tue Sep 12 18:13:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 112348 Delivered-To: patches@linaro.org Received: by 10.140.106.117 with SMTP id d108csp5548909qgf; Tue, 12 Sep 2017 11:13:41 -0700 (PDT) X-Google-Smtp-Source: ADKCNb65qowww6soKKWsw+Mp+jyLbIFH70cgNiRlUGzLlzQLHBssfbv8UkwB9YC7rrBtLHBD06P1 X-Received: by 10.223.195.108 with SMTP id e41mr12596829wrg.51.1505240021739; Tue, 12 Sep 2017 11:13:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505240021; cv=none; d=google.com; s=arc-20160816; b=Omd75nscoB7CsiOkpqJsbZPHUt0sRCz9FcgI5PWxMHkqbqTLPKwN/STpNP3sRsPYAL RGvxxf/9LxsgXsmVYUJLETfD3pMqTGixYrvlKvHs84Jq8rporRIIx5R3V0qGkG2t2dke xeIEXJnYxpz94kf8PAAzB6xlhQSVOvjJQzE7QjEuQqK6Nyj4hxmZjV4PpsCHlspRevTU l3qopGpgawERDMdG++H9lcy/lUk+fy56OJ0n0r8lEiWi5suTa1FjQ0uBVJa1soCssxpK JxKsDlrqxSWNgkYqULpbd6SRAiFLC3L/vHQWb8vYXtVXT08PhQ7PxusDxv95UPl9XDqS vw4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=bpESvZ/5OmlheuZ1ANsRLM3u0F8HOEBbwg6I+XzDjuU=; b=D9XftrHVhhiq6eVGoFsN3La7qo1Mpen9UFgdbTLlkYXPOEhXWLITpCU/oXKthbk3BS RM1wbcvj7hYvRwYPzgjB+b8Yo98HozFG0mjtKFmxLu9M4gz1zsVri8zAnLghU9qN763S q+z+5k0Vbkaj1+8ntlnKGwv/43ZgN0hbitq1I2qWHeUhNbTiEFrg5i362s4/K7NYBoNR n80ADOltFV4CeVeYecgHLHoA8N54AXsMi9Pc0QFxZiASoRL304VLeNvKD0wsYqjkolf0 mTx1R1A4uPHbucjoJ8u1YkWk125n99iOhsbgYgCh3QWGdsn8T1dVo6XrQ/2bZlIMzQhR M+iw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id b9si9492025wrh.36.2017.09.12.11.13.41 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Sep 2017 11:13:41 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1drpgq-00013G-Tx; Tue, 12 Sep 2017 19:13:40 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org Subject: [PATCH 02/19] nvic: Add banked exception states Date: Tue, 12 Sep 2017 19:13:49 +0100 Message-Id: <1505240046-11454-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1505240046-11454-1-git-send-email-peter.maydell@linaro.org> References: <1505240046-11454-1-git-send-email-peter.maydell@linaro.org> For the v8M security extension, some exceptions must be banked between security states. Add the new vecinfo array which holds the state for the banked exceptions and migrate it if the CPU the NVIC is attached to implements the security extension. Signed-off-by: Peter Maydell --- include/hw/intc/armv7m_nvic.h | 14 +++++++++++++ hw/intc/armv7m_nvic.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) -- 2.7.4 Reviewed-by: Richard Henderson diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h index 1a4cce7..317601e 100644 --- a/include/hw/intc/armv7m_nvic.h +++ b/include/hw/intc/armv7m_nvic.h @@ -21,6 +21,8 @@ /* Highest permitted number of exceptions (architectural limit) */ #define NVIC_MAX_VECTORS 512 +/* Number of internal exceptions */ +#define NVIC_INTERNAL_VECTORS 16 typedef struct VecInfo { /* Exception priorities can range from -3 to 255; only the unmodifiable @@ -41,6 +43,18 @@ typedef struct NVICState { ARMCPU *cpu; VecInfo vectors[NVIC_MAX_VECTORS]; + /* If the v8M security extension is implemented, some of the internal + * exceptions are banked between security states (ie there exists both + * a Secure and a NonSecure version of the exception and its state): + * HardFault, MemManage, UsageFault, SVCall, PendSV, SysTick (R_PJHV) + * The rest (including all the external exceptions) are not banked, though + * they may be configurable to target either Secure or NonSecure state. + * We store the secure exception state in sec_vectors[] for the banked + * exceptions, and otherwise use only vectors[] (including for exceptions + * like SecureFault that unconditionally target Secure state). + * Entries in sec_vectors[] for non-banked exception numbers are unused. + */ + VecInfo sec_vectors[NVIC_INTERNAL_VECTORS]; uint32_t prigroup; /* vectpending and exception_prio are both cached state that can diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index d3e2056..694b9e0 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -47,7 +47,7 @@ * For historical reasons QEMU tends to use "interrupt" and * "exception" more or less interchangeably. */ -#define NVIC_FIRST_IRQ 16 +#define NVIC_FIRST_IRQ NVIC_INTERNAL_VECTORS #define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ) /* Effective running priority of the CPU when no exception is active @@ -1158,6 +1158,43 @@ static const VMStateDescription vmstate_VecInfo = { } }; +static bool nvic_security_needed(void *opaque) +{ + NVICState *s = opaque; + + return arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY); +} + +static int nvic_security_post_load(void *opaque, int version_id) +{ + NVICState *s = opaque; + int i; + + /* Check for out of range priority settings */ + if (s->sec_vectors[ARMV7M_EXCP_HARD].prio != -1) { + return 1; + } + for (i = ARMV7M_EXCP_MEM; i < ARRAY_SIZE(s->sec_vectors); i++) { + if (s->sec_vectors[i].prio & ~0xff) { + return 1; + } + } + return 0; +} + +static const VMStateDescription vmstate_nvic_security = { + .name = "nvic/m-security", + .version_id = 1, + .minimum_version_id = 1, + .needed = nvic_security_needed, + .post_load = &nvic_security_post_load, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(sec_vectors, NVICState, NVIC_INTERNAL_VECTORS, 1, + vmstate_VecInfo, VecInfo), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_nvic = { .name = "armv7m_nvic", .version_id = 4, @@ -1195,6 +1232,16 @@ static void armv7m_nvic_reset(DeviceState *dev) s->vectors[ARMV7M_EXCP_NMI].prio = -2; s->vectors[ARMV7M_EXCP_HARD].prio = -1; + if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY)) { + s->sec_vectors[ARMV7M_EXCP_HARD].enabled = 1; + s->sec_vectors[ARMV7M_EXCP_SVC].enabled = 1; + s->sec_vectors[ARMV7M_EXCP_PENDSV].enabled = 1; + s->sec_vectors[ARMV7M_EXCP_SYSTICK].enabled = 1; + + /* AIRCR.BFHFNMINS resets to 0 so Secure HF is priority -1 (R_CMTC) */ + s->sec_vectors[ARMV7M_EXCP_HARD].prio = -1; + } + /* Strictly speaking the reset handler should be enabled. * However, we don't simulate soft resets through the NVIC, * and the reset vector should never be pended.