From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by 10.28.71.27 with SMTP id u27csp1474347wma; Tue, 30 Jan 2018 07:03:20 -0800 (PST) X-Google-Smtp-Source: AH8x225BRJtNvov7CwaLgxnC1fltEBZVvIqpGUPRYt6AK2iPoT8rwpMfsDqKMkDoeNa+0ctWpc6J X-Received: by 10.37.13.86 with SMTP id 83mr1127501ybn.362.1517324600835; Tue, 30 Jan 2018 07:03:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517324600; cv=none; d=google.com; s=arc-20160816; b=gZnHcsLzmx+ooKbFLnrrGLqa8VbKLJZvJ+hfbb4zAw7cO2gZTP292M2lAYr+2MeH5/ FZJzcRQrhVtEF2eB6eKFNucvWz058oDd2gbe7nOtxoNA4N+SX7isS4Tss9RSjmzHaBbM 7M2cz5sbEHVt6GFMLOtETq0MlFuSxowi4VIkM4LgJouidHyIMd/0HpqVzV3VzvT37W2B 1CQqRJHyvDdhVU9j/WUFsSklJ/2+ju00lCxgNVOPBm8/g8mixDT1Ut19uYFa8Kcx+E2A QZaF1i52VfQ27ZIJQMwz3t38iGrCrO2tlwP6e3cCxdqTUCtPN6/A+N3qwY7YFH/xcOUo 5G7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:arc-authentication-results; bh=wa7POKrjenT0+JVtmQlQRH+A4Kun+4t6c/JBqjbuTzM=; b=K9pV6YgfZEj6/+JTQ+4IK+lQuZizR4uweM91/MbQv62SE7VqxdCT7LCFh4bh0FdZSe tnmCARZF1OAofb/fGXN4otq5Fo4j9XlTh1n856wEMQH4JWXduhpj8GcLN90BjZQ0KVqk VKD8xsf3f9Bohavz4u3qgr/yhBydE87ysP4yJHbErQz/Zjl+zGpSOfy5YGXJA84URLeo bAC8qOSHRhxlLBuackL1ZLOBMihERYpMm25mhSLNeKRgzTSUZukEDsEUnmzxpTsraYXA IaFlAdssLe5rSJQvtjT/g8rFl/XLcH0vJmS3GBzW2e/9yLeTko5qAWKqxD/VtX3PDBpA W2pg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id i2si474758ywl.23.2018.01.30.07.03.20 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 30 Jan 2018 07:03:20 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42071 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egXRQ-0000gM-7L for alex.bennee@linaro.org; Tue, 30 Jan 2018 10:03:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49089) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egXQk-0000Bh-7K for qemu-arm@nongnu.org; Tue, 30 Jan 2018 10:02:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1egXQd-0005Zz-NW for qemu-arm@nongnu.org; Tue, 30 Jan 2018 10:02:38 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:46114) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1egXQd-0005Xp-Eq; Tue, 30 Jan 2018 10:02:31 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1egXQW-0005sJ-CG; Tue, 30 Jan 2018 15:02:24 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Tue, 30 Jan 2018 15:02:16 +0000 Message-Id: <1517324542-6607-2-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1517324542-6607-1-git-send-email-peter.maydell@linaro.org> References: <1517324542-6607-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-arm] [PATCH 1/7] target/arm: Add armv7m_nvic_set_pending_derived() X-BeenThere: qemu-arm@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: patches@linaro.org Errors-To: qemu-arm-bounces+alex.bennee=linaro.org@nongnu.org Sender: "Qemu-arm" X-TUID: LXEs5zV0bd5w In order to support derived exceptions (exceptions generated in the course of trying to take an exception), we need to be able to handle prioritizing whether to take the original exception or the derived exception. We do this by introducing a new function armv7m_nvic_set_pending_derived() which the exception-taking code in helper.c will call when a derived exception occurs. Derived exceptions are dealt with mostly like normal pending exceptions, so we share the implementation with the armv7m_nvic_set_pending() function. Note that the way we structure this is significantly different from the v8M Arm ARM pseudocode: that does all the prioritization logic in the DerivedLateArrival() function, whereas we choose to let the existing "identify highest priority exception" logic do the prioritization for us. The effect is the same, though. Signed-off-by: Peter Maydell --- target/arm/cpu.h | 13 ++++++++++ hw/intc/armv7m_nvic.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++-- hw/intc/trace-events | 2 +- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index d2bb59e..9ed03e6 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1506,6 +1506,19 @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque) */ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure); /** + * armv7m_nvic_set_pending_derived: mark this derived exception as pending + * @opaque: the NVIC + * @irq: the exception number to mark pending + * @secure: false for non-banked exceptions or for the nonsecure + * version of a banked exception, true for the secure version of a banked + * exception. + * + * Similar to armv7m_nvic_set_pending(), but specifically for derived + * exceptions (exceptions generated in the course of trying to take + * a different exception). + */ +void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure); +/** * armv7m_nvic_acknowledge_irq: make highest priority pending exception active * @opaque: the NVIC * diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 8ca6cee..b4a6e7c 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -503,8 +503,25 @@ static void armv7m_nvic_clear_pending(void *opaque, int irq, bool secure) } } -void armv7m_nvic_set_pending(void *opaque, int irq, bool secure) +static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure, + bool derived) { + /* Pend an exception, including possibly escalating it to HardFault. + * + * This function handles both "normal" pending of interrupts and + * exceptions, and also derived exceptions (ones which occur as + * a result of trying to take some other exception). + * + * If derived == true, the caller guarantees that we are part way through + * trying to take an exception (but have not yet called + * armv7m_nvic_acknowledge_irq() to make it active), and so: + * - s->vectpending is the "original exception" we were trying to take + * - irq is the "derived exception" + * - nvic_exec_prio(s) gives the priority before exception entry + * Here we handle the prioritization logic which the pseudocode puts + * in the DerivedLateArrival() function. + */ + NVICState *s = (NVICState *)opaque; bool banked = exc_is_banked(irq); VecInfo *vec; @@ -514,7 +531,44 @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure) vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq]; - trace_nvic_set_pending(irq, secure, vec->enabled, vec->prio); + trace_nvic_set_pending(irq, secure, derived, vec->enabled, vec->prio); + + if (derived) { + /* Derived exceptions are always synchronous. */ + assert(irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV); + + if (irq == ARMV7M_EXCP_DEBUG && + exc_group_prio(s, vec->prio, secure) >= nvic_exec_prio(s)) { + /* DebugMonitorFault, but its priority is lower than the + * preempted exception priority: just ignore it. + */ + return; + } + + if (irq == ARMV7M_EXCP_HARD && vec->prio >= s->vectpending_prio) { + /* If this is a terminal exception (one which means we cannot + * take the original exception, like a failure to read its + * vector table entry), then we must take the derived exception. + * If the derived exception can't take priority over the + * original exception, then we go into Lockup. + * + * For QEMU, we rely on the fact that a derived exception is + * terminal if and only if it's reported to us as HardFault, + * which saves having to have an extra argument is_terminal + * that we'd only use in one place. + */ + cpu_abort(&s->cpu->parent_obj, + "Lockup: can't take terminal derived exception " + "(original exception priority %d)\n", + s->vectpending_prio); + } + /* We now continue with the same code as for a normal pending + * exception, which will cause us to pend the derived exception. + * We'll then take either the original or the derived exception + * based on which is higher priority by the usual mechanism + * for selecting the highest priority pending interrupt. + */ + } if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) { /* If a synchronous exception is pending then it may be @@ -585,6 +639,16 @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure) } } +void armv7m_nvic_set_pending(void *opaque, int irq, bool secure) +{ + do_armv7m_nvic_set_pending(opaque, irq, secure, false); +} + +void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure) +{ + do_armv7m_nvic_set_pending(opaque, irq, secure, true); +} + /* Make pending IRQ active. */ bool armv7m_nvic_acknowledge_irq(void *opaque) { diff --git a/hw/intc/trace-events b/hw/intc/trace-events index be76918..09e87d1 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -177,7 +177,7 @@ nvic_set_prio(int irq, bool secure, uint8_t prio) "NVIC set irq %d secure-bank % nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d" nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d" nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled" -nvic_set_pending(int irq, bool secure, int en, int prio) "NVIC set pending irq %d secure-bank %d (enabled: %d priority %d)" +nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)" nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)" nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1" nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC acknowledge IRQ: %d now active (prio %d targets_secure %d)" -- 2.7.4