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 15/18] ioemu: use struct php_dev to pass around PCI pas

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [rfc 15/18] ioemu: use struct php_dev to pass around PCI pass-through assignment parameters
From: Simon Horman <horms@xxxxxxxxxxxx>
Date: Tue, 17 Feb 2009 20:08:03 +1100
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Delivery-date: Tue, 17 Feb 2009 01:33:49 -0800
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: <20090217090748.580007796@xxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: quilt/0.46-1
Signed-off-by: Simon Horman <horms@xxxxxxxxxxx>

--- 
Fri, 13 Feb 2009 13:50:13 +1100
* Account for vslot supplied for hotplug insert

Fri, 13 Feb 2009 15:22:10 +1100
* Rebased
  from "Restore xenfb.h and atkbd_ translation tables for * xenfbfront"
  to "fix memory/fd leak in pt_msix_init()"
Index: ioemu-remote/hw/pass-through.c
===================================================================
--- ioemu-remote.orig/hw/pass-through.c 2009-02-17 17:55:37.000000000 +0900
+++ ioemu-remote/hw/pass-through.c      2009-02-17 17:56:46.000000000 +0900
@@ -34,6 +34,7 @@ struct php_dev {
     uint8_t r_bus;
     uint8_t r_dev;
     uint8_t r_func;
+    uint8_t v_devfn;
     char *opt;
 };
 static struct dpci_infos {
@@ -726,37 +727,65 @@ static const struct pt_reg_grp_info_tbl 
     }, 
 };
 
+static int cmp_php_dev(const struct php_dev *a, const struct php_dev *b)
+{
+    if (a->r_bus != b->r_bus)
+    {
+        return a->r_bus - b->r_bus;
+    }
+    if (a->r_dev != b->r_dev)
+    {
+        return a->r_dev - b->r_dev;
+    }
+    if (a->r_func != b->r_func)
+    {
+        return a->r_func - b->r_func;
+    }
+
+    return 0;
+}
+
+static void cpy_php_dev(struct php_dev *dst, const struct php_dev *src)
+{
+    memcpy(dst, src, sizeof(*dst));
+}
+
 static int token_value(char *token)
 {
     return strtol(token, NULL, 16);
 }
 
-static int next_bdf(char **str, int *seg, int *bus, int *dev, int *func, char 
**opt)
+static struct php_dev next_bdf(char **str)
 {
     char *token;
     const char *delim = ":.-";
+    struct php_dev bdf;
+
+    memset(&bdf, 0, sizeof(bdf));
 
     if ( !(*str) ||
           ( !strchr(*str, ':') && !strchr(*str, '.')) )
-        return 0;
+        return bdf;
 
     token  = strsep(str, delim);
-    *seg = token_value(token);
+    /* segment */
 
     token  = strsep(str, delim);
-    *bus  = token_value(token);
+    bdf.r_bus  = token_value(token);
 
     token  = strsep(str, delim);
-    *dev  = token_value(token);
+    bdf.r_dev  = token_value(token);
 
     token  = strsep(str, delim);
-    *opt = strchr(token, ',');
-    if (*opt)
-        *(*opt)++ = '\0';
+    bdf.opt = strchr(token, ',');
+    if (bdf.opt)
+        *(bdf.opt)++ = '\0';
 
-    *func  = token_value(token);
+    bdf.r_func  = token_value(token);
 
-    return 1;
+    bdf.valid = 1;
+
+    return bdf;
 }
 
 static int get_next_keyval(char **option, char **key, char **val)
