qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Luc Michel <luc.michel@greensocs.com>
To: qemu-devel@nongnu.org
Cc: Luc Michel <luc.michel@greensocs.com>,
	qemu-arm@nongnu.org, Peter Maydell <peter.maydell@linaro.org>,
	saipava@xilinx.com, edgari@xilinx.com, mark.burton@greensocs.com,
	Jan Kiszka <jan.kiszka@web.de>
Subject: [Qemu-devel] [PATCH v5 12/20] intc/arm_gic: Implement virtualization extensions in gic_(deactivate|complete_irq)
Date: Fri, 27 Jul 2018 11:54:13 +0200	[thread overview]
Message-ID: <20180727095421.386-13-luc.michel@greensocs.com> (raw)
In-Reply-To: <20180727095421.386-1-luc.michel@greensocs.com>

Implement virtualization extensions in the gic_deactivate_irq() and
gic_complete_irq() functions.

When the guest writes an invalid vIRQ to V_EOIR or V_DIR, since the
GICv2 specification is not entirely clear here, we adopt the behaviour
observed on real hardware:
  * When V_CTRL.EOIMode is false (EOI split is disabled):
    - In case of an invalid vIRQ write to V_EOIR:
      -> If some bits are set in H_APR, an invalid vIRQ write to V_EOIR
         triggers a priority drop, and increments V_HCR.EOICount.
      -> If V_APR is already cleared, nothing happen

    - An invalid vIRQ write to V_DIR is ignored.

  * When V_CTRL.EOIMode is true:
    - In case of an invalid vIRQ write to V_EOIR:
      -> If some bits are set in H_APR, an invalid vIRQ write to V_EOIR
         triggers a priority drop.
      -> If V_APR is already cleared, nothing happen

    - An invalid vIRQ write to V_DIR increments V_HCR.EOICount.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
---
 hw/intc/arm_gic.c | 51 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index d80acde989..3cddf65826 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -581,31 +581,41 @@ static bool gic_eoi_split(GICState *s, int cpu, MemTxAttrs attrs)
 
 static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 {
     int group;
 
-    if (irq >= s->num_irq) {
+    if (irq >= GIC_MAXIRQ || (!gic_is_vcpu(cpu) && irq >= s->num_irq)) {
         /*
          * This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_DIR, the GIC ignores that write.
          * 2. If software writes the number of a non-existent interrupt
          * this must be a subcase of "value written is not an active interrupt"
-         * and so this is UNPREDICTABLE. We choose to ignore it.
+         * and so this is UNPREDICTABLE. We choose to ignore it. For vCPUs,
+         * all IRQs potentially exist, so this limit does not apply.
          */
         return;
     }
 
-    group = gic_has_groups(s) && gic_test_group(s, irq, cpu);
-
     if (!gic_eoi_split(s, cpu, attrs)) {
         /* This is UNPREDICTABLE; we choose to ignore it */
         qemu_log_mask(LOG_GUEST_ERROR,
                       "gic_deactivate_irq: GICC_DIR write when EOIMode clear");
         return;
     }
 
+    if (gic_is_vcpu(cpu) && !gic_virq_is_valid(s, irq, cpu)) {
+        /* This vIRQ does not have an LR entry which is either active or
+         * pending and active. Increment EOICount and ignore the write.
+         */
+        int rcpu = gic_get_vcpu_real_id(cpu);
+        s->h_hcr[rcpu] += 1 << R_GICH_HCR_EOICount_SHIFT;
+        return;
+    }
+
+    group = gic_has_groups(s) && gic_test_group(s, irq, cpu);
+
     if (gic_cpu_ns_access(s, cpu, attrs) && !group) {
         DPRINTF("Non-secure DI for Group0 interrupt %d ignored\n", irq);
         return;
     }
 
@@ -616,10 +626,43 @@ static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 {
     int cm = 1 << cpu;
     int group;
 
     DPRINTF("EOI %d\n", irq);
+    if (gic_is_vcpu(cpu)) {
+        /* The call to gic_prio_drop() will clear a bit in GICH_APR iff the
+         * running prio is < 0x100.
+         */
+        bool prio_drop = s->running_priority[cpu] < 0x100;
+
+        if (irq >= GIC_MAXIRQ) {
+            /* Ignore spurious interrupt */
+            return;
+        }
+
+        gic_drop_prio(s, cpu, 0);
+
+        if (!gic_eoi_split(s, cpu, attrs)) {
+            bool valid = gic_virq_is_valid(s, irq, cpu);
+            if (prio_drop && !valid) {
+                /* We are in a situation where:
+                 *   - V_CTRL.EOIMode is false (no EOI split),
+                 *   - The call to gic_drop_prio() cleared a bit in GICH_APR,
+                 *   - This vIRQ does not have an LR entry which is either
+                 *     active or pending and active.
+                 * In that case, we must increment EOICount.
+                 */
+                int rcpu = gic_get_vcpu_real_id(cpu);
+                s->h_hcr[rcpu] += 1 << R_GICH_HCR_EOICount_SHIFT;
+            } else if (valid) {
+                gic_clear_active(s, irq, cpu);
+            }
+        }
+
+        return;
+    }
+
     if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
          * 2. If software writes the number of a non-existent interrupt
-- 
2.18.0

  parent reply	other threads:[~2018-07-27  9:55 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-27  9:54 [Qemu-devel] [PATCH v5 00/20] arm_gic: add virtualization extensions support Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 01/20] intc/arm_gic: Refactor operations on the distributor Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 02/20] intc/arm_gic: Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 03/20] intc/arm_gic: Remove some dead code and put some functions static Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 04/20] vmstate.h: Provide VMSTATE_UINT16_SUB_ARRAY Luc Michel
2018-07-27 12:41   ` [Qemu-devel] [Qemu-arm] " Philippe Mathieu-Daudé
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 05/20] intc/arm_gic: Add the virtualization extensions to the GIC state Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 06/20] intc/arm_gic: Add virtual interface register definitions Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 07/20] intc/arm_gic: Add virtualization extensions helper macros and functions Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 08/20] intc/arm_gic: Refactor secure/ns access check in the CPU interface Luc Michel
2018-07-27 12:45   ` [Qemu-devel] [Qemu-arm] " Philippe Mathieu-Daudé
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 09/20] intc/arm_gic: Add virtualization enabled IRQ helper functions Luc Michel
2018-07-27 12:48   ` [Qemu-devel] [Qemu-arm] " Philippe Mathieu-Daudé
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 10/20] intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio) Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq Luc Michel
2018-07-27  9:54 ` Luc Michel [this message]
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 13/20] intc/arm_gic: Implement virtualization extensions in gic_cpu_(read|write) Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 14/20] intc/arm_gic: Wire the vCPU interface Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 15/20] intc/arm_gic: Implement the virtual interface registers Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 16/20] intc/arm_gic: Implement gic_update_virt() function Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 17/20] intc/arm_gic: Implement maintenance interrupt generation Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 18/20] intc/arm_gic: Improve traces Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 19/20] xlnx-zynqmp: Improve GIC wiring and MMIO mapping Luc Michel
2018-07-27  9:54 ` [Qemu-devel] [PATCH v5 20/20] arm/virt: Add support for GICv2 virtualization extensions Luc Michel
2018-07-30 17:14 ` [Qemu-devel] [PATCH v5 00/20] arm_gic: add virtualization extensions support 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=20180727095421.386-13-luc.michel@greensocs.com \
    --to=luc.michel@greensocs.com \
    --cc=edgari@xilinx.com \
    --cc=jan.kiszka@web.de \
    --cc=mark.burton@greensocs.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=saipava@xilinx.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).