All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.