@@ -802,31 +831,31 @@ static void msi_set_enable(struct pt_dev
  *         0: no free hotplug slots, but normal slot should okay
  *        >0: the new hotplug devfn
  */
-static int insert_to_php_devfn(int bus, int dev, int func, int devfn,
-                                char *opt)
+static int insert_to_php_devfn(const struct php_dev *bdf)
 {
     int php_slot, php_func, php_devfn, php_devfn_match;
 
     /* preferred virt pci slot */
-    if ( devfn >= PHP_DEVFN_START && devfn < PHP_DEVFN_END )
+    if ( bdf->v_devfn >= PHP_DEVFN_START && bdf->v_devfn < PHP_DEVFN_END )
     {
-        php_devfn = PCI_TO_PHP_DEVFN(devfn);
-        if ( !dpci_infos.php_devs[php_devfn].valid )
+        php_devfn = PCI_TO_PHP_DEVFN(bdf->v_devfn);
+        if ( !dpci_infos.php_devs[php_devfn].valid ||
+             !cmp_php_dev(&dpci_infos.php_devs[php_devfn], bdf) )
             goto found;
     }
-    if ( devfn != 0 )
+    if ( bdf->v_devfn != 0 )
         return -1;
 
     /* Co-locate functions for the same device in the same slot */
     for ( php_slot = 0; php_slot < PHP_SLOT_LEN; php_slot++ )
     {
-        php_devfn = PCI_DEVFN(php_slot, func);
+        php_devfn = PCI_DEVFN(php_slot, bdf->r_func);
         for ( php_func = 0; php_func < 8; php_func++ )
         {
             php_devfn_match = PCI_DEVFN(php_slot, php_func);
             if ( dpci_infos.php_devs[php_devfn_match].valid &&
-                 dpci_infos.php_devs[php_devfn_match].r_bus == bus &&
-                 dpci_infos.php_devs[php_devfn_match].r_dev == dev &&
+                 dpci_infos.php_devs[php_devfn_match].r_bus == bdf->r_bus &&
+                 dpci_infos.php_devs[php_devfn_match].r_dev == bdf->r_dev &&
                  !dpci_infos.php_devs[php_devfn].valid )
                 goto found;
         }
@@ -844,12 +873,9 @@ static int insert_to_php_devfn(int bus, 
     return 0;
 
 found:
-    dpci_infos.php_devs[php_devfn].valid  = 1;
-    dpci_infos.php_devs[php_devfn].r_bus  = bus;
-    dpci_infos.php_devs[php_devfn].r_dev  = dev;
-    dpci_infos.php_devs[php_devfn].r_func = func;
-    dpci_infos.php_devs[php_devfn].opt = opt;
-    return PHP_TO_PCI_DEVFN(php_devfn);
+    cpy_php_dev(&dpci_infos.php_devs[php_devfn], bdf);
+    dpci_infos.php_devs[php_devfn].v_devfn = PHP_TO_PCI_DEVFN(php_devfn);
+    return dpci_infos.php_devs[php_devfn].v_devfn;
 }
 
 /* Insert a new pass-through device into function 0 of a specific pci slot.
@@ -857,7 +883,8 @@ found:
  */
 int insert_bdf_to_php_devfn(char *bdf_slt)
 {
-    int seg, bus, dev, func, slot;
+    int slot;
+    struct php_dev bdf;
     char *bdf_str, *slt_str, *opt;
     const char *delim="@";
 
@@ -865,12 +892,15 @@ int insert_bdf_to_php_devfn(char *bdf_sl
     slt_str = bdf_slt;
     slot = token_value(slt_str);
 
-    if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func, &opt))
+    bdf = next_bdf(&bdf_str);
+    if (!bdf.valid)
     {
         return -1;
     }
 
-    return insert_to_php_devfn(bus, dev, func, PCI_DEVFN(slot, 0), opt);
+    bdf.v_devfn = PCI_DEVFN(slot, 0);
+
+    return insert_to_php_devfn(&bdf);
 
 }
 
@@ -896,22 +926,22 @@ int test_php_devfn(int devfn)
 /* find the pci slot for pass-through dev with specified BDF */
 int bdf_to_php_devfn(char *bdf_str)
 {
-    int seg, bus, dev, func, i;
-    char *opt;
+    int i;
+    struct php_dev bdf;
 
-    if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func, &opt))
+    bdf = next_bdf(&bdf_str);
+    if (!bdf.valid)
     {
         return -1;
     }
-    PT_LOG("%s: bdf: %04x:%02x.%x\n", __func__, bus, dev, func);
+    PT_LOG("%s: bdf: %04x:%02x.%x\n", __func__, bdf.r_bus, bdf.r_dev,
+           bdf.r_func);
 
     /* locate the virtual pci slot for this VTd device */
     for ( i = 0; i < PHP_DEVFN_LEN; i++ )
     {
         if ( dpci_infos.php_devs[i].valid &&
-           dpci_infos.php_devs[i].r_bus == bus &&
-           dpci_infos.php_devs[i].r_dev  == dev &&
-           dpci_infos.php_devs[i].r_func == func )
+             cmp_php_dev(&dpci_infos.php_devs[i], &bdf) )
         {
             return PHP_TO_PCI_DEVFN(i);
         }
@@ -3093,9 +3123,8 @@ static int pt_msixctrl_reg_write(struct 
 }
 
 static struct pt_dev * register_real_device(PCIBus *e_bus,
-        const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev,
-        uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access,
-        char *opt)
+        const char *e_dev_name, struct php_dev *bdf,
+        uint32_t machine_irq, struct pci_access *pci_access)
 {
     int rc = -1, i;
     struct pt_dev *assigned_device = NULL;
@@ -3107,14 +3136,14 @@ static struct pt_dev * register_real_dev
     int msi_translate;
 
     PT_LOG("Assigning real physical device %02x:%02x.%x ...\n",
-        r_bus, r_dev, r_func);
+        bdf->r_bus, bdf->r_dev, bdf->r_func);
 
     /* Find real device structure */
     for (pci_dev = pci_access->devices; pci_dev != NULL;
          pci_dev = pci_dev->next)
     {
-        if ((r_bus == pci_dev->bus) && (r_dev == pci_dev->dev)
-            && (r_func == pci_dev->func))
+        if ((bdf->r_bus == pci_dev->bus) && (bdf->r_dev == pci_dev->dev)
+            && (bdf->r_func == pci_dev->func))
             break;
     }
     if ( pci_dev == NULL )
