Skip to content

Commit 15d2974

Browse files
authored
Merge pull request #48 from sysprog21/fix-pci-bar
Preserve full BAR layout across guest sizing
2 parents 20bf18f + 833b3d0 commit 15d2974

3 files changed

Lines changed: 22 additions & 12 deletions

File tree

src/pci.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ static void pci_command_bar(struct pci_dev *dev)
5252
bool enable_mem =
5353
PCI_HDR_READ(dev->hdr, PCI_COMMAND, 16) & PCI_COMMAND_MEMORY;
5454
for (int i = 0; i < PCI_STD_NUM_BARS; i++) {
55-
struct bus *bus = dev->bar_is_io_space[i] ? dev->io_bus : dev->mmio_bus;
56-
bool enable = dev->bar_is_io_space[i] ? enable_io : enable_mem;
55+
bool is_io = dev->bar_layout[i] & PCI_BASE_ADDRESS_SPACE_IO;
56+
struct bus *bus = is_io ? dev->io_bus : dev->mmio_bus;
57+
bool enable = is_io ? enable_io : enable_mem;
5758

5859
if (enable)
5960
pci_activate_bar(dev, i, bus);
@@ -71,9 +72,9 @@ static void pci_config_bar(struct pci_dev *dev, uint8_t bar)
7172
{
7273
uint32_t mask = ~(dev->bar_size[bar] - 1);
7374
uint32_t old_bar = PCI_HDR_READ(dev->hdr, PCI_BAR_OFFSET(bar), 32);
74-
uint32_t new_bar = (old_bar & mask) | dev->bar_is_io_space[bar];
75+
uint32_t new_bar = (old_bar & mask) | (dev->bar_layout[bar] & ~mask);
7576
PCI_HDR_WRITE(dev->hdr, PCI_BAR_OFFSET(bar), new_bar, 32);
76-
dev->space_dev[bar].base = new_bar;
77+
dev->space_dev[bar].base = new_bar & mask;
7778
}
7879

7980
static void pci_config_write(struct pci_dev *dev,
@@ -145,14 +146,17 @@ static void pci_mmio_io(void *owner,
145146
void pci_set_bar(struct pci_dev *dev,
146147
uint8_t bar,
147148
uint32_t bar_size,
148-
bool is_io_space,
149+
uint32_t layout,
149150
dev_io_fn do_io)
150151
{
151-
/* TODO: mem type, prefetch */
152-
/* FIXME: bar_size must be power of 2 */
153-
PCI_HDR_WRITE(dev->hdr, PCI_BAR_OFFSET(bar), is_io_space, 32);
152+
/*
153+
* FIXME: bar_size must be a power of two.
154+
* TODO: 64-bit BARs need a second adjacent slot for the upper dword;
155+
* only 32-bit memory and I/O BARs are wired up here.
156+
*/
157+
PCI_HDR_WRITE(dev->hdr, PCI_BAR_OFFSET(bar), layout, 32);
154158
dev->bar_size[bar] = bar_size;
155-
dev->bar_is_io_space[bar] = is_io_space;
159+
dev->bar_layout[bar] = layout;
156160
dev_init(&dev->space_dev[bar], 0, bar_size, dev, do_io);
157161
}
158162

src/pci.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct pci_dev {
3030
void *hdr;
3131
uint32_t bar_size[6];
3232
bool bar_active[6];
33-
bool bar_is_io_space[6];
33+
uint32_t bar_layout[6];
3434
struct dev space_dev[6];
3535
struct dev config_dev;
3636
struct bus *io_bus;
@@ -46,10 +46,15 @@ struct pci {
4646
struct dev pci_mmio_dev;
4747
};
4848

49+
/*
50+
* Configure a PCI BAR. @layout is a bitmask of PCI_BASE_ADDRESS_* flags
51+
* from <linux/pci_regs.h> (space, mem type, prefetch). The non-address
52+
* bits are preserved across guest BAR sizing probes.
53+
*/
4954
void pci_set_bar(struct pci_dev *dev,
5055
uint8_t bar,
5156
uint32_t bar_size,
52-
bool is_io_space,
57+
uint32_t layout,
5358
dev_io_fn do_io);
5459
void pci_set_status(struct pci_dev *dev, uint16_t status);
5560
void pci_dev_register(struct pci_dev *dev);

src/virtio-pci.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,8 @@ void virtio_pci_init(struct virtio_pci_dev *dev,
268268
PCI_HDR_WRITE(dev->pci_dev.hdr, PCI_HEADER_TYPE, PCI_HEADER_TYPE_NORMAL, 8);
269269
PCI_HDR_WRITE(dev->pci_dev.hdr, PCI_INTERRUPT_PIN, 1, 8);
270270
pci_set_status(&dev->pci_dev, PCI_STATUS_CAP_LIST | PCI_STATUS_INTERRUPT);
271-
pci_set_bar(&dev->pci_dev, 0, 0x100, PCI_BASE_ADDRESS_SPACE_MEMORY,
271+
pci_set_bar(&dev->pci_dev, 0, 0x100,
272+
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32,
272273
virtio_pci_space_io);
273274
virtio_pci_set_cap(dev, cap_list);
274275
dev->device_feature |=

0 commit comments

Comments
 (0)