[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [qemu-xen-4.3-testing] xen/pt: split out calculation of throughable mask in PCI config space handling



commit 8599757a0a68333eca419e20561eaf49ab1f24e2
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Wed Jun 10 14:14:25 2015 +0100
Commit:     Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
CommitDate: Wed Jun 10 14:14:25 2015 +0100

    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@xxxxxxxx>
    Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
    Reviewed-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
 hw/pass-through.c |   59 +++++++++++++++++++++-------------------------------
 1 files changed, 24 insertions(+), 35 deletions(-)

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 7d4ef0e..9ec9211 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -3440,6 +3440,15 @@ static int pt_bar_reg_read(struct pt_dev *ptdev,
 }
 
 
+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,
@@ -3447,14 +3456,13 @@ static int pt_byte_reg_write(struct pt_dev *ptdev,
 {
     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;
@@ -3467,14 +3475,13 @@ static int pt_word_reg_write(struct pt_dev *ptdev,
 {
     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;
@@ -3487,14 +3494,13 @@ static int pt_long_reg_write(struct pt_dev *ptdev,
 {
     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;
@@ -3507,7 +3513,7 @@ static int pt_cmd_reg_write(struct pt_dev *ptdev,
 {
     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 */
@@ -3515,8 +3521,6 @@ static int pt_cmd_reg_write(struct pt_dev *ptdev,
     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)
@@ -3562,7 +3566,6 @@ static int pt_bar_reg_write(struct pt_dev *ptdev,
     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;
@@ -3689,8 +3692,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 = 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);
@@ -3717,9 +3719,8 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev,
     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];
@@ -3729,7 +3730,6 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev,
     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 */
@@ -3749,7 +3749,6 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev,
         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*/
@@ -3774,7 +3773,7 @@ static int pt_pmcsr_reg_write(struct pt_dev *ptdev,
     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;
 
@@ -3783,7 +3782,6 @@ static int pt_pmcsr_reg_write(struct pt_dev *ptdev,
     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);
 
@@ -3892,7 +3890,7 @@ static int pt_msgctrl_reg_write(struct pt_dev *ptdev,
 {
     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;
@@ -3904,8 +3902,10 @@ static int pt_msgctrl_reg_write(struct pt_dev *ptdev,
     /* 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 &
@@ -3913,10 +3913,6 @@ static int pt_msgctrl_reg_write(struct pt_dev *ptdev,
 
     /* 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 */
@@ -3970,7 +3966,6 @@ static int pt_msgaddr32_reg_write(struct pt_dev *ptdev,
 {
     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 */
@@ -3980,8 +3975,7 @@ static int pt_msgaddr32_reg_write(struct pt_dev *ptdev,
     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)
@@ -4000,7 +3994,6 @@ static int pt_msgaddr64_reg_write(struct pt_dev *ptdev,
 {
     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 */
@@ -4018,8 +4011,7 @@ static int pt_msgaddr64_reg_write(struct pt_dev *ptdev,
     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)
@@ -4039,7 +4031,6 @@ static int pt_msgdata_reg_write(struct pt_dev *ptdev,
 {
     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;
@@ -4060,8 +4051,7 @@ static int pt_msgdata_reg_write(struct pt_dev *ptdev,
     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)
@@ -4080,7 +4070,7 @@ static int pt_msixctrl_reg_write(struct pt_dev *ptdev,
 {
     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 */
@@ -4088,7 +4078,6 @@ static int pt_msixctrl_reg_write(struct pt_dev *ptdev,
     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 */
--
generated by git-patchbot for /home/xen/git/qemu-xen-4.3-testing.git

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.