* [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough
@ 2015-06-05 8:44 Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 01/10] i440fx: make types configurable at run-time Tiejun Chen
` (11 more replies)
0 siblings, 12 replies; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
v8:
* Rebase on the latest qemu tree
* Cleanup one xen leftover in patch #3
v7:
* Instead of "-gfx_passthru" we'd like to make that a machine
option, "-machine xxx,igd-passthru=on""
* try to make something as common shared by others like KvmGT in
the future
* Just read those real value from host bridge pci
configuration space when create host bridge then put in dev->config.
v6:
* Drop introducing a new machine specific to IGD passthrough
* Try to share some codes from KVM stuff in qemu to retrive VGA BIOS
* Currently IGD drivers always need to access PCH by 1f.0. But we
don't want to poke that directly to get ID, and although in real
world different GPU should have different PCH. But actually the
different PCH DIDs likely map to different PCH SKUs. We do the
same thing for the GPU. For PCH, the different SKUs are going to
be all the same silicon design and implementation, just different
features turn on and off with fuses. The SW interfaces should be
consistent across all SKUs in a given family (eg LPT). But just
same features may not be supported.
Most of these different PCH features probably don't matter to the
Gfx driver, but obviously any difference in display port connections
will so it should be fine with any PCH in case of passthrough.
So currently use one PCH version, 0x8c4e, to cover all HSW(Haswell)
scenarios, 0x9cc3 for BDW(Broadwell).
* Drop igd write ops since its fine to emulate that, and we also shrink
those igd read ops as necessary.
* Rebase and cleanup all patches.
v5:
* Simplify to make sure its really inherited from the standard one in patch #3
* Then drop the original patch #3
v4:
* Rebase on latest tree
* Drop patch #2
* Regenerate patches after Michael introduce patch #1
* We need to use this pci_type as a index to reuse I440FX_PCI_DEVICE()
* Test: boot with a preinstalled winxp
./i386-softmmu/qemu-system-i386 -hda winxp-32.img -m 2560 -boot c -machine pc
v3:
* Drop patch #4
* Add one patch #1 from Michael
* Rebase
* In./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
v2:
* Fix some coding style
* New patch to separate i440fx_init
* Just add prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough
* Based on patch #2 to regenerate
* Unify prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough like patch #3
* Test: boot with a preinstalled ubuntu 14.04
./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
As we discussed we need to create a separate machine to support current
IGD passthrough.
----------------------------------------------------------------
Michael S. Tsirkin (1):
i440fx: make types configurable at run-time
Tiejun Chen (9):
pc_init1: pass parameters just with types
piix: create host bridge to passthrough
hw/pci-assign: split pci-assign.c
xen, gfx passthrough: basic graphics passthrough support
xen, gfx passthrough: retrieve VGA BIOS to work
igd gfx passthrough: create a isa bridge
xen, gfx passthrough: register a isa bridge
xen, gfx passthrough: register host bridge specific to passthrough
xen, gfx passthrough: add opregion mapping
hw/core/machine.c | 20 +++
hw/i386/Makefile.objs | 1 +
hw/i386/kvm/pci-assign.c | 82 +---------
hw/i386/pc_piix.c | 151 ++++++++++++++++++-
hw/i386/pci-assign-load-rom.c | 93 ++++++++++++
hw/pci-host/piix.c | 91 +++++++++++-
hw/xen/Makefile.objs | 1 +
hw/xen/xen-host-pci-device.c | 5 +
hw/xen/xen-host-pci-device.h | 1 +
hw/xen/xen_pt.c | 32 ++++
hw/xen/xen_pt.h | 21 ++-
hw/xen/xen_pt_config_init.c | 51 ++++++-
hw/xen/xen_pt_graphics.c | 272 ++++++++++++++++++++++++++++++++++
include/hw/boards.h | 1 +
include/hw/i386/pc.h | 8 +-
include/hw/pci/pci-assign.h | 27 ++++
include/hw/xen/xen.h | 1 +
qemu-options.hx | 3 +
vl.c | 10 ++
19 files changed, 780 insertions(+), 91 deletions(-)
create mode 100644 hw/i386/pci-assign-load-rom.c
create mode 100644 hw/xen/xen_pt_graphics.c
create mode 100644 include/hw/pci/pci-assign.h
Thanks
Tiejun
^ permalink raw reply [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 01/10] i440fx: make types configurable at run-time
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 02/10] pc_init1: pass parameters just with types Tiejun Chen
` (10 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
From: "Michael S. Tsirkin" <mst@redhat.com>
IGD passthrough wants to supply a different pci and
host devices, inheriting i440fx devices. Make types
configurable.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
hw/i386/pc_piix.c | 4 +++-
hw/pci-host/piix.c | 9 ++++-----
include/hw/i386/pc.h | 6 +++++-
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 6e7fa42..c05b7c7 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -202,7 +202,9 @@ static void pc_init1(MachineState *machine)
}
if (pci_enabled) {
- pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
+ pci_bus = i440fx_init(TYPE_I440FX_PCI_HOST_BRIDGE,
+ TYPE_I440FX_PCI_DEVICE,
+ &i440fx_state, &piix3_devfn, &isa_bus, gsi,
system_memory, system_io, machine->ram_size,
below_4g_mem_size,
above_4g_mem_size,
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 723836f..c812eaa 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -40,7 +40,6 @@
* http://download.intel.com/design/chipsets/datashts/29054901.pdf
*/
-#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
#define I440FX_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_PCI_HOST_BRIDGE)
@@ -91,7 +90,6 @@ typedef struct PIIX3State {
MemoryRegion rcr_mem;
} PIIX3State;
-#define TYPE_I440FX_PCI_DEVICE "i440FX"
#define I440FX_PCI_DEVICE(obj) \
OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
@@ -304,7 +302,8 @@ static void i440fx_realize(PCIDevice *dev, Error **errp)
cpu_smm_register(&i440fx_set_smm, d);
}
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
+PCIBus *i440fx_init(const char *host_type, const char *pci_type,
+ PCII440FXState **pi440fx_state,
int *piix3_devfn,
ISABus **isa_bus, qemu_irq *pic,
MemoryRegion *address_space_mem,
@@ -324,7 +323,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
unsigned i;
I440FXState *i440fx;
- dev = qdev_create(NULL, TYPE_I440FX_PCI_HOST_BRIDGE);
+ dev = qdev_create(NULL, host_type);
s = PCI_HOST_BRIDGE(dev);
b = pci_bus_new(dev, NULL, pci_address_space,
address_space_io, 0, TYPE_PCI_BUS);
@@ -332,7 +331,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
qdev_init_nofail(dev);
- d = pci_create_simple(b, 0, TYPE_I440FX_PCI_DEVICE);
+ d = pci_create_simple(b, 0, pci_type);
*pi440fx_state = I440FX_PCI_DEVICE(d);
f = *pi440fx_state;
f->system_memory = address_space_mem;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 27bd748..bb808c9 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -229,7 +229,11 @@ extern int no_hpet;
struct PCII440FXState;
typedef struct PCII440FXState PCII440FXState;
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
+#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
+#define TYPE_I440FX_PCI_DEVICE "i440FX"
+
+PCIBus *i440fx_init(const char *host_type, const char *pci_type,
+ PCII440FXState **pi440fx_state, int *piix_devfn,
ISABus **isa_bus, qemu_irq *pic,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 02/10] pc_init1: pass parameters just with types
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 01/10] i440fx: make types configurable at run-time Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 03/10] piix: create host bridge to passthrough Tiejun Chen
` (9 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
Pass types to configure pc_init1().
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
hw/i386/pc_piix.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c05b7c7..3e2fc04 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -75,7 +75,8 @@ static bool has_reserved_memory = true;
static bool kvmclock_enabled = true;
/* PC hardware initialisation */
-static void pc_init1(MachineState *machine)
+static void pc_init1(MachineState *machine,
+ const char *host_type, const char *pci_type)
{
PCMachineState *pc_machine = PC_MACHINE(machine);
MemoryRegion *system_memory = get_system_memory();
@@ -202,8 +203,8 @@ static void pc_init1(MachineState *machine)
}
if (pci_enabled) {
- pci_bus = i440fx_init(TYPE_I440FX_PCI_HOST_BRIDGE,
- TYPE_I440FX_PCI_DEVICE,
+ pci_bus = i440fx_init(host_type,
+ pci_type,
&i440fx_state, &piix3_devfn, &isa_bus, gsi,
system_memory, system_io, machine->ram_size,
below_4g_mem_size,
@@ -437,7 +438,7 @@ static void pc_init_isa(MachineState *machine)
}
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
enable_compat_apic_id_mode();
- pc_init1(machine);
+ pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE);
}
#ifdef CONFIG_XEN
@@ -445,7 +446,7 @@ static void pc_xen_hvm_init(MachineState *machine)
{
PCIBus *bus;
- pc_init1(machine);
+ pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE);
bus = pci_find_primary_bus();
if (bus != NULL) {
@@ -461,7 +462,8 @@ static void pc_xen_hvm_init(MachineState *machine)
if (compat) { \
compat(machine); \
} \
- pc_init1(machine); \
+ pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, \
+ TYPE_I440FX_PCI_DEVICE); \
} \
DEFINE_PC_MACHINE(suffix, name, pc_init_##suffix, optionfn)
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 03/10] piix: create host bridge to passthrough
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 01/10] i440fx: make types configurable at run-time Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 02/10] pc_init1: pass parameters just with types Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 04/10] hw/pci-assign: split pci-assign.c Tiejun Chen
` (8 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
Implement a pci host bridge specific to passthrough. Actually
this just inherits the standard one. And we also just expose
a minimal real host bridge pci configuration subset.
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
hw/pci-host/piix.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/i386/pc.h | 2 ++
2 files changed, 84 insertions(+)
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index c812eaa..0906ba5 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -728,6 +728,87 @@ static const TypeInfo i440fx_info = {
.class_init = i440fx_class_init,
};
+/* IGD Passthrough Host Bridge. */
+typedef struct {
+ uint8_t offset;
+ uint8_t len;
+} IGDHostInfo;
+
+/* Here we just expose minimal host bridge offset subset. */
+static const IGDHostInfo igd_host_bridge_infos[] = {
+ {0x08, 2}, /* revision id */
+ {0x2c, 2}, /* sybsystem vendor id */
+ {0x2e, 2}, /* sybsystem id */
+ {0x50, 2}, /* SNB: processor graphics control register */
+ {0x52, 2}, /* processor graphics control register */
+ {0xa4, 4}, /* SNB: graphics base of stolen memory */
+ {0xa8, 4}, /* SNB: base of GTT stolen memory */
+};
+
+static int host_pci_config_read(int pos, int len, uint32_t val)
+{
+ char path[PATH_MAX];
+ int config_fd;
+ ssize_t size = sizeof(path);
+ /* Access real host bridge. */
+ int rc = snprintf(path, size, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s",
+ 0, 0, 0, 0, "config");
+
+ if (rc >= size || rc < 0) {
+ return -ENODEV;
+ }
+
+ config_fd = open(path, O_RDWR);
+ if (config_fd < 0) {
+ return -ENODEV;
+ }
+
+ do {
+ rc = pread(config_fd, (uint8_t *)&val, len, pos);
+ } while (rc < 0 && (errno == EINTR || errno == EAGAIN));
+ if (rc != len) {
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int igd_pt_i440fx_initfn(struct PCIDevice *pci_dev)
+{
+ uint32_t val = 0;
+ int rc, i, num;
+ int pos, len;
+
+ num = ARRAY_SIZE(igd_host_bridge_infos);
+ for (i = 0; i < num; i++) {
+ pos = igd_host_bridge_infos[i].offset;
+ len = igd_host_bridge_infos[i].len;
+ rc = host_pci_config_read(pos, len, val);
+ if (rc) {
+ return -ENODEV;
+ }
+ pci_default_write_config(pci_dev, pos, val, len);
+ }
+
+ return 0;
+}
+
+static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = igd_pt_i440fx_initfn;
+ dc->desc = "IGD Passthrough Host bridge";
+}
+
+static const TypeInfo igd_passthrough_i440fx_info = {
+ .name = TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE,
+ .parent = TYPE_I440FX_PCI_DEVICE,
+ .instance_size = sizeof(PCII440FXState),
+ .class_init = igd_passthrough_i440fx_class_init,
+};
+
static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge,
PCIBus *rootbus)
{
@@ -769,6 +850,7 @@ static const TypeInfo i440fx_pcihost_info = {
static void i440fx_register_types(void)
{
type_register_static(&i440fx_info);
+ type_register_static(&igd_passthrough_i440fx_info);
type_register_static(&piix3_info);
type_register_static(&piix3_xen_info);
type_register_static(&i440fx_pcihost_info);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index bb808c9..83962aa 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -232,6 +232,8 @@ typedef struct PCII440FXState PCII440FXState;
#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
#define TYPE_I440FX_PCI_DEVICE "i440FX"
+#define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX"
+
PCIBus *i440fx_init(const char *host_type, const char *pci_type,
PCII440FXState **pi440fx_state, int *piix_devfn,
ISABus **isa_bus, qemu_irq *pic,
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 04/10] hw/pci-assign: split pci-assign.c
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (2 preceding siblings ...)
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 03/10] piix: create host bridge to passthrough Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic graphics passthrough support Tiejun Chen
` (7 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
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 <tiejun.chen@intel.com>
---
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 0be5d97..2b9c98d 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 hw/i386/ssdt-tpm2.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 <stdio.h>
+#include <unistd.h>
+#include <sys/io.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#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 */
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic graphics passthrough support
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (3 preceding siblings ...)
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 04/10] hw/pci-assign: split pci-assign.c Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-07-01 15:45 ` Stefano Stabellini
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retrieve VGA BIOS to work Tiejun Chen
` (6 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
basic gfx passthrough support:
- add a vga type for gfx passthrough
- register/unregister legacy VGA I/O ports and MMIOs for passthrough GFX
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
---
hw/core/machine.c | 20 ++++++++
hw/xen/Makefile.objs | 1 +
hw/xen/xen-host-pci-device.c | 5 ++
hw/xen/xen-host-pci-device.h | 1 +
hw/xen/xen_pt.c | 4 ++
hw/xen/xen_pt.h | 10 +++-
hw/xen/xen_pt_graphics.c | 111 +++++++++++++++++++++++++++++++++++++++++++
include/hw/boards.h | 1 +
qemu-options.hx | 3 ++
vl.c | 10 ++++
10 files changed, 165 insertions(+), 1 deletion(-)
create mode 100644 hw/xen/xen_pt_graphics.c
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 25c45e6..0655665 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -226,6 +226,20 @@ static void machine_set_usb(Object *obj, bool value, Error **errp)
ms->usb_disabled = !value;
}
+static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ return ms->igd_gfx_passthru;
+}
+
+static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ ms->igd_gfx_passthru = value;
+}
+
static char *machine_get_firmware(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
@@ -380,6 +394,12 @@ static void machine_initfn(Object *obj)
object_property_set_description(obj, "usb",
"Set on/off to enable/disable usb",
NULL);
+ object_property_add_bool(obj, "igd-passthru",
+ machine_get_igd_gfx_passthru,
+ machine_set_igd_gfx_passthru, NULL);
+ object_property_set_description(obj, "igd-passthru",
+ "Set on/off to enable/disable igd passthrou",
+ NULL);
object_property_add_str(obj, "firmware",
machine_get_firmware,
machine_set_firmware, NULL);
diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
index a0ca0aa..a9ad7e7 100644
--- a/hw/xen/Makefile.objs
+++ b/hw/xen/Makefile.objs
@@ -3,3 +3,4 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
+obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o xen_pt_graphics.o
diff --git a/hw/xen/xen-host-pci-device.c b/hw/xen/xen-host-pci-device.c
index 743b37b..a54b7de 100644
--- a/hw/xen/xen-host-pci-device.c
+++ b/hw/xen/xen-host-pci-device.c
@@ -376,6 +376,11 @@ int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
goto error;
}
d->irq = v;
+ rc = xen_host_pci_get_hex_value(d, "class", &v);
+ if (rc) {
+ goto error;
+ }
+ d->class_code = v;
d->is_virtfn = xen_host_pci_dev_is_virtfn(d);
return 0;
diff --git a/hw/xen/xen-host-pci-device.h b/hw/xen/xen-host-pci-device.h
index c2486f0..f1e1c30 100644
--- a/hw/xen/xen-host-pci-device.h
+++ b/hw/xen/xen-host-pci-device.h
@@ -25,6 +25,7 @@ typedef struct XenHostPCIDevice {
uint16_t vendor_id;
uint16_t device_id;
+ uint32_t class_code;
int irq;
XenHostPCIIORegion io_regions[PCI_NUM_REGIONS - 1];
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index 9afcda8..50bdf6f 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -494,6 +494,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s, uint16_t *cmd)
d->rom.size, d->rom.base_addr);
}
+ xen_pt_register_vga_regions(d);
return 0;
}
@@ -798,6 +799,7 @@ out:
static void xen_pt_unregister_device(PCIDevice *d)
{
XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
+ XenHostPCIDevice *host_dev = &s->real_device;
uint8_t machine_irq = s->machine_irq;
uint8_t intx = xen_pt_pci_intx(s);
int rc;
@@ -841,6 +843,8 @@ static void xen_pt_unregister_device(PCIDevice *d)
/* delete all emulated config registers */
xen_pt_config_delete(s);
+ xen_pt_unregister_vga_regions(host_dev);
+
memory_listener_unregister(&s->memory_listener);
memory_listener_unregister(&s->io_listener);
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
index 4bba559..dfa6171 100644
--- a/hw/xen/xen_pt.h
+++ b/hw/xen/xen_pt.h
@@ -301,5 +301,13 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
return s->msix && s->msix->bar_index == bar;
}
-
+extern bool has_igd_gfx_passthru;
+static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
+{
+ return (has_igd_gfx_passthru
+ && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA));
+}
+int xen_pt_register_vga_regions(XenHostPCIDevice *dev);
+int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev);
+int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev);
#endif /* !XEN_PT_H */
diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
new file mode 100644
index 0000000..9b3df81
--- /dev/null
+++ b/hw/xen/xen_pt_graphics.c
@@ -0,0 +1,111 @@
+/*
+ * graphics passthrough
+ */
+#include "xen_pt.h"
+#include "xen-host-pci-device.h"
+#include "hw/xen/xen_backend.h"
+
+typedef struct VGARegion {
+ int type; /* Memory or port I/O */
+ uint64_t guest_base_addr;
+ uint64_t machine_base_addr;
+ uint64_t size; /* size of the region */
+ int rc;
+} VGARegion;
+
+#define IORESOURCE_IO 0x00000100
+#define IORESOURCE_MEM 0x00000200
+
+static struct VGARegion vga_args[] = {
+ {
+ .type = IORESOURCE_IO,
+ .guest_base_addr = 0x3B0,
+ .machine_base_addr = 0x3B0,
+ .size = 0xC,
+ .rc = -1,
+ },
+ {
+ .type = IORESOURCE_IO,
+ .guest_base_addr = 0x3C0,
+ .machine_base_addr = 0x3C0,
+ .size = 0x20,
+ .rc = -1,
+ },
+ {
+ .type = IORESOURCE_MEM,
+ .guest_base_addr = 0xa0000 >> XC_PAGE_SHIFT,
+ .machine_base_addr = 0xa0000 >> XC_PAGE_SHIFT,
+ .size = 0x20,
+ .rc = -1,
+ },
+};
+
+/*
+ * register VGA resources for the domain with assigned gfx
+ */
+int xen_pt_register_vga_regions(XenHostPCIDevice *dev)
+{
+ int i = 0;
+
+ if (!is_igd_vga_passthrough(dev)) {
+ return 0;
+ }
+
+ for (i = 0 ; i < ARRAY_SIZE(vga_args); i++) {
+ if (vga_args[i].type == IORESOURCE_IO) {
+ vga_args[i].rc = xc_domain_ioport_mapping(xen_xc, xen_domid,
+ vga_args[i].guest_base_addr,
+ vga_args[i].machine_base_addr,
+ vga_args[i].size, DPCI_ADD_MAPPING);
+ } else {
+ vga_args[i].rc = xc_domain_memory_mapping(xen_xc, xen_domid,
+ vga_args[i].guest_base_addr,
+ vga_args[i].machine_base_addr,
+ vga_args[i].size, DPCI_ADD_MAPPING);
+ }
+
+ if (vga_args[i].rc) {
+ XEN_PT_ERR(NULL, "VGA %s mapping failed! (rc: %i)\n",
+ vga_args[i].type == IORESOURCE_IO ? "ioport" : "memory",
+ vga_args[i].rc);
+ return vga_args[i].rc;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * unregister VGA resources for the domain with assigned gfx
+ */
+int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
+{
+ int i = 0;
+
+ if (!is_igd_vga_passthrough(dev)) {
+ return 0;
+ }
+
+ for (i = 0 ; i < ARRAY_SIZE(vga_args); i++) {
+ if (vga_args[i].type == IORESOURCE_IO) {
+ vga_args[i].rc = xc_domain_ioport_mapping(xen_xc, xen_domid,
+ vga_args[i].guest_base_addr,
+ vga_args[i].machine_base_addr,
+ vga_args[i].size, DPCI_REMOVE_MAPPING);
+ } else {
+ vga_args[i].rc = xc_domain_memory_mapping(xen_xc, xen_domid,
+ vga_args[i].guest_base_addr,
+ vga_args[i].machine_base_addr,
+ vga_args[i].size, DPCI_REMOVE_MAPPING);
+ }
+
+ if (vga_args[i].rc) {
+ XEN_PT_ERR(NULL, "VGA %s unmapping failed! (rc: %i)\n",
+ vga_args[i].type == IORESOURCE_IO ? "ioport" : "memory",
+ vga_args[i].rc);
+ return vga_args[i].rc;
+ }
+ }
+
+ return 0;
+}
diff --git a/include/hw/boards.h b/include/hw/boards.h
index ff79797..a7b75ac 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -134,6 +134,7 @@ struct MachineState {
bool mem_merge;
bool usb;
bool usb_disabled;
+ bool igd_gfx_passthru;
char *firmware;
bool iommu;
bool suppress_vmdesc;
diff --git a/qemu-options.hx b/qemu-options.hx
index 7edd1f1..964ba0d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,6 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
" dump-guest-core=on|off include guest memory in a core dump (default=on)\n"
" mem-merge=on|off controls memory merge support (default: on)\n"
" iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n"
+ " igd-passthru=on|off controls IGD GFX passthrough support (default=off)\n"
" aes-key-wrap=on|off controls support for AES key wrapping (default=on)\n"
" dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n"
" suppress-vmdesc=on|off disables self-describing migration (default=off)\n",
@@ -55,6 +56,8 @@ than one accelerator specified, the next one is used if the previous one fails
to initialize.
@item kernel_irqchip=on|off
Enables in-kernel irqchip support for the chosen accelerator when available.
+@item gfx_passthru=on|off
+Enables IGD GFX passthrough support for the chosen machine when available.
@item vmport=on|off|auto
Enables emulation of VMWare IO port, for vmmouse etc. auto says to select the
value based on accel. For accel=xen the default is off otherwise the default
diff --git a/vl.c b/vl.c
index 1d4c089..34c1d55 100644
--- a/vl.c
+++ b/vl.c
@@ -1224,6 +1224,13 @@ static void configure_msg(QemuOpts *opts)
enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true);
}
+/* Now we still need this for compatibility with XEN. */
+bool has_igd_gfx_passthru;
+static void igd_gfx_passthru(void)
+{
+ has_igd_gfx_passthru = current_machine->igd_gfx_passthru;
+}
+
/***********************************************************/
/* USB devices */
@@ -4256,6 +4263,9 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ /* Check if IGD GFX passthrough. */
+ igd_gfx_passthru();
+
/* init generic devices */
if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, 1) != 0)
exit(1);
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retrieve VGA BIOS to work
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (4 preceding siblings ...)
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic graphics passthrough support Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-07-01 15:51 ` Stefano Stabellini
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 07/10] igd gfx passthrough: create a isa bridge Tiejun Chen
` (5 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
Now we retrieve VGA bios like kvm stuff in qemu but we need to
fix Device Identification in case if its not matched with the
real IGD device since Seabios is always trying to compare this
ID to work out VGA BIOS.
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
hw/xen/xen_pt.c | 10 ++++++
hw/xen/xen_pt.h | 5 +++
hw/xen/xen_pt_graphics.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 94 insertions(+)
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index 50bdf6f..3bf2233 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -717,6 +717,16 @@ static int xen_pt_initfn(PCIDevice *d)
s->memory_listener = xen_pt_memory_listener;
s->io_listener = xen_pt_io_listener;
+ /* Setup VGA bios for passthrough GFX */
+ if ((s->real_device.domain == 0) && (s->real_device.bus == 0) &&
+ (s->real_device.dev == 2) && (s->real_device.func == 0)) {
+ if (xen_pt_setup_vga(s, &s->real_device) < 0) {
+ XEN_PT_ERR(d, "Setup VGA BIOS of passthrough GFX failed!\n");
+ xen_host_pci_device_put(&s->real_device);
+ return -1;
+ }
+ }
+
/* Handle real device's MMIO/PIO BARs */
xen_pt_register_regions(s, &cmd);
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
index dfa6171..6c42754 100644
--- a/hw/xen/xen_pt.h
+++ b/hw/xen/xen_pt.h
@@ -301,6 +301,11 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
return s->msix && s->msix->bar_index == bar;
}
+extern 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);
extern bool has_igd_gfx_passthru;
static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
{
diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
index 9b3df81..3232296 100644
--- a/hw/xen/xen_pt_graphics.c
+++ b/hw/xen/xen_pt_graphics.c
@@ -109,3 +109,82 @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
return 0;
}
+
+static void *get_vgabios(XenPCIPassthroughState *s, int *size,
+ XenHostPCIDevice *dev)
+{
+ return pci_assign_dev_load_option_rom(&s->dev, OBJECT(&s->dev), size,
+ dev->domain, dev->bus,
+ dev->dev, dev->func);
+}
+
+/* Refer to Seabios. */
+struct rom_header {
+ uint16_t signature;
+ uint8_t size;
+ uint8_t initVector[4];
+ uint8_t reserved[17];
+ uint16_t pcioffset;
+ uint16_t pnpoffset;
+} __attribute__((packed));
+
+struct pci_data {
+ uint32_t signature;
+ uint16_t vendor;
+ uint16_t device;
+ uint16_t vitaldata;
+ uint16_t dlen;
+ uint8_t drevision;
+ uint8_t class_lo;
+ uint16_t class_hi;
+ uint16_t ilen;
+ uint16_t irevision;
+ uint8_t type;
+ uint8_t indicator;
+ uint16_t reserved;
+} __attribute__((packed));
+
+int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
+{
+ unsigned char *bios = NULL;
+ struct rom_header *rom;
+ int bios_size;
+ char *c = NULL;
+ char checksum = 0;
+ uint32_t len = 0;
+ struct pci_data *pd = NULL;
+
+ if (!is_igd_vga_passthrough(dev)) {
+ return -1;
+ }
+
+ bios = get_vgabios(s, &bios_size, dev);
+ if (!bios) {
+ XEN_PT_ERR(&s->dev, "VGA: Can't getting VBIOS!\n");
+ return -1;
+ }
+
+ /* Currently we fixed this address as a primary. */
+ rom = (struct rom_header *)bios;
+ pd = (void *)(bios + (unsigned char)rom->pcioffset);
+
+ /* We may need to fixup Device Identification. */
+ if (pd->device != s->real_device.device_id) {
+ pd->device = s->real_device.device_id;
+
+ len = rom->size * 512;
+ /* Then adjust the bios checksum */
+ for (c = (char *)bios; c < ((char *)bios + len); c++) {
+ checksum += *c;
+ }
+ if (checksum) {
+ bios[len - 1] -= checksum;
+ XEN_PT_LOG(&s->dev, "vga bios checksum is adjusted %x!\n",
+ checksum);
+ }
+ }
+
+ /* Currently we fixed this address as a primary for legacy BIOS. */
+ cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
+ return 0;
+}
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 07/10] igd gfx passthrough: create a isa bridge
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (5 preceding siblings ...)
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retrieve VGA BIOS to work Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 08/10] xen, gfx passthrough: register " Tiejun Chen
` (4 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
Currently IGD drivers always need to access PCH by 1f.0. But we
don't want to poke that directly to get ID, and although in real
world different GPU should have different PCH. But actually the
different PCH DIDs likely map to different PCH SKUs. We do the
same thing for the GPU. For PCH, the different SKUs are going to
be all the same silicon design and implementation, just different
features turn on and off with fuses. The SW interfaces should be
consistent across all SKUs in a given family (eg LPT). But just
same features may not be supported.
Most of these different PCH features probably don't matter to the
Gfx driver, but obviously any difference in display port connections
will so it should be fine with any PCH in case of passthrough.
So currently use one PCH version, 0x8c4e, to cover all HSW(Haswell)
scenarios, 0x9cc3 for BDW(Broadwell).
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
hw/i386/pc_piix.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 112 insertions(+)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 3e2fc04..6054b5a 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -904,6 +904,118 @@ static void pc_i440fx_0_10_machine_options(MachineClass *m)
DEFINE_I440FX_MACHINE(v0_10, "pc-0.10", pc_compat_0_13,
pc_i440fx_0_10_machine_options);
+typedef struct {
+ uint16_t gpu_device_id;
+ uint16_t pch_device_id;
+ uint8_t pch_revision_id;
+} IGDDeviceIDInfo;
+
+/* In real world different GPU should have different PCH. But actually
+ * the different PCH DIDs likely map to different PCH SKUs. We do the
+ * same thing for the GPU. For PCH, the different SKUs are going to be
+ * all the same silicon design and implementation, just different
+ * features turn on and off with fuses. The SW interfaces should be
+ * consistent across all SKUs in a given family (eg LPT). But just same
+ * features may not be supported.
+ *
+ * Most of these different PCH features probably don't matter to the
+ * Gfx driver, but obviously any difference in display port connections
+ * will so it should be fine with any PCH in case of passthrough.
+ *
+ * So currently use one PCH version, 0x8c4e, to cover all HSW(Haswell)
+ * scenarios, 0x9cc3 for BDW(Broadwell).
+ */
+static const IGDDeviceIDInfo igd_combo_id_infos[] = {
+ /* HSW Classic */
+ {0x0402, 0x8c4e, 0x04}, /* HSWGT1D, HSWD_w7 */
+ {0x0406, 0x8c4e, 0x04}, /* HSWGT1M, HSWM_w7 */
+ {0x0412, 0x8c4e, 0x04}, /* HSWGT2D, HSWD_w7 */
+ {0x0416, 0x8c4e, 0x04}, /* HSWGT2M, HSWM_w7 */
+ {0x041E, 0x8c4e, 0x04}, /* HSWGT15D, HSWD_w7 */
+ /* HSW ULT */
+ {0x0A06, 0x8c4e, 0x04}, /* HSWGT1UT, HSWM_w7 */
+ {0x0A16, 0x8c4e, 0x04}, /* HSWGT2UT, HSWM_w7 */
+ {0x0A26, 0x8c4e, 0x06}, /* HSWGT3UT, HSWM_w7 */
+ {0x0A2E, 0x8c4e, 0x04}, /* HSWGT3UT28W, HSWM_w7 */
+ {0x0A1E, 0x8c4e, 0x04}, /* HSWGT2UX, HSWM_w7 */
+ {0x0A0E, 0x8c4e, 0x04}, /* HSWGT1ULX, HSWM_w7 */
+ /* HSW CRW */
+ {0x0D26, 0x8c4e, 0x04}, /* HSWGT3CW, HSWM_w7 */
+ {0x0D22, 0x8c4e, 0x04}, /* HSWGT3CWDT, HSWD_w7 */
+ /* HSW Server */
+ {0x041A, 0x8c4e, 0x04}, /* HSWSVGT2, HSWD_w7 */
+ /* HSW SRVR */
+ {0x040A, 0x8c4e, 0x04}, /* HSWSVGT1, HSWD_w7 */
+ /* BSW */
+ {0x1606, 0x9cc3, 0x03}, /* BDWULTGT1, BDWM_w7 */
+ {0x1616, 0x9cc3, 0x03}, /* BDWULTGT2, BDWM_w7 */
+ {0x1626, 0x9cc3, 0x03}, /* BDWULTGT3, BDWM_w7 */
+ {0x160E, 0x9cc3, 0x03}, /* BDWULXGT1, BDWM_w7 */
+ {0x161E, 0x9cc3, 0x03}, /* BDWULXGT2, BDWM_w7 */
+ {0x1602, 0x9cc3, 0x03}, /* BDWHALOGT1, BDWM_w7 */
+ {0x1612, 0x9cc3, 0x03}, /* BDWHALOGT2, BDWM_w7 */
+ {0x1622, 0x9cc3, 0x03}, /* BDWHALOGT3, BDWM_w7 */
+ {0x162B, 0x9cc3, 0x03}, /* BDWHALO28W, BDWM_w7 */
+ {0x162A, 0x9cc3, 0x03}, /* BDWGT3WRKS, BDWM_w7 */
+ {0x162D, 0x9cc3, 0x03}, /* BDWGT3SRVR, BDWM_w7 */
+};
+
+static void isa_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ dc->desc = "ISA bridge faked to support IGD PT";
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+};
+
+static TypeInfo isa_bridge_info = {
+ .name = "igd-passthrough-isa-bridge",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = isa_bridge_class_init,
+};
+
+static void pt_graphics_register_types(void)
+{
+ type_register_static(&isa_bridge_info);
+}
+type_init(pt_graphics_register_types)
+
+void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id)
+{
+ struct PCIDevice *bridge_dev;
+ int i, num;
+ uint16_t pch_dev_id = 0xffff;
+ uint8_t pch_rev_id;
+
+ num = ARRAY_SIZE(igd_combo_id_infos);
+ for (i = 0; i < num; i++) {
+ if (gpu_dev_id == igd_combo_id_infos[i].gpu_device_id) {
+ pch_dev_id = igd_combo_id_infos[i].pch_device_id;
+ pch_rev_id = igd_combo_id_infos[i].pch_revision_id;
+ }
+ }
+
+ if (pch_dev_id == 0xffff) {
+ return;
+ }
+
+ /* Currently IGD drivers always need to access PCH by 1f.0. */
+ bridge_dev = pci_create_simple(bus, PCI_DEVFN(0x1f, 0),
+ "igd-passthrough-isa-bridge");
+
+ /*
+ * Note that vendor id is always PCI_VENDOR_ID_INTEL.
+ */
+ if (!bridge_dev) {
+ fprintf(stderr, "set igd-passthrough-isa-bridge failed!\n");
+ return;
+ }
+ pci_config_set_device_id(bridge_dev->config, pch_dev_id);
+ pci_config_set_revision(bridge_dev->config, pch_rev_id);
+}
static void isapc_machine_options(MachineClass *m)
{
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 08/10] xen, gfx passthrough: register a isa bridge
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (6 preceding siblings ...)
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 07/10] igd gfx passthrough: create a isa bridge Tiejun Chen
@ 2015-06-05 8:44 ` Tiejun Chen
2015-07-01 15:55 ` Stefano Stabellini
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 09/10] xen, gfx passthrough: register host bridge specific to passthrough Tiejun Chen
` (3 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:44 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
Currently we just register this isa bridge when we use IGD
passthrough in Xen side.
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
hw/xen/xen_pt.c | 18 ++++++++++++++++++
include/hw/xen/xen.h | 1 +
2 files changed, 19 insertions(+)
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index 3bf2233..fff169d 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -676,6 +676,21 @@ static const MemoryListener xen_pt_io_listener = {
.priority = 10,
};
+static void
+xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
+ XenHostPCIDevice *dev)
+{
+ uint16_t gpu_dev_id;
+ PCIDevice *d = &s->dev;
+
+ if (!is_igd_vga_passthrough(dev)) {
+ return;
+ }
+
+ gpu_dev_id = dev->device_id;
+ igd_passthrough_isa_bridge_create(d->bus, gpu_dev_id);
+}
+
/* init */
static int xen_pt_initfn(PCIDevice *d)
@@ -725,6 +740,9 @@ static int xen_pt_initfn(PCIDevice *d)
xen_host_pci_device_put(&s->real_device);
return -1;
}
+
+ /* Register ISA bridge for passthrough GFX. */
+ xen_igd_passthrough_isa_bridge_create(s, &s->real_device);
}
/* Handle real device's MMIO/PIO BARs */
diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
index 4356af4..703148e 100644
--- a/include/hw/xen/xen.h
+++ b/include/hw/xen/xen.h
@@ -51,4 +51,5 @@ void xen_register_framebuffer(struct MemoryRegion *mr);
# define HVM_MAX_VCPUS 32
#endif
+extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id);
#endif /* QEMU_HW_XEN_H */
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 09/10] xen, gfx passthrough: register host bridge specific to passthrough
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (7 preceding siblings ...)
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 08/10] xen, gfx passthrough: register " Tiejun Chen
@ 2015-06-05 8:45 ` Tiejun Chen
2015-07-01 15:58 ` Stefano Stabellini
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 10/10] xen, gfx passthrough: add opregion mapping Tiejun Chen
` (2 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:45 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
Just register that pci host bridge specific to passthrough.
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
hw/i386/pc_piix.c | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 6054b5a..938b1be 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -50,7 +50,8 @@
#include "cpu.h"
#include "qemu/error-report.h"
#ifdef CONFIG_XEN
-# include <xen/hvm/hvm_info_table.h>
+#include <xen/hvm/hvm_info_table.h>
+#include "hw/xen/xen_pt.h"
#endif
#define MAX_IDE_BUS 2
@@ -442,11 +443,33 @@ static void pc_init_isa(MachineState *machine)
}
#ifdef CONFIG_XEN
+static void igd_passthrough_pc_init_pci(MachineState *machine)
+{
+ pc_init1(machine,
+ TYPE_I440FX_PCI_HOST_BRIDGE,
+ TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE);
+}
+
+static void pc_init_pci(MachineState *machine)
+{
+ pc_init1(machine,
+ TYPE_I440FX_PCI_HOST_BRIDGE,
+ TYPE_I440FX_PCI_DEVICE);
+}
+
+static void pc_xen_hvm_init_pci(MachineState *machine)
+{
+ if (has_igd_gfx_passthru)
+ igd_passthrough_pc_init_pci(machine);
+ else
+ pc_init_pci(machine);
+}
+
static void pc_xen_hvm_init(MachineState *machine)
{
PCIBus *bus;
- pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE);
+ pc_xen_hvm_init_pci(machine);
bus = pci_find_primary_bus();
if (bus != NULL) {
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [v8][RESEND][PATCH 10/10] xen, gfx passthrough: add opregion mapping
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (8 preceding siblings ...)
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 09/10] xen, gfx passthrough: register host bridge specific to passthrough Tiejun Chen
@ 2015-06-05 8:45 ` Tiejun Chen
2015-07-01 16:01 ` Stefano Stabellini
2015-07-01 1:39 ` [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Chen, Tiejun
2015-07-02 6:22 ` Michael S. Tsirkin
11 siblings, 1 reply; 22+ messages in thread
From: Tiejun Chen @ 2015-06-05 8:45 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
The OpRegion shouldn't be mapped 1:1 because the address in the host
can't be used in the guest directly.
This patch traps read and write access to the opregion of the Intel
GPU config space (offset 0xfc).
The original patch is from Jean Guyader <jean.guyader@eu.citrix.com>
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
---
hw/xen/xen_pt.h | 6 +++-
hw/xen/xen_pt_config_init.c | 51 ++++++++++++++++++++++++++--
hw/xen/xen_pt_graphics.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 136 insertions(+), 3 deletions(-)
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
index 6c42754..aa29271 100644
--- a/hw/xen/xen_pt.h
+++ b/hw/xen/xen_pt.h
@@ -36,6 +36,9 @@ typedef struct XenPTReg XenPTReg;
typedef struct XenPCIPassthroughState XenPCIPassthroughState;
+uint32_t igd_read_opregion(XenPCIPassthroughState *s);
+void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
+
/* function type for config reg */
typedef int (*xen_pt_conf_reg_init)
(XenPCIPassthroughState *, XenPTRegInfo *, uint32_t real_offset,
@@ -62,8 +65,9 @@ typedef int (*xen_pt_conf_byte_read)
#define XEN_PT_BAR_ALLF 0xFFFFFFFF
#define XEN_PT_BAR_UNMAPPED (-1)
-#define PCI_CAP_MAX 48
+#define XEN_PCI_CAP_MAX 48
+#define XEN_PCI_INTEL_OPREGION 0xfc
typedef enum {
XEN_PT_GRP_TYPE_HARDWIRED = 0, /* 0 Hardwired reg group */
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
index f3cf069..b018518 100644
--- a/hw/xen/xen_pt_config_init.c
+++ b/hw/xen/xen_pt_config_init.c
@@ -553,6 +553,22 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
return 0;
}
+static int xen_pt_intel_opregion_read(XenPCIPassthroughState *s,
+ XenPTReg *cfg_entry,
+ uint32_t *value, uint32_t valid_mask)
+{
+ *value = igd_read_opregion(s);
+ return 0;
+}
+
+static int xen_pt_intel_opregion_write(XenPCIPassthroughState *s,
+ XenPTReg *cfg_entry, uint32_t *value,
+ uint32_t dev_value, uint32_t valid_mask)
+{
+ igd_write_opregion(s, *value);
+ return 0;
+}
+
/* Header Type0 reg static information table */
static XenPTRegInfo xen_pt_emu_reg_header0[] = {
/* Vendor ID reg */
@@ -1493,6 +1509,19 @@ static XenPTRegInfo xen_pt_emu_reg_msix[] = {
},
};
+static XenPTRegInfo xen_pt_emu_reg_igd_opregion[] = {
+ /* Intel IGFX OpRegion reg */
+ {
+ .offset = 0x0,
+ .size = 4,
+ .init_val = 0,
+ .u.dw.read = xen_pt_intel_opregion_read,
+ .u.dw.write = xen_pt_intel_opregion_write,
+ },
+ {
+ .size = 0,
+ },
+};
/****************************
* Capabilities
@@ -1730,6 +1759,14 @@ static const XenPTRegGroupInfo xen_pt_emu_reg_grps[] = {
.size_init = xen_pt_msix_size_init,
.emu_regs = xen_pt_emu_reg_msix,
},
+ /* Intel IGD Opregion group */
+ {
+ .grp_id = XEN_PCI_INTEL_OPREGION,
+ .grp_type = XEN_PT_GRP_TYPE_EMU,
+ .grp_size = 0x4,
+ .size_init = xen_pt_reg_grp_size_init,
+ .emu_regs = xen_pt_emu_reg_igd_opregion,
+ },
{
.grp_size = 0,
},
@@ -1780,7 +1817,7 @@ out:
static uint8_t find_cap_offset(XenPCIPassthroughState *s, uint8_t cap)
{
uint8_t id;
- unsigned max_cap = PCI_CAP_MAX;
+ unsigned max_cap = XEN_PCI_CAP_MAX;
uint8_t pos = PCI_CAPABILITY_LIST;
uint8_t status = 0;
@@ -1859,7 +1896,8 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
uint32_t reg_grp_offset = 0;
XenPTRegGroup *reg_grp_entry = NULL;
- if (xen_pt_emu_reg_grps[i].grp_id != 0xFF) {
+ if (xen_pt_emu_reg_grps[i].grp_id != 0xFF
+ && xen_pt_emu_reg_grps[i].grp_id != XEN_PCI_INTEL_OPREGION) {
if (xen_pt_hide_dev_cap(&s->real_device,
xen_pt_emu_reg_grps[i].grp_id)) {
continue;
@@ -1872,6 +1910,15 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
}
}
+ /*
+ * By default we will trap up to 0x40 in the cfg space.
+ * If an intel device is pass through we need to trap 0xfc,
+ * therefore the size should be 0xff.
+ */
+ if (xen_pt_emu_reg_grps[i].grp_id == XEN_PCI_INTEL_OPREGION) {
+ reg_grp_offset = XEN_PCI_INTEL_OPREGION;
+ }
+
reg_grp_entry = g_new0(XenPTRegGroup, 1);
QLIST_INIT(®_grp_entry->reg_tbl_list);
QLIST_INSERT_HEAD(&s->reg_grps, reg_grp_entry, entries);
diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
index 3232296..df6069b 100644
--- a/hw/xen/xen_pt_graphics.c
+++ b/hw/xen/xen_pt_graphics.c
@@ -5,6 +5,11 @@
#include "xen-host-pci-device.h"
#include "hw/xen/xen_backend.h"
+static unsigned long igd_guest_opregion;
+static unsigned long igd_host_opregion;
+
+#define XEN_PCI_INTEL_OPREGION_MASK 0xfff
+
typedef struct VGARegion {
int type; /* Memory or port I/O */
uint64_t guest_base_addr;
@@ -81,6 +86,7 @@ int xen_pt_register_vga_regions(XenHostPCIDevice *dev)
int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
{
int i = 0;
+ int ret = 0;
if (!is_igd_vga_passthrough(dev)) {
return 0;
@@ -107,6 +113,17 @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
}
}
+ if (igd_guest_opregion) {
+ ret = xc_domain_memory_mapping(xen_xc, xen_domid,
+ (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
+ (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
+ 3,
+ DPCI_REMOVE_MAPPING);
+ if (ret) {
+ return ret;
+ }
+ }
+
return 0;
}
@@ -188,3 +205,68 @@ int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
return 0;
}
+
+uint32_t igd_read_opregion(XenPCIPassthroughState *s)
+{
+ uint32_t val = 0;
+
+ if (!igd_guest_opregion) {
+ return val;
+ }
+
+ val = igd_guest_opregion;
+
+ XEN_PT_LOG(&s->dev, "Read opregion val=%x\n", val);
+ return val;
+}
+
+#define XEN_PCI_INTEL_OPREGION_PAGES 0x3
+#define XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED 0x1
+void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val)
+{
+ int ret;
+
+ if (igd_guest_opregion) {
+ XEN_PT_LOG(&s->dev, "opregion register already been set, ignoring %x\n",
+ val);
+ return;
+ }
+
+ /* We just work with LE. */
+ xen_host_pci_get_block(&s->real_device, XEN_PCI_INTEL_OPREGION,
+ (uint8_t *)&igd_host_opregion, 4);
+ igd_guest_opregion = (unsigned long)(val & ~XEN_PCI_INTEL_OPREGION_MASK)
+ | (igd_host_opregion & XEN_PCI_INTEL_OPREGION_MASK);
+
+ ret = xc_domain_iomem_permission(xen_xc, xen_domid,
+ (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
+ XEN_PCI_INTEL_OPREGION_PAGES,
+ XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED);
+
+ if (ret) {
+ XEN_PT_ERR(&s->dev, "[%d]:Can't enable to access IGD host opregion:"
+ " 0x%lx.\n", ret,
+ (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT)),
+ igd_guest_opregion = 0;
+ return;
+ }
+
+ ret = xc_domain_memory_mapping(xen_xc, xen_domid,
+ (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
+ (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
+ XEN_PCI_INTEL_OPREGION_PAGES,
+ DPCI_ADD_MAPPING);
+
+ if (ret) {
+ XEN_PT_ERR(&s->dev, "[%d]:Can't map IGD host opregion:0x%lx to"
+ " guest opregion:0x%lx.\n", ret,
+ (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
+ (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
+ igd_guest_opregion = 0;
+ return;
+ }
+
+ XEN_PT_LOG(&s->dev, "Map OpRegion: 0x%lx -> 0x%lx\n",
+ (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
+ (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
+}
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (9 preceding siblings ...)
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 10/10] xen, gfx passthrough: add opregion mapping Tiejun Chen
@ 2015-07-01 1:39 ` Chen, Tiejun
2015-07-01 16:03 ` Stefano Stabellini
2015-07-02 6:22 ` Michael S. Tsirkin
11 siblings, 1 reply; 22+ messages in thread
From: Chen, Tiejun @ 2015-07-01 1:39 UTC (permalink / raw)
To: mst, pbonzini, rth, ehabkost; +Cc: qemu-devel
Ping...
Thanks
Tiejun
On 2015/6/5 16:44, Tiejun Chen wrote:
> v8:
>
> * Rebase on the latest qemu tree
> * Cleanup one xen leftover in patch #3
>
> v7:
>
> * Instead of "-gfx_passthru" we'd like to make that a machine
> option, "-machine xxx,igd-passthru=on""
> * try to make something as common shared by others like KvmGT in
> the future
> * Just read those real value from host bridge pci
> configuration space when create host bridge then put in dev->config.
>
> v6:
>
> * Drop introducing a new machine specific to IGD passthrough
> * Try to share some codes from KVM stuff in qemu to retrive VGA BIOS
> * Currently IGD drivers always need to access PCH by 1f.0. But we
> don't want to poke that directly to get ID, and although in real
> world different GPU should have different PCH. But actually the
> different PCH DIDs likely map to different PCH SKUs. We do the
> same thing for the GPU. For PCH, the different SKUs are going to
> be all the same silicon design and implementation, just different
> features turn on and off with fuses. The SW interfaces should be
> consistent across all SKUs in a given family (eg LPT). But just
> same features may not be supported.
>
> Most of these different PCH features probably don't matter to the
> Gfx driver, but obviously any difference in display port connections
> will so it should be fine with any PCH in case of passthrough.
>
> So currently use one PCH version, 0x8c4e, to cover all HSW(Haswell)
> scenarios, 0x9cc3 for BDW(Broadwell).
> * Drop igd write ops since its fine to emulate that, and we also shrink
> those igd read ops as necessary.
> * Rebase and cleanup all patches.
>
> v5:
>
> * Simplify to make sure its really inherited from the standard one in patch #3
> * Then drop the original patch #3
>
> v4:
>
> * Rebase on latest tree
> * Drop patch #2
> * Regenerate patches after Michael introduce patch #1
> * We need to use this pci_type as a index to reuse I440FX_PCI_DEVICE()
> * Test: boot with a preinstalled winxp
> ./i386-softmmu/qemu-system-i386 -hda winxp-32.img -m 2560 -boot c -machine pc
>
> v3:
>
> * Drop patch #4
> * Add one patch #1 from Michael
> * Rebase
> * In./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
>
> v2:
>
> * Fix some coding style
> * New patch to separate i440fx_init
> * Just add prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough
> * Based on patch #2 to regenerate
> * Unify prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough like patch #3
> * Test: boot with a preinstalled ubuntu 14.04
> ./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
>
> As we discussed we need to create a separate machine to support current
> IGD passthrough.
>
> ----------------------------------------------------------------
> Michael S. Tsirkin (1):
> i440fx: make types configurable at run-time
>
> Tiejun Chen (9):
> pc_init1: pass parameters just with types
> piix: create host bridge to passthrough
> hw/pci-assign: split pci-assign.c
> xen, gfx passthrough: basic graphics passthrough support
> xen, gfx passthrough: retrieve VGA BIOS to work
> igd gfx passthrough: create a isa bridge
> xen, gfx passthrough: register a isa bridge
> xen, gfx passthrough: register host bridge specific to passthrough
> xen, gfx passthrough: add opregion mapping
>
> hw/core/machine.c | 20 +++
> hw/i386/Makefile.objs | 1 +
> hw/i386/kvm/pci-assign.c | 82 +---------
> hw/i386/pc_piix.c | 151 ++++++++++++++++++-
> hw/i386/pci-assign-load-rom.c | 93 ++++++++++++
> hw/pci-host/piix.c | 91 +++++++++++-
> hw/xen/Makefile.objs | 1 +
> hw/xen/xen-host-pci-device.c | 5 +
> hw/xen/xen-host-pci-device.h | 1 +
> hw/xen/xen_pt.c | 32 ++++
> hw/xen/xen_pt.h | 21 ++-
> hw/xen/xen_pt_config_init.c | 51 ++++++-
> hw/xen/xen_pt_graphics.c | 272 ++++++++++++++++++++++++++++++++++
> include/hw/boards.h | 1 +
> include/hw/i386/pc.h | 8 +-
> include/hw/pci/pci-assign.h | 27 ++++
> include/hw/xen/xen.h | 1 +
> qemu-options.hx | 3 +
> vl.c | 10 ++
> 19 files changed, 780 insertions(+), 91 deletions(-)
> create mode 100644 hw/i386/pci-assign-load-rom.c
> create mode 100644 hw/xen/xen_pt_graphics.c
> create mode 100644 include/hw/pci/pci-assign.h
>
> Thanks
> Tiejun
>
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic graphics passthrough support
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic graphics passthrough support Tiejun Chen
@ 2015-07-01 15:45 ` Stefano Stabellini
0 siblings, 0 replies; 22+ messages in thread
From: Stefano Stabellini @ 2015-07-01 15:45 UTC (permalink / raw)
To: Tiejun Chen; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
On Fri, 5 Jun 2015, Tiejun Chen wrote:
> basic gfx passthrough support:
> - add a vga type for gfx passthrough
> - register/unregister legacy VGA I/O ports and MMIOs for passthrough GFX
>
> Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> hw/core/machine.c | 20 ++++++++
> hw/xen/Makefile.objs | 1 +
> hw/xen/xen-host-pci-device.c | 5 ++
> hw/xen/xen-host-pci-device.h | 1 +
> hw/xen/xen_pt.c | 4 ++
> hw/xen/xen_pt.h | 10 +++-
> hw/xen/xen_pt_graphics.c | 111 +++++++++++++++++++++++++++++++++++++++++++
> include/hw/boards.h | 1 +
> qemu-options.hx | 3 ++
> vl.c | 10 ++++
> 10 files changed, 165 insertions(+), 1 deletion(-)
> create mode 100644 hw/xen/xen_pt_graphics.c
>
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 25c45e6..0655665 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -226,6 +226,20 @@ static void machine_set_usb(Object *obj, bool value, Error **errp)
> ms->usb_disabled = !value;
> }
>
> +static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
> +{
> + MachineState *ms = MACHINE(obj);
> +
> + return ms->igd_gfx_passthru;
> +}
> +
> +static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
> +{
> + MachineState *ms = MACHINE(obj);
> +
> + ms->igd_gfx_passthru = value;
> +}
> +
> static char *machine_get_firmware(Object *obj, Error **errp)
> {
> MachineState *ms = MACHINE(obj);
> @@ -380,6 +394,12 @@ static void machine_initfn(Object *obj)
> object_property_set_description(obj, "usb",
> "Set on/off to enable/disable usb",
> NULL);
> + object_property_add_bool(obj, "igd-passthru",
> + machine_get_igd_gfx_passthru,
> + machine_set_igd_gfx_passthru, NULL);
> + object_property_set_description(obj, "igd-passthru",
> + "Set on/off to enable/disable igd passthrou",
> + NULL);
> object_property_add_str(obj, "firmware",
> machine_get_firmware,
> machine_set_firmware, NULL);
> diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
> index a0ca0aa..a9ad7e7 100644
> --- a/hw/xen/Makefile.objs
> +++ b/hw/xen/Makefile.objs
> @@ -3,3 +3,4 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
>
> obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
> obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
> +obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o xen_pt_graphics.o
> diff --git a/hw/xen/xen-host-pci-device.c b/hw/xen/xen-host-pci-device.c
> index 743b37b..a54b7de 100644
> --- a/hw/xen/xen-host-pci-device.c
> +++ b/hw/xen/xen-host-pci-device.c
> @@ -376,6 +376,11 @@ int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
> goto error;
> }
> d->irq = v;
> + rc = xen_host_pci_get_hex_value(d, "class", &v);
> + if (rc) {
> + goto error;
> + }
> + d->class_code = v;
> d->is_virtfn = xen_host_pci_dev_is_virtfn(d);
>
> return 0;
> diff --git a/hw/xen/xen-host-pci-device.h b/hw/xen/xen-host-pci-device.h
> index c2486f0..f1e1c30 100644
> --- a/hw/xen/xen-host-pci-device.h
> +++ b/hw/xen/xen-host-pci-device.h
> @@ -25,6 +25,7 @@ typedef struct XenHostPCIDevice {
>
> uint16_t vendor_id;
> uint16_t device_id;
> + uint32_t class_code;
> int irq;
>
> XenHostPCIIORegion io_regions[PCI_NUM_REGIONS - 1];
> diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
> index 9afcda8..50bdf6f 100644
> --- a/hw/xen/xen_pt.c
> +++ b/hw/xen/xen_pt.c
> @@ -494,6 +494,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s, uint16_t *cmd)
> d->rom.size, d->rom.base_addr);
> }
>
> + xen_pt_register_vga_regions(d);
> return 0;
> }
>
> @@ -798,6 +799,7 @@ out:
> static void xen_pt_unregister_device(PCIDevice *d)
> {
> XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
> + XenHostPCIDevice *host_dev = &s->real_device;
> uint8_t machine_irq = s->machine_irq;
> uint8_t intx = xen_pt_pci_intx(s);
> int rc;
> @@ -841,6 +843,8 @@ static void xen_pt_unregister_device(PCIDevice *d)
> /* delete all emulated config registers */
> xen_pt_config_delete(s);
>
> + xen_pt_unregister_vga_regions(host_dev);
> +
> memory_listener_unregister(&s->memory_listener);
> memory_listener_unregister(&s->io_listener);
>
> diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
> index 4bba559..dfa6171 100644
> --- a/hw/xen/xen_pt.h
> +++ b/hw/xen/xen_pt.h
> @@ -301,5 +301,13 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
> return s->msix && s->msix->bar_index == bar;
> }
>
> -
> +extern bool has_igd_gfx_passthru;
> +static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
> +{
> + return (has_igd_gfx_passthru
> + && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA));
> +}
> +int xen_pt_register_vga_regions(XenHostPCIDevice *dev);
> +int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev);
> +int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev);
> #endif /* !XEN_PT_H */
> diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
> new file mode 100644
> index 0000000..9b3df81
> --- /dev/null
> +++ b/hw/xen/xen_pt_graphics.c
> @@ -0,0 +1,111 @@
> +/*
> + * graphics passthrough
> + */
> +#include "xen_pt.h"
> +#include "xen-host-pci-device.h"
> +#include "hw/xen/xen_backend.h"
> +
> +typedef struct VGARegion {
> + int type; /* Memory or port I/O */
> + uint64_t guest_base_addr;
> + uint64_t machine_base_addr;
> + uint64_t size; /* size of the region */
> + int rc;
> +} VGARegion;
> +
> +#define IORESOURCE_IO 0x00000100
> +#define IORESOURCE_MEM 0x00000200
> +
> +static struct VGARegion vga_args[] = {
> + {
> + .type = IORESOURCE_IO,
> + .guest_base_addr = 0x3B0,
> + .machine_base_addr = 0x3B0,
> + .size = 0xC,
> + .rc = -1,
> + },
> + {
> + .type = IORESOURCE_IO,
> + .guest_base_addr = 0x3C0,
> + .machine_base_addr = 0x3C0,
> + .size = 0x20,
> + .rc = -1,
> + },
> + {
> + .type = IORESOURCE_MEM,
> + .guest_base_addr = 0xa0000 >> XC_PAGE_SHIFT,
> + .machine_base_addr = 0xa0000 >> XC_PAGE_SHIFT,
> + .size = 0x20,
> + .rc = -1,
> + },
> +};
> +
> +/*
> + * register VGA resources for the domain with assigned gfx
> + */
> +int xen_pt_register_vga_regions(XenHostPCIDevice *dev)
> +{
> + int i = 0;
> +
> + if (!is_igd_vga_passthrough(dev)) {
> + return 0;
> + }
> +
> + for (i = 0 ; i < ARRAY_SIZE(vga_args); i++) {
> + if (vga_args[i].type == IORESOURCE_IO) {
> + vga_args[i].rc = xc_domain_ioport_mapping(xen_xc, xen_domid,
> + vga_args[i].guest_base_addr,
> + vga_args[i].machine_base_addr,
> + vga_args[i].size, DPCI_ADD_MAPPING);
> + } else {
> + vga_args[i].rc = xc_domain_memory_mapping(xen_xc, xen_domid,
> + vga_args[i].guest_base_addr,
> + vga_args[i].machine_base_addr,
> + vga_args[i].size, DPCI_ADD_MAPPING);
> + }
> +
> + if (vga_args[i].rc) {
> + XEN_PT_ERR(NULL, "VGA %s mapping failed! (rc: %i)\n",
> + vga_args[i].type == IORESOURCE_IO ? "ioport" : "memory",
> + vga_args[i].rc);
> + return vga_args[i].rc;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * unregister VGA resources for the domain with assigned gfx
> + */
> +int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
> +{
> + int i = 0;
> +
> + if (!is_igd_vga_passthrough(dev)) {
> + return 0;
> + }
> +
> + for (i = 0 ; i < ARRAY_SIZE(vga_args); i++) {
> + if (vga_args[i].type == IORESOURCE_IO) {
> + vga_args[i].rc = xc_domain_ioport_mapping(xen_xc, xen_domid,
> + vga_args[i].guest_base_addr,
> + vga_args[i].machine_base_addr,
> + vga_args[i].size, DPCI_REMOVE_MAPPING);
> + } else {
> + vga_args[i].rc = xc_domain_memory_mapping(xen_xc, xen_domid,
> + vga_args[i].guest_base_addr,
> + vga_args[i].machine_base_addr,
> + vga_args[i].size, DPCI_REMOVE_MAPPING);
> + }
> +
> + if (vga_args[i].rc) {
> + XEN_PT_ERR(NULL, "VGA %s unmapping failed! (rc: %i)\n",
> + vga_args[i].type == IORESOURCE_IO ? "ioport" : "memory",
> + vga_args[i].rc);
> + return vga_args[i].rc;
> + }
> + }
> +
> + return 0;
> +}
> diff --git a/include/hw/boards.h b/include/hw/boards.h
> index ff79797..a7b75ac 100644
> --- a/include/hw/boards.h
> +++ b/include/hw/boards.h
> @@ -134,6 +134,7 @@ struct MachineState {
> bool mem_merge;
> bool usb;
> bool usb_disabled;
> + bool igd_gfx_passthru;
> char *firmware;
> bool iommu;
> bool suppress_vmdesc;
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 7edd1f1..964ba0d 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -38,6 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
> " dump-guest-core=on|off include guest memory in a core dump (default=on)\n"
> " mem-merge=on|off controls memory merge support (default: on)\n"
> " iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n"
> + " igd-passthru=on|off controls IGD GFX passthrough support (default=off)\n"
> " aes-key-wrap=on|off controls support for AES key wrapping (default=on)\n"
> " dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n"
> " suppress-vmdesc=on|off disables self-describing migration (default=off)\n",
> @@ -55,6 +56,8 @@ than one accelerator specified, the next one is used if the previous one fails
> to initialize.
> @item kernel_irqchip=on|off
> Enables in-kernel irqchip support for the chosen accelerator when available.
> +@item gfx_passthru=on|off
> +Enables IGD GFX passthrough support for the chosen machine when available.
> @item vmport=on|off|auto
> Enables emulation of VMWare IO port, for vmmouse etc. auto says to select the
> value based on accel. For accel=xen the default is off otherwise the default
> diff --git a/vl.c b/vl.c
> index 1d4c089..34c1d55 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1224,6 +1224,13 @@ static void configure_msg(QemuOpts *opts)
> enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true);
> }
>
> +/* Now we still need this for compatibility with XEN. */
> +bool has_igd_gfx_passthru;
> +static void igd_gfx_passthru(void)
> +{
> + has_igd_gfx_passthru = current_machine->igd_gfx_passthru;
> +}
> +
> /***********************************************************/
> /* USB devices */
>
> @@ -4256,6 +4263,9 @@ int main(int argc, char **argv, char **envp)
> exit(1);
> }
>
> + /* Check if IGD GFX passthrough. */
> + igd_gfx_passthru();
> +
> /* init generic devices */
> if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, 1) != 0)
> exit(1);
> --
> 1.9.1
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retrieve VGA BIOS to work
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retrieve VGA BIOS to work Tiejun Chen
@ 2015-07-01 15:51 ` Stefano Stabellini
0 siblings, 0 replies; 22+ messages in thread
From: Stefano Stabellini @ 2015-07-01 15:51 UTC (permalink / raw)
To: Tiejun Chen; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
On Fri, 5 Jun 2015, Tiejun Chen wrote:
> Now we retrieve VGA bios like kvm stuff in qemu but we need to
> fix Device Identification in case if its not matched with the
> real IGD device since Seabios is always trying to compare this
> ID to work out VGA BIOS.
>
> Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> hw/xen/xen_pt.c | 10 ++++++
> hw/xen/xen_pt.h | 5 +++
> hw/xen/xen_pt_graphics.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 94 insertions(+)
>
> diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
> index 50bdf6f..3bf2233 100644
> --- a/hw/xen/xen_pt.c
> +++ b/hw/xen/xen_pt.c
> @@ -717,6 +717,16 @@ static int xen_pt_initfn(PCIDevice *d)
> s->memory_listener = xen_pt_memory_listener;
> s->io_listener = xen_pt_io_listener;
>
> + /* Setup VGA bios for passthrough GFX */
> + if ((s->real_device.domain == 0) && (s->real_device.bus == 0) &&
> + (s->real_device.dev == 2) && (s->real_device.func == 0)) {
> + if (xen_pt_setup_vga(s, &s->real_device) < 0) {
> + XEN_PT_ERR(d, "Setup VGA BIOS of passthrough GFX failed!\n");
> + xen_host_pci_device_put(&s->real_device);
> + return -1;
> + }
> + }
> +
> /* Handle real device's MMIO/PIO BARs */
> xen_pt_register_regions(s, &cmd);
>
> diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
> index dfa6171..6c42754 100644
> --- a/hw/xen/xen_pt.h
> +++ b/hw/xen/xen_pt.h
> @@ -301,6 +301,11 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
> return s->msix && s->msix->bar_index == bar;
> }
>
> +extern 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);
> extern bool has_igd_gfx_passthru;
> static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
> {
> diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
> index 9b3df81..3232296 100644
> --- a/hw/xen/xen_pt_graphics.c
> +++ b/hw/xen/xen_pt_graphics.c
> @@ -109,3 +109,82 @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
>
> return 0;
> }
> +
> +static void *get_vgabios(XenPCIPassthroughState *s, int *size,
> + XenHostPCIDevice *dev)
> +{
> + return pci_assign_dev_load_option_rom(&s->dev, OBJECT(&s->dev), size,
> + dev->domain, dev->bus,
> + dev->dev, dev->func);
> +}
> +
> +/* Refer to Seabios. */
> +struct rom_header {
> + uint16_t signature;
> + uint8_t size;
> + uint8_t initVector[4];
> + uint8_t reserved[17];
> + uint16_t pcioffset;
> + uint16_t pnpoffset;
> +} __attribute__((packed));
> +
> +struct pci_data {
> + uint32_t signature;
> + uint16_t vendor;
> + uint16_t device;
> + uint16_t vitaldata;
> + uint16_t dlen;
> + uint8_t drevision;
> + uint8_t class_lo;
> + uint16_t class_hi;
> + uint16_t ilen;
> + uint16_t irevision;
> + uint8_t type;
> + uint8_t indicator;
> + uint16_t reserved;
> +} __attribute__((packed));
> +
> +int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
> +{
> + unsigned char *bios = NULL;
> + struct rom_header *rom;
> + int bios_size;
> + char *c = NULL;
> + char checksum = 0;
> + uint32_t len = 0;
> + struct pci_data *pd = NULL;
> +
> + if (!is_igd_vga_passthrough(dev)) {
> + return -1;
> + }
> +
> + bios = get_vgabios(s, &bios_size, dev);
> + if (!bios) {
> + XEN_PT_ERR(&s->dev, "VGA: Can't getting VBIOS!\n");
> + return -1;
> + }
> +
> + /* Currently we fixed this address as a primary. */
> + rom = (struct rom_header *)bios;
> + pd = (void *)(bios + (unsigned char)rom->pcioffset);
> +
> + /* We may need to fixup Device Identification. */
> + if (pd->device != s->real_device.device_id) {
> + pd->device = s->real_device.device_id;
> +
> + len = rom->size * 512;
> + /* Then adjust the bios checksum */
> + for (c = (char *)bios; c < ((char *)bios + len); c++) {
> + checksum += *c;
> + }
> + if (checksum) {
> + bios[len - 1] -= checksum;
> + XEN_PT_LOG(&s->dev, "vga bios checksum is adjusted %x!\n",
> + checksum);
> + }
> + }
> +
> + /* Currently we fixed this address as a primary for legacy BIOS. */
> + cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
> + return 0;
> +}
> --
> 1.9.1
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 08/10] xen, gfx passthrough: register a isa bridge
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 08/10] xen, gfx passthrough: register " Tiejun Chen
@ 2015-07-01 15:55 ` Stefano Stabellini
2015-07-03 1:51 ` Chen, Tiejun
0 siblings, 1 reply; 22+ messages in thread
From: Stefano Stabellini @ 2015-07-01 15:55 UTC (permalink / raw)
To: Tiejun Chen; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
On Fri, 5 Jun 2015, Tiejun Chen wrote:
> Currently we just register this isa bridge when we use IGD
> passthrough in Xen side.
>
> Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
> ---
> hw/xen/xen_pt.c | 18 ++++++++++++++++++
> include/hw/xen/xen.h | 1 +
> 2 files changed, 19 insertions(+)
>
> diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
> index 3bf2233..fff169d 100644
> --- a/hw/xen/xen_pt.c
> +++ b/hw/xen/xen_pt.c
> @@ -676,6 +676,21 @@ static const MemoryListener xen_pt_io_listener = {
> .priority = 10,
> };
>
> +static void
> +xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
> + XenHostPCIDevice *dev)
> +{
> + uint16_t gpu_dev_id;
> + PCIDevice *d = &s->dev;
> +
> + if (!is_igd_vga_passthrough(dev)) {
> + return;
> + }
I would rather move the if into xen_pt_initfn, otherwise reading
xen_pt_initfn it looks like we are going to create an isa bridge
regardless.
> + gpu_dev_id = dev->device_id;
> + igd_passthrough_isa_bridge_create(d->bus, gpu_dev_id);
> +}
> +
> /* init */
>
> static int xen_pt_initfn(PCIDevice *d)
> @@ -725,6 +740,9 @@ static int xen_pt_initfn(PCIDevice *d)
> xen_host_pci_device_put(&s->real_device);
> return -1;
> }
> +
> + /* Register ISA bridge for passthrough GFX. */
> + xen_igd_passthrough_isa_bridge_create(s, &s->real_device);
> }
>
> /* Handle real device's MMIO/PIO BARs */
> diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
> index 4356af4..703148e 100644
> --- a/include/hw/xen/xen.h
> +++ b/include/hw/xen/xen.h
> @@ -51,4 +51,5 @@ void xen_register_framebuffer(struct MemoryRegion *mr);
> # define HVM_MAX_VCPUS 32
> #endif
>
> +extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id);
> #endif /* QEMU_HW_XEN_H */
Either static or extern. You probably want to drop this declaration.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 09/10] xen, gfx passthrough: register host bridge specific to passthrough
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 09/10] xen, gfx passthrough: register host bridge specific to passthrough Tiejun Chen
@ 2015-07-01 15:58 ` Stefano Stabellini
2015-07-03 3:11 ` Chen, Tiejun
0 siblings, 1 reply; 22+ messages in thread
From: Stefano Stabellini @ 2015-07-01 15:58 UTC (permalink / raw)
To: Tiejun Chen; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
On Fri, 5 Jun 2015, Tiejun Chen wrote:
> Just register that pci host bridge specific to passthrough.
>
> Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
> ---
> hw/i386/pc_piix.c | 27 +++++++++++++++++++++++++--
> 1 file changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 6054b5a..938b1be 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -50,7 +50,8 @@
> #include "cpu.h"
> #include "qemu/error-report.h"
> #ifdef CONFIG_XEN
> -# include <xen/hvm/hvm_info_table.h>
> +#include <xen/hvm/hvm_info_table.h>
> +#include "hw/xen/xen_pt.h"
> #endif
>
> #define MAX_IDE_BUS 2
> @@ -442,11 +443,33 @@ static void pc_init_isa(MachineState *machine)
> }
>
> #ifdef CONFIG_XEN
> +static void igd_passthrough_pc_init_pci(MachineState *machine)
> +{
> + pc_init1(machine,
> + TYPE_I440FX_PCI_HOST_BRIDGE,
> + TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE);
> +}
> +
> +static void pc_init_pci(MachineState *machine)
> +{
> + pc_init1(machine,
> + TYPE_I440FX_PCI_HOST_BRIDGE,
> + TYPE_I440FX_PCI_DEVICE);
> +}
> +
> +static void pc_xen_hvm_init_pci(MachineState *machine)
> +{
> + if (has_igd_gfx_passthru)
> + igd_passthrough_pc_init_pci(machine);
> + else
> + pc_init_pci(machine);
> +}
I don't see any value in introducing pc_init_pci and
igd_passthrough_pc_init_pci. I would expand both of them here.
> static void pc_xen_hvm_init(MachineState *machine)
> {
> PCIBus *bus;
>
> - pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE);
> + pc_xen_hvm_init_pci(machine);
>
> bus = pci_find_primary_bus();
> if (bus != NULL) {
> --
> 1.9.1
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 10/10] xen, gfx passthrough: add opregion mapping
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 10/10] xen, gfx passthrough: add opregion mapping Tiejun Chen
@ 2015-07-01 16:01 ` Stefano Stabellini
0 siblings, 0 replies; 22+ messages in thread
From: Stefano Stabellini @ 2015-07-01 16:01 UTC (permalink / raw)
To: Tiejun Chen; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
On Fri, 5 Jun 2015, Tiejun Chen wrote:
> The OpRegion shouldn't be mapped 1:1 because the address in the host
> can't be used in the guest directly.
>
> This patch traps read and write access to the opregion of the Intel
> GPU config space (offset 0xfc).
>
> The original patch is from Jean Guyader <jean.guyader@eu.citrix.com>
>
> Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> hw/xen/xen_pt.h | 6 +++-
> hw/xen/xen_pt_config_init.c | 51 ++++++++++++++++++++++++++--
> hw/xen/xen_pt_graphics.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 136 insertions(+), 3 deletions(-)
>
> diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
> index 6c42754..aa29271 100644
> --- a/hw/xen/xen_pt.h
> +++ b/hw/xen/xen_pt.h
> @@ -36,6 +36,9 @@ typedef struct XenPTReg XenPTReg;
>
> typedef struct XenPCIPassthroughState XenPCIPassthroughState;
>
> +uint32_t igd_read_opregion(XenPCIPassthroughState *s);
> +void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
> +
> /* function type for config reg */
> typedef int (*xen_pt_conf_reg_init)
> (XenPCIPassthroughState *, XenPTRegInfo *, uint32_t real_offset,
> @@ -62,8 +65,9 @@ typedef int (*xen_pt_conf_byte_read)
> #define XEN_PT_BAR_ALLF 0xFFFFFFFF
> #define XEN_PT_BAR_UNMAPPED (-1)
>
> -#define PCI_CAP_MAX 48
> +#define XEN_PCI_CAP_MAX 48
>
> +#define XEN_PCI_INTEL_OPREGION 0xfc
>
> typedef enum {
> XEN_PT_GRP_TYPE_HARDWIRED = 0, /* 0 Hardwired reg group */
> diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
> index f3cf069..b018518 100644
> --- a/hw/xen/xen_pt_config_init.c
> +++ b/hw/xen/xen_pt_config_init.c
> @@ -553,6 +553,22 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
> return 0;
> }
>
> +static int xen_pt_intel_opregion_read(XenPCIPassthroughState *s,
> + XenPTReg *cfg_entry,
> + uint32_t *value, uint32_t valid_mask)
> +{
> + *value = igd_read_opregion(s);
> + return 0;
> +}
> +
> +static int xen_pt_intel_opregion_write(XenPCIPassthroughState *s,
> + XenPTReg *cfg_entry, uint32_t *value,
> + uint32_t dev_value, uint32_t valid_mask)
> +{
> + igd_write_opregion(s, *value);
> + return 0;
> +}
> +
> /* Header Type0 reg static information table */
> static XenPTRegInfo xen_pt_emu_reg_header0[] = {
> /* Vendor ID reg */
> @@ -1493,6 +1509,19 @@ static XenPTRegInfo xen_pt_emu_reg_msix[] = {
> },
> };
>
> +static XenPTRegInfo xen_pt_emu_reg_igd_opregion[] = {
> + /* Intel IGFX OpRegion reg */
> + {
> + .offset = 0x0,
> + .size = 4,
> + .init_val = 0,
> + .u.dw.read = xen_pt_intel_opregion_read,
> + .u.dw.write = xen_pt_intel_opregion_write,
> + },
> + {
> + .size = 0,
> + },
> +};
>
> /****************************
> * Capabilities
> @@ -1730,6 +1759,14 @@ static const XenPTRegGroupInfo xen_pt_emu_reg_grps[] = {
> .size_init = xen_pt_msix_size_init,
> .emu_regs = xen_pt_emu_reg_msix,
> },
> + /* Intel IGD Opregion group */
> + {
> + .grp_id = XEN_PCI_INTEL_OPREGION,
> + .grp_type = XEN_PT_GRP_TYPE_EMU,
> + .grp_size = 0x4,
> + .size_init = xen_pt_reg_grp_size_init,
> + .emu_regs = xen_pt_emu_reg_igd_opregion,
> + },
> {
> .grp_size = 0,
> },
> @@ -1780,7 +1817,7 @@ out:
> static uint8_t find_cap_offset(XenPCIPassthroughState *s, uint8_t cap)
> {
> uint8_t id;
> - unsigned max_cap = PCI_CAP_MAX;
> + unsigned max_cap = XEN_PCI_CAP_MAX;
> uint8_t pos = PCI_CAPABILITY_LIST;
> uint8_t status = 0;
>
> @@ -1859,7 +1896,8 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
> uint32_t reg_grp_offset = 0;
> XenPTRegGroup *reg_grp_entry = NULL;
>
> - if (xen_pt_emu_reg_grps[i].grp_id != 0xFF) {
> + if (xen_pt_emu_reg_grps[i].grp_id != 0xFF
> + && xen_pt_emu_reg_grps[i].grp_id != XEN_PCI_INTEL_OPREGION) {
> if (xen_pt_hide_dev_cap(&s->real_device,
> xen_pt_emu_reg_grps[i].grp_id)) {
> continue;
> @@ -1872,6 +1910,15 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
> }
> }
>
> + /*
> + * By default we will trap up to 0x40 in the cfg space.
> + * If an intel device is pass through we need to trap 0xfc,
> + * therefore the size should be 0xff.
> + */
> + if (xen_pt_emu_reg_grps[i].grp_id == XEN_PCI_INTEL_OPREGION) {
> + reg_grp_offset = XEN_PCI_INTEL_OPREGION;
> + }
> +
> reg_grp_entry = g_new0(XenPTRegGroup, 1);
> QLIST_INIT(®_grp_entry->reg_tbl_list);
> QLIST_INSERT_HEAD(&s->reg_grps, reg_grp_entry, entries);
> diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
> index 3232296..df6069b 100644
> --- a/hw/xen/xen_pt_graphics.c
> +++ b/hw/xen/xen_pt_graphics.c
> @@ -5,6 +5,11 @@
> #include "xen-host-pci-device.h"
> #include "hw/xen/xen_backend.h"
>
> +static unsigned long igd_guest_opregion;
> +static unsigned long igd_host_opregion;
> +
> +#define XEN_PCI_INTEL_OPREGION_MASK 0xfff
> +
> typedef struct VGARegion {
> int type; /* Memory or port I/O */
> uint64_t guest_base_addr;
> @@ -81,6 +86,7 @@ int xen_pt_register_vga_regions(XenHostPCIDevice *dev)
> int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
> {
> int i = 0;
> + int ret = 0;
>
> if (!is_igd_vga_passthrough(dev)) {
> return 0;
> @@ -107,6 +113,17 @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
> }
> }
>
> + if (igd_guest_opregion) {
> + ret = xc_domain_memory_mapping(xen_xc, xen_domid,
> + (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
> + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> + 3,
> + DPCI_REMOVE_MAPPING);
> + if (ret) {
> + return ret;
> + }
> + }
> +
> return 0;
> }
>
> @@ -188,3 +205,68 @@ int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
> cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
> return 0;
> }
> +
> +uint32_t igd_read_opregion(XenPCIPassthroughState *s)
> +{
> + uint32_t val = 0;
> +
> + if (!igd_guest_opregion) {
> + return val;
> + }
> +
> + val = igd_guest_opregion;
> +
> + XEN_PT_LOG(&s->dev, "Read opregion val=%x\n", val);
> + return val;
> +}
> +
> +#define XEN_PCI_INTEL_OPREGION_PAGES 0x3
> +#define XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED 0x1
> +void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val)
> +{
> + int ret;
> +
> + if (igd_guest_opregion) {
> + XEN_PT_LOG(&s->dev, "opregion register already been set, ignoring %x\n",
> + val);
> + return;
> + }
> +
> + /* We just work with LE. */
> + xen_host_pci_get_block(&s->real_device, XEN_PCI_INTEL_OPREGION,
> + (uint8_t *)&igd_host_opregion, 4);
> + igd_guest_opregion = (unsigned long)(val & ~XEN_PCI_INTEL_OPREGION_MASK)
> + | (igd_host_opregion & XEN_PCI_INTEL_OPREGION_MASK);
> +
> + ret = xc_domain_iomem_permission(xen_xc, xen_domid,
> + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> + XEN_PCI_INTEL_OPREGION_PAGES,
> + XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED);
> +
> + if (ret) {
> + XEN_PT_ERR(&s->dev, "[%d]:Can't enable to access IGD host opregion:"
> + " 0x%lx.\n", ret,
> + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT)),
> + igd_guest_opregion = 0;
> + return;
> + }
> +
> + ret = xc_domain_memory_mapping(xen_xc, xen_domid,
> + (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
> + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> + XEN_PCI_INTEL_OPREGION_PAGES,
> + DPCI_ADD_MAPPING);
> +
> + if (ret) {
> + XEN_PT_ERR(&s->dev, "[%d]:Can't map IGD host opregion:0x%lx to"
> + " guest opregion:0x%lx.\n", ret,
> + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> + (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
> + igd_guest_opregion = 0;
> + return;
> + }
> +
> + XEN_PT_LOG(&s->dev, "Map OpRegion: 0x%lx -> 0x%lx\n",
> + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> + (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
> +}
> --
> 1.9.1
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough
2015-07-01 1:39 ` [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Chen, Tiejun
@ 2015-07-01 16:03 ` Stefano Stabellini
2015-07-03 3:17 ` Chen, Tiejun
0 siblings, 1 reply; 22+ messages in thread
From: Stefano Stabellini @ 2015-07-01 16:03 UTC (permalink / raw)
To: Chen, Tiejun; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
Aside from a couple of really minor stylistic issues, I think the patch
series can go in from my point of view. However it looks like you are
still missing a few acked-by/reviewed-by on the non-xen patches.
On Wed, 1 Jul 2015, Chen, Tiejun wrote:
> Ping...
>
> Thanks
> Tiejun
>
> On 2015/6/5 16:44, Tiejun Chen wrote:
> > v8:
> >
> > * Rebase on the latest qemu tree
> > * Cleanup one xen leftover in patch #3
> >
> > v7:
> >
> > * Instead of "-gfx_passthru" we'd like to make that a machine
> > option, "-machine xxx,igd-passthru=on""
> > * try to make something as common shared by others like KvmGT in
> > the future
> > * Just read those real value from host bridge pci
> > configuration space when create host bridge then put in dev->config.
> >
> > v6:
> >
> > * Drop introducing a new machine specific to IGD passthrough
> > * Try to share some codes from KVM stuff in qemu to retrive VGA BIOS
> > * Currently IGD drivers always need to access PCH by 1f.0. But we
> > don't want to poke that directly to get ID, and although in real
> > world different GPU should have different PCH. But actually the
> > different PCH DIDs likely map to different PCH SKUs. We do the
> > same thing for the GPU. For PCH, the different SKUs are going to
> > be all the same silicon design and implementation, just different
> > features turn on and off with fuses. The SW interfaces should be
> > consistent across all SKUs in a given family (eg LPT). But just
> > same features may not be supported.
> >
> > Most of these different PCH features probably don't matter to the
> > Gfx driver, but obviously any difference in display port connections
> > will so it should be fine with any PCH in case of passthrough.
> >
> > So currently use one PCH version, 0x8c4e, to cover all HSW(Haswell)
> > scenarios, 0x9cc3 for BDW(Broadwell).
> > * Drop igd write ops since its fine to emulate that, and we also shrink
> > those igd read ops as necessary.
> > * Rebase and cleanup all patches.
> >
> > v5:
> >
> > * Simplify to make sure its really inherited from the standard one in patch
> > #3
> > * Then drop the original patch #3
> >
> > v4:
> >
> > * Rebase on latest tree
> > * Drop patch #2
> > * Regenerate patches after Michael introduce patch #1
> > * We need to use this pci_type as a index to reuse I440FX_PCI_DEVICE()
> > * Test: boot with a preinstalled winxp
> > ./i386-softmmu/qemu-system-i386 -hda winxp-32.img -m 2560 -boot c
> > -machine pc
> >
> > v3:
> >
> > * Drop patch #4
> > * Add one patch #1 from Michael
> > * Rebase
> > * In./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine
> > pc
> >
> > v2:
> >
> > * Fix some coding style
> > * New patch to separate i440fx_init
> > * Just add prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough
> > * Based on patch #2 to regenerate
> > * Unify prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough like patch #3
> > * Test: boot with a preinstalled ubuntu 14.04
> > ./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
> >
> > As we discussed we need to create a separate machine to support current
> > IGD passthrough.
> >
> > ----------------------------------------------------------------
> > Michael S. Tsirkin (1):
> > i440fx: make types configurable at run-time
> >
> > Tiejun Chen (9):
> > pc_init1: pass parameters just with types
> > piix: create host bridge to passthrough
> > hw/pci-assign: split pci-assign.c
> > xen, gfx passthrough: basic graphics passthrough support
> > xen, gfx passthrough: retrieve VGA BIOS to work
> > igd gfx passthrough: create a isa bridge
> > xen, gfx passthrough: register a isa bridge
> > xen, gfx passthrough: register host bridge specific to passthrough
> > xen, gfx passthrough: add opregion mapping
> >
> > hw/core/machine.c | 20 +++
> > hw/i386/Makefile.objs | 1 +
> > hw/i386/kvm/pci-assign.c | 82 +---------
> > hw/i386/pc_piix.c | 151 ++++++++++++++++++-
> > hw/i386/pci-assign-load-rom.c | 93 ++++++++++++
> > hw/pci-host/piix.c | 91 +++++++++++-
> > hw/xen/Makefile.objs | 1 +
> > hw/xen/xen-host-pci-device.c | 5 +
> > hw/xen/xen-host-pci-device.h | 1 +
> > hw/xen/xen_pt.c | 32 ++++
> > hw/xen/xen_pt.h | 21 ++-
> > hw/xen/xen_pt_config_init.c | 51 ++++++-
> > hw/xen/xen_pt_graphics.c | 272 ++++++++++++++++++++++++++++++++++
> > include/hw/boards.h | 1 +
> > include/hw/i386/pc.h | 8 +-
> > include/hw/pci/pci-assign.h | 27 ++++
> > include/hw/xen/xen.h | 1 +
> > qemu-options.hx | 3 +
> > vl.c | 10 ++
> > 19 files changed, 780 insertions(+), 91 deletions(-)
> > create mode 100644 hw/i386/pci-assign-load-rom.c
> > create mode 100644 hw/xen/xen_pt_graphics.c
> > create mode 100644 include/hw/pci/pci-assign.h
> >
> > Thanks
> > Tiejun
> >
> >
> >
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
` (10 preceding siblings ...)
2015-07-01 1:39 ` [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Chen, Tiejun
@ 2015-07-02 6:22 ` Michael S. Tsirkin
11 siblings, 0 replies; 22+ messages in thread
From: Michael S. Tsirkin @ 2015-07-02 6:22 UTC (permalink / raw)
To: Tiejun Chen; +Cc: qemu-devel, pbonzini, ehabkost, rth
On Fri, Jun 05, 2015 at 04:44:51PM +0800, Tiejun Chen wrote:
> v8:
>
> * Rebase on the latest qemu tree
> * Cleanup one xen leftover in patch #3
For the PC bits:
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> v7:
>
> * Instead of "-gfx_passthru" we'd like to make that a machine
> option, "-machine xxx,igd-passthru=on""
> * try to make something as common shared by others like KvmGT in
> the future
> * Just read those real value from host bridge pci
> configuration space when create host bridge then put in dev->config.
>
> v6:
>
> * Drop introducing a new machine specific to IGD passthrough
> * Try to share some codes from KVM stuff in qemu to retrive VGA BIOS
> * Currently IGD drivers always need to access PCH by 1f.0. But we
> don't want to poke that directly to get ID, and although in real
> world different GPU should have different PCH. But actually the
> different PCH DIDs likely map to different PCH SKUs. We do the
> same thing for the GPU. For PCH, the different SKUs are going to
> be all the same silicon design and implementation, just different
> features turn on and off with fuses. The SW interfaces should be
> consistent across all SKUs in a given family (eg LPT). But just
> same features may not be supported.
>
> Most of these different PCH features probably don't matter to the
> Gfx driver, but obviously any difference in display port connections
> will so it should be fine with any PCH in case of passthrough.
>
> So currently use one PCH version, 0x8c4e, to cover all HSW(Haswell)
> scenarios, 0x9cc3 for BDW(Broadwell).
> * Drop igd write ops since its fine to emulate that, and we also shrink
> those igd read ops as necessary.
> * Rebase and cleanup all patches.
>
> v5:
>
> * Simplify to make sure its really inherited from the standard one in patch #3
> * Then drop the original patch #3
>
> v4:
>
> * Rebase on latest tree
> * Drop patch #2
> * Regenerate patches after Michael introduce patch #1
> * We need to use this pci_type as a index to reuse I440FX_PCI_DEVICE()
> * Test: boot with a preinstalled winxp
> ./i386-softmmu/qemu-system-i386 -hda winxp-32.img -m 2560 -boot c -machine pc
>
> v3:
>
> * Drop patch #4
> * Add one patch #1 from Michael
> * Rebase
> * In./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
>
> v2:
>
> * Fix some coding style
> * New patch to separate i440fx_init
> * Just add prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough
> * Based on patch #2 to regenerate
> * Unify prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough like patch #3
> * Test: boot with a preinstalled ubuntu 14.04
> ./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
>
> As we discussed we need to create a separate machine to support current
> IGD passthrough.
>
> ----------------------------------------------------------------
> Michael S. Tsirkin (1):
> i440fx: make types configurable at run-time
>
> Tiejun Chen (9):
> pc_init1: pass parameters just with types
> piix: create host bridge to passthrough
> hw/pci-assign: split pci-assign.c
> xen, gfx passthrough: basic graphics passthrough support
> xen, gfx passthrough: retrieve VGA BIOS to work
> igd gfx passthrough: create a isa bridge
> xen, gfx passthrough: register a isa bridge
> xen, gfx passthrough: register host bridge specific to passthrough
> xen, gfx passthrough: add opregion mapping
>
> hw/core/machine.c | 20 +++
> hw/i386/Makefile.objs | 1 +
> hw/i386/kvm/pci-assign.c | 82 +---------
> hw/i386/pc_piix.c | 151 ++++++++++++++++++-
> hw/i386/pci-assign-load-rom.c | 93 ++++++++++++
> hw/pci-host/piix.c | 91 +++++++++++-
> hw/xen/Makefile.objs | 1 +
> hw/xen/xen-host-pci-device.c | 5 +
> hw/xen/xen-host-pci-device.h | 1 +
> hw/xen/xen_pt.c | 32 ++++
> hw/xen/xen_pt.h | 21 ++-
> hw/xen/xen_pt_config_init.c | 51 ++++++-
> hw/xen/xen_pt_graphics.c | 272 ++++++++++++++++++++++++++++++++++
> include/hw/boards.h | 1 +
> include/hw/i386/pc.h | 8 +-
> include/hw/pci/pci-assign.h | 27 ++++
> include/hw/xen/xen.h | 1 +
> qemu-options.hx | 3 +
> vl.c | 10 ++
> 19 files changed, 780 insertions(+), 91 deletions(-)
> create mode 100644 hw/i386/pci-assign-load-rom.c
> create mode 100644 hw/xen/xen_pt_graphics.c
> create mode 100644 include/hw/pci/pci-assign.h
>
> Thanks
> Tiejun
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 08/10] xen, gfx passthrough: register a isa bridge
2015-07-01 15:55 ` Stefano Stabellini
@ 2015-07-03 1:51 ` Chen, Tiejun
0 siblings, 0 replies; 22+ messages in thread
From: Chen, Tiejun @ 2015-07-03 1:51 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
>> +static void
>> +xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
>> + XenHostPCIDevice *dev)
>> +{
>> + uint16_t gpu_dev_id;
>> + PCIDevice *d = &s->dev;
>> +
>> + if (!is_igd_vga_passthrough(dev)) {
>> + return;
>> + }
>
> I would rather move the if into xen_pt_initfn, otherwise reading
> xen_pt_initfn it looks like we are going to create an isa bridge
> regardless.
This makes sense.
>
>
>> + gpu_dev_id = dev->device_id;
>> + igd_passthrough_isa_bridge_create(d->bus, gpu_dev_id);
>> +}
>> +
>> /* init */
>>
>> static int xen_pt_initfn(PCIDevice *d)
>> @@ -725,6 +740,9 @@ static int xen_pt_initfn(PCIDevice *d)
I'd like to add something like,
if (!is_igd_vga_passthrough(&s->real_device)) {
XEN_PT_ERR(d, "Need to enable igd-passthru if you're trying"
" to passthrough IGD GFX.\n");
xen_host_pci_device_put(&s->real_device);
return -1;
}
>> xen_host_pci_device_put(&s->real_device);
>> return -1;
>> }
>> +
>> + /* Register ISA bridge for passthrough GFX. */
>> + xen_igd_passthrough_isa_bridge_create(s, &s->real_device);
>> }
>>
>> /* Handle real device's MMIO/PIO BARs */
>> diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
>> index 4356af4..703148e 100644
>> --- a/include/hw/xen/xen.h
>> +++ b/include/hw/xen/xen.h
>> @@ -51,4 +51,5 @@ void xen_register_framebuffer(struct MemoryRegion *mr);
>> # define HVM_MAX_VCPUS 32
>> #endif
>>
>> +extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id);
>> #endif /* QEMU_HW_XEN_H */
>
> Either static or extern. You probably want to drop this declaration.
>
I just guess you're confused between igd_passthrough_isa_bridge_create()
and xen_igd_passthrough_isa_bridge_create(), or am I wrong?
Note igd_passthrough_isa_bridge_create() is defined in the pc_piix.c file.
Thanks
Tiejun
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 09/10] xen, gfx passthrough: register host bridge specific to passthrough
2015-07-01 15:58 ` Stefano Stabellini
@ 2015-07-03 3:11 ` Chen, Tiejun
0 siblings, 0 replies; 22+ messages in thread
From: Chen, Tiejun @ 2015-07-03 3:11 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: qemu-devel, pbonzini, rth, ehabkost, mst
>> #ifdef CONFIG_XEN
>> +static void igd_passthrough_pc_init_pci(MachineState *machine)
>> +{
>> + pc_init1(machine,
>> + TYPE_I440FX_PCI_HOST_BRIDGE,
>> + TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE);
>> +}
>> +
>> +static void pc_init_pci(MachineState *machine)
>> +{
>> + pc_init1(machine,
>> + TYPE_I440FX_PCI_HOST_BRIDGE,
>> + TYPE_I440FX_PCI_DEVICE);
>> +}
>> +
>> +static void pc_xen_hvm_init_pci(MachineState *machine)
>> +{
>> + if (has_igd_gfx_passthru)
>> + igd_passthrough_pc_init_pci(machine);
>> + else
>> + pc_init_pci(machine);
>> +}
>
> I don't see any value in introducing pc_init_pci and
> igd_passthrough_pc_init_pci. I would expand both of them here.
>
Agree, and what about this?
static void pc_xen_hvm_init_pci(MachineState *machine)
{
const char *pci_type = has_igd_gfx_passthru ?
TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE :
TYPE_I440FX_PCI_DEVICE;
pc_init1(machine,
TYPE_I440FX_PCI_HOST_BRIDGE,
pci_type);
}
Thanks
Tiejun
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough
2015-07-01 16:03 ` Stefano Stabellini
@ 2015-07-03 3:17 ` Chen, Tiejun
0 siblings, 0 replies; 22+ messages in thread
From: Chen, Tiejun @ 2015-07-03 3:17 UTC (permalink / raw)
To: Stefano Stabellini, mst; +Cc: qemu-devel, pbonzini, ehabkost, rth
On 2015/7/2 0:03, Stefano Stabellini wrote:
> Aside from a couple of really minor stylistic issues, I think the patch
Thanks for your review.
> series can go in from my point of view. However it looks like you are
> still missing a few acked-by/reviewed-by on the non-xen patches.
Just yesterday Michael Acked them :)
Note once you're fine to my replies to your previous comments, I'd like
to rebase them on the latest and then send out the last revision adding
Acked-by with you and Michael.
Thanks
Tiejun
>
> On Wed, 1 Jul 2015, Chen, Tiejun wrote:
>> Ping...
>>
>> Thanks
>> Tiejun
>>
>> On 2015/6/5 16:44, Tiejun Chen wrote:
>>> v8:
>>>
>>> * Rebase on the latest qemu tree
>>> * Cleanup one xen leftover in patch #3
>>>
>>> v7:
>>>
>>> * Instead of "-gfx_passthru" we'd like to make that a machine
>>> option, "-machine xxx,igd-passthru=on""
>>> * try to make something as common shared by others like KvmGT in
>>> the future
>>> * Just read those real value from host bridge pci
>>> configuration space when create host bridge then put in dev->config.
>>>
>>> v6:
>>>
>>> * Drop introducing a new machine specific to IGD passthrough
>>> * Try to share some codes from KVM stuff in qemu to retrive VGA BIOS
>>> * Currently IGD drivers always need to access PCH by 1f.0. But we
>>> don't want to poke that directly to get ID, and although in real
>>> world different GPU should have different PCH. But actually the
>>> different PCH DIDs likely map to different PCH SKUs. We do the
>>> same thing for the GPU. For PCH, the different SKUs are going to
>>> be all the same silicon design and implementation, just different
>>> features turn on and off with fuses. The SW interfaces should be
>>> consistent across all SKUs in a given family (eg LPT). But just
>>> same features may not be supported.
>>>
>>> Most of these different PCH features probably don't matter to the
>>> Gfx driver, but obviously any difference in display port connections
>>> will so it should be fine with any PCH in case of passthrough.
>>>
>>> So currently use one PCH version, 0x8c4e, to cover all HSW(Haswell)
>>> scenarios, 0x9cc3 for BDW(Broadwell).
>>> * Drop igd write ops since its fine to emulate that, and we also shrink
>>> those igd read ops as necessary.
>>> * Rebase and cleanup all patches.
>>>
>>> v5:
>>>
>>> * Simplify to make sure its really inherited from the standard one in patch
>>> #3
>>> * Then drop the original patch #3
>>>
>>> v4:
>>>
>>> * Rebase on latest tree
>>> * Drop patch #2
>>> * Regenerate patches after Michael introduce patch #1
>>> * We need to use this pci_type as a index to reuse I440FX_PCI_DEVICE()
>>> * Test: boot with a preinstalled winxp
>>> ./i386-softmmu/qemu-system-i386 -hda winxp-32.img -m 2560 -boot c
>>> -machine pc
>>>
>>> v3:
>>>
>>> * Drop patch #4
>>> * Add one patch #1 from Michael
>>> * Rebase
>>> * In./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine
>>> pc
>>>
>>> v2:
>>>
>>> * Fix some coding style
>>> * New patch to separate i440fx_init
>>> * Just add prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough
>>> * Based on patch #2 to regenerate
>>> * Unify prefix with XEN_IGD_PASSTHROUGH/xen_igd_passthrough like patch #3
>>> * Test: boot with a preinstalled ubuntu 14.04
>>> ./i386-softmmu/qemu-system-i386 -hda test.img -m 2560 -boot c -machine pc
>>>
>>> As we discussed we need to create a separate machine to support current
>>> IGD passthrough.
>>>
>>> ----------------------------------------------------------------
>>> Michael S. Tsirkin (1):
>>> i440fx: make types configurable at run-time
>>>
>>> Tiejun Chen (9):
>>> pc_init1: pass parameters just with types
>>> piix: create host bridge to passthrough
>>> hw/pci-assign: split pci-assign.c
>>> xen, gfx passthrough: basic graphics passthrough support
>>> xen, gfx passthrough: retrieve VGA BIOS to work
>>> igd gfx passthrough: create a isa bridge
>>> xen, gfx passthrough: register a isa bridge
>>> xen, gfx passthrough: register host bridge specific to passthrough
>>> xen, gfx passthrough: add opregion mapping
>>>
>>> hw/core/machine.c | 20 +++
>>> hw/i386/Makefile.objs | 1 +
>>> hw/i386/kvm/pci-assign.c | 82 +---------
>>> hw/i386/pc_piix.c | 151 ++++++++++++++++++-
>>> hw/i386/pci-assign-load-rom.c | 93 ++++++++++++
>>> hw/pci-host/piix.c | 91 +++++++++++-
>>> hw/xen/Makefile.objs | 1 +
>>> hw/xen/xen-host-pci-device.c | 5 +
>>> hw/xen/xen-host-pci-device.h | 1 +
>>> hw/xen/xen_pt.c | 32 ++++
>>> hw/xen/xen_pt.h | 21 ++-
>>> hw/xen/xen_pt_config_init.c | 51 ++++++-
>>> hw/xen/xen_pt_graphics.c | 272 ++++++++++++++++++++++++++++++++++
>>> include/hw/boards.h | 1 +
>>> include/hw/i386/pc.h | 8 +-
>>> include/hw/pci/pci-assign.h | 27 ++++
>>> include/hw/xen/xen.h | 1 +
>>> qemu-options.hx | 3 +
>>> vl.c | 10 ++
>>> 19 files changed, 780 insertions(+), 91 deletions(-)
>>> create mode 100644 hw/i386/pci-assign-load-rom.c
>>> create mode 100644 hw/xen/xen_pt_graphics.c
>>> create mode 100644 include/hw/pci/pci-assign.h
>>>
>>> Thanks
>>> Tiejun
>>>
>>>
>>>
>>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2015-07-03 3:17 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-05 8:44 [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 01/10] i440fx: make types configurable at run-time Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 02/10] pc_init1: pass parameters just with types Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 03/10] piix: create host bridge to passthrough Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 04/10] hw/pci-assign: split pci-assign.c Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic graphics passthrough support Tiejun Chen
2015-07-01 15:45 ` Stefano Stabellini
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retrieve VGA BIOS to work Tiejun Chen
2015-07-01 15:51 ` Stefano Stabellini
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 07/10] igd gfx passthrough: create a isa bridge Tiejun Chen
2015-06-05 8:44 ` [Qemu-devel] [v8][RESEND][PATCH 08/10] xen, gfx passthrough: register " Tiejun Chen
2015-07-01 15:55 ` Stefano Stabellini
2015-07-03 1:51 ` Chen, Tiejun
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 09/10] xen, gfx passthrough: register host bridge specific to passthrough Tiejun Chen
2015-07-01 15:58 ` Stefano Stabellini
2015-07-03 3:11 ` Chen, Tiejun
2015-06-05 8:45 ` [Qemu-devel] [v8][RESEND][PATCH 10/10] xen, gfx passthrough: add opregion mapping Tiejun Chen
2015-07-01 16:01 ` Stefano Stabellini
2015-07-01 1:39 ` [Qemu-devel] [v8][RESEND][PATCH 00/10] xen: add Intel IGD passthrough Chen, Tiejun
2015-07-01 16:03 ` Stefano Stabellini
2015-07-03 3:17 ` Chen, Tiejun
2015-07-02 6:22 ` Michael S. Tsirkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).