From patchwork Wed Mar 18 09:06:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tiejun Chen X-Patchwork-Id: 451290 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 2CA6D14009B for ; Wed, 18 Mar 2015 20:13:43 +1100 (AEDT) Received: from localhost ([::1]:59973 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YYA2n-0005R2-33 for incoming@patchwork.ozlabs.org; Wed, 18 Mar 2015 05:13:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46243) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YY9xD-0003ts-Sr for qemu-devel@nongnu.org; Wed, 18 Mar 2015 05:08:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YY9xB-0001vf-Vi for qemu-devel@nongnu.org; Wed, 18 Mar 2015 05:07:55 -0400 Received: from mga03.intel.com ([134.134.136.65]:50843) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YY9xB-0001uB-KD for qemu-devel@nongnu.org; Wed, 18 Mar 2015 05:07:53 -0400 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga103.jf.intel.com with ESMTP; 18 Mar 2015 02:04:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,421,1422950400"; d="scan'208";a="468829568" Received: from tchen0-linux.bj.intel.com ([10.238.154.91]) by FMSMGA003.fm.intel.com with ESMTP; 18 Mar 2015 02:00:34 -0700 From: Tiejun Chen To: mst@redhat.com, kraxel@redhat.com, pbonzini@redhat.com, rth@twiddle.net Date: Wed, 18 Mar 2015 17:06:35 +0800 Message-Id: <1426669601-13891-5-git-send-email-tiejun.chen@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1426669601-13891-1-git-send-email-tiejun.chen@intel.com> References: <1426669601-13891-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: 134.134.136.65 Cc: allen.m.kay@intel.com, qemu-devel@nongnu.org Subject: [Qemu-devel] [v7][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 e058a39..8bd1932 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -7,6 +7,7 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-y += kvmvapic.o obj-y += acpi-build.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/q35-acpi-dsdt.hex \ hw/i386/ssdt-tpm.hex diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index 9db7c77..fe870c9 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; @@ -1893,73 +1883,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 */