Add SR-IOV support for HVM guest.
Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx>
diff --git a/hw/pass-through.c b/hw/pass-through.c
index 77ab759..da1a86b 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -47,6 +47,10 @@ struct dpci_infos {
/* prototype */
static uint32_t pt_common_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_vendor_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_device_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_status_reg_init(struct pt_dev *ptdev,
@@ -90,6 +94,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);
@@ -151,6 +158,28 @@ static int pt_msixctrl_reg_write(struct pt_dev *ptdev,
/* Header Type0 reg static infomation table */
static struct pt_reg_info_tbl pt_emu_reg_header0_tbl[] = {
+ /* Vendor ID reg */
+ {
+ .offset = PCI_VENDOR_ID,
+ .size = 2,
+ .init_val = 0x0000,
+ .ro_mask = 0xFFFF,
+ .emu_mask = 0xFFFF,
+ .init = pt_vendor_reg_init,
+ .u.w.read = pt_word_reg_read,
+ .u.w.write = pt_word_reg_write,
+ },
+ /* Device ID reg */
+ {
+ .offset = PCI_DEVICE_ID,
+ .size = 2,
+ .init_val = 0x0000,
+ .ro_mask = 0xFFFF,
+ .emu_mask = 0xFFFF,
+ .init = pt_device_reg_init,
+ .u.w.read = pt_word_reg_read,
+ .u.w.write = pt_word_reg_write,
+ },
/* Command reg */
{
.offset = PCI_COMMAND,
@@ -159,7 +188,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,
},
/* Capabilities Pointer reg */
@@ -1753,6 +1782,14 @@ static void pt_config_delete(struct pt_dev *ptdev)
}
}
+/* check if the device is a Virtual Function */
+static int pt_is_vf(struct pt_dev *ptdev)
+{
+ uint32_t head = PT_BAR_ALLF; /* Vendor and Device ID */
+
+ return !memcmp(&head, ptdev->dev.config, sizeof(head));
+}
+
/* initialize common register value */
static uint32_t pt_common_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset)
@@ -1760,6 +1797,20 @@ static uint32_t pt_common_reg_init(struct pt_dev *ptdev,
return reg->init_val;
}
+/* initialize Vendor ID register value */
+static uint32_t pt_vendor_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+ return ptdev->pci_dev->vendor_id;
+}
+
+/* initialize Device ID register value */
+static uint32_t pt_device_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+ return ptdev->pci_dev->device_id;
+}
+
/* initialize Capabilities Pointer or Next Pointer register */
static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset)
@@ -2218,6 +2269,26 @@ 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 (pt_is_vf(ptdev))
+ emu_mask |= PCI_COMMAND_MEMORY;
+
+ /* emulate word register */
+ valid_emu_mask = emu_mask & valid_mask;
+ *value = ((*value & ~valid_emu_mask) |
+ (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,
@@ -2337,14 +2408,18 @@ 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 (pt_is_vf(ptdev))
+ 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 = ((*value & writable_mask) |
(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 = ((*value & throughable_mask) | (dev_value & ~throughable_mask));
/* mapping BAR */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|