* [Qemu-devel] [PATCH 1/3] qemu: [NOT FOR COMMIT] Update linux headers for vfio VGA
2013-01-07 22:21 [Qemu-devel] [PATCH 0/3] Towards vfio-base VGA device assignment Alex Williamson
@ 2013-01-07 22:22 ` Alex Williamson
2013-01-07 22:22 ` [Qemu-devel] [PATCH 2/3] vfio-pci: [NOT FOR COMMIT] Add support for VGA MMIO and I/O port access Alex Williamson
2013-01-07 22:22 ` [Qemu-devel] [PATCH 3/3] vfio-pci: [NOT FOR COMMIT] Hack around HD5450 I/O port backdoor Alex Williamson
2 siblings, 0 replies; 4+ messages in thread
From: Alex Williamson @ 2013-01-07 22:22 UTC (permalink / raw)
To: alex.williamson, kvm; +Cc: qemu-devel
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
| 86 ++++++++++++++++++++++++++++++++++
| 13 +++--
| 21 ++++++--
| 6 +-
| 9 ++--
| 6 +-
| 6 +-
7 files changed, 124 insertions(+), 23 deletions(-)
--git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 1bea4d8..2fba8a6 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -221,6 +221,12 @@ struct kvm_sregs {
__u32 dbsr; /* KVM_SREGS_E_UPDATE_DBSR */
__u32 dbcr[3];
+ /*
+ * iac/dac registers are 64bit wide, while this API
+ * interface provides only lower 32 bits on 64 bit
+ * processors. ONE_REG interface is added for 64bit
+ * iac/dac registers.
+ */
__u32 iac[4];
__u32 dac[2];
__u32 dvc[2];
@@ -325,6 +331,86 @@ struct kvm_book3e_206_tlb_params {
__u32 reserved[8];
};
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+ __u64 flags;
+ __u64 start_index;
+ __u64 reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY ((__u64)0x1)
+#define KVM_GET_HTAB_WRITE ((__u64)0x2)
+
+/*
+ * Data read on the file descriptor is formatted as a series of
+ * records, each consisting of a header followed by a series of
+ * `n_valid' HPTEs (16 bytes each), which are all valid. Following
+ * those valid HPTEs there are `n_invalid' invalid HPTEs, which
+ * are not represented explicitly in the stream. The same format
+ * is used for writing.
+ */
+struct kvm_get_htab_header {
+ __u32 index;
+ __u16 n_valid;
+ __u16 n_invalid;
+};
+
#define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_PPC_DABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_PPC_DSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
+#define KVM_REG_PPC_PURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
+#define KVM_REG_PPC_SPURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
+#define KVM_REG_PPC_DAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
+#define KVM_REG_PPC_DSISR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
+#define KVM_REG_PPC_AMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
+#define KVM_REG_PPC_UAMOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
+
+#define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
+#define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
+#define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+
+#define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
+#define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
+#define KVM_REG_PPC_PMC3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
+#define KVM_REG_PPC_PMC4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
+#define KVM_REG_PPC_PMC5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
+#define KVM_REG_PPC_PMC6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
+#define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
+#define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
+
+/* 32 floating-point registers */
+#define KVM_REG_PPC_FPR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
+#define KVM_REG_PPC_FPR(n) (KVM_REG_PPC_FPR0 + (n))
+#define KVM_REG_PPC_FPR31 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
+
+/* 32 VMX/Altivec vector registers */
+#define KVM_REG_PPC_VR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
+#define KVM_REG_PPC_VR(n) (KVM_REG_PPC_VR0 + (n))
+#define KVM_REG_PPC_VR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
+
+/* 32 double-width FP registers for VSX */
+/* High-order halves overlap with FP regs */
+#define KVM_REG_PPC_VSR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
+#define KVM_REG_PPC_VSR(n) (KVM_REG_PPC_VSR0 + (n))
+#define KVM_REG_PPC_VSR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
+
+/* FP and vector status/control registers */
+#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
+
+/* Virtual processor areas */
+/* For SLB & DTL, address in high (first) half, length in low half */
+#define KVM_REG_PPC_VPA_ADDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
+#define KVM_REG_PPC_VPA_SLB (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
+#define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
+
+#define KVM_REG_PPC_EPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
#endif /* __LINUX_KVM_POWERPC_H */
--git a/linux-headers/asm-powerpc/kvm_para.h b/linux-headers/asm-powerpc/kvm_para.h
index 5e04383..484bcaa 100644
--- a/linux-headers/asm-powerpc/kvm_para.h
+++ b/linux-headers/asm-powerpc/kvm_para.h
@@ -17,8 +17,8 @@
* Authors: Hollis Blanchard <hollisb@us.ibm.com>
*/
-#ifndef _UAPI__POWERPC_KVM_PARA_H__
-#define _UAPI__POWERPC_KVM_PARA_H__
+#ifndef __POWERPC_KVM_PARA_H__
+#define __POWERPC_KVM_PARA_H__
#include <linux/types.h>
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
};
#define KVM_SC_MAGIC_R0 0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM (42 << 16)
-#define HC_EV_SUCCESS 0
-#define HC_EV_UNIMPLEMENTED 12
+
+#define KVM_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <uapi/asm/epapr_hcalls.h>
#define KVM_FEATURE_MAGIC_PAGE 1
@@ -87,4 +88,4 @@ struct kvm_vcpu_arch_shared {
#define KVM_MAGIC_FEAT_MAS0_TO_SPRG7 (1 << 1)
-#endif /* _UAPI__POWERPC_KVM_PARA_H__ */
+#endif /* __POWERPC_KVM_PARA_H__ */
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 81d2feb..bfdbf4d 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -167,10 +167,15 @@ struct kvm_pit_config {
#define KVM_EXIT_OSI 18
#define KVM_EXIT_PAPR_HCALL 19
#define KVM_EXIT_S390_UCONTROL 20
+#define KVM_EXIT_WATCHDOG 21
/* For KVM_EXIT_INTERNAL_ERROR */
-#define KVM_INTERNAL_ERROR_EMULATION 1
-#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Emulate instruction failed. */
+#define KVM_INTERNAL_ERROR_EMULATION 1
+/* Encounter unexpected simultaneous exceptions. */
+#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Encounter unexpected vm-exit due to delivery event. */
+#define KVM_INTERNAL_ERROR_DELIVERY_EV 3
/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
struct kvm_run {
@@ -477,6 +482,8 @@ struct kvm_ppc_smmu_info {
struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
};
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
+
#define KVMIO 0xAE
/* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -626,6 +633,8 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_READONLY_MEM 81
#endif
#define KVM_CAP_IRQFD_RESAMPLE 82
+#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
+#define KVM_CAP_PPC_HTAB_FD 84
#ifdef KVM_CAP_IRQ_ROUTING
@@ -848,6 +857,11 @@ struct kvm_s390_ucas_mapping {
#define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info)
/* Available with KVM_CAP_PPC_ALLOC_HTAB */
#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32)
+#define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_PPC_HTAB_FD */
+#define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)
/*
* ioctls for vcpu fds
@@ -911,9 +925,6 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_XCRS */
#define KVM_GET_XCRS _IOR(KVMIO, 0xa6, struct kvm_xcrs)
#define KVM_SET_XCRS _IOW(KVMIO, 0xa7, struct kvm_xcrs)
-#define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce)
-/* Available with KVM_CAP_RMA */
-#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
/* Available with KVM_CAP_SW_TLB */
#define KVM_DIRTY_TLB _IOW(KVMIO, 0xaa, struct kvm_dirty_tlb)
/* Available with KVM_CAP_ONE_REG */
--git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
index cea2c5c..7bdcf93 100644
--- a/linux-headers/linux/kvm_para.h
+++ b/linux-headers/linux/kvm_para.h
@@ -1,5 +1,5 @@
-#ifndef _UAPI__LINUX_KVM_PARA_H
-#define _UAPI__LINUX_KVM_PARA_H
+#ifndef __LINUX_KVM_PARA_H
+#define __LINUX_KVM_PARA_H
/*
* This header file provides a method for making a hypercall to the host
@@ -25,4 +25,4 @@
*/
#include <asm/kvm_para.h>
-#endif /* _UAPI__LINUX_KVM_PARA_H */
+#endif /* __LINUX_KVM_PARA_H */
--git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 4758d1b..1effe3f 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -8,8 +8,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#ifndef _UAPIVFIO_H
-#define _UAPIVFIO_H
+#ifndef VFIO_H
+#define VFIO_H
#include <linux/types.h>
#include <linux/ioctl.h>
@@ -147,6 +147,7 @@ struct vfio_device_info {
__u32 flags;
#define VFIO_DEVICE_FLAGS_RESET (1 << 0) /* Device supports reset */
#define VFIO_DEVICE_FLAGS_PCI (1 << 1) /* vfio-pci device */
+#define VFIO_DEVICE_FLAGS_VGA (1 << 2) /* Device supports VGA ranges */
__u32 num_regions; /* Max region index + 1 */
__u32 num_irqs; /* Max IRQ index + 1 */
};
@@ -303,6 +304,8 @@ enum {
VFIO_PCI_BAR5_REGION_INDEX,
VFIO_PCI_ROM_REGION_INDEX,
VFIO_PCI_CONFIG_REGION_INDEX,
+ VFIO_PCI_LEGACY_MMIO_REGION_INDEX,
+ VFIO_PCI_LEGACY_IOPORT_REGION_INDEX,
VFIO_PCI_NUM_REGIONS
};
@@ -365,4 +368,4 @@ struct vfio_iommu_type1_dma_unmap {
#define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14)
-#endif /* _UAPIVFIO_H */
+#endif /* VFIO_H */
--git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h
index b7cda39..4f51d8f 100644
--- a/linux-headers/linux/virtio_config.h
+++ b/linux-headers/linux/virtio_config.h
@@ -1,5 +1,5 @@
-#ifndef _UAPI_LINUX_VIRTIO_CONFIG_H
-#define _UAPI_LINUX_VIRTIO_CONFIG_H
+#ifndef _LINUX_VIRTIO_CONFIG_H
+#define _LINUX_VIRTIO_CONFIG_H
/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
* anyone can use the definitions to implement compatible drivers/servers.
*
@@ -51,4 +51,4 @@
* suppressed them? */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
-#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
+#endif /* _LINUX_VIRTIO_CONFIG_H */
--git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h
index 921694a..1b333e2 100644
--- a/linux-headers/linux/virtio_ring.h
+++ b/linux-headers/linux/virtio_ring.h
@@ -1,5 +1,5 @@
-#ifndef _UAPI_LINUX_VIRTIO_RING_H
-#define _UAPI_LINUX_VIRTIO_RING_H
+#ifndef _LINUX_VIRTIO_RING_H
+#define _LINUX_VIRTIO_RING_H
/* An interface for efficient virtio implementation, currently for use by KVM
* and lguest, but hopefully others soon. Do NOT change this since it will
* break existing servers and clients.
@@ -160,4 +160,4 @@ static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old
return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);
}
-#endif /* _UAPI_LINUX_VIRTIO_RING_H */
+#endif /* _LINUX_VIRTIO_RING_H */
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH 2/3] vfio-pci: [NOT FOR COMMIT] Add support for VGA MMIO and I/O port access
2013-01-07 22:21 [Qemu-devel] [PATCH 0/3] Towards vfio-base VGA device assignment Alex Williamson
2013-01-07 22:22 ` [Qemu-devel] [PATCH 1/3] qemu: [NOT FOR COMMIT] Update linux headers for vfio VGA Alex Williamson
@ 2013-01-07 22:22 ` Alex Williamson
2013-01-07 22:22 ` [Qemu-devel] [PATCH 3/3] vfio-pci: [NOT FOR COMMIT] Hack around HD5450 I/O port backdoor Alex Williamson
2 siblings, 0 replies; 4+ messages in thread
From: Alex Williamson @ 2013-01-07 22:22 UTC (permalink / raw)
To: alex.williamson, kvm; +Cc: qemu-devel
With this, some VGA cards can make it through VGA BIOS init, but I
have yet to see one sync the monitor in VGA text mode. Only tested
with -vga none. This adds a new option to vfio-pci, vga=on, which
enables legacy VGA ranges.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
hw/vfio_pci.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 172 insertions(+), 1 deletion(-)
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 94c61ab..846e8de 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -59,6 +59,15 @@ typedef struct VFIOBAR {
uint8_t nr; /* cache the BAR number for debug */
} VFIOBAR;
+typedef struct VFIOLegacyIO {
+ off_t fd_offset;
+ int fd;
+ MemoryRegion mem;
+ off_t region_offset;
+ size_t size;
+ uint32_t flags;
+} VFIOLegacyIO;
+
typedef struct VFIOINTx {
bool pending; /* interrupt pending */
bool kvm_accel; /* set when QEMU bypass through KVM enabled */
@@ -126,10 +135,15 @@ typedef struct VFIODevice {
int nr_vectors; /* Number of MSI/MSIX vectors currently in use */
int interrupt; /* Current interrupt type */
VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
+ VFIOLegacyIO vga[3]; /* 0xa0000, 0x3b0, 0x3c0 */
PCIHostDeviceAddress host;
QLIST_ENTRY(VFIODevice) next;
struct VFIOGroup *group;
+ uint32_t features;
+#define VFIO_FEATURE_ENABLE_VGA_BIT 0
+#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
bool reset_works;
+ bool has_vga;
} VFIODevice;
typedef struct VFIOGroup {
@@ -958,6 +972,87 @@ static const MemoryRegionOps vfio_bar_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static void vfio_legacy_write(void *opaque, hwaddr addr,
+ uint64_t data, unsigned size)
+{
+ VFIOLegacyIO *io = opaque;
+ union {
+ uint8_t byte;
+ uint16_t word;
+ uint32_t dword;
+ uint64_t qword;
+ } buf;
+ off_t offset = io->fd_offset + io->region_offset + addr;
+
+ switch (size) {
+ case 1:
+ buf.byte = data;
+ break;
+ case 2:
+ buf.word = cpu_to_le16(data);
+ break;
+ case 4:
+ buf.dword = cpu_to_le32(data);
+ break;
+ default:
+ hw_error("vfio: unsupported write size, %d bytes\n", size);
+ break;
+ }
+
+ if (pwrite(io->fd, &buf, size, offset) != size) {
+ error_report("%s(,0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m\n",
+ __func__, io->region_offset + addr, data, size);
+ }
+
+ DPRINTF("%s(0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n",
+ __func__, io->region_offset + addr, data, size);
+}
+
+static uint64_t vfio_legacy_read(void *opaque, hwaddr addr, unsigned size)
+{
+ VFIOLegacyIO *io = opaque;
+ union {
+ uint8_t byte;
+ uint16_t word;
+ uint32_t dword;
+ uint64_t qword;
+ } buf;
+ uint64_t data = 0;
+ off_t offset = io->fd_offset + io->region_offset + addr;
+
+ if (pread(io->fd, &buf, size, offset) != size) {
+ error_report("%s(,0x%"HWADDR_PRIx", %d) failed: %m\n",
+ __func__, io->region_offset + addr, size);
+ return (uint64_t)-1;
+ }
+
+ switch (size) {
+ case 1:
+ data = buf.byte;
+ break;
+ case 2:
+ data = le16_to_cpu(buf.word);
+ break;
+ case 4:
+ data = le32_to_cpu(buf.dword);
+ break;
+ default:
+ hw_error("vfio: unsupported read size, %d bytes\n", size);
+ break;
+ }
+
+ DPRINTF("%s(0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n",
+ __func__, io->region_offset + addr, size, data);
+
+ return data;
+}
+
+static const MemoryRegionOps vfio_legacy_ops = {
+ .read = vfio_legacy_read,
+ .write = vfio_legacy_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
/*
* PCI config space
*/
@@ -1498,6 +1593,27 @@ static void vfio_map_bars(VFIODevice *vdev)
for (i = 0; i < PCI_ROM_SLOT; i++) {
vfio_map_bar(vdev, i);
}
+
+ if (vdev->has_vga && (vdev->features & VFIO_FEATURE_ENABLE_VGA)) {
+ memory_region_init_io(&vdev->vga[0].mem, &vfio_legacy_ops,
+ &vdev->vga[0], "vfio-vga-mmio@0xa0000",
+ 0xc0000 - 0xa0000);
+ memory_region_add_subregion_overlap(pci_address_space(&vdev->pdev),
+ 0xa0000, &vdev->vga[0].mem, 1);
+ memory_region_set_coalescing(&vdev->vga[0].mem);
+
+ memory_region_init_io(&vdev->vga[1].mem, &vfio_legacy_ops,
+ &vdev->vga[1], "vfio-vga-io@0x3b0",
+ 0x3bc - 0x3b0);
+ memory_region_add_subregion_overlap(pci_address_space_io(&vdev->pdev),
+ 0x3b0, &vdev->vga[1].mem, 1);
+
+ memory_region_init_io(&vdev->vga[2].mem, &vfio_legacy_ops,
+ &vdev->vga[2], "vfio-vga-io@0x3c0",
+ 0x3e0 - 0x3c0);
+ memory_region_add_subregion_overlap(pci_address_space_io(&vdev->pdev),
+ 0x3c0, &vdev->vga[2].mem, 1);
+ }
}
static void vfio_unmap_bars(VFIODevice *vdev)
@@ -1507,6 +1623,20 @@ static void vfio_unmap_bars(VFIODevice *vdev)
for (i = 0; i < PCI_ROM_SLOT; i++) {
vfio_unmap_bar(vdev, i);
}
+
+ if (vdev->has_vga && (vdev->features & VFIO_FEATURE_ENABLE_VGA)) {
+ memory_region_del_subregion(pci_address_space(&vdev->pdev),
+ &vdev->vga[0].mem);
+ memory_region_destroy(&vdev->vga[0].mem);
+
+ memory_region_del_subregion(pci_address_space_io(&vdev->pdev),
+ &vdev->vga[1].mem);
+ memory_region_destroy(&vdev->vga[1].mem);
+
+ memory_region_del_subregion(pci_address_space_io(&vdev->pdev),
+ &vdev->vga[2].mem);
+ memory_region_destroy(&vdev->vga[2].mem);
+ }
}
/*
@@ -1838,7 +1968,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
error_report("Warning, device %s does not support reset\n", name);
}
- if (dev_info.num_regions != VFIO_PCI_NUM_REGIONS) {
+ if (dev_info.num_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) {
error_report("vfio: unexpected number of io regions %u\n",
dev_info.num_regions);
goto error;
@@ -1902,6 +2032,45 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
vdev->config_size = reg_info.size;
vdev->config_offset = reg_info.offset;
+ if (dev_info.num_regions > VFIO_PCI_CONFIG_REGION_INDEX + 1 &&
+ dev_info.flags & VFIO_DEVICE_FLAGS_VGA) {
+ struct vfio_region_info mmio_info, io_info;
+
+ mmio_info.argsz = io_info.argsz = sizeof(struct vfio_region_info);
+ mmio_info.index = VFIO_PCI_LEGACY_MMIO_REGION_INDEX;
+ io_info.index = VFIO_PCI_LEGACY_IOPORT_REGION_INDEX;
+
+ ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &mmio_info);
+ if (ret) {
+ error_report("vfio: Unable to access VGA MMIO resources: %m\n");
+ ret = 0;
+ goto error;
+ }
+
+ vdev->vga[0].flags = mmio_info.flags;
+ vdev->vga[0].size = mmio_info.size;
+ vdev->vga[0].fd_offset = mmio_info.offset;
+ vdev->vga[0].fd = vdev->fd;
+ vdev->vga[0].region_offset = 0xa0000;
+
+ ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &io_info);
+ if (ret) {
+ error_report("vfio: Unable to access VGA IOPORT resources: %m\n");
+ ret = 0;
+ goto error;
+ }
+
+ vdev->vga[1].flags = vdev->vga[2].flags = io_info.flags;
+ vdev->vga[1].size = vdev->vga[2].size = io_info.size;
+ vdev->vga[1].fd_offset = vdev->vga[2].fd_offset = io_info.offset;
+ vdev->vga[1].fd = vdev->vga[2].fd = vdev->fd;
+
+ vdev->vga[1].region_offset = 0x3b0;
+ vdev->vga[2].region_offset = 0x3c0;
+
+ vdev->has_vga = true;
+ }
+
error:
if (ret) {
QLIST_REMOVE(vdev, next);
@@ -2096,6 +2265,8 @@ static Property vfio_pci_dev_properties[] = {
DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host),
DEFINE_PROP_UINT32("x-intx-mmap-timeout-ms", VFIODevice,
intx.mmap_timeout, 1100),
+ DEFINE_PROP_BIT("vga", VFIODevice, features,
+ VFIO_FEATURE_ENABLE_VGA_BIT, false),
/*
* TODO - support passed fds... is this necessary?
* DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
^ permalink raw reply related [flat|nested] 4+ messages in thread