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

[PATCH v1 3/3] xen/vpci: header: filter PCI capabilities


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
  • Date: Thu, 10 Aug 2023 15:12:59 -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
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; 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=lytXEfn42x+yZhPe84LRwE9cDWxa0qd6RBGQUU59Ly0=; b=g4dRTSGvgsMDqTRw0FGBQGlxzce8Gje880i5DUj/oLLOH64+LurECP3u6ebezPzuKcHur5jeRYV7+HF7qrtqa6fB4dyzO2Iiz+W2U8l5C14iQN1bBP57rqrWBbqTWShoGtuUJ40eCWT02xUFrIiTQZKcxSREDuuR7FzqhjGaa/P0yMwvX5xA0rwJcJGGSTG8PRYB4cIl82d3YmVC3/PvbK0Tr5mKludxyTjUVxpT+HTuF5nb7QfmXzghxqq9/NTCGvPD2dejm22AHynmPPeUVdKHG1A7q+8nYLIg9cnHpJvgwKUGRHooTH4jJsd0mH05/3N5LZqOUGelgWCHcF7aVw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=EuvnqIb/Lo+1HHUQsz+GLNW7b3fYKuThTtzLoi6MSmleFvcriK5cc769dD2rY+Q563RvdXO6tjpeU1A7pdwWnzCiSNtGxJnSqGO0I5lMJpA3JV/0lNYxIVQ2yFZ147s8wb/t4rhFs9SdoaYG64+ddPoUZeTb71IuAZtLzpTtkroWGXi31ygJkB3YqP3YJaIpF2XJ/G8YqrDk2yZdrtsrIJlq0S3piPu+mO6NxyDf/J70tAu5lrxxVM8nQy8jkZ5TUbMxMjE/NlLlcaygtTZSkxCnocoQ+tCgS2Nx5fFCLF5hneINw49KPReBus1k4UL0b9avK2GX86+CcST2b0TCHg==
  • Cc: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Delivery-date: Thu, 10 Aug 2023 19:14:20 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Xen vPCI only supports virtualizing the MSI and MSI-X capabilities, so all other
PCI capabilities should be hidden from a domU for now. We parse the physical PCI
capabilities linked list and add vPCI register handlers for the next elements,
inserting our own next value, thus presenting a modified linked list to the
domU.

Signed-off-by: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
---

If there are no capabilities to be exposed to the guest, a future status
register handler likely would want to mask the PCI_STATUS_CAP_LIST bit. I'm
thinking we could track this in struct vpci_header as follows:

vpci.h:
     struct vpci_header {
         ...
+        bool mask_cap_list : 1;
     } header;

header.c:init_bars():
         rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
                                PCI_CAPABILITY_LIST, 1,
                                (void *)(uintptr_t)next);
         if ( rc )
             return rc;

+        if ( !next )
+            header->mask_cap_list = true;
+
         for ( ttl = 48; ttl > 0; ttl-- )
         {
             uint8_t pos;
---
 xen/drivers/vpci/header.c | 78 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c
index 60f7049e3498..cb1304fa1eed 100644
--- a/xen/drivers/vpci/header.c
+++ b/xen/drivers/vpci/header.c
@@ -513,6 +513,36 @@ static void cf_check rom_write(
         rom->addr = val & PCI_ROM_ADDRESS_MASK;
 }
 
+static uint8_t vpci_find_next_cap(pci_sbdf_t sbdf, uint8_t pos)
+{
+    uint8_t id;
+    int ttl;
+
+    if ( pos < 0x40 )
+        pos = pci_conf_read8(sbdf, PCI_CAPABILITY_LIST);
+    else
+        pos = pci_conf_read8(sbdf, pos + PCI_CAP_LIST_NEXT);
+
+    for ( ttl = 48; ttl > 0; ttl-- )
+    {
+        if ( pos < 0x40 )
+            break;
+
+        pos &= ~3;
+        id = pci_conf_read8(sbdf, pos + PCI_CAP_LIST_ID);
+
+        if ( id == 0xff )
+            break;
+
+        if ( id == PCI_CAP_ID_MSI ||
+             id == PCI_CAP_ID_MSIX )
+            return pos;
+
+        pos = pci_conf_read8(sbdf, pos + PCI_CAP_LIST_NEXT);
+    }
+    return 0;
+}
+
 static int cf_check init_bars(struct pci_dev *pdev)
 {
     uint16_t cmd;
@@ -544,6 +574,54 @@ static int cf_check init_bars(struct pci_dev *pdev)
     if ( rc )
         return rc;
 
+    if ( !is_hardware_domain(pdev->domain) )
+    {
+        if ( (pci_conf_read16(pdev->sbdf, PCI_STATUS) & PCI_STATUS_CAP_LIST)
+             == 0 )
+        {
+            /* RAZ/WI */
+            rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
+                                   PCI_CAPABILITY_LIST, 1, NULL);
+            if ( rc )
+                return rc;
+        }
+        else
+        {
+            /* Only expose capabilities to the guest that vPCI can handle. */
+            uint8_t next, ttl;
+
+            next = vpci_find_next_cap(pdev->sbdf, PCI_CAPABILITY_LIST);
+
+            rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
+                                   PCI_CAPABILITY_LIST, 1,
+                                   (void *)(uintptr_t)next);
+            if ( rc )
+                return rc;
+
+            for ( ttl = 48; ttl > 0; ttl-- )
+            {
+                uint8_t pos;
+
+                if ( !next )
+                    break;
+
+                pos = next;
+                next = vpci_find_next_cap(pdev->sbdf, pos);
+
+                rc = vpci_add_register(pdev->vpci, vpci_hw_read8, NULL,
+                                       pos + PCI_CAP_LIST_ID, 1, NULL);
+                if ( rc )
+                    return rc;
+
+                rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
+                                       pos + PCI_CAP_LIST_NEXT, 1,
+                                       (void *)(uintptr_t)next);
+                if ( rc )
+                    return rc;
+            }
+        }
+    }
+
     if ( pdev->ignore_bars )
         return 0;
 
-- 
2.41.0




 


Rackspace

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