All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mykyta Poturai <Mykyta_Poturai@epam.com>
To: "xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>
Cc: Mykyta Poturai <Mykyta_Poturai@epam.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Julien Grall <julien@xen.org>,
	Bertrand Marquis <bertrand.marquis@arm.com>,
	Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>,
	Michal Orzel <michal.orzel@amd.com>
Subject: [XEN PATCH v2 13/25] arm: new VGIC: Handle ITS related GICv3 redistributor registers
Date: Fri, 10 Nov 2023 12:56:20 +0000	[thread overview]
Message-ID: <c20cd7affcf945d7ddc5eed5e5b0e27d0a39cfd7.1699618395.git.mykyta_poturai@epam.com> (raw)
In-Reply-To: <cover.1699618395.git.mykyta_poturai@epam.com>

In the GICv3 redistributor there are the PENDBASER and PROPBASER
registers which we did not emulate so far, as they only make sense
when having an ITS. In preparation for that emulate those MMIO
accesses by storing the 64-bit data written into it into a variable
which we later read in the ITS emulation.
We also sanitise the registers, making sure RES0 regions are respected
and checking for valid memory attributes.

Based on Linux commit 0aa1de57319c4 by Andre Przywara

Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
---
 xen/arch/arm/include/asm/new_vgic.h |   3 +
 xen/arch/arm/vgic/vgic-mmio-v3.c    | 168 +++++++++++++++++++++++++++-
 2 files changed, 169 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/include/asm/new_vgic.h b/xen/arch/arm/include/asm/new_vgic.h
index 9eafab45ff..b037b6cf61 100644
--- a/xen/arch/arm/include/asm/new_vgic.h
+++ b/xen/arch/arm/include/asm/new_vgic.h
@@ -199,6 +199,9 @@ struct vgic_cpu {
 
     /* Cache guest interrupt ID bits */
     uint32_t num_id_bits;
+
+    /* GICR_CTLR.{ENABLE_LPIS,RWP} */
+    atomic_t ctlr;
 };
 
 static inline paddr_t vgic_cpu_base(const struct vgic_dist *vgic)
diff --git a/xen/arch/arm/vgic/vgic-mmio-v3.c b/xen/arch/arm/vgic/vgic-mmio-v3.c
index 19ebf723ee..2fb44cfe6a 100644
--- a/xen/arch/arm/vgic/vgic-mmio-v3.c
+++ b/xen/arch/arm/vgic/vgic-mmio-v3.c
@@ -42,6 +42,18 @@ unsigned long extract_bytes(uint64_t data, unsigned int offset,
     return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
 }
 
