From patchwork Fri Oct 8 15:12:52 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 241511 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o98FCAsj010023 for ; Fri, 8 Oct 2010 15:14:45 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758697Ab0JHPMz (ORCPT ); Fri, 8 Oct 2010 11:12:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52957 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754788Ab0JHPMy (ORCPT ); Fri, 8 Oct 2010 11:12:54 -0400 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o98FCsJQ020345 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 8 Oct 2010 11:12:54 -0400 Received: from [10.3.113.94] (ovpn-113-94.phx2.redhat.com [10.3.113.94]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o98FCrYP014006; Fri, 8 Oct 2010 11:12:53 -0400 Subject: Re: [PATCH 2/2] device-assignment: Allow PCI to manage the option ROM From: Alex Williamson To: "Michael S. Tsirkin" Cc: kvm@vger.kernel.org, ddutile@redhat.com, chrisw@redhat.com In-Reply-To: <20101008084033.GA6927@redhat.com> References: <20101004212311.11167.40425.stgit@s20.home> <20101004212630.11167.93029.stgit@s20.home> <20101007171858.GA15537@redhat.com> <1286472841.3020.56.camel@x201> <20101007224523.GB20504@redhat.com> <1286510545.3016.36.camel@x201> <20101008084033.GA6927@redhat.com> Date: Fri, 08 Oct 2010 09:12:52 -0600 Message-ID: <1286550772.3016.49.camel@x201> Mime-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 08 Oct 2010 15:14:46 +0000 (UTC) diff --git a/hw/device-assignment.c b/hw/device-assignment.c index 26cb797..94561ef 100644 --- a/hw/device-assignment.c +++ b/hw/device-assignment.c @@ -1622,6 +1622,7 @@ void add_assigned_devices(PCIBus *bus, const char **devices, int n_devices) static void assigned_dev_load_option_rom(AssignedDevice *dev) { char name[32], rom_file[64]; + size_t size; FILE *fp; uint8_t val; struct stat st; @@ -1654,20 +1655,23 @@ static void assigned_dev_load_option_rom(AssignedDevice *dev) if (fwrite(&val, 1, 1, fp) != 1) { goto close_rom; } + + fseek(fp, 0, SEEK_END); + size = ftell(fp); fseek(fp, 0, SEEK_SET); snprintf(name, sizeof(name), "%s.rom", dev->dev.qdev.info->name); - dev->dev.rom_offset = qemu_ram_alloc(&dev->dev.qdev, name, st.st_size); + dev->dev.rom_offset = qemu_ram_alloc(&dev->dev.qdev, name, size); + dev->dev.rom_size = size; ptr = qemu_get_ram_ptr(dev->dev.rom_offset); - memset(ptr, 0xff, st.st_size); - if (!fread(ptr, 1, st.st_size, fp)) { + if (!fread(ptr, 1, size, fp)) { fprintf(stderr, "pci-assign: Cannot read from host %s\n" "\tDevice option ROM contents are probably invalid " "(check dmesg).\n\tSkip option ROM probe with rombar=0, " "or load from file with romfile=\n", rom_file); qemu_ram_free(dev->dev.rom_offset); - dev->dev.rom_offset = 0; + dev->dev.rom_offset = dev->dev.rom_size = 0; goto close_rom; } diff --git a/hw/pci.c b/hw/pci.c index 07e9661..bd15eb7 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1973,9 +1973,49 @@ static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id, return next; } -void pci_map_option_rom(PCIDevice *pdev, int region_num, pcibus_t addr, pcibus_t size, int type) +static uint32_t rom_readb(void *opaque, target_phys_addr_t addr) { - cpu_register_physical_memory(addr, size, pdev->rom_offset); + PCIDevice *pdev = opaque; + + if (addr > pdev->rom_size) + return 0xff; + + return *(uint8_t *)qemu_get_ram_ptr(pdev->rom_offset + addr); +} + +static uint32_t rom_readw(void *opaque, target_phys_addr_t addr) +{ + PCIDevice *pdev = opaque; + + if (addr > pdev->rom_size) + return 0xffff; + + return *(uint16_t *)qemu_get_ram_ptr(pdev->rom_offset + addr); +} + +static uint32_t rom_readl(void *opaque, target_phys_addr_t addr) +{ + PCIDevice *pdev = opaque; + + if (addr > pdev->rom_size) + return 0xffffffff; + + return *(uint32_t *)qemu_get_ram_ptr(pdev->rom_offset + addr); +} + +static CPUReadMemoryFunc * const rom_reads[] = { + &rom_readb, &rom_readw, &rom_readl +}; + +static CPUWriteMemoryFunc * const rom_writes[] = { NULL, NULL, NULL }; + +void pci_map_option_rom(PCIDevice *pdev, int region_num, pcibus_t addr, + pcibus_t size, int type) +{ + int m; + + m = cpu_register_io_memory(rom_reads, rom_writes, pdev); + cpu_register_physical_memory(addr, size, m); } /* Add an option rom for the device */ @@ -2016,9 +2056,7 @@ static int pci_add_option_rom(PCIDevice *pdev) __FUNCTION__, pdev->romfile); return -1; } - if (size & (size - 1)) { - size = 1 << qemu_fls(size); - } + pdev->rom_size = size; if (pdev->qdev.info->vmsd) snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->vmsd->name); @@ -2030,6 +2068,11 @@ static int pci_add_option_rom(PCIDevice *pdev) load_image(path, ptr); qemu_free(path); + /* Round up size for the BAR */ + if (size & (size - 1)) { + size = 1 << qemu_fls(size); + } + pci_register_bar(pdev, PCI_ROM_SLOT, size, 0, pci_map_option_rom); @@ -2042,7 +2085,7 @@ static void pci_del_option_rom(PCIDevice *pdev) return; qemu_ram_free(pdev->rom_offset); - pdev->rom_offset = 0; + pdev->rom_offset = pdev->rom_size = 0; } /* Reserve space and add capability to the linked list in pci config space */ diff --git a/hw/pci.h b/hw/pci.h index 9ee8db3..ed87b1a 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -187,6 +187,7 @@ struct PCIDevice { /* Location of option rom */ char *romfile; ram_addr_t rom_offset; + size_t rom_size; uint32_t rom_bar; /* How much space does an MSIX table need. */