WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [rfc 3/8] qemu-xen: pass-through: use devfn instead of slots

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [rfc 3/8] qemu-xen: pass-through: use devfn instead of slots as the unit for pass-through
From: Simon Horman <horms@xxxxxxxxxxxx>
Date: Wed, 17 Jun 2009 18:07:39 +1000
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>, Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>, Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>, Dexuan Cui <dexuan.cui@xxxxxxxxx>
Delivery-date: Wed, 17 Jun 2009 01:15:14 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <20090617080736.631945993@xxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: quilt/0.46-1
This is part of support for multi-function PCI devices in guests

Instead of reading a slot number from xend, read a devfn.
This and subsequent other changes will allow xend to ask
for more than one function to be inserted into a single slot -
by specifying which function of the slot should be used.

This is a minimal patch for this change. A subsequent
patch that has a lot of noise to rename slot to devfn follows.

This patch breaks compatibility with xend and corresponding
patches to xend are required.

Cc: Dexuan Cui <dexuan.cui@xxxxxxxxx>
Cc: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>

--- 

* co-dependent with xend patch
  "xend: pass-through: use devfn instead of slots as the unit for pass-through"

Changes

Thu, 21 May 2009 12:09:30 +1000
* __insert_to_pci_slot() should operate on a vdevfn not a vslot when
  it automatically allocating a vslot

Thu, 28 May 2009 22:36:54 +1000
* Up-port to 16a3f599db2afcd87137294f8c497597ddcccde1

Index: ioemu-remote/hw/pass-through.c
===================================================================
--- ioemu-remote.orig/hw/pass-through.c 2009-06-15 11:25:44.000000000 +1000
+++ ioemu-remote/hw/pass-through.c      2009-06-15 11:25:45.000000000 +1000
@@ -103,7 +103,7 @@ struct php_dev {
 };
 struct dpci_infos {
 
-    struct php_dev php_devs[NR_PCI_DEV];
+    struct php_dev php_devs[NR_PCI_DEVFN];
 
     PCIBus *e_bus;
     struct pci_access *pci_access;
@@ -859,7 +859,7 @@ static int parse_bdf(char **str, int *se
     }
     else
     {
-        *vslot = AUTO_PHP_SLOT;
+        *vslot = AUTO_PHP_DEVFN;
         *opt = token;
     }
 
@@ -903,30 +903,30 @@ static int pci_slot_match(int bus, int d
 }
 
 /* Insert a new pass-through device into a specific pci slot.
- * input  dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_SLOT
+ * input  dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_DEVFN
  * return -2: requested slot not available
  *        -1: no free slots
  *        >=0: the new hotplug slot
  */
-static int __insert_to_pci_slot(int bus, int dev, int func, int slot,
+static int __insert_to_pci_slot(int bus, int dev, int func, int devfn,
                                 char *opt)
 {
     PCIBus *e_bus = dpci_infos.e_bus;
+    int slot;
 
-    /* preferred virt pci slot */
-    if ( slot != AUTO_PHP_SLOT)
+    /* preferred virt pci devfn */
+    if ( devfn != AUTO_PHP_DEVFN )
     {
-        if ( !test_pci_slot(slot) &&
-             !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) )
+        if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) )
             goto found;
         return -2;
     }
 
-    /* slot == 0, pick up a free one */
+    /* pick a free slot */
     for ( slot = 0; slot < NR_PCI_DEV; slot++ )
     {
-        if ( !test_pci_slot(slot) &&
-             !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) )
+        devfn = PCI_DEVFN(slot, 0);
+        if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) )
             goto found;
     }
 
@@ -934,12 +934,12 @@ static int __insert_to_pci_slot(int bus,
     return -1;
 
 found:
-    dpci_infos.php_devs[slot].valid  = 1;
-    dpci_infos.php_devs[slot].r_bus  = bus;
-    dpci_infos.php_devs[slot].r_dev  = dev;
-    dpci_infos.php_devs[slot].r_func = func;
-    dpci_infos.php_devs[slot].opt = opt;
-    return slot;
+    dpci_infos.php_devs[devfn].valid  = 1;
+    dpci_infos.php_devs[devfn].r_bus  = bus;
+    dpci_infos.php_devs[devfn].r_dev  = dev;
+    dpci_infos.php_devs[devfn].r_func = func;
+    dpci_infos.php_devs[devfn].opt = opt;
+    return devfn;
 }
 
 /* Insert a new pass-through device into a specific pci slot.
@@ -966,7 +966,7 @@ int insert_to_pci_slot(char *bdf_slt)
  */
 int test_pci_slot(int slot)
 {
-    if ( slot < 0 || slot >= NR_PCI_DEV )
+    if ( slot < 0 || slot >= NR_PCI_DEVFN )
         return -1;
 
     if ( dpci_infos.php_devs[slot].valid )
@@ -987,7 +987,7 @@ int bdf_to_slot(char *bdf_str)
     }
 
     /* locate the virtual pci slot for this VTd device */
-    for ( i = 0; i < NR_PCI_DEV; i++ )
+    for ( i = 0; i < NR_PCI_DEVFN; i++ )
     {
         if ( pci_slot_match(bus, dev, func, i) )
             return i;
@@ -4037,7 +4037,7 @@ static struct pt_dev * register_real_dev
 
     /* Register device */
     assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name,
-                                sizeof(struct pt_dev), PCI_DEVFN(e_slot, 0),
+                                sizeof(struct pt_dev), e_slot,
                                 pt_pci_read_config, pt_pci_write_config);
     if ( assigned_device == NULL )
     {
Index: ioemu-remote/hw/pci.h
===================================================================
--- ioemu-remote.orig/hw/pci.h  2009-06-15 11:25:38.000000000 +1000
+++ ioemu-remote/hw/pci.h       2009-06-15 11:25:45.000000000 +1000
@@ -255,8 +255,11 @@ void pci_info(void);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         pci_map_irq_fn map_irq, const char *name);
 