+uint64_t update_64bit_reg(u64 reg, unsigned int offset, unsigned int len,
+                          unsigned long val)
+{
+    int lower = (offset & 4) * 8;
+    int upper = lower + 8 * len - 1;
+
+    reg &= ~GENMASK_ULL(upper, lower);
+    val &= GENMASK_ULL(len * 8 - 1, 0);
+
+    return reg | ((u64)val << lower);
+}
+
 static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct vcpu *vcpu)
 {
     unsigned long affinity;
@@ -369,6 +381,158 @@ static unsigned long vgic_mmio_read_v3_idregs(struct vcpu *vcpu, paddr_t addr,
     return 0;
 }
 
+bool vgic_lpis_enabled(struct vcpu *vcpu)
+{
+    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+
+    return atomic_read(&vgic_cpu->ctlr) == GICR_CTLR_ENABLE_LPIS;
+}
+
+/* We want to avoid outer shareable. */
+u64 vgic_sanitise_shareability(u64 field)
+{
+    switch ( field )
+    {
+    case GIC_BASER_OuterShareable:
+        return GIC_BASER_InnerShareable;
+    default:
+        return field;
+    }
+}
+
+/* Avoid any inner non-cacheable mapping. */
+u64 vgic_sanitise_inner_cacheability(u64 field)
+{
+    switch ( field )
+    {
+    case GIC_BASER_CACHE_nCnB:
+    case GIC_BASER_CACHE_nC:
+        return GIC_BASER_CACHE_RaWb;
+    default:
+        return field;
+    }
+}
+
+/* Non-cacheable or same-as-inner are OK. */
+u64 vgic_sanitise_outer_cacheability(u64 field)
+{
+    switch ( field )
+    {
+    case GIC_BASER_CACHE_SameAsInner:
+    case GIC_BASER_CACHE_nC:
+        return field;
+    default:
+        return GIC_BASER_CACHE_SameAsInner;
+    }
+}
+
+u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
+                        u64 (*sanitise_fn)(u64))
+{
+    u64 field = (reg & field_mask) >> field_shift;
+
+    field     = sanitise_fn(field) << field_shift;
+    return (reg & ~field_mask) | field;
+}
+
+#define PROPBASER_RES0_MASK                                                    \
+    (GENMASK_ULL(63, 59) | GENMASK_ULL(55, 52) | GENMASK_ULL(6, 5))
+#define PENDBASER_RES0_MASK                                                    \
+    (BIT(63, ULL) | GENMASK_ULL(61, 59) | GENMASK_ULL(55, 52) |                \
+     GENMASK_ULL(15, 12) | GENMASK_ULL(6, 0))
+
+static u64 vgic_sanitise_pendbaser(u64 reg)
+{
+    reg = vgic_sanitise_field(reg, GICR_PENDBASER_SHAREABILITY_MASK,
+                              GICR_PENDBASER_SHAREABILITY_SHIFT,
+                              vgic_sanitise_shareability);
+    reg = vgic_sanitise_field(reg, GICR_PENDBASER_INNER_CACHEABILITY_MASK,
+                              GICR_PENDBASER_INNER_CACHEABILITY_SHIFT,
+                              vgic_sanitise_inner_cacheability);
+    reg = vgic_sanitise_field(reg, GICR_PENDBASER_OUTER_CACHEABILITY_MASK,
+                              GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT,
+                              vgic_sanitise_outer_cacheability);
+
+    reg &= ~PENDBASER_RES0_MASK;
+
+    return reg;
+}
+
+static u64 vgic_sanitise_propbaser(u64 reg)
+{
+    reg = vgic_sanitise_field(reg, GICR_PROPBASER_SHAREABILITY_MASK,
+                              GICR_PROPBASER_SHAREABILITY_SHIFT,
+                              vgic_sanitise_shareability);
+    reg = vgic_sanitise_field(reg, GICR_PROPBASER_INNER_CACHEABILITY_MASK,
+                              GICR_PROPBASER_INNER_CACHEABILITY_SHIFT,
+                              vgic_sanitise_inner_cacheability);
+    reg = vgic_sanitise_field(reg, GICR_PROPBASER_OUTER_CACHEABILITY_MASK,
+                              GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT,
+                              vgic_sanitise_outer_cacheability);
+
+    reg &= ~PROPBASER_RES0_MASK;
+    return reg;
+}
+
+static unsigned long vgic_mmio_read_propbase(struct vcpu *vcpu, paddr_t addr,
+                                             unsigned int len)
+{
+    struct vgic_dist *dist = &vcpu->domain->arch.vgic;
+
+    return extract_bytes(dist->propbaser, addr & 7, len);
+}
+
+static void vgic_mmio_write_propbase(struct vcpu *vcpu, paddr_t addr,
+                                     unsigned int len, unsigned long val)
+{
+    struct vgic_dist *dist = &vcpu->domain->arch.vgic;
+    u64 old_propbaser, propbaser;
+
+    /* Storing a value with LPIs already enabled is undefined */
+    if ( vgic_lpis_enabled(vcpu) )
+        return;
+
+    do
+    {
+        old_propbaser = dist->propbaser;
+        propbaser     = old_propbaser;
+        propbaser     = update_64bit_reg(propbaser, addr & 4, len, val);
+        propbaser     = vgic_sanitise_propbaser(propbaser);
+    } while ( cmpxchg64(&dist->propbaser, old_propbaser, propbaser) !=
+              old_propbaser );
+}
+
+static unsigned long vgic_mmio_read_pendbase(struct vcpu *vcpu, paddr_t addr,
+                                             unsigned int len)
+{
+    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    u64 value                 = vgic_cpu->pendbaser;
+
+    value &= ~GICR_PENDBASER_PTZ;
+
+    return extract_bytes(value, addr & 7, len);
+}
+
+static void vgic_mmio_write_pendbase(struct vcpu *vcpu, paddr_t addr,
+                                     unsigned int len, unsigned long val)
+{
+    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    u64 old_pendbaser, pendbaser;
+
+    /* Storing a value with LPIs already enabled is undefined */
+    if ( vgic_lpis_enabled(vcpu) )
+        return;
+
+    do
+    {
+        old_pendbaser = vgic_cpu->pendbaser;
+        pendbaser     = old_pendbaser;
+        pendbaser     = update_64bit_reg(pendbaser, addr & 4, len, val);
+        pendbaser     = vgic_sanitise_pendbaser(pendbaser);
+    } while ( cmpxchg64(&vgic_cpu->pendbaser, old_pendbaser, pendbaser) !=
+              old_pendbaser );
+}
+
 static const struct vgic_register_region vgic_v3_dist_registers[] = {
     REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
         vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc,
@@ -435,10 +599,10 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
         vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
         VGIC_ACCESS_32bit),
     REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
