All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andre Przywara <andre.przywara@linaro.org>
To: Stefano Stabellini <sstabellini@kernel.org>,
	Julien Grall <julien.grall@arm.com>
Cc: xen-devel@lists.xenproject.org
Subject: [PATCH v2 20/45] ARM: new VGIC: Add GICv2 world switch backend
Date: Thu, 15 Mar 2018 20:30:25 +0000	[thread overview]
Message-ID: <20180315203050.19791-21-andre.przywara@linaro.org> (raw)
In-Reply-To: <20180315203050.19791-1-andre.przywara@linaro.org>

Processing maintenance interrupts and accessing the list registers
are dependent on the host's GIC version.
Introduce vgic-v2.c to contain GICv2 specific functions.
Implement the GICv2 specific code for syncing the emulation state
into the VGIC registers.
This also adds the hook to let Xen setup the host GIC addresses.

This is based on Linux commit 140b086dd197, written by Marc Zyngier.

Signed-off-by: Andre Przywara <andre.przywara@linaro.org>
---
Changelog v1 ... v2:
- remove v2 specific underflow function (now generic)
- re-add Linux code to properly handle acked level IRQs

 xen/arch/arm/vgic/vgic-v2.c | 229 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/vgic/vgic.c    |   6 ++
 xen/arch/arm/vgic/vgic.h    |   9 ++
 3 files changed, 244 insertions(+)
 create mode 100644 xen/arch/arm/vgic/vgic-v2.c

diff --git a/xen/arch/arm/vgic/vgic-v2.c b/xen/arch/arm/vgic/vgic-v2.c
new file mode 100644
index 0000000000..bc5c7895f4
--- /dev/null
+++ b/xen/arch/arm/vgic/vgic-v2.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2015, 2016 ARM Ltd.
+ * Imported from Linux ("new" KVM VGIC) and heavily adapted to Xen.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/new_vgic.h>
+#include <asm/bug.h>
+#include <asm/gic.h>
+#include <asm/io.h>
+#include <xen/sched.h>
+#include <xen/sizes.h>
+
+#include "vgic.h"
+
+static struct {
+    bool enabled;
+    paddr_t dbase;          /* Distributor interface address */
+    paddr_t cbase;          /* CPU interface address & size */
+    paddr_t csize;
+    paddr_t vbase;          /* Virtual CPU interface address */
+
+    /* Offset to add to get an 8kB contiguous region if GIC is aliased */
+    uint32_t aliased_offset;
+} gic_v2_hw_data;
+
+void vgic_v2_setup_hw(paddr_t dbase, paddr_t cbase, paddr_t csize,
+                      paddr_t vbase, uint32_t aliased_offset)
+{
+    gic_v2_hw_data.enabled = true;
+    gic_v2_hw_data.dbase = dbase;
+    gic_v2_hw_data.cbase = cbase;
+    gic_v2_hw_data.csize = csize;
+    gic_v2_hw_data.vbase = vbase;
+    gic_v2_hw_data.aliased_offset = aliased_offset;
+}
+
+/*
+ * transfer the content of the LRs back into the corresponding ap_list:
+ * - active bit is transferred as is
+ * - pending bit is
+ *   - transferred as is in case of edge sensitive IRQs
+ *   - set to the line-level (resample time) for level sensitive IRQs
+ */
+void vgic_v2_fold_lr_state(struct vcpu *vcpu)
+{
+    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    unsigned int used_lrs = vcpu->arch.vgic.used_lrs;
+    unsigned long flags;
+    unsigned int lr;
+
+    if ( !used_lrs )    /* No LRs used, so nothing to sync back here. */
+        return;
+
+    gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 0);
+
+    for ( lr = 0; lr < used_lrs; lr++ )
+    {
+        struct gic_lr lr_val;
+        uint32_t intid;
+        struct vgic_irq *irq;
+
+        gic_hw_ops->read_lr(lr, &lr_val);
+
+        /*
+         * TODO: Possible optimization to avoid reading LRs:
+         * Read the ELRSR to find out which of our LRs have been cleared
+         * by the guest. We just need to know the IRQ number for those, which
+         * we could save in an array when populating the LRs.
+         * This trades one MMIO access (ELRSR) for possibly more than one (LRs),
+         * but requires some more code to save the IRQ number and to handle
+         * those finished IRQs according to the algorithm below.
+         * We need some numbers to justify this: chances are that we don't
+         * have many LRs in use most of the time, so we might not save much.
+         */
+        gic_hw_ops->clear_lr(lr);
+
+        intid = lr_val.virq;
+        irq = vgic_get_irq(vcpu->domain, vcpu, intid);
+
+        spin_lock_irqsave(&irq->irq_lock, flags);
+
+        /* Always preserve the active bit */
+        irq->active = lr_val.active;
+
+        /* Edge is the only case where we preserve the pending bit */
+        if ( irq->config == VGIC_CONFIG_EDGE && lr_val.pending )
+        {
+            irq->pending_latch = true;
+
+            if ( vgic_irq_is_sgi(intid) )
+                irq->source |= (1U << lr_val.virt.source);
+        }
+
+        /* Clear soft pending state when level irqs have been acked. */
+        if ( irq->config == VGIC_CONFIG_LEVEL && !lr_val.pending )
+                irq->pending_latch = false;
+
+	/*
+	 * Level-triggered mapped IRQs are special because we only
+	 * observe rising edges as input to the VGIC.
+	 *
+	 * If the guest never acked the interrupt we have to sample
+	 * the physical line and set the line level, because the
+	 * device state could have changed or we simply need to
+	 * process the still pending interrupt later.
+	 *
+	 * If this causes us to lower the level, we have to also clear
+	 * the physical active state, since we will otherwise never be
+	 * told when the interrupt becomes asserted again.
+	 */
+        if ( vgic_irq_is_mapped_level(irq) && lr_val.pending )
+        {
+            struct irq_desc *irqd;
+
+            ASSERT(irq->hwintid >= VGIC_NR_PRIVATE_IRQS);
+
+            irqd = irq_to_desc(irq->hwintid);
+            irq->line_level = gic_read_pending_state(irqd);
+
+            if ( !irq->line_level )
+                gic_set_active_state(irqd, false);
+        }
+
+        spin_unlock_irqrestore(&irq->irq_lock, flags);
+        vgic_put_irq(vcpu->domain, irq);
+    }
+
+    gic_hw_ops->update_hcr_status(GICH_HCR_EN, 0);
+    vgic_cpu->used_lrs = 0;
+}
+
+/**
+ * vgic_v2_populate_lr() - Populates an LR with the state of a given IRQ.
+ * @vcpu: The VCPU which the given @irq belongs to.
+ * @irq:  The IRQ to convert into an LR. The irq_lock must be held already.
+ * @lr:   The LR number to transfer the state into.
+ *
+ * This moves a virtual IRQ, represented by its vgic_irq, into a list register.
+ * Apart from translating the logical state into the LR bitfields, it also
+ * changes some state in the vgic_irq.
+ * For an edge sensitive IRQ the pending state is cleared in struct vgic_irq,
+ * for a level sensitive IRQ the pending state value is unchanged, as it is
+ * dictated directly by the input line level.
+ *
+ * If @irq describes an SGI with multiple sources, we choose the
+ * lowest-numbered source VCPU and clear that bit in the source bitmap.
+ *
+ * The irq_lock must be held by the caller.
+ */
+void vgic_v2_populate_lr(struct vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+    struct gic_lr lr_val = {0};
+
+    lr_val.virq = irq->intid;
+
+    if ( irq_is_pending(irq) )
+    {
+        lr_val.pending = true;
+
+        if ( irq->config == VGIC_CONFIG_EDGE )
+            irq->pending_latch = false;
+
+        if ( vgic_irq_is_sgi(irq->intid) )
+        {
+            u32 src = ffs(irq->source);
+
+            BUG_ON(!src);
+            lr_val.virt.source = (src - 1);
+            irq->source &= ~(1 << (src - 1));
+            if ( irq->source )
+                irq->pending_latch = true;
+        }
+    }
+
+    lr_val.active = irq->active;
+
+    if ( irq->hw )
+    {
+        lr_val.hw_status = 1;
+        lr_val.hw.pirq = irq->hwintid;
+        /*
+         * Never set pending+active on a HW interrupt, as the
+         * pending state is kept at the physical distributor
+         * level.
+         */
+        if ( irq->active && irq_is_pending(irq) )
+            lr_val.pending = false;
+    }
+    else
+    {
+        if ( irq->config == VGIC_CONFIG_LEVEL )
+            lr_val.virt.eoi = 1;
+    }
+
+    /*
+     * Level-triggered mapped IRQs are special because we only observe
+     * rising edges as input to the VGIC.  We therefore lower the line
+     * level here, so that we can take new virtual IRQs.  See
+     * vgic_v2_fold_lr_state for more info.
+     */
+    if ( vgic_irq_is_mapped_level(irq) && lr_val.pending )
+        irq->line_level = false;
+
+    /* The GICv2 LR only holds five bits of priority. */
+    lr_val.priority = irq->priority >> 3;
+
+    gic_hw_ops->write_lr(lr, &lr_val);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/vgic/vgic.c b/xen/arch/arm/vgic/vgic.c
index e82d498766..035c8c8f74 100644
--- a/xen/arch/arm/vgic/vgic.c
+++ b/xen/arch/arm/vgic/vgic.c
@@ -510,6 +510,7 @@ retry:
 
 static void vgic_fold_lr_state(struct vcpu *vcpu)
 {
+    vgic_v2_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -517,6 +518,8 @@ static void vgic_populate_lr(struct vcpu *vcpu,
                              struct vgic_irq *irq, int lr)
 {
     ASSERT(spin_is_locked(&irq->irq_lock));
+
+    vgic_v2_populate_lr(vcpu, irq, lr);
 }
 
 static void vgic_set_underflow(struct vcpu *vcpu)
@@ -630,7 +633,10 @@ void vgic_sync_to_lrs(void)
     spin_lock(&current->arch.vgic.ap_list_lock);
     vgic_flush_lr_state(current);
     spin_unlock(&current->arch.vgic.ap_list_lock);
+
+    gic_hw_ops->update_hcr_status(GICH_HCR_EN, 1);
 }
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/vgic/vgic.h b/xen/arch/arm/vgic/vgic.h
index f530cfa078..41cc0c5b54 100644
--- a/xen/arch/arm/vgic/vgic.h
+++ b/xen/arch/arm/vgic/vgic.h
@@ -27,6 +27,11 @@ static inline bool irq_is_pending(struct vgic_irq *irq)
         return irq->pending_latch || irq->line_level;
 }
 
