Use new rom loading infrastructure. Devices can simply register option roms now. Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx> --- hw/device-assignment.c | 144 ++++++++++++++++++++--------------------------- hw/device-assignment.h | 1 - hw/pc.c | 3 - 3 files changed, 61 insertions(+), 87 deletions(-) diff --git a/hw/device-assignment.c b/hw/device-assignment.c index 237060f..6f792db 100644 --- a/hw/device-assignment.c +++ b/hw/device-assignment.c @@ -37,6 +37,7 @@ #include "sysemu.h" #include "console.h" #include "device-assignment.h" +#include "loader.h" /* From linux/ioport.h */ #define IORESOURCE_IO 0x00000100 /* Resource type */ @@ -56,6 +57,8 @@ #define DEBUG(fmt, ...) do { } while(0) #endif +static void assigned_dev_load_option_rom(AssignedDevice *dev); + static uint32_t guest_to_host_ioport(AssignedDevRegion *region, uint32_t addr) { return region->u.r_baseport + (addr - region->e_physbase); @@ -1168,6 +1171,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev) if (assigned_dev_register_msix_mmio(dev)) goto assigned_out; + assigned_dev_load_option_rom(dev); return 0; assigned_out: @@ -1329,11 +1333,10 @@ struct option_rom_pci_header { * both 2KB and target page size. */ #define OPTION_ROM_ALIGN(x) (((x) + 2047) & ~2047) -static int scan_option_rom(uint8_t devfn, void *roms, ram_addr_t offset) +static void scan_option_rom(const char *name, uint8_t devfn, void *roms) { - int i, size, total_size; + int i, size; uint8_t csum; - ram_addr_t addr; struct option_rom_header *rom; struct option_rom_pci_header *pcih; @@ -1362,29 +1365,12 @@ static int scan_option_rom(uint8_t devfn, void *roms, ram_addr_t offset) rom = (struct option_rom_header *)((char *)rom + size); } - - return 0; + return; found: - /* The size should be both 2K-aligned and page-aligned */ - total_size = (TARGET_PAGE_SIZE < 2048) - ? OPTION_ROM_ALIGN(size + 1) - : TARGET_PAGE_ALIGN(size + 1); - - /* Size of all available ram space is 0x10000 (0xd0000 to 0xe0000) */ - if ((offset + total_size) > 0x10000u) { - fprintf(stderr, "Option ROM size %x exceeds available space\n", size); - return 0; - } - - addr = qemu_ram_alloc(total_size); - cpu_register_physical_memory(0xd0000 + offset, total_size, addr | IO_MEM_ROM); - - /* Write ROM data and devfn to phys_addr */ - cpu_physical_memory_write_rom(0xd0000 + offset, (uint8_t *)rom, size); - cpu_physical_memory_write_rom(0xd0000 + offset + size, &devfn, 1); - - return total_size; + rom_add_blob(name ? name : "assigned device", rom, size, + PC_ROM_MIN_OPTION, PC_ROM_MAX, PC_ROM_ALIGN); + return; } /* @@ -1392,75 +1378,67 @@ static int scan_option_rom(uint8_t devfn, void *roms, ram_addr_t offset) * load the corresponding ROM data to RAM. If an error occurs while loading an * option ROM, we just ignore that option ROM and continue with the next one. */ -ram_addr_t assigned_dev_load_option_roms(ram_addr_t rom_base_offset) +static void assigned_dev_load_option_rom(AssignedDevice *dev) { - ram_addr_t offset = rom_base_offset; - AssignedDevice *dev; - - QLIST_FOREACH(dev, &devs, next) { - int size, len; - void *buf; - FILE *fp; - uint8_t i = 1; - char rom_file[64]; + int size, len; + void *buf; + FILE *fp; + uint8_t i = 1; + char rom_file[64]; - snprintf(rom_file, sizeof(rom_file), - "/sys/bus/pci/devices/0000:%02x:%02x.%01x/rom", - dev->host.bus, dev->host.dev, dev->host.func); + snprintf(rom_file, sizeof(rom_file), + "/sys/bus/pci/devices/0000:%02x:%02x.%01x/rom", + dev->host.bus, dev->host.dev, dev->host.func); - if (access(rom_file, F_OK)) - continue; - - /* Write something to the ROM file to enable it */ - fp = fopen(rom_file, "wb"); - if (fp == NULL) - continue; - len = fwrite(&i, 1, 1, fp); - fclose(fp); - if (len != 1) - continue; - - /* The file has to be closed and reopened, otherwise it won't work */ - fp = fopen(rom_file, "rb"); - if (fp == NULL) - continue; + if (access(rom_file, F_OK)) + return; - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); + /* Write something to the ROM file to enable it */ + fp = fopen(rom_file, "wb"); + if (fp == NULL) + return; + len = fwrite(&i, 1, 1, fp); + fclose(fp); + if (len != 1) + return; - buf = malloc(size); - if (buf == NULL) { - fclose(fp); - continue; - } + /* The file has to be closed and reopened, otherwise it won't work */ + fp = fopen(rom_file, "rb"); + if (fp == NULL) + return; - fread(buf, size, 1, fp); - if (!feof(fp) || ferror(fp)) { - free(buf); - fclose(fp); - continue; - } + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); - /* Copy ROM contents into the space backing the ROM BAR */ - if (dev->v_addrs[PCI_ROM_SLOT].r_size >= size && - dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase) { - mprotect(dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase, - size, PROT_READ | PROT_WRITE); - memcpy(dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase, - buf, size); - mprotect(dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase, - size, PROT_READ); - } - - if (!dev->dev.qdev.hotplugged) { - /* Scan the buffer for suitable ROMs and increase the offset */ - offset += scan_option_rom(dev->dev.devfn, buf, offset); - } + buf = malloc(size); + if (buf == NULL) { + fclose(fp); + return; + } + fread(buf, size, 1, fp); + if (!feof(fp) || ferror(fp)) { free(buf); fclose(fp); + return; + } + fclose(fp); + + /* Copy ROM contents into the space backing the ROM BAR */ + if (dev->v_addrs[PCI_ROM_SLOT].r_size >= size && + dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase) { + mprotect(dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase, + size, PROT_READ | PROT_WRITE); + memcpy(dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase, + buf, size); + mprotect(dev->v_addrs[PCI_ROM_SLOT].u.r_virtbase, + size, PROT_READ); } - return offset; + if (!dev->dev.qdev.hotplugged) { + /* Scan the buffer for suitable ROMs and increase the offset */ + scan_option_rom(dev->dev.qdev.id, dev->dev.devfn, buf); + } + free(buf); } diff --git a/hw/device-assignment.h b/hw/device-assignment.h index ef92474..31696ba 100644 --- a/hw/device-assignment.h +++ b/hw/device-assignment.h @@ -107,7 +107,6 @@ typedef struct AssignedDevice { QemuOpts *add_assigned_device(const char *arg); void add_assigned_devices(PCIBus *bus, const char **devices, int n_devices); -ram_addr_t assigned_dev_load_option_roms(ram_addr_t rom_base_offset); void assigned_dev_update_irqs(void); #define MAX_DEV_ASSIGN_CMDLINE 8 diff --git a/hw/pc.c b/hw/pc.c index a72cced..b4c7ac5 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1364,9 +1364,6 @@ static void pc_init1(ram_addr_t ram_size, #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT if (kvm_enabled()) { add_assigned_devices(pci_bus, assigned_devices, assigned_devices_index); -#ifdef FIXME /* pci_option_rom_offset */ - assigned_dev_load_option_roms(pci_option_rom_offset); -#endif } #endif /* CONFIG_KVM_DEVICE_ASSIGNMENT */ } -- 1.6.2.5 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html