From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-arm@nongnu.org, qemu-devel@nongnu.org
Cc: patches@linaro.org, Shlomo Pongratz <shlomo.pongratz@huawei.com>,
Shlomo Pongratz <shlomopongratz@gmail.com>,
Pavel Fedin <p.fedin@samsung.com>,
Shannon Zhao <shannon.zhao@linaro.org>,
Christoffer Dall <christoffer.dall@linaro.org>
Subject: [Qemu-devel] [PATCH v2 16/22] hw/intc/arm_gicv3: Implement gicv3_cpuif_update()
Date: Thu, 26 May 2016 15:55:34 +0100 [thread overview]
Message-ID: <1464274540-19693-17-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1464274540-19693-1-git-send-email-peter.maydell@linaro.org>
Implement the gicv3_cpuif_update() function which deals with correctly
asserting IRQ and FIQ based on the current running priority of the CPU,
the priority of the highest priority pending interrupt and the CPU's
current exception level and security state.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/intc/arm_gicv3_cpuif.c | 140 +++++++++++++++++++++++++++++++++++++++++++++-
hw/intc/gicv3_internal.h | 5 +-
trace-events | 2 +
3 files changed, 142 insertions(+), 5 deletions(-)
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index e112646..7faf3c0 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -36,6 +36,142 @@ static bool gicv3_use_ns_bank(CPUARMState *env)
return !arm_is_secure_below_el3(env);
}
+static int icc_highest_active_prio(GICv3CPUState *cs)
+{
+ /* Calculate the current running priority based on the set bits
+ * in the Active Priority Registers.
+ */
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cs->icc_apr[0]); i++) {
+ uint32_t apr = cs->icc_apr[GICV3_G0][i] |
+ cs->icc_apr[GICV3_G1][i] | cs->icc_apr[GICV3_G1NS][i];
+
+ if (!apr) {
+ continue;
+ }
+ return (i * 32 + ctz32(apr)) << (GIC_MIN_BPR + 1);
+ }
+ /* No current active interrupts: return idle priority */
+ return 0xff;
+}
+
+static uint32_t icc_gprio_mask(GICv3CPUState *cs, int group)
+{
+ /* Return a mask word which clears the subpriority bits from
+ * a priority value for an interrupt in the specified group.
+ * This depends on the BPR value:
+ * a BPR of 0 means the group priority bits are [7:1];
+ * a BPR of 1 means they are [7:2], and so on down to
+ * a BPR of 7 meaning no group priority bits at all.
+ * Which BPR to use depends on the group of the interrupt and
+ * the current ICC_CTLR.CBPR settings.
+ */
+ if ((group == GICV3_G1 && cs->icc_ctlr_el1[GICV3_S] & ICC_CTLR_EL1_CBPR) ||
+ (group == GICV3_G1NS &&
+ cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR)) {
+ group = GICV3_G0;
+ }
+
+ return ~0U << ((cs->icc_bpr[group] & 7) + 1);
+}
+
+static bool icc_no_enabled_hppi(GICv3CPUState *cs)
+{
+ /* Return true if there is no pending interrupt, or the
+ * highest priority pending interrupt is in a group which has been
+ * disabled at the CPU interface by the ICC_IGRPEN* register enable bits.
+ */
+ return cs->hppi.prio == 0xff || (cs->icc_igrpen[cs->hppi.grp] == 0);
+}
+
+static bool icc_hppi_can_preempt(GICv3CPUState *cs)
+{
+ /* Return true if we have a pending interrupt of sufficient
+ * priority to preempt.
+ */
+ int rprio;
+ uint32_t mask;
+
+ if (icc_no_enabled_hppi(cs)) {
+ return false;
+ }
+
+ if (cs->hppi.prio >= cs->icc_pmr_el1) {
+ /* Priority mask masks this interrupt */
+ return false;
+ }
+
+ rprio = icc_highest_active_prio(cs);
+ if (rprio == 0xff) {
+ /* No currently running interrupt so we can preempt */
+ return true;
+ }
+
+ mask = icc_gprio_mask(cs, cs->hppi.grp);
+
+ /* We only preempt a running interrupt if the pending interrupt's
+ * group priority is sufficient (the subpriorities are not considered).
+ */
+ if ((cs->hppi.prio & mask) < (rprio & mask)) {
+ return true;
+ }
+
+ return false;
+}
+
+void gicv3_cpuif_update(GICv3CPUState *cs)
+{
+ /* Tell the CPU about its highest priority pending interrupt */
+ int irqlevel = 0;
+ int fiqlevel = 0;
+ ARMCPU *cpu = ARM_CPU(cs->cpu);
+ CPUARMState *env = &cpu->env;
+
+ trace_gicv3_cpuif_update(gicv3_redist_affid(cs), cs->hppi.irq,
+ cs->hppi.grp, cs->hppi.prio);
+
+ if (cs->hppi.grp == GICV3_G1 && !arm_feature(env, ARM_FEATURE_EL3)) {
+ /* If a Security-enabled GIC sends a G1S interrupt to a
+ * Security-disabled CPU, we must treat it as if it were G0.
+ */
+ cs->hppi.grp = GICV3_G0;
+ }
+
+ if (icc_hppi_can_preempt(cs)) {
+ /* We have an interrupt: should we signal it as IRQ or FIQ?
+ * This is described in the GICv3 spec section 4.6.2.
+ */
+ bool isfiq;
+
+ switch (cs->hppi.grp) {
+ case GICV3_G0:
+ isfiq = true;
+ break;
+ case GICV3_G1:
+ isfiq = (!arm_is_secure(env) ||
+ (arm_current_el(env) == 3 && arm_el_is_aa64(env, 3)));
+ break;
+ case GICV3_G1NS:
+ isfiq = arm_is_secure(env);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (isfiq) {
+ fiqlevel = 1;
+ } else {
+ irqlevel = 1;
+ }
+ }
+
+ trace_gicv3_cpuif_set_irqs(gicv3_redist_affid(cs), fiqlevel, irqlevel);
+
+ qemu_set_irq(cs->parent_fiq, fiqlevel);
+ qemu_set_irq(cs->parent_irq, irqlevel);
+}
+
static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
GICv3CPUState *cs = icc_cs_from_env(env);
@@ -617,7 +753,9 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
{
- /* Do nothing for now. */
+ GICv3CPUState *cs = opaque;
+
+ gicv3_cpuif_update(cs);
}
void gicv3_init_cpuif(GICv3State *s)
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index bd96419..d06ef3e 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -222,10 +222,7 @@ void gicv3_init_cpuif(GICv3State *s);
* current running priority or the CPU's current exception level or
* security state.
*/
-static inline void gicv3_cpuif_update(GICv3CPUState *cs)
-{
- /* This will be implemented in a later commit. */
-}
+void gicv3_cpuif_update(GICv3CPUState *cs);
static inline uint32_t gicv3_iidr(void)
{
diff --git a/trace-events b/trace-events
index bfc7251..e84cea9 100644
--- a/trace-events
+++ b/trace-events
@@ -1932,6 +1932,8 @@ gicv3_icc_ctlr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR read cpu %x valu
gicv3_icc_ctlr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR write cpu %x value 0x%" PRIx64
gicv3_icc_ctlr_el3_read(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR_EL3 read cpu %x value 0x%" PRIx64
gicv3_icc_ctlr_el3_write(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR_EL3 write cpu %x value 0x%" PRIx64
+gicv3_cpuif_update(uint32_t cpuid, int irq, int grp, int prio) "GICv3 CPU i/f %x HPPI update: irq %d group %d prio %d"
+gicv3_cpuif_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f %x HPPI update: setting FIQ %d IRQ %d"
# hw/intc/arm_gicv3_dist.c
gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
--
1.9.1
next prev parent reply other threads:[~2016-05-26 14:56 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-26 14:55 [Qemu-devel] [PATCH v2 00/22] GICv3 emulation Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 01/22] migration: Define VMSTATE_UINT64_2DARRAY Peter Maydell
2016-06-07 3:32 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 02/22] bitops.h: Implement half-shuffle and half-unshuffle ops Peter Maydell
2016-06-07 6:35 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 03/22] target-arm: Define new arm_is_el3_or_mon() function Peter Maydell
2016-06-07 6:32 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 04/22] target-arm: Provide hook to tell GICv3 about changes of security state Peter Maydell
2016-06-14 1:49 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 05/22] target-arm: Add mp-affinity property for ARM CPU class Peter Maydell
2016-06-07 7:55 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 06/22] hw/intc/arm_gicv3: Add state information Peter Maydell
2016-06-07 7:51 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 07/22] hw/intc/arm_gicv3: Move irq lines into GICv3CPUState structure Peter Maydell
2016-06-07 8:33 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 08/22] hw/intc/arm_gicv3: Add vmstate descriptors Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 09/22] hw/intc/arm_gicv3: ARM GICv3 device framework Peter Maydell
2016-06-07 9:01 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 10/22] hw/intc/arm_gicv3: Implement functions to identify next pending irq Peter Maydell
2016-06-08 1:57 ` Shannon Zhao
2016-06-09 15:24 ` Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 11/22] hw/intc/arm_gicv3: Implement GICv3 distributor registers Peter Maydell
2016-06-13 6:27 ` Shannon Zhao
2016-06-13 9:04 ` Peter Maydell
2016-06-13 9:35 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 12/22] hw/intc/arm_gicv3: Implement GICv3 redistributor registers Peter Maydell
2016-06-14 3:09 ` Shannon Zhao
2016-06-14 12:25 ` Peter Maydell
2016-06-14 12:28 ` Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 13/22] hw/intc/arm_gicv3: Wire up distributor and redistributor MMIO regions Peter Maydell
2016-06-13 7:19 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 14/22] hw/intc/arm_gicv3: Implement gicv3_set_irq() Peter Maydell
2016-06-13 7:49 ` Shannon Zhao
2016-06-13 9:07 ` Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 15/22] hw/intc/arm_gicv3: Implement GICv3 CPU interface registers Peter Maydell
2016-05-26 14:55 ` Peter Maydell [this message]
2016-06-13 7:56 ` [Qemu-devel] [PATCH v2 16/22] hw/intc/arm_gicv3: Implement gicv3_cpuif_update() Shannon Zhao
2016-06-13 9:10 ` Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 17/22] hw/intc/arm_gicv3: Implement CPU i/f SGI generation registers Peter Maydell
2016-06-14 6:24 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 18/22] hw/intc/arm_gicv3: Add IRQ handling CPU interface registers Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 19/22] target-arm/machine.c: Allow user to request GICv3 emulation Peter Maydell
2016-06-13 11:38 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 20/22] target-arm/monitor.c: Advertise emulated GICv3 in capabilities Peter Maydell
2016-06-13 11:40 ` Shannon Zhao
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 21/22] NOT-FOR-UPSTREAM: kernel: Add definitions for GICv3 attributes Peter Maydell
2016-06-13 11:51 ` Shannon Zhao
2016-06-13 12:02 ` Peter Maydell
2016-05-26 14:55 ` [Qemu-devel] [PATCH v2 22/22] RFC: hw/intc/arm_gicv3_kvm: Implement get/put functions Peter Maydell
2016-05-30 11:15 ` [Qemu-devel] [PATCH v2 00/22] GICv3 emulation Andrew Jones
2016-06-06 14:42 ` [Qemu-devel] [Qemu-arm] " Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1464274540-19693-17-git-send-email-peter.maydell@linaro.org \
--to=peter.maydell@linaro.org \
--cc=christoffer.dall@linaro.org \
--cc=p.fedin@samsung.com \
--cc=patches@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=shannon.zhao@linaro.org \
--cc=shlomo.pongratz@huawei.com \
--cc=shlomopongratz@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).