1 Upstream-Status: Backport
3 Signed-off-by: Kai Kang <kai.kang@windriver.com>
5 From 0e7ef22136955169a0fd03c4e41af95662352733 Mon Sep 17 00:00:00 2001
6 From: Jan Beulich <jbeulich@suse.com>
7 Date: Tue, 2 Jun 2015 15:07:01 +0000
8 Subject: xen/pt: split out calculation of throughable mask in
9 PCI config space handling
10 Bug-Debian: http://bugs.debian.org/787547
12 This is just to avoid having to adjust that calculation later in
15 Note that including ->ro_mask in get_throughable_mask()'s calculation
16 is only an apparent (i.e. benign) behavioral change: For r/o fields it
17 doesn't matter > whether they get passed through - either the same flag
18 is also set in emu_mask (then there's no change at all) or the field is
19 r/o in hardware (and hence a write won't change it anyway).
21 This is a preparatory patch for XSA-131.
23 Signed-off-by: Jan Beulich <jbeulich@suse.com>
24 Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
25 Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
27 hw/xen/xen_pt_config_init.c | 51 ++++++++++++++++++---------------------------
28 1 file changed, 20 insertions(+), 31 deletions(-)
30 diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
31 index 027ac32..3833b9e 100644
32 --- a/hw/xen/xen_pt_config_init.c
33 +++ b/hw/xen/xen_pt_config_init.c
34 @@ -95,6 +95,14 @@ XenPTReg *xen_pt_find_reg(XenPTRegGroup *reg_grp, uint32_t address)
38 +static uint32_t get_throughable_mask(const XenPCIPassthroughState *s,
39 + const XenPTRegInfo *reg,
40 + uint32_t valid_mask)
42 + uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask);
44 + return throughable_mask & valid_mask;
48 * general register functions
49 @@ -157,14 +165,13 @@ static int xen_pt_byte_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
51 XenPTRegInfo *reg = cfg_entry->reg;
52 uint8_t writable_mask = 0;
53 - uint8_t throughable_mask = 0;
54 + uint8_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
56 /* modify emulate register */
57 writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
58 cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
60 /* create value for writing to I/O device register */
61 - throughable_mask = ~reg->emu_mask & valid_mask;
62 *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
65 @@ -175,14 +182,13 @@ static int xen_pt_word_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
67 XenPTRegInfo *reg = cfg_entry->reg;
68 uint16_t writable_mask = 0;
69 - uint16_t throughable_mask = 0;
70 + uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
72 /* modify emulate register */
73 writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
74 cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
76 /* create value for writing to I/O device register */
77 - throughable_mask = ~reg->emu_mask & valid_mask;
78 *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
81 @@ -193,14 +199,13 @@ static int xen_pt_long_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
83 XenPTRegInfo *reg = cfg_entry->reg;
84 uint32_t writable_mask = 0;
85 - uint32_t throughable_mask = 0;
86 + uint32_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
88 /* modify emulate register */
89 writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
90 cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
92 /* create value for writing to I/O device register */
93 - throughable_mask = ~reg->emu_mask & valid_mask;
94 *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
97 @@ -292,15 +297,13 @@ static int xen_pt_cmd_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
99 XenPTRegInfo *reg = cfg_entry->reg;
100 uint16_t writable_mask = 0;
101 - uint16_t throughable_mask = 0;
102 + uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
104 /* modify emulate register */
105 writable_mask = ~reg->ro_mask & valid_mask;
106 cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
108 /* create value for writing to I/O device register */
109 - throughable_mask = ~reg->emu_mask & valid_mask;
111 if (*val & PCI_COMMAND_INTX_DISABLE) {
112 throughable_mask |= PCI_COMMAND_INTX_DISABLE;
114 @@ -454,7 +457,6 @@ static int xen_pt_bar_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
115 PCIDevice *d = &s->dev;
116 const PCIIORegion *r;
117 uint32_t writable_mask = 0;
118 - uint32_t throughable_mask = 0;
119 uint32_t bar_emu_mask = 0;
120 uint32_t bar_ro_mask = 0;
122 @@ -511,8 +513,7 @@ static int xen_pt_bar_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
125 /* create value for writing to I/O device register */
126 - throughable_mask = ~bar_emu_mask & valid_mask;
127 - *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
128 + *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0);
132 @@ -526,9 +527,8 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
133 XenPTRegion *base = NULL;
134 PCIDevice *d = (PCIDevice *)&s->dev;
135 uint32_t writable_mask = 0;
136 - uint32_t throughable_mask = 0;
137 + uint32_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
139 - uint32_t bar_emu_mask = 0;
140 uint32_t bar_ro_mask = 0;
142 r_size = d->io_regions[PCI_ROM_SLOT].size;
143 @@ -537,7 +537,6 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
144 r_size = xen_pt_get_emul_size(base->bar_flag, r_size);
146 /* set emulate mask and read-only mask */
147 - bar_emu_mask = reg->emu_mask;
148 bar_ro_mask = (reg->ro_mask | (r_size - 1)) & ~PCI_ROM_ADDRESS_ENABLE;
150 /* modify emulate register */
151 @@ -545,7 +544,6 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
152 cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
154 /* create value for writing to I/O device register */
155 - throughable_mask = ~bar_emu_mask & valid_mask;
156 *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
159 @@ -940,14 +938,13 @@ static int xen_pt_pmcsr_reg_write(XenPCIPassthroughState *s,
161 XenPTRegInfo *reg = cfg_entry->reg;
162 uint16_t writable_mask = 0;
163 - uint16_t throughable_mask = 0;
164 + uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
166 /* modify emulate register */
167 writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
168 cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
170 /* create value for writing to I/O device register */
171 - throughable_mask = ~reg->emu_mask & valid_mask;
172 *val = XEN_PT_MERGE_VALUE(*val, dev_value & ~PCI_PM_CTRL_PME_STATUS,
175 @@ -1036,7 +1033,7 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,
176 XenPTRegInfo *reg = cfg_entry->reg;
177 XenPTMSI *msi = s->msi;
178 uint16_t writable_mask = 0;
179 - uint16_t throughable_mask = 0;
180 + uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
182 /* Currently no support for multi-vector */
183 if (*val & PCI_MSI_FLAGS_QSIZE) {
184 @@ -1049,7 +1046,6 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,
185 msi->flags |= cfg_entry->data & ~PCI_MSI_FLAGS_ENABLE;
187 /* create value for writing to I/O device register */
188 - throughable_mask = ~reg->emu_mask & valid_mask;
189 *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
192 @@ -1161,7 +1157,6 @@ static int xen_pt_msgaddr32_reg_write(XenPCIPassthroughState *s,
194 XenPTRegInfo *reg = cfg_entry->reg;
195 uint32_t writable_mask = 0;
196 - uint32_t throughable_mask = 0;
197 uint32_t old_addr = cfg_entry->data;
199 /* modify emulate register */
200 @@ -1170,8 +1165,7 @@ static int xen_pt_msgaddr32_reg_write(XenPCIPassthroughState *s,
201 s->msi->addr_lo = cfg_entry->data;
203 /* create value for writing to I/O device register */
204 - throughable_mask = ~reg->emu_mask & valid_mask;
205 - *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
206 + *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0);
209 if (cfg_entry->data != old_addr) {
210 @@ -1189,7 +1183,6 @@ static int xen_pt_msgaddr64_reg_write(XenPCIPassthroughState *s,
212 XenPTRegInfo *reg = cfg_entry->reg;
213 uint32_t writable_mask = 0;
214 - uint32_t throughable_mask = 0;
215 uint32_t old_addr = cfg_entry->data;
217 /* check whether the type is 64 bit or not */
218 @@ -1206,8 +1199,7 @@ static int xen_pt_msgaddr64_reg_write(XenPCIPassthroughState *s,
219 s->msi->addr_hi = cfg_entry->data;
221 /* create value for writing to I/O device register */
222 - throughable_mask = ~reg->emu_mask & valid_mask;
223 - *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
224 + *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0);
227 if (cfg_entry->data != old_addr) {
228 @@ -1229,7 +1221,6 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s,
229 XenPTRegInfo *reg = cfg_entry->reg;
230 XenPTMSI *msi = s->msi;
231 uint16_t writable_mask = 0;
232 - uint16_t throughable_mask = 0;
233 uint16_t old_data = cfg_entry->data;
234 uint32_t offset = reg->offset;
236 @@ -1247,8 +1238,7 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s,
237 msi->data = cfg_entry->data;
239 /* create value for writing to I/O device register */
240 - throughable_mask = ~reg->emu_mask & valid_mask;
241 - *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
242 + *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0);
245 if (cfg_entry->data != old_data) {
246 @@ -1410,7 +1400,7 @@ static int xen_pt_msixctrl_reg_write(XenPCIPassthroughState *s,
248 XenPTRegInfo *reg = cfg_entry->reg;
249 uint16_t writable_mask = 0;
250 - uint16_t throughable_mask = 0;
251 + uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
252 int debug_msix_enabled_old;
254 /* modify emulate register */
255 @@ -1418,7 +1408,6 @@ static int xen_pt_msixctrl_reg_write(XenPCIPassthroughState *s,
256 cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
258 /* create value for writing to I/O device register */
259 - throughable_mask = ~reg->emu_mask & valid_mask;
260 *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);