+static inline bool vgic_irq_is_mapped_level(struct vgic_irq *irq)
+{
+    return irq->config == VGIC_CONFIG_LEVEL && irq->hw;
+}
+
 struct vgic_irq *vgic_get_irq(struct domain *d, struct vcpu *vcpu,
                               u32 intid);
 void vgic_put_irq(struct domain *d, struct vgic_irq *irq);
@@ -41,6 +46,10 @@ static inline void vgic_get_irq_kref(struct vgic_irq *irq)
     atomic_inc(&irq->refcount);
 }
 
+void vgic_v2_fold_lr_state(struct vcpu *vcpu);
+void vgic_v2_populate_lr(struct vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v2_set_underflow(struct vcpu *vcpu);
+
 #endif
 
 /*
-- 
2.14.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2018-03-15 20:31 UTC|newest]

Thread overview: 106+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-15 20:30 [PATCH v2 00/45] New VGIC(-v2) implementation Andre Przywara
2018-03-15 20:30 ` [PATCH v2 01/45] ARM: VGIC: rename gic_event_needs_delivery() Andre Przywara
2018-03-16 10:58   ` Julien Grall
2018-03-16 21:21   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 02/45] ARM: Implement vcpu_kick() Andre Przywara
2018-03-16 10:59   ` Julien Grall
2018-03-16 21:23   ` Stefano Stabellini
2018-03-20 10:35   ` Jan Beulich
2018-03-21  4:10     ` Julien Grall
2018-03-21  7:40       ` Jan Beulich
2018-03-15 20:30 ` [PATCH v2 03/45] xen/arm: gic: Fix indentation in gic_update_one_lr Andre Przywara
2018-03-15 20:30 ` [PATCH v2 04/45] xen/arm: vgic: Override the group in lr everytime Andre Przywara
2018-03-16 21:25   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 05/45] xen/arm: gic: Use bool instead of uint8_t for the hw_status in gic_lr Andre Przywara
2018-03-16 21:25   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 06/45] xen/arm: gic: Split the field state in gic_lr in 2 fields active and pending Andre Przywara
2018-03-16 21:34   ` Stefano Stabellini
2018-03-16 22:14     ` Julien Grall
2018-03-16 22:52       ` Stefano Stabellini
2018-03-19  9:10         ` Andre Przywara
2018-03-15 20:30 ` [PATCH v2 07/45] xen/arm: GIC: Only set pirq in the LR when hw_status is set Andre Przywara
2018-03-16 21:38   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 08/45] ARM: GIC: extend LR read/write functions to cover EOI and source Andre Przywara
2018-03-16 21:43   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 09/45] ARM: GIC: Allow tweaking the active and pending state of an IRQ Andre Przywara
2018-03-16 16:05   ` Andre Przywara
2018-03-19  9:30     ` Julien Grall
2018-03-19 17:54       ` Andre Przywara
2018-03-20  0:57         ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 10/45] ARM: GIC: Allow reading pending state of a hardware IRQ Andre Przywara
2018-03-19 10:04   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 11/45] ARM: timer: Handle level triggered IRQs correctly Andre Przywara
2018-03-19 10:07   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 12/45] ARM: evtchn: " Andre Przywara
2018-03-19 10:54   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 13/45] ARM: vPL011: Use the VGIC's level triggered IRQs handling if available Andre Przywara
2018-03-19 10:59   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 14/45] ARM: new VGIC: Add data structure definitions Andre Przywara
2018-03-19 11:01   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 15/45] ARM: new VGIC: Add acccessor to new struct vgic_irq instance Andre Przywara
2018-03-19 11:04   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 16/45] ARM: new VGIC: Implement virtual IRQ injection Andre Przywara
2018-03-19 12:48   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 17/45] Add list_sort() routine from Linux Andre Przywara
2018-03-16 10:47   ` Jan Beulich
2018-03-15 20:30 ` [PATCH v2 18/45] ARM: new VGIC: Add IRQ sorting Andre Przywara
2018-03-19 12:51   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 19/45] ARM: new VGIC: Add IRQ sync/flush framework Andre Przywara
2018-03-19 14:17   ` Julien Grall
2018-03-19 17:32     ` Andre Przywara
2018-03-15 20:30 ` Andre Przywara [this message]
2018-03-19 14:36   ` [PATCH v2 20/45] ARM: new VGIC: Add GICv2 world switch backend Julien Grall
2018-03-15 20:30 ` [PATCH v2 21/45] ARM: new VGIC: Implement vgic_vcpu_pending_irq Andre Przywara
2018-03-19  7:55   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 22/45] ARM: new VGIC: Add MMIO handling framework Andre Przywara
2018-03-19  7:59   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 23/45] ARM: new VGIC: Add GICv2 " Andre Przywara
2018-03-15 20:30 ` [PATCH v2 24/45] ARM: new VGIC: Add CTLR, TYPER and IIDR handlers Andre Przywara
2018-03-19  8:13   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 25/45] ARM: new VGIC: Add ENABLE registers handlers Andre Przywara
2018-03-19  8:22   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 26/45] ARM: new VGIC: Add PENDING " Andre Przywara
2018-03-19  8:25   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 27/45] ARM: new VGIC: Add ACTIVE " Andre Przywara
2018-03-19  8:27   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 28/45] ARM: new VGIC: Add PRIORITY " Andre Przywara
2018-03-19  9:40   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 29/45] ARM: new VGIC: Add CONFIG " Andre Przywara
2018-03-15 20:30 ` [PATCH v2 30/45] ARM: new VGIC: Add TARGET " Andre Przywara
2018-03-19  9:44   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 31/45] ARM: new VGIC: Add SGIR register handler Andre Przywara
2018-03-19  9:47   ` Julien Grall
2018-03-19 16:21     ` Andre Przywara
2018-03-15 20:30 ` [PATCH v2 32/45] ARM: new VGIC: Add SGIPENDR register handlers Andre Przywara
2018-03-15 20:30 ` [PATCH v2 33/45] ARM: new VGIC: Handle hardware mapped IRQs Andre Przywara
2018-03-15 20:30 ` [PATCH v2 34/45] ARM: new VGIC: Add event channel IRQ handling Andre Przywara
2018-03-15 20:30 ` [PATCH v2 35/45] ARM: new VGIC: Handle virtual IRQ allocation/reservation Andre Przywara
2018-03-15 20:30 ` [PATCH v2 36/45] ARM: new VGIC: Dump virtual IRQ info Andre Przywara
2018-03-15 20:30 ` [PATCH v2 37/45] ARM: new VGIC: Provide system register emulation stub Andre Przywara
2018-03-15 20:30 ` [PATCH v2 38/45] ARM: new VGIC: Implement arch_move_irqs() Andre Przywara
2018-03-19  9:53   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 39/45] ARM: new VGIC: Add preliminary stub implementation Andre Przywara
2018-03-19  9:54   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 40/45] ARM: new VGIC: vgic-init: register VGIC Andre Przywara
2018-03-20  1:17   ` Julien Grall
2018-03-20 17:11     ` Andre Przywara
2018-03-21  4:29       ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 41/45] ARM: new VGIC: Add vgic_v2_enable Andre Przywara
2018-03-19  9:57   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 42/45] ARM: new VGIC: vgic-init: implement vgic_init Andre Przywara
2018-03-20  3:02   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 43/45] ARM: new VGIC: vgic-init: implement map_resources Andre Przywara
2018-03-20  3:10   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 44/45] ARM: new VGIC: Allocate two pages for struct vcpu Andre Przywara
2018-03-19 10:00   ` Julien Grall
2018-03-19 10:04     ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 45/45] ARM: VGIC: wire new VGIC(-v2) files into Xen build system Andre Przywara
2018-03-16 10:48   ` Jan Beulich
2018-03-16 11:10     ` Andre Przywara
2018-03-16 11:32       ` Jan Beulich
2018-03-16 15:13         ` Andre Przywara
2018-03-16 15:34           ` Jan Beulich
2018-03-20  3:13   ` Julien Grall
2018-03-20 15:57     ` Andre Przywara
2018-03-20  8:30 ` [PATCH v2 00/45] New VGIC(-v2) implementation Julien Grall
2018-03-20 11:20   ` Andre Przywara

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=20180315203050.19791-21-andre.przywara@linaro.org \
    --to=andre.przywara@linaro.org \
    --cc=julien.grall@arm.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /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.