@@ -3125,19 +3154,16 @@ static struct pt_dev * register_real_dev
     pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | 
PCI_FILL_SIZES);
     pt_libpci_fixup(pci_dev);
 
-    if ( e_devfn == PCI_DEVFN_AUTO ) {
-        /*indicate a static assignment(not hotplug), so find a free PCI hot 
plug slot */
-        free_devfn = insert_to_php_devfn(r_bus, r_dev, r_func, 0, NULL);
-        if ( free_devfn > 0 )
-            e_devfn = free_devfn;
-        else
-            PT_LOG("Error: no free virtual PCI hot plug slot, thus no live 
migration.\n");
-    }
+    free_devfn = insert_to_php_devfn(bdf);
+    if ( free_devfn <= 0 )
+        PT_LOG("Error: no free virtual PCI hot plug slot, "
+               "thus no live migration.\n");
 
     msi_translate = direct_pci_msitranslate;
-    while (opt) {
-        if (get_next_keyval(&opt, &key, &val)) {
-            PT_LOG("Error: unrecognized PCI assignment option \"%s\"\n", opt);
+    while (bdf->opt) {
+        if (get_next_keyval(&bdf->opt, &key, &val)) {
+            PT_LOG("Error: unrecognized PCI assignment option \"%s\"\n",
+                   bdf->opt);
             break;
         }
 
@@ -3164,7 +3190,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), e_devfn,
+                                sizeof(struct pt_dev), free_devfn,
                                 pt_pci_read_config, pt_pci_write_config);
     if ( assigned_device == NULL )
     {
@@ -3181,9 +3207,9 @@ static struct pt_dev * register_real_dev
 
     /* Assign device */
     machine_bdf.reg = 0;
-    machine_bdf.bus = r_bus;
-    machine_bdf.dev = r_dev;
-    machine_bdf.func = r_func;
+    machine_bdf.bus = bdf->r_bus;
+    machine_bdf.dev = bdf->r_dev;
+    machine_bdf.func = bdf->r_func;
     rc = xc_assign_device(xc_handle, domid, machine_bdf.value);
     if ( rc < 0 )
         PT_LOG("Error: xc_assign_device error %d\n", rc);
@@ -3273,7 +3299,7 @@ static struct pt_dev * register_real_dev
 
 out:
     PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n"
-           "IRQ type = %s\n", r_bus, r_dev, r_func,
+           "IRQ type = %s\n", bdf->r_bus, bdf->r_dev, bdf->r_func,
            assigned_device->msi_trans_en? "MSI-INTx":"INTx");
 
     return assigned_device;
@@ -3353,18 +3379,11 @@ static int unregister_real_device(int ph
 int power_on_php_devfn(int php_devfn)
 {
     struct php_dev *php_dev = &dpci_infos.php_devs[php_devfn];
-    int pci_devfn = PHP_TO_PCI_DEVFN(php_devfn);
     struct pt_dev *pt_dev;
-    pt_dev = 
-        register_real_device(dpci_infos.e_bus,
-            "DIRECT PCI",
-            pci_devfn,
-            php_dev->r_bus,
-            php_dev->r_dev,
-            php_dev->r_func,
-            PT_MACHINE_IRQ_AUTO,
-            dpci_infos.pci_access,
-            php_dev->opt);
+
+    pt_dev = register_real_device(dpci_infos.e_bus, "DIRECT PCI",
+                                  php_dev, PT_MACHINE_IRQ_AUTO,
+                                  dpci_infos.pci_access);
 
     php_dev->opt = NULL;
 
@@ -3381,14 +3400,14 @@ int power_off_php_devfn(int php_devfn)
 
 int pt_init(PCIBus *e_bus, const char *direct_pci)
 {
-    int seg, b, d, f, status = -1;
+    int status = -1;
     struct pt_dev *pt_dev;
     struct pci_access *pci_access;
     char *vslots;
     char slot_str[8];
     char *direct_pci_head = NULL;
     char *direct_pci_p = NULL;
-    char *opt;
+    struct php_dev bdf;
 
     /* Initialize libpci */
     pci_access = pci_alloc();
@@ -3417,14 +3436,20 @@ int pt_init(PCIBus *e_bus, const char *d
     vslots = qemu_mallocz ( strlen(direct_pci) / 3 );
 
     /* Assign given devices to guest */
-    while ( next_bdf(&direct_pci_p, &seg, &b, &d, &f, &opt) )
+    while (1)
     {
+        bdf = next_bdf(&direct_pci_p);
+        if (!bdf.valid)
+        {
+            break;
+        }
         /* Register real device with the emulated bus */
-        pt_dev = register_real_device(e_bus, "DIRECT PCI", PCI_DEVFN_AUTO,
-            b, d, f, PT_MACHINE_IRQ_AUTO, pci_access, opt);
+        pt_dev = register_real_device(e_bus, "DIRECT PCI",
+                                      &bdf, PT_MACHINE_IRQ_AUTO, pci_access);
         if ( pt_dev == NULL )
         {
-            PT_LOG("Error: Registration failed (%02x:%02x.%x)\n", b, d, f);
+            PT_LOG("Error: Registration failed (%02x:%02x.%x)\n",
+                   bdf.r_bus, bdf.r_dev, bdf.r_func);
             goto err;
         }
 

-- 

-- 
Simon Horman
  VA Linux Systems Japan K.K., Sydney, Australia Satellite Office
  H: www.vergenet.net/~horms/             W: www.valinux.co.jp/en


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

<Prev in Thread] Current Thread [Next in Thread>