All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Williamson <alex.williamson@hp.com>
To: kvm@vger.kernel.org, sheng@linux.intel.com
Cc: alex.williamson@hp.com
Subject: [PATCH 2/2] kvm: device-assignment: Add PCI option ROM support
Date: Wed, 06 May 2009 09:49:01 -0600	[thread overview]
Message-ID: <20090506154901.17937.49152.stgit@dl380g6-3.ned.telco.ned.telco> (raw)
In-Reply-To: <20090506154850.17937.95258.stgit@dl380g6-3.ned.telco.ned.telco>

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.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
---

 hw/device-assignment.c |   59 ++++++++++++++++++++++++++++++++++++------------
 hw/device-assignment.h |    5 +---
 2 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 0a5f850..a7365c8 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;
 
@@ -1391,6 +1410,16 @@ ram_addr_t assigned_dev_load_option_roms(ram_addr_t rom_base_offset)
             continue;
         }
 
+        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;
 


      parent reply	other threads:[~2009-05-06 15:48 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-06 15:48 [PATCH 0/2] device-assignment: option ROM support Alex Williamson
2009-05-06 15:48 ` [PATCH 1/2] kvm: bios: Use a different mask to size the option ROM BAR Alex Williamson
2009-05-07 12:10   ` Avi Kivity
2009-05-06 15:49 ` Alex Williamson [this message]

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=20090506154901.17937.49152.stgit@dl380g6-3.ned.telco.ned.telco \
    --to=alex.williamson@hp.com \
    --cc=kvm@vger.kernel.org \
    --cc=sheng@linux.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.