This patch cleanups the code of PCI passthrough.
- Use LIST_FOREACH(). Don't use lh_first, le_next directly.
- Use pci_{read, write}_block instead of "switch(len) case [124]
pci_{read, write}_{byte, word, long}();".
- Eliminate duplicate codes using PT_MEARGE_VALUE macro.
- Define PCI_ERR_* macro in pass-through.h if libpci is old.
- Remove the unreasonable loop from pt_aer_reg_{save,restore}.
- Enable pt_aer_reg_{save,restore}, even if libpci is old.
- Fix ro_mask and remove unnecessary pt_xxx_reg_write functions.
- Add "Error:" or "Warning:" to messages.
- Remove verbose messages.
Thanks,
--
Yuji Shimada.
Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxx>
diff --git a/hw/pass-through.c b/hw/pass-through.c
index c2a6ec1..1de0162 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -126,18 +126,6 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev,
static int pt_pmcsr_reg_write(struct pt_dev *ptdev,
struct pt_reg_tbl *cfg_entry,
uint16_t *value, uint16_t dev_value, uint16_t valid_mask);
-static int pt_devctrl_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask);
-static int pt_linkctrl_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask);
-static int pt_devctrl2_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask);
-static int pt_linkctrl2_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask);
static int pt_msgctrl_reg_write(struct pt_dev *ptdev,
struct pt_reg_tbl *cfg_entry,
uint16_t *value, uint16_t dev_value, uint16_t valid_mask);
@@ -413,7 +401,7 @@ static struct pt_reg_info_tbl pt_emu_reg_pm_tbl[] = {
.offset = PCI_PM_CTRL,
.size = 2,
.init_val = 0x0008,
- .ro_mask = 0x60FC,
+ .ro_mask = 0xE1FC,
.emu_mask = 0x8100,
.init = pt_pmcsr_reg_init,
.u.w.read = pt_word_reg_read,
@@ -494,11 +482,11 @@ static struct pt_reg_info_tbl pt_emu_reg_pcie_tbl[] = {
.offset = PCI_EXP_DEVCTL,
.size = 2,
.init_val = 0x2810,
- .ro_mask = 0x0000,
+ .ro_mask = 0x8400,
.emu_mask = 0xFFFF,
.init = pt_common_reg_init,
.u.w.read = pt_word_reg_read,
- .u.w.write = pt_devctrl_reg_write,
+ .u.w.write = pt_word_reg_write,
.u.w.restore = pt_word_reg_restore,
},
/* Link Control reg */
@@ -506,11 +494,11 @@ static struct pt_reg_info_tbl pt_emu_reg_pcie_tbl[] = {
.offset = PCI_EXP_LNKCTL,
.size = 2,
.init_val = 0x0000,
- .ro_mask = 0x0000,
+ .ro_mask = 0xFC34,
.emu_mask = 0xFFFF,
.init = pt_linkctrl_reg_init,
.u.w.read = pt_word_reg_read,
- .u.w.write = pt_linkctrl_reg_write,
+ .u.w.write = pt_word_reg_write,
.u.w.restore = pt_word_reg_restore,
},
/* Device Control 2 reg */
@@ -518,11 +506,11 @@ static struct pt_reg_info_tbl pt_emu_reg_pcie_tbl[] = {
.offset = 0x28,
.size = 2,
.init_val = 0x0000,
- .ro_mask = 0x0000,
+ .ro_mask = 0xFFE0,
.emu_mask = 0xFFFF,
.init = pt_devctrl2_reg_init,
.u.w.read = pt_word_reg_read,
- .u.w.write = pt_devctrl2_reg_write,
+ .u.w.write = pt_word_reg_write,
.u.w.restore = pt_word_reg_restore,
},
/* Link Control 2 reg */
@@ -530,11 +518,11 @@ static struct pt_reg_info_tbl pt_emu_reg_pcie_tbl[] = {
.offset = 0x30,
.size = 2,
.init_val = 0x0000,
- .ro_mask = 0x0000,
+ .ro_mask = 0xE040,
.emu_mask = 0xFFFF,
.init = pt_linkctrl2_reg_init,
.u.w.read = pt_word_reg_read,
- .u.w.write = pt_linkctrl2_reg_write,
+ .u.w.write = pt_word_reg_write,
.u.w.restore = pt_word_reg_restore,
},
{
@@ -1051,8 +1039,7 @@ struct pt_reg_grp_tbl* pt_find_reg_grp(
struct pt_reg_grp_tbl* reg_grp_entry = NULL;
/* find register group entry */
- for (reg_grp_entry = ptdev->reg_grp_tbl_head.lh_first; reg_grp_entry;
- reg_grp_entry = reg_grp_entry->entries.le_next)
+ LIST_FOREACH(reg_grp_entry, &ptdev->reg_grp_tbl_head, entries)
{
/* check address */
if ((reg_grp_entry->base_offset <= address) &&
@@ -1075,8 +1062,7 @@ struct pt_reg_tbl* pt_find_reg(
uint32_t real_offset = 0;
/* find register entry */
- for (reg_entry = reg_grp->reg_tbl_head.lh_first; reg_entry;
- reg_entry = reg_entry->entries.le_next)
+ LIST_FOREACH(reg_entry, ®_grp->reg_tbl_head, entries)
{
reg = reg_entry->reg;
real_offset = (reg_grp->base_offset + reg->offset);
@@ -1140,7 +1126,7 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t
address, uint32_t val,
/* check offset range */
if (address >= 0xFF)
{
- PT_LOG("Failed to write register with offset exceeding FFh. "
+ PT_LOG("Error: Failed to write register with offset exceeding FFh. "
"[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
address, len);
@@ -1150,7 +1136,7 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t
address, uint32_t val,
/* check write size */
if ((len != 1) && (len != 2) && (len != 4))
{
- PT_LOG("Failed to write register with invalid access length. "
+ PT_LOG("Error: Failed to write register with invalid access length. "
"[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
address, len);
@@ -1160,8 +1146,8 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t
address, uint32_t val,
/* check offset alignment */
if (address & (len-1))
{
- PT_LOG("Failed to write register with invalid access size alignment. "
- "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
+ PT_LOG("Error: Failed to write register with invalid access size "
+ "alignment. [%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
address, len);
goto exit;
@@ -1172,8 +1158,8 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t
address, uint32_t val,
if ((index >= 0) && (val > 0 && val < PT_BAR_ALLF) &&
(assigned_device->bases[index].bar_flag == PT_BAR_FLAG_UNUSED))
{
- PT_LOG("Guest attempt to set address to unused Base Address Register. "
- "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
+ PT_LOG("Warning: Guest attempt to set address to unused Base Address "
+ "Register. [%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F),
(d->devfn & 0x7), address, len);
}
@@ -1194,7 +1180,7 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t
address, uint32_t val,
if (reg_grp->grp_type == GRP_TYPE_HARDWIRED)
{
/* ignore silently */
- PT_LOG("Access to 0 Hardwired register. "
+ PT_LOG("Warning: Access to 0 Hardwired register. "
"[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F),
(d->devfn & 0x7), address, len);
@@ -1203,28 +1189,14 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t
address, uint32_t val,
}
/* read I/O device register value */
- switch (len) {
- case 1:
- read_val = pci_read_byte(pci_dev, address);
- break;
- case 2:
- read_val = pci_read_word(pci_dev, address);
- break;
- case 4:
- read_val = pci_read_long(pci_dev, address);
- break;
- }
+ ret = pci_read_block(pci_dev, address, (uint8_t *)&read_val, len);
- /* check libpci result */
- valid_mask = (0xFFFFFFFF >> ((4 - len) << 3));
- if ((read_val & valid_mask) == valid_mask)
+ if (!ret)
{
- PT_LOG("Warning: Return ALL F from libpci read. "
- "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
- pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
- address, len);
+ PT_LOG("Error: pci_read_block failed. return value[%d].\n", ret);
+ memset((uint8_t *)&read_val, 0xff, len);
}
-
+
/* pass directly to libpci for passthrough type register group */
if (reg_grp_entry == NULL)
goto out;
@@ -1303,17 +1277,10 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t
address, uint32_t val,
val >>= ((address & 3) << 3);
out:
- switch (len){
- case 1:
- pci_write_byte(pci_dev, address, val);
- break;
- case 2:
- pci_write_word(pci_dev, address, val);
- break;
- case 4:
- pci_write_long(pci_dev, address, val);
- break;
- }
+ ret = pci_write_block(pci_dev, address, (uint8_t *)&val, len);
+
+ if (!ret)
+ PT_LOG("Error: pci_write_block failed. return value[%d].\n", ret);
if (pm_state->flags & PT_FLAG_TRANSITING)
/* set QEMUTimer */
@@ -1329,7 +1298,7 @@ static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t
address, int len)
struct pt_dev *assigned_device = (struct pt_dev *)d;
struct pci_dev *pci_dev = assigned_device->pci_dev;
struct pt_pm_info *pm_state = assigned_device->pm_state;
- uint32_t val = 0xFFFFFFFF;
+ uint32_t val = 0;
struct pt_reg_grp_tbl *reg_grp_entry = NULL;
struct pt_reg_grp_info_tbl *reg_grp = NULL;
struct pt_reg_tbl *reg_entry = NULL;
@@ -1344,7 +1313,7 @@ static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t
address, int len)
/* check offset range */
if (address >= 0xFF)
{
- PT_LOG("Failed to read register with offset exceeding FFh. "
+ PT_LOG("Error: Failed to read register with offset exceeding FFh. "
"[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
address, len);
@@ -1354,7 +1323,7 @@ static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t
address, int len)
/* check read size */
if ((len != 1) && (len != 2) && (len != 4))
{
- PT_LOG("Failed to read register with invalid access length. "
+ PT_LOG("Error: Failed to read register with invalid access length. "
"[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
address, len);
@@ -1364,8 +1333,8 @@ static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t
address, int len)
/* check offset alignment */
if (address & (len-1))
{
- PT_LOG("Failed to read register with invalid access size alignment. "
- "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
+ PT_LOG("Error: Failed to read register with invalid access size "
+ "alignment. [%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
address, len);
goto exit;
@@ -1393,26 +1362,12 @@ static uint32_t pt_pci_read_config(PCIDevice *d,
uint32_t address, int len)
}
/* read I/O device register value */
- switch (len) {
- case 1:
- val = pci_read_byte(pci_dev, address);
- break;
- case 2:
- val = pci_read_word(pci_dev, address);
- break;
- case 4:
- val = pci_read_long(pci_dev, address);
- break;
- }
+ ret = pci_read_block(pci_dev, address, (uint8_t *)&val, len);
- /* check libpci result */
- valid_mask = (0xFFFFFFFF >> ((4 - len) << 3));
- if ((val & valid_mask) == valid_mask)
+ if (!ret)
{
- PT_LOG("Warning: Return ALL F from libpci read. "
- "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",
- pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
- address, len);
+ PT_LOG("Error: pci_read_block failed. return value[%d].\n", ret);
+ memset((uint8_t *)&val, 0xff, len);
}
/* just return the I/O device register value for
@@ -1514,7 +1471,7 @@ static void pt_libpci_fixup(struct pci_dev *dev)
fp = fopen(path, "r");
if ( !fp )
{
- PT_LOG("Can't open %s: %s\n", path, strerror(errno));
+ PT_LOG("Error: Can't open %s: %s\n", path, strerror(errno));
return;
}
@@ -1522,7 +1479,7 @@ static void pt_libpci_fixup(struct pci_dev *dev)
{
if ( fscanf(fp, "%llx %llx %llx", &start, &end, &flags) != 3 )
{
- PT_LOG("Syntax error in %s\n", path);
+ PT_LOG("Error: Syntax error in %s\n", path);
break;
}
@@ -1800,8 +1757,8 @@ static void pt_bar_mapping(struct pt_dev *ptdev, int
io_enable, int mem_enable)
/* check overlapped address */
ret = pt_chk_bar_overlap(dev->bus, dev->devfn, r_addr, r_size);
if (ret > 0)
- PT_LOG("ptdev[%02x:%02x.%x][Region:%d][Address:%08xh][Size:%08xh] "
- "is overlapped.\n", pci_bus_num(dev->bus),
+ PT_LOG("Warning: ptdev[%02x:%02x.%x][Region:%d][Address:%08xh]"
+ "[Size:%08xh] is overlapped.\n", pci_bus_num(dev->bus),
(dev->devfn >> 3) & 0x1F, (dev->devfn & 0x7),
i, r_addr, r_size);
@@ -1841,68 +1798,51 @@ int check_power_state(struct pt_dev *ptdev)
return 0;
}
-/* save AER register */
-static void pt_aer_reg_save(struct pt_dev *ptdev)
+/* save AER one register */
+static void aer_save_one_register(struct pt_dev *ptdev, int offset)
{
PCIDevice *d = &ptdev->dev;
uint32_t aer_base = ptdev->pm_state->aer_base;
- int i = 0;
- /* Root Port and Root Complex Event Collector need size expansion */
- int aer_size = 0x2c;
-#ifdef PCI_ERR_UNCOR_MASK
- for (i=0; i < aer_size; i+=4)
- {
- switch (i) {
- /* after reset, following register values should be restored.
- * So, save them.
- */
- case PCI_ERR_UNCOR_MASK:
- case PCI_ERR_UNCOR_SEVER:
- case PCI_ERR_COR_MASK:
- case PCI_ERR_CAP:
- *(uint32_t*)(d->config + (aer_base + i))
- = pci_read_long(ptdev->pci_dev, (aer_base + i));
- break;
- default:
- break;
- }
- }
-#endif
+ *(uint32_t*)(d->config + (aer_base + offset))
+ = pci_read_long(ptdev->pci_dev, (aer_base + offset));
}
-/* restore AER register */
-static void pt_aer_reg_restore(struct pt_dev *ptdev)
+/* save AER registers */
+static void pt_aer_reg_save(struct pt_dev *ptdev)
+{
+ /* after reset, following register values should be restored.
+ * So, save them.
+ */
+ aer_save_one_register(ptdev, PCI_ERR_UNCOR_MASK);
+ aer_save_one_register(ptdev, PCI_ERR_UNCOR_SEVER);
+ aer_save_one_register(ptdev, PCI_ERR_COR_MASK);
+ aer_save_one_register(ptdev, PCI_ERR_CAP);
+}
+
+/* restore AER one register */
+static void aer_restore_one_register(struct pt_dev *ptdev, int offset)
{
PCIDevice *d = &ptdev->dev;
uint32_t aer_base = ptdev->pm_state->aer_base;
- int i = 0;
uint32_t config = 0;
- /* Root Port and Root Complex Event Collector need size expansion */
- int aer_size = 0x2c;
-#ifdef PCI_ERR_UNCOR_MASK
- for (i=0; i < aer_size; i+=4)
- {
- switch (i) {
- /* the following registers should be reconfigured to correct values
- * after reset. restore them.
- */
- case PCI_ERR_UNCOR_MASK:
- case PCI_ERR_UNCOR_SEVER:
- case PCI_ERR_COR_MASK:
- case PCI_ERR_CAP:
- config = *(uint32_t*)(d->config + (aer_base + i));
- pci_write_long(ptdev->pci_dev, (aer_base + i), config);
- break;
- /* other registers should not be reconfigured after reset
- * if there is no reason
- */
- default:
- break;
- }
- }
-#endif
+ config = *(uint32_t*)(d->config + (aer_base + offset));
+ pci_write_long(ptdev->pci_dev, (aer_base + offset), config);
+}
+
+/* restore AER registers */
+static void pt_aer_reg_restore(struct pt_dev *ptdev)
+{
+ /* the following registers should be reconfigured to correct values
+ * after reset. restore them.
+ * other registers should not be reconfigured after reset
+ * if there is no reason
+ */
+ aer_restore_one_register(ptdev, PCI_ERR_UNCOR_MASK);
+ aer_restore_one_register(ptdev, PCI_ERR_UNCOR_SEVER);
+ aer_restore_one_register(ptdev, PCI_ERR_COR_MASK);
+ aer_restore_one_register(ptdev, PCI_ERR_CAP);
}
/* reset Interrupt and I/O resource */
@@ -2115,7 +2055,7 @@ static int pt_config_reg_init(struct pt_dev *ptdev,
reg_entry = qemu_mallocz(sizeof(struct pt_reg_tbl));
if (reg_entry == NULL)
{
- PT_LOG("Failed to allocate memory.\n");
+ PT_LOG("Error: Failed to allocate memory.\n");
err = -1;
goto out;
}
@@ -2171,7 +2111,7 @@ static int pt_config_init(struct pt_dev *ptdev)
reg_grp_entry = qemu_mallocz(sizeof(struct pt_reg_grp_tbl));
if (reg_grp_entry == NULL)
{
- PT_LOG("Failed to allocate memory.\n");
+ PT_LOG("Error: Failed to allocate memory.\n");
err = -1;
goto out;
}
@@ -2239,10 +2179,10 @@ static void pt_config_delete(struct pt_dev *ptdev)
}
/* free all register group entry */
- while ((reg_grp_entry = ptdev->reg_grp_tbl_head.lh_first) != NULL)
+ while((reg_grp_entry = LIST_FIRST(&ptdev->reg_grp_tbl_head)) != NULL)
{
/* free all register entry */
- while ((reg_entry = reg_grp_entry->reg_tbl_head.lh_first) != NULL)
+ while((reg_entry = LIST_FIRST(®_grp_entry->reg_tbl_head)) != NULL)
{
LIST_REMOVE(reg_entry, entries);
qemu_free(reg_entry);
@@ -2624,7 +2564,7 @@ static uint8_t pt_msi_size_init(struct pt_dev *ptdev,
if ( !ptdev->msi )
{
/* exit I/O emulator */
- PT_LOG("error allocation pt_msi_info. I/O emulator exit.\n");
+ PT_LOG("Error: Allocating pt_msi_info failed. I/O emulator exit.\n");
exit(1);
}
memset(ptdev->msi, 0, sizeof(struct pt_msi_info));
@@ -2754,8 +2694,7 @@ static int pt_byte_reg_read(struct pt_dev *ptdev,
/* emulate byte register */
valid_emu_mask = reg->emu_mask & valid_mask;
- *value = ((*value & ~valid_emu_mask) |
- (cfg_entry->data & valid_emu_mask));
+ *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask);
return 0;
}
@@ -2770,8 +2709,7 @@ static int pt_word_reg_read(struct pt_dev *ptdev,
/* emulate word register */
valid_emu_mask = reg->emu_mask & valid_mask;
- *value = ((*value & ~valid_emu_mask) |
- (cfg_entry->data & valid_emu_mask));
+ *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask);
return 0;
}
@@ -2786,8 +2724,7 @@ static int pt_long_reg_read(struct pt_dev *ptdev,
/* emulate long register */
valid_emu_mask = reg->emu_mask & valid_mask;
- *value = ((*value & ~valid_emu_mask) |
- (cfg_entry->data & valid_emu_mask));
+ *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask);
return 0;
}
@@ -2833,8 +2770,7 @@ static int pt_bar_reg_read(struct pt_dev *ptdev,
/* emulate BAR */
valid_emu_mask = bar_emu_mask & valid_mask;
- *value = ((*value & ~valid_emu_mask) |
- (cfg_entry->data & valid_emu_mask));
+ *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask);
return 0;
}
@@ -2850,13 +2786,11 @@ static int pt_byte_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
return 0;
}
@@ -2872,13 +2806,11 @@ static int pt_word_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
return 0;
}
@@ -2894,13 +2826,11 @@ static int pt_long_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
return 0;
}
@@ -2917,12 +2847,11 @@ static int pt_cmd_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_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;
- *value = ((*value & throughable_mask) | (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
/* mapping BAR */
pt_bar_mapping(ptdev, wr_value & PCI_COMMAND_IO,
@@ -2988,8 +2917,7 @@ static int pt_bar_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = bar_emu_mask & ~bar_ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
/* check whether we need to update the virtual region address or not */
switch (ptdev->bases[index].bar_flag)
@@ -3007,7 +2935,8 @@ static int pt_bar_reg_write(struct pt_dev *ptdev,
if ((last_addr >= 0x10000) &&
(cfg_entry->data != (PT_BAR_ALLF & ~bar_ro_mask)))
{
- PT_LOG("Guest attempt to set Base Address over the 64KB. "
+ PT_LOG("Warning: Guest attempt to set Base Address "
+ "over the 64KB. "
"[%02x:%02x.%x][Offset:%02xh][Address:%08xh][Size:%08xh]\n",
pci_bus_num(d->bus),
((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
@@ -3023,7 +2952,7 @@ static int pt_bar_reg_write(struct pt_dev *ptdev,
{
if (cfg_entry->data != (PT_BAR_ALLF & ~bar_ro_mask))
{
- PT_LOG("Guest attempt to set high MMIO Base Address. "
+ PT_LOG("Warning: Guest attempt to set high MMIO Base Address. "
"Ignore mapping. "
"[%02x:%02x.%x][Offset:%02xh][High Address:%08xh]\n",
pci_bus_num(d->bus),
@@ -3066,8 +2995,7 @@ static int pt_bar_reg_write(struct pt_dev *ptdev,
exit:
/* create value for writing to I/O device register */
throughable_mask = ~bar_emu_mask & valid_mask;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
return 0;
}
@@ -3099,16 +3027,14 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev
*ptdev,
/* modify emulate register */
writable_mask = bar_emu_mask & ~bar_ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
/* update the corresponding virtual region address */
r->addr = cfg_entry->data;
/* create value for writing to I/O device register */
throughable_mask = ~bar_emu_mask & valid_mask;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
return 0;
}
@@ -3122,22 +3048,16 @@ static int pt_pmcsr_reg_write(struct pt_dev *ptdev,
PCIDevice *d = &ptdev->dev;
uint16_t writable_mask = 0;
uint16_t throughable_mask = 0;
- uint16_t pmcsr_mask = (PCI_PM_CTRL_PME_ENABLE |
- PCI_PM_CTRL_DATA_SEL_MASK |
- PCI_PM_CTRL_PME_STATUS);
struct pt_pm_info *pm_state = ptdev->pm_state;
uint16_t read_val = 0;
/* modify emulate register */
- writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask & ~pmcsr_mask;
-
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ writable_mask = reg->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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
/* set I/O device power state */
pm_state->cur_state = (dev_value & PCI_PM_CTRL_STATE_MASK);
@@ -3236,101 +3156,6 @@ static int pt_pmcsr_reg_write(struct pt_dev *ptdev,
return 0;
}
-/* write Device Control register */
-static int pt_devctrl_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask)
-{
- struct pt_reg_info_tbl *reg = cfg_entry->reg;
- uint16_t writable_mask = 0;
- uint16_t throughable_mask = 0;
- uint16_t devctrl_mask = (PCI_EXP_DEVCTL_AUX_PME | 0x8000);
-
- /* modify emulate register */
- writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask & ~devctrl_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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
-
- return 0;
-}
-
-/* write Link Control register */
-static int pt_linkctrl_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask)
-{
- struct pt_reg_info_tbl *reg = cfg_entry->reg;
- uint16_t writable_mask = 0;
- uint16_t throughable_mask = 0;
- uint16_t linkctrl_mask = (0x04 | PCI_EXP_LNKCTL_DISABLE |
- PCI_EXP_LNKCTL_RETRAIN |
- 0x0400 | 0x0800 | 0xF000);
-
- /* modify emulate register */
- writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask &
~linkctrl_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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
-
- return 0;
-}
-
-/* write Device Control2 register */
-static int pt_devctrl2_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask)
-{
- struct pt_reg_info_tbl *reg = cfg_entry->reg;
- uint16_t writable_mask = 0;
- uint16_t throughable_mask = 0;
- uint16_t devctrl2_mask = 0xFFE0;
-
- /* modify emulate register */
- writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask &
~devctrl2_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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
-
- return 0;
-}
-
-/* write Link Control2 register */
-static int pt_linkctrl2_reg_write(struct pt_dev *ptdev,
- struct pt_reg_tbl *cfg_entry,
- uint16_t *value, uint16_t dev_value, uint16_t valid_mask)
-{
- struct pt_reg_info_tbl *reg = cfg_entry->reg;
- uint16_t writable_mask = 0;
- uint16_t throughable_mask = 0;
- uint16_t linkctrl2_mask = (0x0040 | 0xE000);
-
- /* modify emulate register */
- writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask &
- ~linkctrl2_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;
- *value = ((*value & throughable_mask) |
- (dev_value & ~throughable_mask));
-
- return 0;
-}
-
/* write Message Control register */
static int pt_msgctrl_reg_write(struct pt_dev *ptdev,
struct pt_reg_tbl *cfg_entry,
@@ -3346,22 +3171,19 @@ static int pt_msgctrl_reg_write(struct pt_dev *ptdev,
/* Currently no support for multi-vector */
if ((*value & PCI_MSI_FLAGS_QSIZE) != 0x0)
- PT_LOG("try to set more than 1 vector ctrl %x\n", *value);
+ PT_LOG("Warning: try to set more than 1 vector ctrl %x\n", *value);
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
/* update the msi_info too */
ptdev->msi->flags |= cfg_entry->data &
~(MSI_FLAG_UNINIT | PT_MSI_MAPPED | PCI_MSI_FLAGS_ENABLE);
- PT_LOG("old_ctrl:%04xh new_ctrl:%04xh\n", old_ctrl, cfg_entry->data);
-
/* create value for writing to I/O device register */
val = *value;
throughable_mask = ~reg->emu_mask & valid_mask;
- *value = ((*value & throughable_mask) | (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
/* update MSI */
if (val & PCI_MSI_FLAGS_ENABLE)
@@ -3420,16 +3242,13 @@ static int pt_msgaddr32_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
/* update the msi_info too */
ptdev->msi->addr_lo = cfg_entry->data;
- PT_LOG("old_addr_lo:%08xh new_addr_lo:%08xh\n", old_addr, cfg_entry->data);
-
/* create value for writing to I/O device register */
throughable_mask = ~reg->emu_mask & valid_mask;
- *value = ((*value & throughable_mask) | (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
/* update MSI */
if (cfg_entry->data != old_addr)
@@ -3455,22 +3274,19 @@ static int pt_msgaddr64_reg_write(struct pt_dev *ptdev,
if (!(ptdev->msi->flags & PCI_MSI_FLAGS_64BIT))
{
/* exit I/O emulator */
- PT_LOG("why comes to Upper Address without 64 bit support??\n");
+ PT_LOG("Error: why comes to Upper Address without 64 bit support??\n");
return -1;
}
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
/* update the msi_info too */
ptdev->msi->addr_hi = cfg_entry->data;
- PT_LOG("old_addr_hi:%08xh new_addr_hi:%08xh\n", old_addr, cfg_entry->data);
-
/* create value for writing to I/O device register */
throughable_mask = ~reg->emu_mask & valid_mask;
- *value = ((*value & throughable_mask) | (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
/* update MSI */
if (cfg_entry->data != old_addr)
@@ -3506,16 +3322,13 @@ static int pt_msgdata_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
/* update the msi_info too */
ptdev->msi->data = cfg_entry->data;
- PT_LOG("old_data:%04xh new_data:%04xh\n", old_data, cfg_entry->data);
-
/* create value for writing to I/O device register */
throughable_mask = ~reg->emu_mask & valid_mask;
- *value = ((*value & throughable_mask) | (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
/* update MSI */
if (cfg_entry->data != old_data)
@@ -3539,14 +3352,11 @@ static int pt_msixctrl_reg_write(struct pt_dev *ptdev,
/* modify emulate register */
writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
- cfg_entry->data = ((*value & writable_mask) |
- (cfg_entry->data & ~writable_mask));
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
- PT_LOG("old_ctrl:%04xh new_ctrl:%04xh\n", old_ctrl, cfg_entry->data);
-
/* create value for writing to I/O device register */
throughable_mask = ~reg->emu_mask & valid_mask;
- *value = ((*value & throughable_mask) | (dev_value & ~throughable_mask));
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
/* update MSI-X */
if ((*value & PCI_MSIX_ENABLE) && !(*value & PCI_MSIX_MASK))
@@ -3979,7 +3789,7 @@ int pt_init(PCIBus *e_bus, const char *direct_pci)
pci_access = pci_alloc();
if ( pci_access == NULL )
{
- PT_LOG("pci_access is NULL\n");
+ PT_LOG("Error: pci_access is NULL\n");
return -1;
}
pci_init(pci_access);
diff --git a/hw/pass-through.h b/hw/pass-through.h
index b44b9d7..2b2dbd2 100644
--- a/hw/pass-through.h
+++ b/hw/pass-through.h
@@ -86,6 +86,26 @@
#define PCI_EXP_TYPE_ROOT_EC 0xa
#endif
+#ifndef PCI_ERR_UNCOR_MASK
+/* Uncorrectable Error Mask */
+#define PCI_ERR_UNCOR_MASK 8
+#endif
+
+#ifndef PCI_ERR_UNCOR_SEVER
+/* Uncorrectable Error Severity */
+#define PCI_ERR_UNCOR_SEVER 12
+#endif
+
+#ifndef PCI_ERR_COR_MASK
+/* Correctable Error Mask */
+#define PCI_ERR_COR_MASK 20
+#endif
+
+#ifndef PCI_ERR_CAP
+/* Advanced Error Capabilities */
+#define PCI_ERR_CAP 24
+#endif
+
#ifndef PCI_EXT_CAP_ID
/* Extended Capabilities (PCI-X 2.0 and PCI Express) */
#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
diff --git a/hw/pt-msi.c b/hw/pt-msi.c
index bdd1b38..6b0aaa1 100644
--- a/hw/pt-msi.c
+++ b/hw/pt-msi.c
@@ -68,7 +68,7 @@ int pt_msi_setup(struct pt_dev *dev)
if ( !(dev->msi->flags & MSI_FLAG_UNINIT) )
{
- PT_LOG("setup physical after initialized?? \n");
+ PT_LOG("Error: setup physical after initialized?? \n");
return -1;
}
@@ -76,13 +76,13 @@ int pt_msi_setup(struct pt_dev *dev)
dev->pci_dev->dev << 3 | dev->pci_dev->func,
dev->pci_dev->bus, 0, 0) )
{
- PT_LOG("error map msi\n");
+ PT_LOG("Error: Mapping of MSI failed.\n");
return -1;
}
if ( pirq < 0 )
{
- PT_LOG("invalid pirq number\n");
+ PT_LOG("Error: Invalid pirq number\n");
return -1;
}
@@ -125,7 +125,7 @@ int pt_msi_update(struct pt_dev *d)
addr = (uint64_t)d->msi->addr_hi << 32 | d->msi->addr_lo;
gflags = __get_msi_gflags(d->msi->data, addr);
- PT_LOG("now update msi with pirq %x gvec %x\n", d->msi->pirq, gvec);
+ PT_LOG("Update msi with pirq %x gvec %x\n", d->msi->pirq, gvec);
return xc_domain_update_msi_irq(xc_handle, domid, gvec,
d->msi->pirq, gflags);
}
@@ -295,19 +295,19 @@ static int pt_msix_update_one(struct pt_dev *dev, int
entry_nr)
dev->msix->table_base);
if ( ret )
{
- PT_LOG("error map msix entry %x\n", entry_nr);
+ PT_LOG("Error: Mapping msix entry %x\n", entry_nr);
return ret;
}
entry->pirq = pirq;
}
- PT_LOG("now update msix entry %x with pirq %x gvec %x\n",
+ PT_LOG("Update msix entry %x with pirq %x gvec %x\n",
entry_nr, pirq, gvec);
ret = xc_domain_update_msi_irq(xc_handle, domid, gvec, pirq, gflags);
if ( ret )
{
- PT_LOG("error update msix irq info for entry %d\n", entry_nr);
+ PT_LOG("Error: Updating msix irq info for entry %d\n", entry_nr);
return ret;
}
@@ -378,7 +378,7 @@ void pt_msix_disable(struct pt_dev *dev)
static void pci_msix_invalid_write(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
- PT_LOG("invalid write to MSI-X table, \
+ PT_LOG("Error: Invalid write to MSI-X table, \
only dword access is allowed.\n");
}
@@ -391,8 +391,8 @@ static void pci_msix_writel(void *opaque,
target_phys_addr_t addr, uint32_t val)
if ( addr % 4 )
{
- PT_LOG("unaligned dword access to MSI-X table, addr %016"PRIx64"\n",
- addr);
+ PT_LOG("Error: Unaligned dword access to MSI-X table, \
+ addr %016"PRIx64"\n", addr);
return;
}
@@ -402,8 +402,8 @@ static void pci_msix_writel(void *opaque,
target_phys_addr_t addr, uint32_t val)
if ( offset != 3 && msix->enabled && !(entry->io_mem[3] & 0x1) )
{
- PT_LOG("can not update msix entry %d since MSI-X is already \
- function now.\n", entry_nr);
+ PT_LOG("Error: Can't update msix entry %d since MSI-X is already \
+ function.\n", entry_nr);
return;
}
@@ -427,7 +427,7 @@ static CPUWriteMemoryFunc *pci_msix_write[] = {
static uint32_t pci_msix_invalid_read(void *opaque, target_phys_addr_t addr)
{
- PT_LOG("invalid read to MSI-X table, \
+ PT_LOG("Error: Invalid read to MSI-X table, \
only dword access is allowed.\n");
return 0;
}
@@ -440,8 +440,8 @@ static uint32_t pci_msix_readl(void *opaque,
target_phys_addr_t addr)
if ( addr % 4 )
{
- PT_LOG("unaligned dword access to MSI-X table, addr %016"PRIx64"\n",
- addr);
+ PT_LOG("Error: Unaligned dword access to MSI-X table, \
+ addr %016"PRIx64"\n", addr);
return 0;
}
@@ -504,7 +504,7 @@ int pt_msix_init(struct pt_dev *dev, int pos)
if ( id != PCI_CAP_ID_MSIX )
{
- PT_LOG("error id %x pos %x\n", id, pos);
+ PT_LOG("Error: Invalid id %x pos %x\n", id, pos);
return -1;
}
@@ -516,7 +516,7 @@ int pt_msix_init(struct pt_dev *dev, int pos)
+ total_entries*sizeof(struct msix_entry_info));
if ( !dev->msix )
{
- PT_LOG("error allocation pt_msix_info\n");
+ PT_LOG("Error: Allocating pt_msix_info failed.\n");
return -1;
}
memset(dev->msix, 0, sizeof(struct pt_msix_info)
@@ -538,7 +538,7 @@ int pt_msix_init(struct pt_dev *dev, int pos)
fd = open("/dev/mem", O_RDWR);
if ( fd == -1 )
{
- PT_LOG("Can't open /dev/mem: %s\n", strerror(errno));
+ PT_LOG("Error: Can't open /dev/mem: %s\n", strerror(errno));
goto error_out;
}
dev->msix->phys_iomem_base = mmap(0, total_entries * 16,
@@ -546,7 +546,7 @@ int pt_msix_init(struct pt_dev *dev, int pos)
fd, dev->msix->table_base + table_off);
if ( dev->msix->phys_iomem_base == MAP_FAILED )
{
- PT_LOG("Can't map physical MSI-X table: %s\n", strerror(errno));
+ PT_LOG("Error: Can't map physical MSI-X table: %s\n", strerror(errno));
close(fd);
goto error_out;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|