From: Alex Williamson <alex.williamson@hp.com>
To: kvm@vger.kernel.org
Cc: sheng.yang@intel.com, alex.williamson@hp.com
Subject: [PATCH] kvm: device-assignment: Add PCI option ROM support
Date: Mon, 15 Jun 2009 10:29:17 -0600 [thread overview]
Message-ID: <20090615162815.4830.38216.stgit@host.lart> (raw)
The PCI code already knows about option ROMs, so we just need to
mmap some space for it, load it with a copy of the contents, and
complete the plubming to the generic code.
With this a Linux guest can get access to the ROM contents via
/sys/bus/pci/devices/<dev>/rom. This might also enable the BIOS
to execute ROMs by loading them dynamically from the device
rather than hoping they all fit into RAM.
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
---
hw/device-assignment.c | 60 ++++++++++++++++++++++++++++++++++++------------
hw/device-assignment.h | 5 +---
2 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 65920d0..dfcd670 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -286,8 +286,8 @@ static void assigned_dev_pci_write_config(PCIDevice *d, uint32_t address,
/* Continue to program the card */
}
- if ((address >= 0x10 && address <= 0x24) || address == 0x34 ||
- address == 0x3c || address == 0x3d ||
+ if ((address >= 0x10 && address <= 0x24) || address == 0x30 ||
+ address == 0x34 || address == 0x3c || address == 0x3d ||
pci_access_cap_config(d, address, len)) {
/* used for update-mappings (BAR emulation) */
pci_default_write_config(d, address, val, len);
@@ -322,8 +322,8 @@ static uint32_t assigned_dev_pci_read_config(PCIDevice *d, uint32_t address,
AssignedDevice *pci_dev = container_of(d, AssignedDevice, dev);
if (address < 0x4 || (pci_dev->need_emulate_cmd && address == 0x4) ||
- (address >= 0x10 && address <= 0x24) || address == 0x34 ||
- address == 0x3c || address == 0x3d ||
+ (address >= 0x10 && address <= 0x24) || address == 0x30 ||
+ address == 0x34 || address == 0x3c || address == 0x3d ||
pci_access_cap_config(d, address, len)) {
val = pci_default_read_config(d, address, len);
DEBUG("(%x.%x): address=%04x val=0x%08x len=%d\n",
@@ -384,11 +384,20 @@ static int assigned_dev_register_regions(PCIRegion *io_regions,
/* map physical memory */
pci_dev->v_addrs[i].e_physbase = cur_region->base_addr;
- pci_dev->v_addrs[i].u.r_virtbase =
- mmap(NULL,
- (cur_region->size + 0xFFF) & 0xFFFFF000,
- PROT_WRITE | PROT_READ, MAP_SHARED,
- cur_region->resource_fd, (off_t) 0);
+ if (i == PCI_ROM_SLOT) {
+ pci_dev->v_addrs[i].u.r_virtbase =
+ mmap(NULL,
+ (cur_region->size + 0xFFF) & 0xFFFFF000,
+ PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE,
+ 0, (off_t) 0);
+
+ } else {
+ pci_dev->v_addrs[i].u.r_virtbase =
+ mmap(NULL,
+ (cur_region->size + 0xFFF) & 0xFFFFF000,
+ PROT_WRITE | PROT_READ, MAP_SHARED,
+ cur_region->resource_fd, (off_t) 0);
+ }
if (pci_dev->v_addrs[i].u.r_virtbase == MAP_FAILED) {
pci_dev->v_addrs[i].u.r_virtbase = NULL;
@@ -397,6 +406,14 @@ static int assigned_dev_register_regions(PCIRegion *io_regions,
(uint32_t) (cur_region->base_addr));
return -1;
}
+
+ if (i == PCI_ROM_SLOT) {
+ memset(pci_dev->v_addrs[i].u.r_virtbase, 0,
+ (cur_region->size + 0xFFF) & 0xFFFFF000);
+ mprotect(pci_dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase,
+ (cur_region->size + 0xFFF) & 0xFFFFF000, PROT_READ);
+ }
+
pci_dev->v_addrs[i].r_size = cur_region->size;
pci_dev->v_addrs[i].e_size = 0;
@@ -468,7 +485,7 @@ again:
return 1;
}
- for (r = 0; r < MAX_IO_REGIONS; r++) {
+ for (r = 0; r < PCI_NUM_REGIONS; r++) {
if (fscanf(f, "%lli %lli %lli\n", &start, &end, &flags) != 3)
break;
@@ -480,11 +497,13 @@ again:
continue;
if (flags & IORESOURCE_MEM) {
flags &= ~IORESOURCE_IO;
- snprintf(name, sizeof(name), "%sresource%d", dir, r);
- fd = open(name, O_RDWR);
- if (fd == -1)
- continue; /* probably ROM */
- rp->resource_fd = fd;
+ if (r != PCI_ROM_SLOT) {
+ snprintf(name, sizeof(name), "%sresource%d", dir, r);
+ fd = open(name, O_RDWR);
+ if (fd == -1)
+ continue;
+ rp->resource_fd = fd;
+ }
} else
flags &= ~IORESOURCE_PREFETCH;
@@ -1390,6 +1409,17 @@ ram_addr_t assigned_dev_load_option_roms(ram_addr_t rom_base_offset)
continue;
}
+ /* Copy ROM contents into the space backing the ROM BAR */
+ if (adev->assigned_dev->v_addrs[PCI_ROM_SLOT].r_size >= size &&
+ adev->assigned_dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase) {
+ mprotect(adev->assigned_dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase,
+ size, PROT_READ | PROT_WRITE);
+ memcpy(adev->assigned_dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase,
+ buf, size);
+ mprotect(adev->assigned_dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase,
+ size, PROT_READ);
+ }
+
/* Scan the buffer for suitable ROMs and increase the offset */
offset += scan_option_rom(adev->assigned_dev->dev.devfn, buf, offset);
diff --git a/hw/device-assignment.h b/hw/device-assignment.h
index c691e11..713f9b7 100644
--- a/hw/device-assignment.h
+++ b/hw/device-assignment.h
@@ -36,9 +36,6 @@
/* From include/linux/pci.h in the kernel sources */
#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
-/* The number of BARs in the config space header */
-#define MAX_IO_REGIONS (6)
-
typedef struct {
int type; /* Memory or port I/O */
int valid;
@@ -53,7 +50,7 @@ typedef struct {
uint16_t region_number; /* number of active regions */
/* Port I/O or MMIO Regions */
- PCIRegion regions[MAX_IO_REGIONS];
+ PCIRegion regions[PCI_NUM_REGIONS];
int config_fd;
} PCIDevRegions;
next reply other threads:[~2009-06-15 16:28 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-06-15 16:29 Alex Williamson [this message]
2009-06-18 5:30 ` [PATCH] kvm: device-assignment: Add PCI option ROM support Yang, Sheng
2009-06-18 16:28 ` Alex Williamson
2009-06-19 7:27 ` Yang, Sheng
2009-06-19 13:44 ` Alex Williamson
2009-06-22 5:32 ` Yang, Sheng
2009-06-22 16:09 ` Alex Williamson
2009-06-23 1:25 ` Yang, Sheng
2009-06-22 8:38 ` Avi Kivity
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090615162815.4830.38216.stgit@host.lart \
--to=alex.williamson@hp.com \
--cc=kvm@vger.kernel.org \
--cc=sheng.yang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.