[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v19 2/3] vpci: acquire d->pci_lock in I/O handlers


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
  • Date: Tue, 15 Apr 2025 12:54:01 -0400
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.xenproject.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0)
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=lx8Lph3IBrxQ9Lis7LuGMBrvW2qwScDxY+y3wh5OujI=; b=nQZybeLSv/5B/tJIEXAR+7nriVjt1VuqVjTKRs8CTzA+0GAIYzgAEOC2mZ5KM6YRgEnv13M6TAqewtHHy+elM0ba9oz6SaBDmxiEgTRu0F+TzNzTPCM3qq49/Fd9ecwD4Nlf+iNxOeKHTqIdxW+eMfp8N+WivxdvOjpxrkqHKS0D0f/huAzOOYUVFx3Y+fPmL9faTrM74//TnTyMyooJWAqNUwSf1Mvu0nOl5eiLWD0oiH0gSsglqSS46RjaC/6WO9lAaRwu+kr1i4zKnaTAJZEQABUrFPU+gnj8/gZD6GBzJFYVUAd5gbSr/78lDE2fBT54Mld3W/yyEGKb3oNsyw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=RrPVFxXMyhlGAOR9Gb69ZZsrpBZlqYovLm8bqDxv1nmSnMJ18R4DIJ4c9khnlptUR1qhCiuUqRvwFN1yn5GU5sFyZQ2E3OCp5jlcUPSyvgd2r6hseWusVo8I5YKOGOXTeZ7eZ+6VEMK9N2U1dKCxOLUkVQY1Zge/6p4HFMx43WPv6D+oANFIXstigUYTlf9yevehLBE0w1UUGHJNG2z7pG2KGoLMiltKoFK7k2RLspszwKRGBRja2/PhqF0i0KW/Av5UHcDrZf3fDt0dzSkku8k030EOz47Wr4w1zTqDBHicAgctjQZ8Ka0gitCph6udg9TpsDmhdJK5N7deKEhUFg==
  • Cc: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, "Volodymyr Babchuk" <Volodymyr_Babchuk@xxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, "Andrew Cooper" <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Delivery-date: Tue, 15 Apr 2025 16:54:37 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

In preparation for translating virtual PCI bus topology (where a pdev
lookup will be needed in the vPCI I/O handlers), acquire d->pci_lock in
the vPCI I/O handlers.

While here, adjust indentation in vpci_ecam_{read,write}.

Signed-off-by: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
---
v18->v19:
* new patch

While the current patch series focus is Arm, this is also prerequisite
for eventually enabling x86 PVH domU passthrough. Similar to Arm, a call
to vpci_translate_virtual_device() would be added in
xen/arch/x86/hvm/io.c:vpci_portio_{read,write} and
vpci_mmcfg_{read,write}.
---
 xen/arch/arm/vpci.c     | 11 +++++++++--
 xen/arch/x86/hvm/io.c   | 10 +++++++++-
 xen/drivers/vpci/vpci.c | 21 ++++++++++-----------
 3 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/vpci.c b/xen/arch/arm/vpci.c
index b63a356bb4a8..828c5c745bd9 100644
--- a/xen/arch/arm/vpci.c
+++ b/xen/arch/arm/vpci.c
@@ -34,15 +34,18 @@ static int vpci_mmio_read(struct vcpu *v, mmio_info_t *info,
     /* data is needed to prevent a pointer cast on 32bit */
     unsigned long data;
 
+    read_lock(&v->domain->pci_lock);
     if ( vpci_ecam_read(sbdf, ECAM_REG_OFFSET(info->gpa),
                         1U << info->dabt.size, &data) )
     {
         *r = data;
+        read_unlock(&v->domain->pci_lock);
         return 1;
     }
 
     *r = invalid;
 
+    read_unlock(&v->domain->pci_lock);
     return 0;
 }
 