-#define NR_PCI_DEV 32
-#define AUTO_PHP_SLOT NR_PCI_DEV
+#define NR_PCI_FUNC    8
+#define NR_PCI_DEV     32
+#define NR_PCI_DEVFN   (NR_PCI_FUNC * NR_PCI_DEV)
+#define AUTO_PHP_SLOT  NR_PCI_DEV
+#define AUTO_PHP_DEVFN NR_PCI_DEVFN
 
 int insert_to_pci_slot(char*);
 int test_pci_slot(int);
Index: ioemu-remote/hw/piix4acpi.c
===================================================================
--- ioemu-remote.orig/hw/piix4acpi.c    2009-06-15 11:25:38.000000000 +1000
+++ ioemu-remote/hw/piix4acpi.c 2009-06-15 11:25:45.000000000 +1000
@@ -33,6 +33,8 @@
 #include <xen/hvm/ioreq.h>
 #include <xen/hvm/params.h>
 
+#include <pci/header.h>
+
 /* PM1a_CNT bits, as defined in the ACPI specification. */
 #define SCI_EN            (1 <<  0)
 #define GBL_RLS           (1 <<  2)
@@ -276,7 +278,7 @@ static void acpi_php_writeb(void *opaque
             hotplug_slots->plug_slot = 0;
 
             /* power off the slot */
-            power_off_php_slot(slot);
+            power_off_php_slot(PCI_DEVFN(slot, 0));
 
             /* signal the CP ACPI hot remove done. */
             xenstore_record_dm_state("pci-removed");
@@ -459,17 +461,32 @@ static void acpi_sci_intr(GPEState *s)
     }
 }
 
-void acpi_php_del(int slot)
+void acpi_php_del(int devfn)
 {
     GPEState *s = &gpe_state;
+    int slot, func;
+
+    slot = PCI_SLOT(devfn);
+    func = PCI_FUNC(devfn);
 
-    if ( test_pci_slot(slot) < 0 ) {
-        fprintf(logfile, "hot remove: pci slot %d "
-                "is not used by a hotplug device.\n", slot);
+    if ( test_pci_slot(devfn) < 0 ) {
+        fprintf(logfile, "hot remove: pci slot 0x%02x, function 0x%x "
+                "is not used by a hotplug device.\n", slot, func);
 
         return;
     }
 
+    /* ACPI PHP can only work on slots
+     * So only remove zero-functions -
+     * which will remove all other fucntions of the same device in the
+     * guest.
+     */
+    if ( func ) {
+        fprintf(logfile, "hot remove: Attempt to remove non-zero function "
+                "slot=0x%02x func=0x%0x.\n", slot, func);
+        return;
+    }
+
     /* update the php controller status */
     php_slots.plug_evt = PHP_EVT_REMOVE;
     php_slots.plug_slot = slot;
@@ -478,18 +495,19 @@ void acpi_php_del(int slot)
     acpi_sci_intr(s);
 }
 
-void acpi_php_add(int slot)
+void acpi_php_add(int devfn)
 {
     GPEState *s = &gpe_state;
     char ret_str[30];
+    int slot, func;
 
-    if ( slot < 0 ) {
-        fprintf(logfile, "hot add pci slot %d exceed.\n", slot);
+    if ( devfn < 0 ) {
+        fprintf(logfile, "hot add pci devfn %d exceed.\n", devfn);
 
-        if ( slot == -1 )
-            sprintf(ret_str, "no free hotplug slots");
-        else if ( slot == -2 )
-            sprintf(ret_str, "wrong bdf or vslot");
+        if ( devfn == -1 )
+            sprintf(ret_str, "no free hotplug devfn");
+        else if ( devfn == -2 )
+            sprintf(ret_str, "wrong bdf or vdevfn");
 
         if ( strlen(ret_str) > 0 )
             xenstore_record_dm("parameter", ret_str);
@@ -497,25 +515,40 @@ void acpi_php_add(int slot)
         return;
     }
 
-    /* update the php controller status */
-    php_slots.plug_evt = PHP_EVT_ADD;
-    php_slots.plug_slot = slot;
+    /* ACPI PHP can only work on slots
+     * For function 0 we do a full hot-add.
+     * For other functions we just register the device with the hypervisor.
+     * Assuming that function 0 is added after non-zero functions,
+     * its ACPI PHP event will cause all previously registered functions
+     * to be added to the guest.
+     */
 
-    /* update the slot status as present */
-    php_slots.status[slot] = 0xf;
+    slot = PCI_SLOT(devfn);
+    func = PCI_FUNC(devfn);
 
-    /* power on the slot */
-    power_on_php_slot(slot);
+    if ( !func )
+    {
+        /* update the php controller status */
+        php_slots.plug_evt = PHP_EVT_ADD;
+        php_slots.plug_slot = slot;
+
+        /* update the slot status as present */
+        php_slots.status[slot] = 0xf;
+    }
+
+    /* power on the function */
+    power_on_php_slot(devfn);
 
     /* tell Control panel which slot for the new pass-throgh dev */
-    sprintf(ret_str, "0x%02x", slot);
+    sprintf(ret_str, "0x%02x", devfn);
     xenstore_record_dm("parameter", ret_str);
 
     /* signal the CP ACPI hot insert done */
     xenstore_record_dm_state("pci-inserted");
 
     /* generate a SCI interrupt */
-    acpi_sci_intr(s);
+    if ( !func )
+        acpi_sci_intr(s);
 }
 
 #endif /* CONFIG_PASSTHROUGH */

-- 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel