]> xenbits.xen.org Git - xenclient/ioemu.git/commitdiff
support SR-IOV Virtual Function passthrough
authorIan Jackson <ian.jackson@eu.citrix.com>
Mon, 23 Mar 2009 17:19:30 +0000 (17:19 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Mon, 23 Mar 2009 17:19:30 +0000 (17:19 +0000)
Emulate the Memory Space Enable bit in the Command register because it's
hardwired to 0 for the Virtual Function.

Signed-off-by: Yu Zhao <yu.zhao@intel.com>
hw/pass-through.c
hw/pass-through.h

index 5de35fd4b8951b6b447f3bbada40ce4088368597..0e3d80b9171eb2f24dd0c4f62a836a921f84561a 100644 (file)
@@ -102,6 +102,9 @@ static int pt_word_reg_read(struct pt_dev *ptdev,
 static int pt_long_reg_read(struct pt_dev *ptdev,
     struct pt_reg_tbl *cfg_entry,
     uint32_t *value, uint32_t valid_mask);
+static int pt_cmd_reg_read(struct pt_dev *ptdev,
+    struct pt_reg_tbl *cfg_entry,
+    uint16_t *value, uint16_t valid_mask);
 static int pt_bar_reg_read(struct pt_dev *ptdev,
     struct pt_reg_tbl *cfg_entry,
     uint32_t *value, uint32_t valid_mask);
@@ -207,7 +210,7 @@ static struct pt_reg_info_tbl pt_emu_reg_header0_tbl[] = {
         .ro_mask    = 0xF880,
         .emu_mask   = 0x0340,
         .init       = pt_common_reg_init,
-        .u.w.read   = pt_word_reg_read,
+        .u.w.read   = pt_cmd_reg_read,
         .u.w.write  = pt_cmd_reg_write,
         .u.w.restore  = pt_cmd_reg_restore,
     },
@@ -1493,6 +1496,23 @@ static void pt_libpci_fixup(struct pci_dev *dev)
 #endif /* PCI_LIB_VERSION < 0x030100 */
 }
 
+static int pt_dev_is_virtfn(struct pci_dev *dev)
+{
+    int rc;
+    char path[PATH_MAX];
+    struct stat buf;
+
+    sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.%x/physfn",
+            dev->domain, dev->bus, dev->dev, dev->func);
+
+    rc = !stat(path, &buf);
+    if ( rc )
+        PT_LOG("%04x:%02x:%02x.%x is a SR-IOV Virtual Function\n",
+               dev->domain, dev->bus, dev->dev, dev->func);
+
+    return rc;
+}
+
 static int pt_register_regions(struct pt_dev *assigned_device)
 {
     int i = 0;
@@ -2773,6 +2793,25 @@ static int pt_long_reg_read(struct pt_dev *ptdev,
    return 0;
 }
 
+/* read Command register */
+static int pt_cmd_reg_read(struct pt_dev *ptdev,
+        struct pt_reg_tbl *cfg_entry,
+        uint16_t *value, uint16_t valid_mask)
+{
+    struct pt_reg_info_tbl *reg = cfg_entry->reg;
+    uint16_t valid_emu_mask = 0;
+    uint16_t emu_mask = reg->emu_mask;
+
+    if ( ptdev->is_virtfn )
+        emu_mask |= PCI_COMMAND_MEMORY;
+
+    /* emulate word register */
+    valid_emu_mask = emu_mask & valid_mask;
+    *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask);
+
+    return 0;
+}
+
 /* read BAR */
 static int pt_bar_reg_read(struct pt_dev *ptdev,
         struct pt_reg_tbl *cfg_entry,
@@ -2907,13 +2946,17 @@ static int pt_cmd_reg_write(struct pt_dev *ptdev,
     uint16_t writable_mask = 0;
     uint16_t throughable_mask = 0;
     uint16_t wr_value = *value;
+    uint16_t emu_mask = reg->emu_mask;
+
+    if ( ptdev->is_virtfn )
+        emu_mask |= PCI_COMMAND_MEMORY;
 
     /* modify emulate register */
-    writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
+    writable_mask = emu_mask & ~reg->ro_mask & valid_mask;
     cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
 
     /* create value for writing to I/O device register */
-    throughable_mask = ~reg->emu_mask & valid_mask;
+    throughable_mask = ~emu_mask & valid_mask;
     *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
 
     /* mapping BAR */
@@ -3706,6 +3749,7 @@ struct pt_dev * register_real_device(PCIBus *e_bus,
     assigned_device->pci_dev = pci_dev;
     assigned_device->msi_trans_cap = msi_translate;
     assigned_device->power_mgmt = power_mgmt;
+    assigned_device->is_virtfn = pt_dev_is_virtfn(pci_dev);
 
     /* Assign device */
     machine_bdf.reg = 0;
index b7b5a79349c761b43c1b01920790b72e0722979d..63d1a6db0c22f063786b44e160c9a903e8466e3d 100644 (file)
@@ -216,9 +216,10 @@ struct pt_dev {
     int machine_irq;                            /* saved pirq */
     /* Physical MSI to guest INTx translation when possible */
     int msi_trans_cap;
-    int msi_trans_en;
-    int power_mgmt;
+    unsigned msi_trans_en:1;
+    unsigned power_mgmt:1;
     struct pt_pm_info *pm_state;                /* PM virtualization */
+    unsigned is_virtfn:1;
 };
 
 /* Used for formatting PCI BDF into cf8 format */