8000 xen-pciback: return proper values during BAR sizing · bsd-unix/linux@d2bd05d · GitHub
[go: up one dir, main page]

Skip to content

Commit d2bd05d

Browse files
jbeulichDavid Vrabel
authored andcommitted
xen-pciback: return proper values during BAR sizing
Reads following writes with all address bits set to 1 should return all changeable address bits as one, not the BAR size (nor, as was the case for the upper half of 64-bit BARs, the high half of the region's end address). Presumably this didn't cause any problems so far because consumers use the value to calculate the size (usually via val & -val), and do nothing else with it. But also consider the exception here: Unimplemented BARs should always return all zeroes. And finally, the check for whether to return the sizing address on read for the ROM BAR should ignore all non-address bits, not just the ROM Enable one. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
1 parent d6b186c commit d2bd05d

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

drivers/xen/xen-pciback/conf_space_header.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
145145
/* A write to obtain the length must happen as a 32-bit write.
146146
* This does not (yet) support writing individual bytes
147147
*/
148-
if (value == ~PCI_ROM_ADDRESS_ENABLE)
148+
if ((value | ~PCI_ROM_ADDRESS_MASK) == ~0U)
149149
bar->which = 1;
150150
else {
151151
u32 tmpval;
@@ -225,38 +225,42 @@ static inline void read_dev_bar(struct pci_dev *dev,
225225
(PCI_BASE_ADDRESS_SPACE_MEMORY |
226226
PCI_BASE_ADDRESS_MEM_TYPE_64))) {
227227
bar_info->val = res[pos - 1].start >> 32;
228-
bar_info->len_val = res[pos - 1].end >> 32;
228+
bar_info->len_val = -resource_size(&res[pos - 1]) >> 32;
229229
return;
230230
}
231231
}
232232

233+
if (!res[pos].flags ||
234+
(res[pos].flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET |
235+
IORESOURCE_BUSY)))
236+
return;
237+
233238
bar_info->val = res[pos].start |
234239
(res[pos].flags & PCI_REGION_FLAG_MASK);
235-
bar_info->len_val = resource_size(&res[pos]);
240+
bar_info->len_val = -resource_size(&res[pos]) |
241+
(res[pos].flags & PCI_REGION_FLAG_MASK);
236242
}
237243

238244
static void *bar_init(struct pci_dev *dev, int offset)
239245
{
240-
struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
246+
struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
241247

242248
if (!bar)
243249
return ERR_PTR(-ENOMEM);
244250

245251
read_dev_bar(dev, bar, offset, ~0);
246-
bar->which = 0;
247252

248253
return bar;
249254
}
250255

251256
static void *rom_init(struct pci_dev *dev, int offset)
252257
{
253-
struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
258+
struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
254259

255260
if (!bar)
256261
return ERR_PTR(-ENOMEM);
257262

258263
read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
259-
bar->which = 0;
260264

261265
return bar;
262266
}

0 commit comments

Comments
 (0)
0