@@ -51,9 +54,13 @@ static int vpci_mmio_write(struct vcpu *v, mmio_info_t *info,
 {
     struct pci_host_bridge *bridge = p;
     pci_sbdf_t sbdf = vpci_sbdf_from_gpa(bridge, info->gpa);
+    int ret;
 
-    return vpci_ecam_write(sbdf, ECAM_REG_OFFSET(info->gpa),
-                           1U << info->dabt.size, r);
+    write_lock(&v->domain->pci_lock);
+    ret = vpci_ecam_write(sbdf, ECAM_REG_OFFSET(info->gpa),
+                          1U << info->dabt.size, r);
+    write_unlock(&v->domain->pci_lock);
+    return ret;
 }
 
 static const struct mmio_handler_ops vpci_mmio_handler = {
diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index de6ee6c4dd4d..0b9036528abe 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -261,7 +261,7 @@ static int cf_check vpci_portio_read(
     const struct hvm_io_handler *handler, uint64_t addr, uint32_t size,
     uint64_t *data)
 {
-    const struct domain *d = current->domain;
+    struct domain *d = current->domain;
     unsigned int reg;
     pci_sbdf_t sbdf;
     uint32_t cf8;
@@ -285,7 +285,9 @@ static int cf_check vpci_portio_read(
     if ( !vpci_access_allowed(reg, size) )
         return X86EMUL_OKAY;
 
+    read_lock(&d->pci_lock);
     *data = vpci_read(sbdf, reg, size);
+    read_unlock(&d->pci_lock);
 
     return X86EMUL_OKAY;
 }
@@ -316,7 +318,9 @@ static int cf_check vpci_portio_write(
     if ( !vpci_access_allowed(reg, size) )
         return X86EMUL_OKAY;
 
+    write_lock(&d->pci_lock);
     vpci_write(sbdf, reg, size, data);
+    write_unlock(&d->pci_lock);
 
     return X86EMUL_OKAY;
 }
@@ -424,7 +428,9 @@ static int cf_check vpci_mmcfg_read(
     read_unlock(&d->arch.hvm.mmcfg_lock);
 
     /* Failed reads are not propagated to the caller */
+    read_lock(&d->pci_lock);
     vpci_ecam_read(sbdf, reg, len, data);
+    read_unlock(&d->pci_lock);
 
     return X86EMUL_OKAY;
 }
@@ -449,7 +455,9 @@ static int cf_check vpci_mmcfg_write(
     read_unlock(&d->arch.hvm.mmcfg_lock);
 
     /* Failed writes are not propagated to the caller */
+    write_lock(&d->pci_lock);
     vpci_ecam_write(sbdf, reg, len, data);
+    write_unlock(&d->pci_lock);
 
     return X86EMUL_OKAY;
 }
diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c
index 1e6aa5d799b9..d01fb7be226a 100644
--- a/xen/drivers/vpci/vpci.c
+++ b/xen/drivers/vpci/vpci.c
@@ -440,6 +440,8 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, 
unsigned int size)
     unsigned int data_offset = 0;
     uint32_t data = ~(uint32_t)0;
 
+    ASSERT(rw_is_locked(&d->pci_lock));
+
     if ( !size )
     {
         ASSERT_UNREACHABLE();
@@ -452,15 +454,11 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, 
unsigned int size)
      * If this is hwdom and the device is assigned to DomXEN, acquiring hwdom's
      * pci_lock is sufficient.
      */
-    read_lock(&d->pci_lock);
     pdev = pci_get_pdev(d, sbdf);
     if ( !pdev && is_hardware_domain(d) )
         pdev = pci_get_pdev(dom_xen, sbdf);
     if ( !pdev || !pdev->vpci )
-    {
-        read_unlock(&d->pci_lock);
         return vpci_read_hw(sbdf, reg, size);
-    }
 
     spin_lock(&pdev->vpci->lock);
 
@@ -507,7 +505,6 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, 
unsigned int size)
         ASSERT(data_offset < size);
     }
     spin_unlock(&pdev->vpci->lock);
-    read_unlock(&d->pci_lock);
 
     if ( data_offset < size )
     {
@@ -555,6 +552,8 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned 
int size,
     const struct vpci_register *r;
     unsigned int data_offset = 0;
 
+    ASSERT(rw_is_write_locked(&d->pci_lock));
+
     if ( !size )
     {
         ASSERT_UNREACHABLE();
@@ -570,7 +569,6 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned 
int size,
      * TODO: We need to take pci_locks in exclusive mode only if we
      * are modifying BARs, so there is a room for improvement.
      */
-    write_lock(&d->pci_lock);
     pdev = pci_get_pdev(d, sbdf);
     if ( !pdev && is_hardware_domain(d) )
         pdev = pci_get_pdev(dom_xen, sbdf);
@@ -579,8 +577,6 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned 
int size,
         /* Ignore writes to read-only devices, which have no ->vpci. */
         const unsigned long *ro_map = pci_get_ro_map(sbdf.seg);
 
-        write_unlock(&d->pci_lock);
-
         if ( !ro_map || !test_bit(sbdf.bdf, ro_map) )
             vpci_write_hw(sbdf, reg, size, data);
         return;
@@ -622,7 +618,6 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned 
int size,
         ASSERT(data_offset < size);
     }
     spin_unlock(&pdev->vpci->lock);
-    write_unlock(&d->pci_lock);
 
     if ( data_offset < size )
         /* Tailing gap, write the remaining. */
@@ -651,8 +646,10 @@ bool vpci_access_allowed(unsigned int reg, unsigned int 
len)
 }
 
 bool vpci_ecam_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
-                         unsigned long data)
+                     unsigned long data)
 {
+    ASSERT(rw_is_write_locked(&current->domain->pci_lock));
+
     if ( !vpci_access_allowed(reg, len) ||
          (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
         return false;
@@ -667,8 +664,10 @@ bool vpci_ecam_write(pci_sbdf_t sbdf, unsigned int reg, 
unsigned int len,
 }
 
 bool vpci_ecam_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
-                        unsigned long *data)
+                    unsigned long *data)
 {
+    ASSERT(rw_is_locked(&current->domain->pci_lock));
+
     if ( !vpci_access_allowed(reg, len) ||
          (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
         return false;
-- 
2.49.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.