From patchwork Mon Jan 19 09:28:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tiejun Chen X-Patchwork-Id: 430362 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 06CAE1402B5 for ; Mon, 19 Jan 2015 20:32:58 +1100 (AEDT) Received: from localhost ([::1]:36308 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YD8hc-0000kg-5x for incoming@patchwork.ozlabs.org; Mon, 19 Jan 2015 04:32:56 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50450) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YD8gs-0007qK-7B for qemu-devel@nongnu.org; Mon, 19 Jan 2015 04:32:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YD8gl-0004Fy-P4 for qemu-devel@nongnu.org; Mon, 19 Jan 2015 04:32:10 -0500 Received: from mga01.intel.com ([192.55.52.88]:7128) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YD8gl-0004DN-EN for qemu-devel@nongnu.org; Mon, 19 Jan 2015 04:32:03 -0500 Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga101.fm.intel.com with ESMTP; 19 Jan 2015 01:32:02 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,425,1418112000"; d="scan'208";a="514206577" Received: from tchen0-linux.bj.intel.com ([10.238.154.91]) by orsmga003.jf.intel.com with ESMTP; 19 Jan 2015 01:25:29 -0800 From: Tiejun Chen To: mst@redhat.com, pbonzini@redhat.com, aliguori@amazon.com, rth@twiddle.net Date: Mon, 19 Jan 2015 17:28:37 +0800 Message-Id: <1421659723-2496-5-git-send-email-tiejun.chen@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1421659723-2496-1-git-send-email-tiejun.chen@intel.com> References: <1421659723-2496-1-git-send-email-tiejun.chen@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 192.55.52.88 Cc: yang.z.zhang@intel.com, allen.m.kay@intel.com, qemu-devel@nongnu.org Subject: [Qemu-devel] [v6][PATCH 04/10] hw/pci-assign: split pci-assign.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org We will try to reuse assign_dev_load_option_rom in xen side, and especially its a good beginning to unify pci assign codes both on kvm and xen in the future. Signed-off-by: Tiejun Chen --- hw/i386/Makefile.objs | 1 + hw/i386/kvm/pci-assign.c | 82 ++++---------------------------------- hw/i386/pci-assign-load-rom.c | 93 +++++++++++++++++++++++++++++++++++++++++++ include/hw/pci/pci-assign.h | 27 +++++++++++++ 4 files changed, 128 insertions(+), 75 deletions(-) create mode 100644 hw/i386/pci-assign-load-rom.c create mode 100644 include/hw/pci/pci-assign.h diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 9d419ad..195afc0 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -8,6 +8,7 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-y += kvmvapic.o obj-y += acpi-build.o obj-y += bios-linker-loader.o +obj-y += pci-assign-load-rom.o hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \ hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \ hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \ diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index bb206da..2e715b2 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -37,6 +37,7 @@ #include "hw/pci/pci.h" #include "hw/pci/msi.h" #include "kvm_i386.h" +#include "hw/pci/pci-assign.h" #define MSIX_PAGE_SIZE 0x1000 @@ -48,17 +49,6 @@ #define IORESOURCE_PREFETCH 0x00002000 /* No side effects */ #define IORESOURCE_MEM_64 0x00100000 -//#define DEVICE_ASSIGNMENT_DEBUG - -#ifdef DEVICE_ASSIGNMENT_DEBUG -#define DEBUG(fmt, ...) \ - do { \ - fprintf(stderr, "%s: " fmt, __func__ , __VA_ARGS__); \ - } while (0) -#else -#define DEBUG(fmt, ...) -#endif - typedef struct PCIRegion { int type; /* Memory or port I/O */ int valid; @@ -1899,73 +1889,15 @@ static void assign_register_types(void) type_init(assign_register_types) -/* - * Scan the assigned devices for the devices that have an option ROM, and then - * 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. - */ static void assigned_dev_load_option_rom(AssignedDevice *dev) { - char name[32], rom_file[64]; - FILE *fp; - uint8_t val; - struct stat st; - void *ptr; - - /* If loading ROM from file, pci handles it */ - if (dev->dev.romfile || !dev->dev.rom_bar) { - return; - } + int size = 0; - snprintf(rom_file, sizeof(rom_file), - "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom", - dev->host.domain, dev->host.bus, dev->host.slot, - dev->host.function); + pci_assign_dev_load_option_rom(&dev->dev, OBJECT(dev), &size, + dev->host.domain, dev->host.bus, + dev->host.slot, dev->host.function); - if (stat(rom_file, &st)) { - return; - } - - if (access(rom_file, F_OK)) { - error_report("pci-assign: Insufficient privileges for %s", rom_file); - return; - } - - /* Write "1" to the ROM file to enable it */ - fp = fopen(rom_file, "r+"); - if (fp == NULL) { - return; + if (!size) { + error_report("pci-assign: Invalid ROM."); } - val = 1; - if (fwrite(&val, 1, 1, fp) != 1) { - goto close_rom; - } - fseek(fp, 0, SEEK_SET); - - snprintf(name, sizeof(name), "%s.rom", - object_get_typename(OBJECT(dev))); - memory_region_init_ram(&dev->dev.rom, OBJECT(dev), name, st.st_size, - &error_abort); - vmstate_register_ram(&dev->dev.rom, &dev->dev.qdev); - ptr = memory_region_get_ram_ptr(&dev->dev.rom); - memset(ptr, 0xff, st.st_size); - - if (!fread(ptr, 1, st.st_size, fp)) { - error_report("pci-assign: Cannot read from host %s", rom_file); - error_printf("Device option ROM contents are probably invalid " - "(check dmesg).\nSkip option ROM probe with rombar=0, " - "or load from file with romfile=\n"); - goto close_rom; - } - - pci_register_bar(&dev->dev, PCI_ROM_SLOT, 0, &dev->dev.rom); - dev->dev.has_rom = true; -close_rom: - /* Write "0" to disable ROM */ - fseek(fp, 0, SEEK_SET); - val = 0; - if (!fwrite(&val, 1, 1, fp)) { - DEBUG("%s\n", "Failed to disable pci-sysfs rom file"); - } - fclose(fp); } diff --git a/hw/i386/pci-assign-load-rom.c b/hw/i386/pci-assign-load-rom.c new file mode 100644 index 0000000..a04b540 --- /dev/null +++ b/hw/i386/pci-assign-load-rom.c @@ -0,0 +1,93 @@ +/* + * This is splited from hw/i386/kvm/pci-assign.c + */ +#include +#include +#include +#include +#include +#include +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "qemu/error-report.h" +#include "ui/console.h" +#include "hw/loader.h" +#include "monitor/monitor.h" +#include "qemu/range.h" +#include "sysemu/sysemu.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci-assign.h" + +/* + * Scan the assigned devices for the devices that have an option ROM, and then + * 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. + */ +void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner, + int *size, unsigned int domain, + unsigned int bus, unsigned int slot, + unsigned int function) +{ + char name[32], rom_file[64]; + FILE *fp; + uint8_t val; + struct stat st; + void *ptr; + + /* If loading ROM from file, pci handles it */ + if (dev->romfile || !dev->rom_bar) { + return NULL; + } + + snprintf(rom_file, sizeof(rom_file), + "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom", + domain, bus, slot, function); + + if (stat(rom_file, &st)) { + return NULL; + } + + if (access(rom_file, F_OK)) { + error_report("pci-assign: Insufficient privileges for %s", rom_file); + return NULL; + } + + /* Write "1" to the ROM file to enable it */ + fp = fopen(rom_file, "r+"); + if (fp == NULL) { + return NULL; + } + val = 1; + if (fwrite(&val, 1, 1, fp) != 1) { + goto close_rom; + } + fseek(fp, 0, SEEK_SET); + + snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner)); + memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort); + vmstate_register_ram(&dev->rom, &dev->qdev); + ptr = memory_region_get_ram_ptr(&dev->rom); + memset(ptr, 0xff, st.st_size); + + if (!fread(ptr, 1, st.st_size, fp)) { + error_report("pci-assign: Cannot read from host %s", rom_file); + error_printf("Device option ROM contents are probably invalid " + "(check dmesg).\nSkip option ROM probe with rombar=0, " + "or load from file with romfile=\n"); + goto close_rom; + } + + pci_register_bar(dev, PCI_ROM_SLOT, 0, &dev->rom); + dev->has_rom = true; + *size = st.st_size; +close_rom: + /* Write "0" to disable ROM */ + fseek(fp, 0, SEEK_SET); + val = 0; + if (!fwrite(&val, 1, 1, fp)) { + DEBUG("%s\n", "Failed to disable pci-sysfs rom file"); + } + fclose(fp); + + return ptr; +} diff --git a/include/hw/pci/pci-assign.h b/include/hw/pci/pci-assign.h new file mode 100644 index 0000000..55f42c5 --- /dev/null +++ b/include/hw/pci/pci-assign.h @@ -0,0 +1,27 @@ +/* + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Just split from hw/i386/kvm/pci-assign.c. + */ +#ifndef PCI_ASSIGN_H +#define PCI_ASSIGN_H + +#include "hw/pci/pci.h" + +//#define DEVICE_ASSIGNMENT_DEBUG + +#ifdef DEVICE_ASSIGNMENT_DEBUG +#define DEBUG(fmt, ...) \ + do { \ + fprintf(stderr, "%s: " fmt, __func__ , __VA_ARGS__); \ + } while (0) +#else +#define DEBUG(fmt, ...) +#endif + +void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner, + int *size, unsigned int domain, + unsigned int bus, unsigned int slot, + unsigned int function); +#endif /* PCI_ASSIGN_H */