-        vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+        vgic_mmio_read_propbase, vgic_mmio_write_propbase, 8,
         VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
     REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
-        vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+        vgic_mmio_read_pendbase, vgic_mmio_write_pendbase, 8,
         VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
     REGISTER_DESC_WITH_LENGTH(GICR_INVLPIR,
         vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
-- 
2.34.1


  parent reply	other threads:[~2023-11-10 13:25 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-10 12:56 [XEN PATCH v2 00/25] arm: Add GICv3 support to the New VGIC Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 01/25] arm: vgic: its: Decouple HW and virtual ITS Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 02/25] arm: new VGIC: Add GICv3 world switch backend Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 03/25] arm: new VGIC: Add GICv3 MMIO handling framework Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 04/25] arm: new VGIC: Add GICv3 CTLR, IIDR, TYPER handlers Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 05/25] arm: new VGIC: Add GICv3 redistributor IIDR and TYPER handler Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 08/25] arm: new VGIC: Add GICv3 SGI system register trap handler Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 07/25] arm: new VGIC: Add GICv3 IROUTER register handlers Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 06/25] arm: new VGIC: Add GICv3 IDREGS register handler Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 10/25] arm: new VGIC: Add vgic_v3_enable Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 11/25] arm: new VGIC: Add alternative redist region storage Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 09/25] arm: new VGIC: vgic_init: implement map_resources Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 14/25] arm: new VGIC: its: Introduce ITS emulation file with MMIO framework Mykyta Poturai
2023-11-10 12:56 ` Mykyta Poturai [this message]
2023-11-10 12:56 ` [XEN PATCH v2 12/25] arm: new VGIC: Wire new GICv3 into the build system Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 17/25] arm: new VGIC: its: Read initial LPI pending table Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 16/25] arm: new VGIC: its: Implement basic ITS register handlers Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 15/25] arm: new VGIC: its: Introduce ITS device list Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 20/25] arm: new VGIC: its: Implement ITS command queue command handlers Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 18/25] arm: new VGIC: its: Allow updates of LPI configuration table Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 19/25] arm: new VGIC: its: Add LPI translation cache definition Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 23/25] arm: new VGIC: its: Enable ITS emulation as a virtual MSI controller Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 22/25] arm: new VGIC: its: Implement MMIO-based LPI invalidation Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 21/25] arm: new VGIC: its: Implement MSI injection in ITS emulation Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 25/25] arm: new VGIC: Improve MMIO handling Mykyta Poturai
2023-11-10 12:56 ` [XEN PATCH v2 24/25] arm: new VGIC: its: Wire new ITS into the build system Mykyta Poturai

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=c20cd7affcf945d7ddc5eed5e5b0e27d0a39cfd7.1699618395.git.mykyta_poturai@epam.com \
    --to=mykyta_poturai@epam.com \
    --cc=Volodymyr_Babchuk@epam.com \
    --cc=bertrand.marquis@arm.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.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.