summaryrefslogtreecommitdiff
path: root/sysutils/xen-tools/files/xsa131-qemut-4.patch
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/xen-tools/files/xsa131-qemut-4.patch')
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-4.patch266
1 files changed, 266 insertions, 0 deletions
diff --git a/sysutils/xen-tools/files/xsa131-qemut-4.patch b/sysutils/xen-tools/files/xsa131-qemut-4.patch
new file mode 100644
index 000000000000..95a7f517003f
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-4.patch
@@ -0,0 +1,266 @@
+xen/pt: split out calculation of throughable mask in PCI config space handling
+
+This is just to avoid having to adjust that calculation later in
+multiple places.
+
+Note that including ->ro_mask in get_throughable_mask()'s calculation
+is only an apparent (i.e. benign) behavioral change: For r/o fields it
+doesn't matter > whether they get passed through - either the same flag
+is also set in emu_mask (then there's no change at all) or the field is
+r/o in hardware (and hence a write won't change it anyway).
+
+This is a preparatory patch for XSA-131.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
+
+--- a/hw/pass-through.c
++++ b/hw/pass-through.c
+@@ -3442,6 +3442,15 @@ static int pt_bar_reg_read(struct pt_dev
+ }
+
+
++static uint32_t get_throughable_mask(const struct pt_dev *ptdev,
++ const struct pt_reg_info_tbl *reg,
++ uint32_t valid_mask)
++{
++ uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask);
++
++ return throughable_mask & valid_mask;
++}
++
+ /* write byte size emulate register */
+ static int pt_byte_reg_write(struct pt_dev *ptdev,
+ struct pt_reg_tbl *cfg_entry,
+@@ -3449,14 +3458,13 @@ static int pt_byte_reg_write(struct pt_d
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint8_t writable_mask = 0;
+- uint8_t throughable_mask = 0;
++ uint8_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+
+ /* modify emulate register */
+ 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 = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
+
+ return 0;
+@@ -3469,14 +3477,13 @@ static int pt_word_reg_write(struct pt_d
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint16_t writable_mask = 0;
+- uint16_t throughable_mask = 0;
++ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+
+ /* modify emulate register */
+ 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 = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
+
+ return 0;
+@@ -3489,14 +3496,13 @@ static int pt_long_reg_write(struct pt_d
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint32_t writable_mask = 0;
+- uint32_t throughable_mask = 0;
++ uint32_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+
+ /* modify emulate register */
+ 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 = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
+
+ return 0;
+@@ -3509,7 +3515,7 @@ static int pt_cmd_reg_write(struct pt_de
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint16_t writable_mask = 0;
+- uint16_t throughable_mask = 0;
++ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+ uint16_t wr_value = *value;
+
+ /* modify emulate register */
+@@ -3517,8 +3523,6 @@ static int pt_cmd_reg_write(struct pt_de
+ 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;
+-
+ if (*value & PCI_COMMAND_DISABLE_INTx)
+ {
+ if (ptdev->msi_trans_en)
+@@ -3564,7 +3568,6 @@ static int pt_bar_reg_write(struct pt_de
+ PCIDevice *d = (PCIDevice *)&ptdev->dev;
+ PCIIORegion *r;
+ uint32_t writable_mask = 0;
+- uint32_t throughable_mask = 0;
+ uint32_t bar_emu_mask = 0;
+ uint32_t bar_ro_mask = 0;
+ uint32_t new_addr, last_addr;
+@@ -3691,8 +3694,7 @@ static int pt_bar_reg_write(struct pt_de
+
+ exit:
+ /* create value for writing to I/O device register */
+- throughable_mask = ~bar_emu_mask & valid_mask;
+- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
++ *value = PT_MERGE_VALUE(*value, dev_value, 0);
+
+ /* After BAR reg update, we need to remap BAR*/
+ reg_grp_entry = pt_find_reg_grp(ptdev, PCI_COMMAND);
+@@ -3719,9 +3721,8 @@ static int pt_exp_rom_bar_reg_write(stru
+ PCIDevice *d = (PCIDevice *)&ptdev->dev;
+ PCIIORegion *r;
+ uint32_t writable_mask = 0;
+- uint32_t throughable_mask = 0;
++ uint32_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+ uint32_t r_size = 0;
+- uint32_t bar_emu_mask = 0;
+ uint32_t bar_ro_mask = 0;
+
+ r = &d->io_regions[PCI_ROM_SLOT];
+@@ -3731,7 +3732,6 @@ static int pt_exp_rom_bar_reg_write(stru
+ PT_GET_EMUL_SIZE(base->bar_flag, r_size);
+
+ /* set emulate mask and read-only mask */
+- bar_emu_mask = reg->emu_mask;
+ bar_ro_mask = (reg->ro_mask | (r_size - 1)) & ~PCI_ROM_ADDRESS_ENABLE;
+
+ /* modify emulate register */
+@@ -3751,7 +3751,6 @@ static int pt_exp_rom_bar_reg_write(stru
+ r->addr = cfg_entry->data;
+
+ /* create value for writing to I/O device register */
+- throughable_mask = ~bar_emu_mask & valid_mask;
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
+
+ /* After BAR reg update, we need to remap BAR*/
+@@ -3776,7 +3775,7 @@ static int pt_pmcsr_reg_write(struct pt_
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ PCIDevice *d = &ptdev->dev;
+ uint16_t writable_mask = 0;
+- uint16_t throughable_mask = 0;
++ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+ struct pt_pm_info *pm_state = ptdev->pm_state;
+ uint16_t read_val = 0;
+
+@@ -3785,7 +3784,6 @@ static int pt_pmcsr_reg_write(struct pt_
+ 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 = PT_MERGE_VALUE(*value, dev_value & ~PCI_PM_CTRL_PME_STATUS,
+ throughable_mask);
+
+@@ -3894,7 +3892,7 @@ static int pt_msgctrl_reg_write(struct p
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint16_t writable_mask = 0;
+- uint16_t throughable_mask = 0;
++ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+ uint16_t old_ctrl = cfg_entry->data;
+ PCIDevice *pd = (PCIDevice *)ptdev;
+ uint16_t val;
+@@ -3906,8 +3904,10 @@ static int pt_msgctrl_reg_write(struct p
+ /* modify emulate register */
+ writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
+ /* also emulate MSI_ENABLE bit for MSI-INTx translation */
+- if (ptdev->msi_trans_en)
++ if (ptdev->msi_trans_en) {
+ writable_mask |= PCI_MSI_FLAGS_ENABLE & valid_mask;
++ throughable_mask &= ~PCI_MSI_FLAGS_ENABLE;
++ }
+ cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
+ /* update the msi_info too */
+ ptdev->msi->flags |= cfg_entry->data &
+@@ -3915,10 +3915,6 @@ static int pt_msgctrl_reg_write(struct p
+
+ /* create value for writing to I/O device register */
+ val = *value;
+- throughable_mask = ~reg->emu_mask & valid_mask;
+- /* don't pass through MSI_ENABLE bit for MSI-INTx translation */
+- if (ptdev->msi_trans_en)
+- throughable_mask &= ~PCI_MSI_FLAGS_ENABLE;
+ *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
+
+ /* update MSI */
+@@ -3972,7 +3968,6 @@ static int pt_msgaddr32_reg_write(struct
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint32_t writable_mask = 0;
+- uint32_t throughable_mask = 0;
+ uint32_t old_addr = cfg_entry->data;
+
+ /* modify emulate register */
+@@ -3982,8 +3977,7 @@ static int pt_msgaddr32_reg_write(struct
+ ptdev->msi->addr_lo = cfg_entry->data;
+
+ /* create value for writing to I/O device register */
+- throughable_mask = ~reg->emu_mask & valid_mask;
+- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
++ *value = PT_MERGE_VALUE(*value, dev_value, 0);
+
+ /* update MSI */
+ if (cfg_entry->data != old_addr)
+@@ -4002,7 +3996,6 @@ static int pt_msgaddr64_reg_write(struct
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint32_t writable_mask = 0;
+- uint32_t throughable_mask = 0;
+ uint32_t old_addr = cfg_entry->data;
+
+ /* check whether the type is 64 bit or not */
+@@ -4020,8 +4013,7 @@ static int pt_msgaddr64_reg_write(struct
+ ptdev->msi->addr_hi = cfg_entry->data;
+
+ /* create value for writing to I/O device register */
+- throughable_mask = ~reg->emu_mask & valid_mask;
+- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
++ *value = PT_MERGE_VALUE(*value, dev_value, 0);
+
+ /* update MSI */
+ if (cfg_entry->data != old_addr)
+@@ -4041,7 +4033,6 @@ static int pt_msgdata_reg_write(struct p
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint16_t writable_mask = 0;
+- uint16_t throughable_mask = 0;
+ uint16_t old_data = cfg_entry->data;
+ uint32_t flags = ptdev->msi->flags;
+ uint32_t offset = reg->offset;
+@@ -4062,8 +4053,7 @@ static int pt_msgdata_reg_write(struct p
+ ptdev->msi->data = cfg_entry->data;
+
+ /* create value for writing to I/O device register */
+- throughable_mask = ~reg->emu_mask & valid_mask;
+- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
++ *value = PT_MERGE_VALUE(*value, dev_value, 0);
+
+ /* update MSI */
+ if (cfg_entry->data != old_data)
+@@ -4082,7 +4072,7 @@ static int pt_msixctrl_reg_write(struct
+ {
+ struct pt_reg_info_tbl *reg = cfg_entry->reg;
+ uint16_t writable_mask = 0;
+- uint16_t throughable_mask = 0;
++ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask);
+ uint16_t old_ctrl = cfg_entry->data;
+
+ /* modify emulate register */
+@@ -4090,7 +4080,6 @@ static int pt_msixctrl_reg_write(struct
+ 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 = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
+
+ /* update MSI-X */