* [Qemu-devel] [PATCH v13 01/12] linux-headers: update headers according to 4.1-rc0
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-29 10:36 ` Christian Borntraeger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 02/12] hw/vfio/platform: vfio-platform skeleton Eric Auger
` (10 subsequent siblings)
11 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
This includes, among other things, VFIO platform driver and
irqfd/arm.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v12 -> v13:
- update for 4.1-rc0 headers
v10 -> v11:
- only includes header modifications related to vfio platform
driver v14 and not those related to
"vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1"
---
include/standard-headers/linux/virtio_blk.h | 8 +-
| 3 +
| 3 +
| 164 +++++++++++++++++-----------
| 4 +
| 65 ++++++++++-
| 2 +
7 files changed, 183 insertions(+), 66 deletions(-)
diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h
index 12016b4..cd601f4 100644
--- a/include/standard-headers/linux/virtio_blk.h
+++ b/include/standard-headers/linux/virtio_blk.h
@@ -58,7 +58,7 @@ struct virtio_blk_config {
uint32_t size_max;
/* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
uint32_t seg_max;
- /* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
+ /* geometry of the device (if VIRTIO_BLK_F_GEOMETRY) */
struct virtio_blk_geometry {
uint16_t cylinders;
uint8_t heads;
@@ -117,7 +117,11 @@ struct virtio_blk_config {
#define VIRTIO_BLK_T_BARRIER 0x80000000
#endif /* !VIRTIO_BLK_NO_LEGACY */
-/* This is the first element of the read scatter-gather list. */
+/*
+ * This comes first in the read scatter-gather list.
+ * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated,
+ * this is the first element of the read scatter-gather list.
+ */
struct virtio_blk_outhdr {
/* VIRTIO_BLK_T* */
__virtio32 type;
--git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
index 0db25bc..2499867 100644
--- a/linux-headers/asm-arm/kvm.h
+++ b/linux-headers/asm-arm/kvm.h
@@ -198,6 +198,9 @@ struct kvm_arch_memory_slot {
/* Highest supported SPI, from VGIC_NR_IRQS */
#define KVM_ARM_IRQ_GIC_MAX 127
+/* One single KVM irqchip, ie. the VGIC */
+#define KVM_NR_IRQCHIPS 1
+
/* PSCI interface */
#define KVM_PSCI_FN_BASE 0x95c1ba5e
#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
--git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
index 3ef77a4..c154c0b 100644
--- a/linux-headers/asm-arm64/kvm.h
+++ b/linux-headers/asm-arm64/kvm.h
@@ -191,6 +191,9 @@ struct kvm_arch_memory_slot {
/* Highest supported SPI, from VGIC_NR_IRQS */
#define KVM_ARM_IRQ_GIC_MAX 127
+/* One single KVM irqchip, ie. the VGIC */
+#define KVM_NR_IRQCHIPS 1
+
/* PSCI interface */
#define KVM_PSCI_FN_BASE 0x95c1ba5e
#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
--git a/linux-headers/asm-mips/kvm.h b/linux-headers/asm-mips/kvm.h
index 2c04b6d..6985eb5 100644
--- a/linux-headers/asm-mips/kvm.h
+++ b/linux-headers/asm-mips/kvm.h
@@ -36,77 +36,85 @@ struct kvm_regs {
/*
* for KVM_GET_FPU and KVM_SET_FPU
- *
- * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs
- * are zero filled.
*/
struct kvm_fpu {
- __u64 fpr[32];
- __u32 fir;
- __u32 fccr;
- __u32 fexr;
- __u32 fenr;
- __u32 fcsr;
- __u32 pad;
};
/*
- * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0
+ * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
* registers. The id field is broken down as follows:
*
- * bits[2..0] - Register 'sel' index.
- * bits[7..3] - Register 'rd' index.
- * bits[15..8] - Must be zero.
- * bits[31..16] - 1 -> CP0 registers.
- * bits[51..32] - Must be zero.
* bits[63..52] - As per linux/kvm.h
+ * bits[51..32] - Must be zero.
+ * bits[31..16] - Register set.
+ *
+ * Register set = 0: GP registers from kvm_regs (see definitions below).
+ *
+ * Register set = 1: CP0 registers.
+ * bits[15..8] - Must be zero.
+ * bits[7..3] - Register 'rd' index.
+ * bits[2..0] - Register 'sel' index.
+ *
+ * Register set = 2: KVM specific registers (see definitions below).
+ *
+ * Register set = 3: FPU / MSA registers (see definitions below).
*
* Other sets registers may be added in the future. Each set would
* have its own identifier in bits[31..16].
- *
- * The registers defined in struct kvm_regs are also accessible, the
- * id values for these are below.
*/
-#define KVM_REG_MIPS_R0 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0)
-#define KVM_REG_MIPS_R1 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 1)
-#define KVM_REG_MIPS_R2 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 2)
-#define KVM_REG_MIPS_R3 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 3)
-#define KVM_REG_MIPS_R4 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 4)
-#define KVM_REG_MIPS_R5 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 5)
-#define KVM_REG_MIPS_R6 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 6)
-#define KVM_REG_MIPS_R7 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 7)
-#define KVM_REG_MIPS_R8 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 8)
-#define KVM_REG_MIPS_R9 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 9)
-#define KVM_REG_MIPS_R10 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 10)
-#define KVM_REG_MIPS_R11 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 11)
-#define KVM_REG_MIPS_R12 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 12)
-#define KVM_REG_MIPS_R13 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 13)
-#define KVM_REG_MIPS_R14 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 14)
-#define KVM_REG_MIPS_R15 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 15)
-#define KVM_REG_MIPS_R16 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 16)
-#define KVM_REG_MIPS_R17 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 17)
-#define KVM_REG_MIPS_R18 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 18)
-#define KVM_REG_MIPS_R19 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 19)
-#define KVM_REG_MIPS_R20 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 20)
-#define KVM_REG_MIPS_R21 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 21)
-#define KVM_REG_MIPS_R22 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 22)
-#define KVM_REG_MIPS_R23 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 23)
-#define KVM_REG_MIPS_R24 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 24)
-#define KVM_REG_MIPS_R25 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 25)
-#define KVM_REG_MIPS_R26 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 26)
-#define KVM_REG_MIPS_R27 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 27)
-#define KVM_REG_MIPS_R28 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 28)
-#define KVM_REG_MIPS_R29 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 29)
-#define KVM_REG_MIPS_R30 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 30)
-#define KVM_REG_MIPS_R31 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 31)
-
-#define KVM_REG_MIPS_HI (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 32)
-#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33)
-#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34)
-
-/* KVM specific control registers */
+#define KVM_REG_MIPS_GP (KVM_REG_MIPS | 0x0000000000000000ULL)
+#define KVM_REG_MIPS_CP0 (KVM_REG_MIPS | 0x0000000000010000ULL)
+#define KVM_REG_MIPS_KVM (KVM_REG_MIPS | 0x0000000000020000ULL)
+#define KVM_REG_MIPS_FPU (KVM_REG_MIPS | 0x0000000000030000ULL)
+
+
+/*
+ * KVM_REG_MIPS_GP - General purpose registers from kvm_regs.
+ */
+
+#define KVM_REG_MIPS_R0 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 0)
+#define KVM_REG_MIPS_R1 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 1)
+#define KVM_REG_MIPS_R2 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 2)
+#define KVM_REG_MIPS_R3 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 3)
+#define KVM_REG_MIPS_R4 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 4)
+#define KVM_REG_MIPS_R5 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 5)
+#define KVM_REG_MIPS_R6 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 6)
+#define KVM_REG_MIPS_R7 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 7)
+#define KVM_REG_MIPS_R8 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 8)
+#define KVM_REG_MIPS_R9 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 9)
+#define KVM_REG_MIPS_R10 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 10)
+#define KVM_REG_MIPS_R11 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 11)
+#define KVM_REG_MIPS_R12 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 12)
+#define KVM_REG_MIPS_R13 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 13)
+#define KVM_REG_MIPS_R14 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 14)
+#define KVM_REG_MIPS_R15 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 15)
+#define KVM_REG_MIPS_R16 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 16)
+#define KVM_REG_MIPS_R17 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 17)
+#define KVM_REG_MIPS_R18 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 18)
+#define KVM_REG_MIPS_R19 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 19)
+#define KVM_REG_MIPS_R20 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 20)
+#define KVM_REG_MIPS_R21 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 21)
+#define KVM_REG_MIPS_R22 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 22)
+#define KVM_REG_MIPS_R23 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 23)
+#define KVM_REG_MIPS_R24 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 24)
+#define KVM_REG_MIPS_R25 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 25)
+#define KVM_REG_MIPS_R26 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 26)
+#define KVM_REG_MIPS_R27 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 27)
+#define KVM_REG_MIPS_R28 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 28)
+#define KVM_REG_MIPS_R29 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 29)
+#define KVM_REG_MIPS_R30 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 30)
+#define KVM_REG_MIPS_R31 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 31)
+
+#define KVM_REG_MIPS_HI (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 32)
+#define KVM_REG_MIPS_LO (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 33)
+#define KVM_REG_MIPS_PC (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 34)
+
+
+/*
+ * KVM_REG_MIPS_KVM - KVM specific control registers.
+ */
/*
* CP0_Count control
@@ -118,8 +126,7 @@ struct kvm_fpu {
* safely without losing time or guest timer interrupts.
* Other: Reserved, do not change.
*/
-#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
- 0x20000 | 0)
+#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 0)
#define KVM_REG_MIPS_COUNT_CTL_DC 0x00000001
/*
@@ -131,15 +138,46 @@ struct kvm_fpu {
* emulated.
* Modifications to times in the future are rejected.
*/
-#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
- 0x20000 | 1)
+#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 1)
/*
* CP0_Count rate in Hz
* Specifies the rate of the CP0_Count timer in Hz. Modifications occur without
* discontinuities in CP0_Count.
*/
-#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
- 0x20000 | 2)
+#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 2)
+
+
+/*
+ * KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers.
+ *
+ * bits[15..8] - Register subset (see definitions below).
+ * bits[7..5] - Must be zero.
+ * bits[4..0] - Register number within register subset.
+ */
+
+#define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL)
+#define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL)
+#define KVM_REG_MIPS_MSACR (KVM_REG_MIPS_FPU | 0x0000000000000200ULL)
+
+/*
+ * KVM_REG_MIPS_FPR - Floating point / Vector registers.
+ */
+#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n))
+#define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64 | (n))
+#define KVM_REG_MIPS_VEC_128(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n))
+
+/*
+ * KVM_REG_MIPS_FCR - Floating point control registers.
+ */
+#define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0)
+#define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31)
+
+/*
+ * KVM_REG_MIPS_MSACR - MIPS SIMD Architecture (MSA) control registers.
+ */
+#define KVM_REG_MIPS_MSA_IR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 0)
+#define KVM_REG_MIPS_MSA_CSR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 1)
+
/*
* KVM MIPS specific structures and definitions
--git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index c5a93eb..512d8f1 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -150,6 +150,7 @@ struct kvm_guest_debug_arch {
#define KVM_SYNC_CRS (1UL << 3)
#define KVM_SYNC_ARCH0 (1UL << 4)
#define KVM_SYNC_PFAULT (1UL << 5)
+#define KVM_SYNC_VRS (1UL << 6)
/* definition of registers in kvm_run */
struct kvm_sync_regs {
__u64 prefix; /* prefix register */
@@ -164,6 +165,9 @@ struct kvm_sync_regs {
__u64 pft; /* pfault token [PFAULT] */
__u64 pfs; /* pfault select [PFAULT] */
__u64 pfc; /* pfault compare [PFAULT] */
+ __u64 vrs[32][2]; /* vector registers */
+ __u8 reserved[512]; /* for future vector expansion */
+ __u32 fpc; /* only valid with vector registers */
};
#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 60a54c8..7039166 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -147,6 +147,16 @@ struct kvm_pit_config {
#define KVM_PIT_SPEAKER_DUMMY 1
+struct kvm_s390_skeys {
+ __u64 start_gfn;
+ __u64 count;
+ __u64 skeydata_addr;
+ __u32 flags;
+ __u32 reserved[9];
+};
+#define KVM_S390_GET_SKEYS_NONE 1
+#define KVM_S390_SKEYS_MAX 1048576
+
#define KVM_EXIT_UNKNOWN 0
#define KVM_EXIT_EXCEPTION 1
#define KVM_EXIT_IO 2
@@ -172,6 +182,7 @@ struct kvm_pit_config {
#define KVM_EXIT_S390_TSCH 22
#define KVM_EXIT_EPR 23
#define KVM_EXIT_SYSTEM_EVENT 24
+#define KVM_EXIT_S390_STSI 25
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -309,6 +320,15 @@ struct kvm_run {
__u32 type;
__u64 flags;
} system_event;
+ /* KVM_EXIT_S390_STSI */
+ struct {
+ __u64 addr;
+ __u8 ar;
+ __u8 reserved;
+ __u8 fc;
+ __u8 sel1;
+ __u16 sel2;
+ } s390_stsi;
/* Fix the size of the union. */
char padding[256];
};
@@ -324,7 +344,7 @@ struct kvm_run {
__u64 kvm_dirty_regs;
union {
struct kvm_sync_regs regs;
- char padding[1024];
+ char padding[2048];
} s;
};
@@ -365,6 +385,24 @@ struct kvm_translation {
__u8 pad[5];
};
+/* for KVM_S390_MEM_OP */
+struct kvm_s390_mem_op {
+ /* in */
+ __u64 gaddr; /* the guest address */
+ __u64 flags; /* flags */
+ __u32 size; /* amount of bytes */
+ __u32 op; /* type of operation */
+ __u64 buf; /* buffer in userspace */
+ __u8 ar; /* the access register number */
+ __u8 reserved[31]; /* should be set to 0 */
+};
+/* types for kvm_s390_mem_op->op */
+#define KVM_S390_MEMOP_LOGICAL_READ 0
+#define KVM_S390_MEMOP_LOGICAL_WRITE 1
+/* flags for kvm_s390_mem_op->flags */
+#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0)
+#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1)
+
/* for KVM_INTERRUPT */
struct kvm_interrupt {
/* in */
@@ -520,6 +558,13 @@ struct kvm_s390_irq {
} u;
};
+struct kvm_s390_irq_state {
+ __u64 buf;
+ __u32 flags;
+ __u32 len;
+ __u32 reserved[4];
+};
+
/* for KVM_SET_GUEST_DEBUG */
#define KVM_GUESTDBG_ENABLE 0x00000001
@@ -760,6 +805,14 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_PPC_ENABLE_HCALL 104
#define KVM_CAP_CHECK_EXTENSION_VM 105
#define KVM_CAP_S390_USER_SIGP 106
+#define KVM_CAP_S390_VECTOR_REGISTERS 107
+#define KVM_CAP_S390_MEM_OP 108
+#define KVM_CAP_S390_USER_STSI 109
+#define KVM_CAP_S390_SKEYS 110
+#define KVM_CAP_MIPS_FPU 111
+#define KVM_CAP_MIPS_MSA 112
+#define KVM_CAP_S390_INJECT_IRQ 113
+#define KVM_CAP_S390_IRQ_STATE 114
#ifdef KVM_CAP_IRQ_ROUTING
@@ -1135,6 +1188,16 @@ struct kvm_s390_ucas_mapping {
#define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init)
#define KVM_ARM_PREFERRED_TARGET _IOR(KVMIO, 0xaf, struct kvm_vcpu_init)
#define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
+/* Available with KVM_CAP_S390_MEM_OP */
+#define KVM_S390_MEM_OP _IOW(KVMIO, 0xb1, struct kvm_s390_mem_op)
+/* Available with KVM_CAP_S390_SKEYS */
+#define KVM_S390_GET_SKEYS _IOW(KVMIO, 0xb2, struct kvm_s390_skeys)
+#define KVM_S390_SET_SKEYS _IOW(KVMIO, 0xb3, struct kvm_s390_skeys)
+/* Available with KVM_CAP_S390_INJECT_IRQ */
+#define KVM_S390_IRQ _IOW(KVMIO, 0xb4, struct kvm_s390_irq)
+/* Available with KVM_CAP_S390_IRQ_STATE */
+#define KVM_S390_SET_IRQ_STATE _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state)
+#define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
--git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 95ba870..0508d0b 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -160,6 +160,8 @@ 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_PLATFORM (1 << 2) /* vfio-platform device */
+#define VFIO_DEVICE_FLAGS_AMBA (1 << 3) /* vfio-amba device */
__u32 num_regions; /* Max region index + 1 */
__u32 num_irqs; /* Max IRQ index + 1 */
};
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v13 01/12] linux-headers: update headers according to 4.1-rc0
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 01/12] linux-headers: update headers according to 4.1-rc0 Eric Auger
@ 2015-04-29 10:36 ` Christian Borntraeger
2015-04-29 11:11 ` Eric Auger
0 siblings, 1 reply; 19+ messages in thread
From: Christian Borntraeger @ 2015-04-29 10:36 UTC (permalink / raw)
To: Eric Auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
Am 28.04.2015 um 18:51 schrieb Eric Auger:
> This includes, among other things, VFIO platform driver and
> irqfd/arm.
>
> Signed-off-by: Eric Auger <eric.auger@linaro.org>
>
> ---
>
> v12 -> v13:
> - update for 4.1-rc0 headers
If you have a chance to update the subject before the pull request, its
4.1-rc1 instead of 4.1-rc0.
Christian
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v13 01/12] linux-headers: update headers according to 4.1-rc0
2015-04-29 10:36 ` Christian Borntraeger
@ 2015-04-29 11:11 ` Eric Auger
0 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-29 11:11 UTC (permalink / raw)
To: Christian Borntraeger, eric.auger, qemu-devel, alex.williamson,
agraf, pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
On 04/29/2015 12:36 PM, Christian Borntraeger wrote:
> Am 28.04.2015 um 18:51 schrieb Eric Auger:
>> This includes, among other things, VFIO platform driver and
>> irqfd/arm.
>>
>> Signed-off-by: Eric Auger <eric.auger@linaro.org>
>>
>> ---
>>
>> v12 -> v13:
>> - update for 4.1-rc0 headers
>
> If you have a chance to update the subject before the pull request, its
> 4.1-rc1 instead of 4.1-rc0.
Hi Christian,
thanks I will update.
Best Regards
Eric
>
> Christian
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 02/12] hw/vfio/platform: vfio-platform skeleton
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 01/12] linux-headers: update headers according to 4.1-rc0 Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 03/12] hw/vfio/platform: add irq assignment Eric Auger
` (9 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
Minimal VFIO platform implementation supporting register space
user mapping but not IRQ assignment.
Signed-off-by: Kim Phillips <kim.phillips@linaro.org>
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v12 -> v13:
- check device name does not contain any /
- handle case where readlink fully fills the buffer
- in vfio_map_region declare size as uint64_t
v11 -> v12:
- add x-mmap property definition, without which the default value of
vbasedev.allow_mmap is false, hence preventing the reg space from
being mapped.
v10 -> v11:
x Take into account Alex Bennee's comments:
- use g_malloc0_n instead of g_malloc0
- use block declarations when possible
- rework readlink returned value treatment
- use g_strlcat in place of strncat
x use g_snprintf in place of snprintf
x correct error handling in vfio_populate_device,
in case of flag not corresponding to platform device
x various cosmetic changes
v9 -> v10:
- vfio_populate_device no more called in common vfio_get_device
but in vfio_base_device_init
v8 -> v9:
- irq management is moved into a separate patch to ease the review
- VFIO_DEVICE_FLAGS_PLATFORM is checked in vfio_populate_device
- g_free of regions added in vfio_populate_device error label
- virtualID becomes 32b
v7 -> v8:
- change proto of vfio_platform_compute_needs_reset and sets
vbasedev->needs_reset to false there
- vfio_[un]mask_irqindex renamed into vfio_[un]mask_single_irqindex
- vfio_register_irq_starter renamed into vfio_kick_irqs
we now use a reset notifier instead of a machine init done notifier.
Enables to get rid of the VfioIrqStarterNotifierParams dangling
pointer. Previously we use pbus first_irq. This is no more possible
since the reset notifier takes a void * and first_irq is a field of
a const struct. So now we pass the DeviceState handle of the
interrupt controller. I tried to keep the code generic, reason why
I did not rely on an architecture specific accessor to retrieve
the gsi number (gic accessor as proposed by Alex). I would like to
avoid creating an ARM VFIO device model. I hope this model
model can work on other archs than arm (no multiple intc?);
wouldn't it be simpler to keep the previous first_irq parameter and
relax the const constraint.
v6 -> v7:
- compat is not exposed anymore as a user option. Rationale is
the vfio device became abstract and a specialization is needed
anyway. The derived device must set the compat string.
- in v6 vfio_start_irq_injection was exposed in vfio-platform.h.
A new function dubbed vfio_register_irq_starter replaces it. It
registers a machine init done notifier that programs & starts
all dynamic VFIO device IRQs. This function is supposed to be
called by the machine file. A set of static helper routines are
added too. It must be called before the creation of the platform
bus device.
v5 -> v6:
- vfio_device property renamed into host property
- correct error handling of VFIO_DEVICE_GET_IRQ_INFO ioctl
and remove PCI related comment
- remove declaration of vfio_setup_irqfd and irqfd_allowed
property.Both belong to next patch (irqfd)
- remove declaration of vfio_intp_interrupt in vfio-platform.h
- functions that can be static get this characteristic
- remove declarations of vfio_region_ops, vfio_memory_listener,
group_list, vfio_address_spaces. All are moved to vfio-common.h
- remove vfio_put_device declaration and definition
- print_regions removed. code moved into vfio_populate_regions
- replace DPRINTF by trace events
- new helper routine to set the trigger eventfd
- dissociate intp init from the injection enablement:
vfio_enable_intp renamed into vfio_init_intp and new function
named vfio_start_eventfd_injection
- injection start moved to vfio_start_irq_injection (not anymore
in vfio_populate_interrupt)
- new start_irq_fn field in VFIOPlatformDevice corresponding to
the function that will be used for starting injection
- user handled eventfd:
x add mutex to protect IRQ state & list manipulation,
x correct misleading comment in vfio_intp_interrupt.
x Fix bugs thanks to fake interrupt modality
- VFIOPlatformDeviceClass becomes abstract
- add error_setg in vfio_platform_realize
v4 -> v5:
- vfio-plaform.h included first
- cleanup error handling in *populate*, vfio_get_device,
vfio_enable_intp
- vfio_put_device not called anymore
- add some includes to follow vfio policy
v3 -> v4:
[Eric Auger]
- merge of "vfio: Add initial IRQ support in platform device"
to get a full functional patch although perfs are limited.
- removal of unrealize function since I currently understand
it is only used with device hot-plug feature.
v2 -> v3:
[Eric Auger]
- further factorization between PCI and platform (VFIORegion,
VFIODevice). same level of functionality.
<= v2:
[Kim Philipps]
- Initial Creation of the device supporting register space mapping
---
hw/vfio/Makefile.objs | 1 +
hw/vfio/platform.c | 288 ++++++++++++++++++++++++++++++++++++++++
include/hw/vfio/vfio-common.h | 1 +
include/hw/vfio/vfio-platform.h | 44 ++++++
trace-events | 5 +
5 files changed, 339 insertions(+)
create mode 100644 hw/vfio/platform.c
create mode 100644 include/hw/vfio/vfio-platform.h
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index e31f30e..c5c76fe 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -1,4 +1,5 @@
ifeq ($(CONFIG_LINUX), y)
obj-$(CONFIG_SOFTMMU) += common.o
obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_SOFTMMU) += platform.o
endif
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
new file mode 100644
index 0000000..48dfc55
--- /dev/null
+++ b/hw/vfio/platform.c
@@ -0,0 +1,288 @@
+/*
+ * vfio based device assignment support - platform devices
+ *
+ * Copyright Linaro Limited, 2014
+ *
+ * Authors:
+ * Kim Phillips <kim.phillips@linaro.org>
+ * Eric Auger <eric.auger@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Based on vfio based PCI device assignment support:
+ * Copyright Red Hat, Inc. 2012
+ */
+
+#include <linux/vfio.h>
+#include <sys/ioctl.h>
+
+#include "hw/vfio/vfio-platform.h"
+#include "qemu/error-report.h"
+#include "qemu/range.h"
+#include "sysemu/sysemu.h"
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "trace.h"
+#include "hw/platform-bus.h"
+
+/* VFIO skeleton */
+
+/* not implemented yet */
+static void vfio_platform_compute_needs_reset(VFIODevice *vbasedev)
+{
+ vbasedev->needs_reset = false;
+}
+
+/* not implemented yet */
+static int vfio_platform_hot_reset_multi(VFIODevice *vbasedev)
+{
+ return 0;
+}
+
+/**
+ * vfio_populate_device - Allocate and populate MMIO region
+ * structs according to driver returned information
+ * @vbasedev: the VFIO device handle
+ *
+ */
+static int vfio_populate_device(VFIODevice *vbasedev)
+{
+ int i, ret = -1;
+ VFIOPlatformDevice *vdev =
+ container_of(vbasedev, VFIOPlatformDevice, vbasedev);
+
+ if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PLATFORM)) {
+ error_report("vfio: Um, this isn't a platform device");
+ return ret;
+ }
+
+ vdev->regions = g_malloc0_n(1,
+ sizeof(VFIORegion *) * vbasedev->num_regions);
+
+ for (i = 0; i < vbasedev->num_regions; i++) {
+ struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
+ VFIORegion *ptr;
+
+ vdev->regions[i] = g_malloc0_n(1, sizeof(VFIORegion));
+ ptr = vdev->regions[i];
+ reg_info.index = i;
+ ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
+ if (ret) {
+ error_report("vfio: Error getting region %d info: %m", i);
+ goto reg_error;
+ }
+ ptr->flags = reg_info.flags;
+ ptr->size = reg_info.size;
+ ptr->fd_offset = reg_info.offset;
+ ptr->nr = i;
+ ptr->vbasedev = vbasedev;
+
+ trace_vfio_platform_populate_regions(ptr->nr,
+ (unsigned long)ptr->flags,
+ (unsigned long)ptr->size,
+ ptr->vbasedev->fd,
+ (unsigned long)ptr->fd_offset);
+ }
+
+ return 0;
+reg_error:
+ for (i = 0; i < vbasedev->num_regions; i++) {
+ g_free(vdev->regions[i]);
+ }
+ g_free(vdev->regions);
+ return ret;
+}
+
+/* specialized functions for VFIO Platform devices */
+static VFIODeviceOps vfio_platform_ops = {
+ .vfio_compute_needs_reset = vfio_platform_compute_needs_reset,
+ .vfio_hot_reset_multi = vfio_platform_hot_reset_multi,
+};
+
+/**
+ * vfio_base_device_init - perform preliminary VFIO setup
+ * @vbasedev: the VFIO device handle
+ *
+ * Implement the VFIO command sequence that allows to discover
+ * assigned device resources: group extraction, device
+ * fd retrieval, resource query.
+ * Precondition: the device name must be initialized
+ */
+static int vfio_base_device_init(VFIODevice *vbasedev)
+{
+ VFIOGroup *group;
+ VFIODevice *vbasedev_iter;
+ char path[PATH_MAX], iommu_group_path[PATH_MAX], *group_name;
+ ssize_t len;
+ struct stat st;
+ int groupid;
+ int ret;
+
+ /* name must be set prior to the call */
+ if (!vbasedev->name || strchr(vbasedev->name, '/')) {
+ return -EINVAL;
+ }
+
+ /* Check that the host device exists */
+ g_snprintf(path, sizeof(path), "/sys/bus/platform/devices/%s/",
+ vbasedev->name);
+
+ if (stat(path, &st) < 0) {
+ error_report("vfio: error: no such host device: %s", path);
+ return -errno;
+ }
+
+ g_strlcat(path, "iommu_group", sizeof(path));
+ len = readlink(path, iommu_group_path, sizeof(iommu_group_path));
+ if (len < 0 || len >= sizeof(iommu_group_path)) {
+ error_report("vfio: error no iommu_group for device");
+ return len < 0 ? -errno : ENAMETOOLONG;
+ }
+
+ iommu_group_path[len] = 0;
+ group_name = basename(iommu_group_path);
+
+ if (sscanf(group_name, "%d", &groupid) != 1) {
+ error_report("vfio: error reading %s: %m", path);
+ return -errno;
+ }
+
+ trace_vfio_platform_base_device_init(vbasedev->name, groupid);
+
+ group = vfio_get_group(groupid, &address_space_memory);
+ if (!group) {
+ error_report("vfio: failed to get group %d", groupid);
+ return -ENOENT;
+ }
+
+ g_snprintf(path, sizeof(path), "%s", vbasedev->name);
+
+ QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
+ if (strcmp(vbasedev_iter->name, vbasedev->name) == 0) {
+ error_report("vfio: error: device %s is already attached", path);
+ vfio_put_group(group);
+ return -EBUSY;
+ }
+ }
+ ret = vfio_get_device(group, path, vbasedev);
+ if (ret) {
+ error_report("vfio: failed to get device %s", path);
+ vfio_put_group(group);
+ return ret;
+ }
+
+ ret = vfio_populate_device(vbasedev);
+ if (ret) {
+ error_report("vfio: failed to populate device %s", path);
+ vfio_put_group(group);
+ }
+
+ return ret;
+}
+
+/**
+ * vfio_map_region - initialize the 2 memory regions for a given
+ * MMIO region index
+ * @vdev: the VFIO platform device handle
+ * @nr: the index of the region
+ *
+ * Init the top memory region and the mmapped memory region beneath
+ * VFIOPlatformDevice is used since VFIODevice is not a QOM Object
+ * and could not be passed to memory region functions
+*/
+static void vfio_map_region(VFIOPlatformDevice *vdev, int nr)
+{
+ VFIORegion *region = vdev->regions[nr];
+ uint64_t size = region->size;
+ char name[64];
+
+ if (!size) {
+ return;
+ }
+
+ g_snprintf(name, sizeof(name), "VFIO %s region %d",
+ vdev->vbasedev.name, nr);
+
+ /* A "slow" read/write mapping underlies all regions */
+ memory_region_init_io(®ion->mem, OBJECT(vdev), &vfio_region_ops,
+ region, name, size);
+
+ g_strlcat(name, " mmap", sizeof(name));
+
+ if (vfio_mmap_region(OBJECT(vdev), region, ®ion->mem,
+ ®ion->mmap_mem, ®ion->mmap, size, 0, name)) {
+ error_report("%s unsupported. Performance may be slow", name);
+ }
+}
+
+/**
+ * vfio_platform_realize - the device realize function
+ * @dev: device state pointer
+ * @errp: error
+ *
+ * initialize the device, its memory regions and IRQ structures
+ * IRQ are started separately
+ */
+static void vfio_platform_realize(DeviceState *dev, Error **errp)
+{
+ VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
+ SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
+ VFIODevice *vbasedev = &vdev->vbasedev;
+ int i, ret;
+
+ vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
+ vbasedev->ops = &vfio_platform_ops;
+
+ trace_vfio_platform_realize(vbasedev->name, vdev->compat);
+
+ ret = vfio_base_device_init(vbasedev);
+ if (ret) {
+ error_setg(errp, "vfio: vfio_base_device_init failed for %s",
+ vbasedev->name);
+ return;
+ }
+
+ for (i = 0; i < vbasedev->num_regions; i++) {
+ vfio_map_region(vdev, i);
+ sysbus_init_mmio(sbdev, &vdev->regions[i]->mem);
+ }
+}
+
+static const VMStateDescription vfio_platform_vmstate = {
+ .name = TYPE_VFIO_PLATFORM,
+ .unmigratable = 1,
+};
+
+static Property vfio_platform_dev_properties[] = {
+ DEFINE_PROP_STRING("host", VFIOPlatformDevice, vbasedev.name),
+ DEFINE_PROP_BOOL("x-mmap", VFIOPlatformDevice, vbasedev.allow_mmap, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vfio_platform_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = vfio_platform_realize;
+ dc->props = vfio_platform_dev_properties;
+ dc->vmsd = &vfio_platform_vmstate;
+ dc->desc = "VFIO-based platform device assignment";
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo vfio_platform_dev_info = {
+ .name = TYPE_VFIO_PLATFORM,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(VFIOPlatformDevice),
+ .class_init = vfio_platform_class_init,
+ .class_size = sizeof(VFIOPlatformDeviceClass),
+ .abstract = true,
+};
+
+static void register_vfio_platform_dev_type(void)
+{
+ type_register_static(&vfio_platform_dev_info);
+}
+
+type_init(register_vfio_platform_dev_type)
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 0d1fb80..59a321d 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -42,6 +42,7 @@
enum {
VFIO_DEVICE_TYPE_PCI = 0,
+ VFIO_DEVICE_TYPE_PLATFORM = 1,
};
typedef struct VFIORegion {
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
new file mode 100644
index 0000000..338f0c6
--- /dev/null
+++ b/include/hw/vfio/vfio-platform.h
@@ -0,0 +1,44 @@
+/*
+ * vfio based device assignment support - platform devices
+ *
+ * Copyright Linaro Limited, 2014
+ *
+ * Authors:
+ * Kim Phillips <kim.phillips@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Based on vfio based PCI device assignment support:
+ * Copyright Red Hat, Inc. 2012
+ */
+
+#ifndef HW_VFIO_VFIO_PLATFORM_H
+#define HW_VFIO_VFIO_PLATFORM_H
+
+#include "hw/sysbus.h"
+#include "hw/vfio/vfio-common.h"
+
+#define TYPE_VFIO_PLATFORM "vfio-platform"
+
+typedef struct VFIOPlatformDevice {
+ SysBusDevice sbdev;
+ VFIODevice vbasedev; /* not a QOM object */
+ VFIORegion **regions;
+ char *compat; /* compatibility string */
+} VFIOPlatformDevice;
+
+typedef struct VFIOPlatformDeviceClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+} VFIOPlatformDeviceClass;
+
+#define VFIO_PLATFORM_DEVICE(obj) \
+ OBJECT_CHECK(VFIOPlatformDevice, (obj), TYPE_VFIO_PLATFORM)
+#define VFIO_PLATFORM_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VFIOPlatformDeviceClass, (klass), TYPE_VFIO_PLATFORM)
+#define VFIO_PLATFORM_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VFIOPlatformDeviceClass, (obj), TYPE_VFIO_PLATFORM)
+
+#endif /*HW_VFIO_VFIO_PLATFORM_H*/
diff --git a/trace-events b/trace-events
index 30eba92..2ccc822 100644
--- a/trace-events
+++ b/trace-events
@@ -1560,6 +1560,11 @@ vfio_put_group(int fd) "close group->fd=%d"
vfio_get_device(const char * name, unsigned int flags, unsigned int num_regions, unsigned int num_irqs) "Device %s flags: %u, regions: %u, irqs: %u"
vfio_put_base_device(int fd) "close vdev->fd=%d"
+# hw/vfio/platform.c
+vfio_platform_populate_regions(int region_index, unsigned long flag, unsigned long size, int fd, unsigned long offset) "- region %d flags = 0x%lx, size = 0x%lx, fd= %d, offset = 0x%lx"
+vfio_platform_base_device_init(char *name, int groupid) "%s belongs to group #%d"
+vfio_platform_realize(char *name, char *compat) "vfio device %s, compat = %s"
+
#hw/acpi/memory_hotplug.c
mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
mhp_acpi_read_addr_lo(uint32_t slot, uint32_t addr) "slot[0x%"PRIx32"] addr lo: 0x%"PRIx32
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 03/12] hw/vfio/platform: add irq assignment
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 01/12] linux-headers: update headers according to 4.1-rc0 Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 02/12] hw/vfio/platform: vfio-platform skeleton Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 04/12] hw/vfio/platform: calxeda xgmac device Eric Auger
` (8 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
This patch adds the code requested to assign interrupts to
a guest. The interrupts are mediated through user handled
eventfds only.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v12 -> v13:
- start user-side eventfd handling at realize time
- remove start_irq_fn
v10 -> v11:
- use block declaration when possible
- change order of vfio_platform_eoi vs vfio_intp_interrupt
- introduce vfio_intp_inject_pending_lockheld following Alex Bennee
comments
- remove unmasking/masked when setting up VFIO signaling
- remove unused kvm_accel member in VFIOINTp struct
- add flags member in VFIOINTp in order to properly discriminate
edge/level-sensitive IRQs; unmask the physical IRQ only in case of
level-sensitive IRQ
- some comment rewording
v8 -> v9:
- free irq related resources in case of error in vfio_populate_device
---
hw/vfio/platform.c | 331 +++++++++++++++++++++++++++++++++++++++-
include/hw/vfio/vfio-platform.h | 32 ++++
trace-events | 7 +
3 files changed, 369 insertions(+), 1 deletion(-)
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index 48dfc55..f484764 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -22,10 +22,299 @@
#include "qemu/range.h"
#include "sysemu/sysemu.h"
#include "exec/memory.h"
+#include "qemu/queue.h"
#include "hw/sysbus.h"
#include "trace.h"
#include "hw/platform-bus.h"
+/*
+ * Functions used whatever the injection method
+ */
+
+/**
+ * vfio_init_intp - allocate, initialize the IRQ struct pointer
+ * and add it into the list of IRQs
+ * @vbasedev: the VFIO device handle
+ * @info: irq info struct retrieved from VFIO driver
+ */
+static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev,
+ struct vfio_irq_info info)
+{
+ int ret;
+ VFIOPlatformDevice *vdev =
+ container_of(vbasedev, VFIOPlatformDevice, vbasedev);
+ SysBusDevice *sbdev = SYS_BUS_DEVICE(vdev);
+ VFIOINTp *intp;
+
+ intp = g_malloc0(sizeof(*intp));
+ intp->vdev = vdev;
+ intp->pin = info.index;
+ intp->flags = info.flags;
+ intp->state = VFIO_IRQ_INACTIVE;
+
+ sysbus_init_irq(sbdev, &intp->qemuirq);
+
+ /* Get an eventfd for trigger */
+ ret = event_notifier_init(&intp->interrupt, 0);
+ if (ret) {
+ g_free(intp);
+ error_report("vfio: Error: trigger event_notifier_init failed ");
+ return NULL;
+ }
+
+ QLIST_INSERT_HEAD(&vdev->intp_list, intp, next);
+ return intp;
+}
+
+/**
+ * vfio_set_trigger_eventfd - set VFIO eventfd handling
+ *
+ * @intp: IRQ struct handle
+ * @handler: handler to be called on eventfd signaling
+ *
+ * Setup VFIO signaling and attach an optional user-side handler
+ * to the eventfd
+ */
+static int vfio_set_trigger_eventfd(VFIOINTp *intp,
+ eventfd_user_side_handler_t handler)
+{
+ VFIODevice *vbasedev = &intp->vdev->vbasedev;
+ struct vfio_irq_set *irq_set;
+ int argsz, ret;
+ int32_t *pfd;
+
+ argsz = sizeof(*irq_set) + sizeof(*pfd);
+ irq_set = g_malloc0(argsz);
+ irq_set->argsz = argsz;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = intp->pin;
+ irq_set->start = 0;
+ irq_set->count = 1;
+ pfd = (int32_t *)&irq_set->data;
+ *pfd = event_notifier_get_fd(&intp->interrupt);
+ qemu_set_fd_handler(*pfd, (IOHandler *)handler, NULL, intp);
+ ret = ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ g_free(irq_set);
+ if (ret < 0) {
+ error_report("vfio: Failed to set trigger eventfd: %m");
+ qemu_set_fd_handler(*pfd, NULL, NULL, NULL);
+ }
+ return ret;
+}
+
+/*
+ * Functions only used when eventfds are handled on user-side
+ * ie. without irqfd
+ */
+
+/**
+ * vfio_mmap_set_enabled - enable/disable the fast path mode
+ * @vdev: the VFIO platform device
+ * @enabled: the target mmap state
+ *
+ * enabled = true ~ fast path = MMIO region is mmaped (no KVM TRAP);
+ * enabled = false ~ slow path = MMIO region is trapped and region callbacks
+ * are called; slow path enables to trap the device IRQ status register reset
+*/
+
+static void vfio_mmap_set_enabled(VFIOPlatformDevice *vdev, bool enabled)
+{
+ int i;
+
+ trace_vfio_platform_mmap_set_enabled(enabled);
+
+ for (i = 0; i < vdev->vbasedev.num_regions; i++) {
+ VFIORegion *region = vdev->regions[i];
+
+ memory_region_set_enabled(®ion->mmap_mem, enabled);
+ }
+}
+
+/**
+ * vfio_intp_mmap_enable - timer function, restores the fast path
+ * if there is no more active IRQ
+ * @opaque: actually points to the VFIO platform device
+ *
+ * Called on mmap timer timout, this function checks whether the
+ * IRQ is still active and if not, restores the fast path.
+ * by construction a single eventfd is handled at a time.
+ * if the IRQ is still active, the timer is re-programmed.
+ */
+static void vfio_intp_mmap_enable(void *opaque)
+{
+ VFIOINTp *tmp;
+ VFIOPlatformDevice *vdev = (VFIOPlatformDevice *)opaque;
+
+ qemu_mutex_lock(&vdev->intp_mutex);
+ QLIST_FOREACH(tmp, &vdev->intp_list, next) {
+ if (tmp->state == VFIO_IRQ_ACTIVE) {
+ trace_vfio_platform_intp_mmap_enable(tmp->pin);
+ /* re-program the timer to check active status later */
+ timer_mod(vdev->mmap_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
+ vdev->mmap_timeout);
+ qemu_mutex_unlock(&vdev->intp_mutex);
+ return;
+ }
+ }
+ vfio_mmap_set_enabled(vdev, true);
+ qemu_mutex_unlock(&vdev->intp_mutex);
+}
+
+/**
+ * vfio_intp_inject_pending_lockheld - Injects a pending IRQ
+ * @opaque: opaque pointer, in practice the VFIOINTp handle
+ *
+ * The function is called on a previous IRQ completion, from
+ * vfio_platform_eoi, while the intp_mutex is locked.
+ * Also in such situation, the slow path already is set and
+ * the mmap timer was already programmed.
+ */
+static void vfio_intp_inject_pending_lockheld(VFIOINTp *intp)
+{
+ trace_vfio_platform_intp_inject_pending_lockheld(intp->pin,
+ event_notifier_get_fd(&intp->interrupt));
+
+ intp->state = VFIO_IRQ_ACTIVE;
+
+ /* trigger the virtual IRQ */
+ qemu_set_irq(intp->qemuirq, 1);
+}
+
+/**
+ * vfio_intp_interrupt - The user-side eventfd handler
+ * @opaque: opaque pointer which in practice is the VFIOINTp handle
+ *
+ * the function is entered in event handler context:
+ * the vIRQ is injected into the guest if there is no other active
+ * or pending IRQ.
+ */
+static void vfio_intp_interrupt(VFIOINTp *intp)
+{
+ int ret;
+ VFIOINTp *tmp;
+ VFIOPlatformDevice *vdev = intp->vdev;
+ bool delay_handling = false;
+
+ qemu_mutex_lock(&vdev->intp_mutex);
+ if (intp->state == VFIO_IRQ_INACTIVE) {
+ QLIST_FOREACH(tmp, &vdev->intp_list, next) {
+ if (tmp->state == VFIO_IRQ_ACTIVE ||
+ tmp->state == VFIO_IRQ_PENDING) {
+ delay_handling = true;
+ break;
+ }
+ }
+ }
+ if (delay_handling) {
+ /*
+ * the new IRQ gets a pending status and is pushed in
+ * the pending queue
+ */
+ intp->state = VFIO_IRQ_PENDING;
+ trace_vfio_intp_interrupt_set_pending(intp->pin);
+ QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue,
+ intp, pqnext);
+ ret = event_notifier_test_and_clear(&intp->interrupt);
+ qemu_mutex_unlock(&vdev->intp_mutex);
+ return;
+ }
+
+ trace_vfio_platform_intp_interrupt(intp->pin,
+ event_notifier_get_fd(&intp->interrupt));
+
+ ret = event_notifier_test_and_clear(&intp->interrupt);
+ if (!ret) {
+ error_report("Error when clearing fd=%d (ret = %d)\n",
+ event_notifier_get_fd(&intp->interrupt), ret);
+ }
+
+ intp->state = VFIO_IRQ_ACTIVE;
+
+ /* sets slow path */
+ vfio_mmap_set_enabled(vdev, false);
+
+ /* trigger the virtual IRQ */
+ qemu_set_irq(intp->qemuirq, 1);
+
+ /*
+ * Schedule the mmap timer which will restore fastpath when no IRQ
+ * is active anymore
+ */
+ if (vdev->mmap_timeout) {
+ timer_mod(vdev->mmap_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
+ vdev->mmap_timeout);
+ }
+ qemu_mutex_unlock(&vdev->intp_mutex);
+}
+
+/**
+ * vfio_platform_eoi - IRQ completion routine
+ * @vbasedev: the VFIO device handle
+ *
+ * De-asserts the active virtual IRQ and unmasks the physical IRQ
+ * (effective for level sensitive IRQ auto-masked by the VFIO driver).
+ * Then it handles next pending IRQ if any.
+ * eoi function is called on the first access to any MMIO region
+ * after an IRQ was triggered, trapped since slow path was set.
+ * It is assumed this access corresponds to the IRQ status
+ * register reset. With such a mechanism, a single IRQ can be
+ * handled at a time since there is no way to know which IRQ
+ * was completed by the guest (we would need additional details
+ * about the IRQ status register mask).
+ */
+static void vfio_platform_eoi(VFIODevice *vbasedev)
+{
+ VFIOINTp *intp;
+ VFIOPlatformDevice *vdev =
+ container_of(vbasedev, VFIOPlatformDevice, vbasedev);
+
+ qemu_mutex_lock(&vdev->intp_mutex);
+ QLIST_FOREACH(intp, &vdev->intp_list, next) {
+ if (intp->state == VFIO_IRQ_ACTIVE) {
+ trace_vfio_platform_eoi(intp->pin,
+ event_notifier_get_fd(&intp->interrupt));
+ intp->state = VFIO_IRQ_INACTIVE;
+
+ /* deassert the virtual IRQ */
+ qemu_set_irq(intp->qemuirq, 0);
+
+ if (intp->flags & VFIO_IRQ_INFO_AUTOMASKED) {
+ /* unmasks the physical level-sensitive IRQ */
+ vfio_unmask_single_irqindex(vbasedev, intp->pin);
+ }
+
+ /* a single IRQ can be active at a time */
+ break;
+ }
+ }
+ /* in case there are pending IRQs, handle the first one */
+ if (!QSIMPLEQ_EMPTY(&vdev->pending_intp_queue)) {
+ intp = QSIMPLEQ_FIRST(&vdev->pending_intp_queue);
+ vfio_intp_inject_pending_lockheld(intp);
+ QSIMPLEQ_REMOVE_HEAD(&vdev->pending_intp_queue, pqnext);
+ }
+ qemu_mutex_unlock(&vdev->intp_mutex);
+}
+
+/**
+ * vfio_start_eventfd_injection - starts the virtual IRQ injection using
+ * user-side handled eventfds
+ * @intp: the IRQ struct pointer
+ */
+
+static int vfio_start_eventfd_injection(VFIOINTp *intp)
+{
+ int ret;
+
+ ret = vfio_set_trigger_eventfd(intp, vfio_intp_interrupt);
+ if (ret) {
+ error_report("vfio: Error: Failed to pass IRQ fd to the driver: %m");
+ }
+ return ret;
+}
+
/* VFIO skeleton */
/* not implemented yet */
@@ -42,12 +331,13 @@ static int vfio_platform_hot_reset_multi(VFIODevice *vbasedev)
/**
* vfio_populate_device - Allocate and populate MMIO region
- * structs according to driver returned information
+ * and IRQ structs according to driver returned information
* @vbasedev: the VFIO device handle
*
*/
static int vfio_populate_device(VFIODevice *vbasedev)
{
+ VFIOINTp *intp, *tmp;
int i, ret = -1;
VFIOPlatformDevice *vdev =
container_of(vbasedev, VFIOPlatformDevice, vbasedev);
@@ -85,7 +375,38 @@ static int vfio_populate_device(VFIODevice *vbasedev)
(unsigned long)ptr->fd_offset);
}
+ vdev->mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+ vfio_intp_mmap_enable, vdev);
+
+ QSIMPLEQ_INIT(&vdev->pending_intp_queue);
+
+ for (i = 0; i < vbasedev->num_irqs; i++) {
+ struct vfio_irq_info irq = { .argsz = sizeof(irq) };
+
+ irq.index = i;
+ ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
+ if (ret) {
+ error_printf("vfio: error getting device %s irq info",
+ vbasedev->name);
+ goto irq_err;
+ } else {
+ trace_vfio_platform_populate_interrupts(irq.index,
+ irq.count,
+ irq.flags);
+ intp = vfio_init_intp(vbasedev, irq);
+ if (!intp) {
+ error_report("vfio: Error installing IRQ %d up", i);
+ goto irq_err;
+ }
+ }
+ }
return 0;
+irq_err:
+ timer_del(vdev->mmap_timer);
+ QLIST_FOREACH_SAFE(intp, &vdev->intp_list, next, tmp) {
+ QLIST_REMOVE(intp, next);
+ g_free(intp);
+ }
reg_error:
for (i = 0; i < vbasedev->num_regions; i++) {
g_free(vdev->regions[i]);
@@ -98,6 +419,7 @@ reg_error:
static VFIODeviceOps vfio_platform_ops = {
.vfio_compute_needs_reset = vfio_platform_compute_needs_reset,
.vfio_hot_reset_multi = vfio_platform_hot_reset_multi,
+ .vfio_eoi = vfio_platform_eoi,
};
/**
@@ -229,6 +551,7 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
VFIODevice *vbasedev = &vdev->vbasedev;
+ VFIOINTp *intp;
int i, ret;
vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
@@ -247,6 +570,10 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
vfio_map_region(vdev, i);
sysbus_init_mmio(sbdev, &vdev->regions[i]->mem);
}
+
+ QLIST_FOREACH(intp, &vdev->intp_list, next) {
+ vfio_start_eventfd_injection(intp);
+ }
}
static const VMStateDescription vfio_platform_vmstate = {
@@ -257,6 +584,8 @@ static const VMStateDescription vfio_platform_vmstate = {
static Property vfio_platform_dev_properties[] = {
DEFINE_PROP_STRING("host", VFIOPlatformDevice, vbasedev.name),
DEFINE_PROP_BOOL("x-mmap", VFIOPlatformDevice, vbasedev.allow_mmap, true),
+ DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
+ mmap_timeout, 1100),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index 338f0c6..ec97e97 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -18,14 +18,46 @@
#include "hw/sysbus.h"
#include "hw/vfio/vfio-common.h"
+#include "qemu/event_notifier.h"
+#include "qemu/queue.h"
+#include "hw/irq.h"
#define TYPE_VFIO_PLATFORM "vfio-platform"
+enum {
+ VFIO_IRQ_INACTIVE = 0,
+ VFIO_IRQ_PENDING = 1,
+ VFIO_IRQ_ACTIVE = 2,
+ /* VFIO_IRQ_ACTIVE_AND_PENDING cannot happen with VFIO */
+};
+
+typedef struct VFIOINTp {
+ QLIST_ENTRY(VFIOINTp) next; /* entry for IRQ list */
+ QSIMPLEQ_ENTRY(VFIOINTp) pqnext; /* entry for pending IRQ queue */
+ EventNotifier interrupt; /* eventfd triggered on interrupt */
+ EventNotifier unmask; /* eventfd for unmask on QEMU bypass */
+ qemu_irq qemuirq;
+ struct VFIOPlatformDevice *vdev; /* back pointer to device */
+ int state; /* inactive, pending, active */
+ uint8_t pin; /* index */
+ uint32_t virtualID; /* virtual IRQ */
+ uint32_t flags; /* IRQ info flags */
+} VFIOINTp;
+
+/* function type for user side eventfd handler */
+typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp);
+
typedef struct VFIOPlatformDevice {
SysBusDevice sbdev;
VFIODevice vbasedev; /* not a QOM object */
VFIORegion **regions;
+ QLIST_HEAD(, VFIOINTp) intp_list; /* list of IRQs */
+ /* queue of pending IRQs */
+ QSIMPLEQ_HEAD(pending_intp_queue, VFIOINTp) pending_intp_queue;
char *compat; /* compatibility string */
+ uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */
+ QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
+ QemuMutex intp_mutex; /* protect the intp_list IRQ state */
} VFIOPlatformDevice;
typedef struct VFIOPlatformDeviceClass {
diff --git a/trace-events b/trace-events
index 2ccc822..ed8ed90 100644
--- a/trace-events
+++ b/trace-events
@@ -1564,6 +1564,13 @@ vfio_put_base_device(int fd) "close vdev->fd=%d"
vfio_platform_populate_regions(int region_index, unsigned long flag, unsigned long size, int fd, unsigned long offset) "- region %d flags = 0x%lx, size = 0x%lx, fd= %d, offset = 0x%lx"
vfio_platform_base_device_init(char *name, int groupid) "%s belongs to group #%d"
vfio_platform_realize(char *name, char *compat) "vfio device %s, compat = %s"
+vfio_platform_eoi(int pin, int fd) "EOI IRQ pin %d (fd=%d)"
+vfio_platform_mmap_set_enabled(bool enabled) "fast path = %d"
+vfio_platform_intp_mmap_enable(int pin) "IRQ #%d still active, stay in slow path"
+vfio_platform_intp_interrupt(int pin, int fd) "Inject IRQ #%d (fd = %d)"
+vfio_platform_intp_inject_pending_lockheld(int pin, int fd) "Inject pending IRQ #%d (fd = %d)"
+vfio_platform_populate_interrupts(int pin, int count, int flags) "- IRQ index %d: count %d, flags=0x%x"
+vfio_intp_interrupt_set_pending(int index) "irq %d is set PENDING"
#hw/acpi/memory_hotplug.c
mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 04/12] hw/vfio/platform: calxeda xgmac device
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (2 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 03/12] hw/vfio/platform: add irq assignment Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 05/12] hw/arm/sysbus-fdt: enable vfio-calxeda-xgmac dynamic instantiation Eric Auger
` (7 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
The platform device class has become abstract. This patch introduces
a calxeda xgmac device that derives from it.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Alex Bennee<alex.bennee@linaro.org>
---
v10 -> v11:
- add Alex Reviewed-by
- move virt modifications in a separate patch
v8 -> v9:
- renamed calxeda_xgmac.c into calxeda-xgmac.c
v7 -> v8:
- add a comment in the header about the MMIO regions and IRQ which
are exposed by the device
v5 -> v6
- back again following Alex Graf advises
- fix a bug related to compat override
v4 -> v5:
removed since device tree was moved to hw/arm/dyn_sysbus_devtree.c
v4: creation for device tree specialization
Conflicts:
hw/arm/virt.c
---
hw/vfio/Makefile.objs | 1 +
hw/vfio/calxeda-xgmac.c | 54 ++++++++++++++++++++++++++++++++++++
include/hw/vfio/vfio-calxeda-xgmac.h | 46 ++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+)
create mode 100644 hw/vfio/calxeda-xgmac.c
create mode 100644 include/hw/vfio/vfio-calxeda-xgmac.h
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index c5c76fe..d540c9d 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -2,4 +2,5 @@ ifeq ($(CONFIG_LINUX), y)
obj-$(CONFIG_SOFTMMU) += common.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_SOFTMMU) += platform.o
+obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
endif
diff --git a/hw/vfio/calxeda-xgmac.c b/hw/vfio/calxeda-xgmac.c
new file mode 100644
index 0000000..c4b8fef
--- /dev/null
+++ b/hw/vfio/calxeda-xgmac.c
@@ -0,0 +1,54 @@
+/*
+ * calxeda xgmac VFIO device
+ *
+ * Copyright Linaro Limited, 2014
+ *
+ * Authors:
+ * Eric Auger <eric.auger@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/vfio/vfio-calxeda-xgmac.h"
+
+static void calxeda_xgmac_realize(DeviceState *dev, Error **errp)
+{
+ VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
+ VFIOCalxedaXgmacDeviceClass *k = VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(dev);
+
+ vdev->compat = g_strdup("calxeda,hb-xgmac");
+
+ k->parent_realize(dev, errp);
+}
+
+static const VMStateDescription vfio_platform_vmstate = {
+ .name = TYPE_VFIO_CALXEDA_XGMAC,
+ .unmigratable = 1,
+};
+
+static void vfio_calxeda_xgmac_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VFIOCalxedaXgmacDeviceClass *vcxc =
+ VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass);
+ vcxc->parent_realize = dc->realize;
+ dc->realize = calxeda_xgmac_realize;
+ dc->desc = "VFIO Calxeda XGMAC";
+}
+
+static const TypeInfo vfio_calxeda_xgmac_dev_info = {
+ .name = TYPE_VFIO_CALXEDA_XGMAC,
+ .parent = TYPE_VFIO_PLATFORM,
+ .instance_size = sizeof(VFIOCalxedaXgmacDevice),
+ .class_init = vfio_calxeda_xgmac_class_init,
+ .class_size = sizeof(VFIOCalxedaXgmacDeviceClass),
+};
+
+static void register_calxeda_xgmac_dev_type(void)
+{
+ type_register_static(&vfio_calxeda_xgmac_dev_info);
+}
+
+type_init(register_calxeda_xgmac_dev_type)
diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h
new file mode 100644
index 0000000..f994775
--- /dev/null
+++ b/include/hw/vfio/vfio-calxeda-xgmac.h
@@ -0,0 +1,46 @@
+/*
+ * VFIO calxeda xgmac device
+ *
+ * Copyright Linaro Limited, 2014
+ *
+ * Authors:
+ * Eric Auger <eric.auger@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_VFIO_VFIO_CALXEDA_XGMAC_H
+#define HW_VFIO_VFIO_CALXEDA_XGMAC_H
+
+#include "hw/vfio/vfio-platform.h"
+
+#define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac"
+
+/**
+ * This device exposes:
+ * - a single MMIO region corresponding to its register space
+ * - 3 IRQS (main and 2 power related IRQs)
+ */
+typedef struct VFIOCalxedaXgmacDevice {
+ VFIOPlatformDevice vdev;
+} VFIOCalxedaXgmacDevice;
+
+typedef struct VFIOCalxedaXgmacDeviceClass {
+ /*< private >*/
+ VFIOPlatformDeviceClass parent_class;
+ /*< public >*/
+ DeviceRealize parent_realize;
+} VFIOCalxedaXgmacDeviceClass;
+
+#define VFIO_CALXEDA_XGMAC_DEVICE(obj) \
+ OBJECT_CHECK(VFIOCalxedaXgmacDevice, (obj), TYPE_VFIO_CALXEDA_XGMAC)
+#define VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VFIOCalxedaXgmacDeviceClass, (klass), \
+ TYPE_VFIO_CALXEDA_XGMAC)
+#define VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VFIOCalxedaXgmacDeviceClass, (obj), \
+ TYPE_VFIO_CALXEDA_XGMAC)
+
+#endif
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 05/12] hw/arm/sysbus-fdt: enable vfio-calxeda-xgmac dynamic instantiation
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (3 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 04/12] hw/vfio/platform: calxeda xgmac device Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 06/12] kvm: rename kvm_irqchip_[add, remove]_irqfd_notifier with gsi suffix Eric Auger
` (6 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
This patch allows the instantiation of the vfio-calxeda-xgmac device
from the QEMU command line (-device vfio-calxeda-xgmac,host="<device>").
A specialized device tree node is created for the guest, containing
compat, dma-coherent, reg and interrupts properties.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v12 -> v13:
- use platform_bus_get_mmio_addr instead of deprecated mmio[0] property.
Thanks to Bharat who pointed this issue out.
- use cpu_to_be32 to mmio_base & size (Vikram report)
v10 -> v11:
- add dma-coherent property to calxeda midway xgmac node (fix)
- use qemu_fdt_setprop to add reg property instead of
qemu_fdt_setprop_sized_cells_from_array
- commit message rewording
v8 -> v9:
- properly free resources in case of errors in
add_calxeda_midway_xgmac_fdt_node
v7 -> v8:
- move the add_fdt_node_functions array declaration between the device
specific code and the generic code to avoid forward declarations of
decice specific functions
- rename add_basic_vfio_fdt_node into
add_calxeda_midway_xgmac_fdt_node
v6 -> v7:
- compat string re-formatting removed since compat string is not exposed
anymore as a user option
- VFIO IRQ kick-off removed from sysbus-fdt and moved to VFIO platform
device
---
hw/arm/sysbus-fdt.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
index 3038b94..3d67acf 100644
--- a/hw/arm/sysbus-fdt.c
+++ b/hw/arm/sysbus-fdt.c
@@ -26,6 +26,8 @@
#include "sysemu/device_tree.h"
#include "hw/platform-bus.h"
#include "sysemu/sysemu.h"
+#include "hw/vfio/vfio-platform.h"
+#include "hw/vfio/vfio-calxeda-xgmac.h"
/*
* internal struct that contains the information to create dynamic
@@ -53,11 +55,81 @@ typedef struct NodeCreationPair {
int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
} NodeCreationPair;
+/* Device Specific Code */
+
+/**
+ * add_calxeda_midway_xgmac_fdt_node
+ *
+ * Generates a simple node with following properties:
+ * compatible string, regs, interrupts, dma-coherent
+ */
+static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
+{
+ PlatformBusFDTData *data = opaque;
+ PlatformBusDevice *pbus = data->pbus;
+ void *fdt = data->fdt;
+ const char *parent_node = data->pbus_node_name;
+ int compat_str_len, i, ret = -1;
+ char *nodename;
+ uint32_t *irq_attr, *reg_attr;
+ uint64_t mmio_base, irq_number;
+ VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
+ VFIODevice *vbasedev = &vdev->vbasedev;
+
+ mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+ nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
+ vbasedev->name, mmio_base);
+ qemu_fdt_add_subnode(fdt, nodename);
+
+ compat_str_len = strlen(vdev->compat) + 1;
+ qemu_fdt_setprop(fdt, nodename, "compatible",
+ vdev->compat, compat_str_len);
+
+ qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
+
+ reg_attr = g_new(uint32_t, vbasedev->num_regions*2);
+ for (i = 0; i < vbasedev->num_regions; i++) {
+ mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
+ reg_attr[2*i] = cpu_to_be32(mmio_base);
+ reg_attr[2*i+1] = cpu_to_be32(
+ memory_region_size(&vdev->regions[i]->mem));
+ }
+ ret = qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
+ vbasedev->num_regions*2*sizeof(uint32_t));
+ if (ret) {
+ error_report("could not set reg property of node %s", nodename);
+ goto fail_reg;
+ }
+
+ irq_attr = g_new(uint32_t, vbasedev->num_irqs*3);
+ for (i = 0; i < vbasedev->num_irqs; i++) {
+ irq_number = platform_bus_get_irqn(pbus, sbdev , i)
+ + data->irq_start;
+ irq_attr[3*i] = cpu_to_be32(0);
+ irq_attr[3*i+1] = cpu_to_be32(irq_number);
+ irq_attr[3*i+2] = cpu_to_be32(0x4);
+ }
+ ret = qemu_fdt_setprop(fdt, nodename, "interrupts",
+ irq_attr, vbasedev->num_irqs*3*sizeof(uint32_t));
+ if (ret) {
+ error_report("could not set interrupts property of node %s",
+ nodename);
+ }
+ g_free(irq_attr);
+fail_reg:
+ g_free(reg_attr);
+ g_free(nodename);
+ return ret;
+}
+
/* list of supported dynamic sysbus devices */
static const NodeCreationPair add_fdt_node_functions[] = {
+ {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
{"", NULL}, /* last element */
};
+/* Generic Code */
+
/**
* add_fdt_node - add the device tree node of a dynamic sysbus device
*
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 06/12] kvm: rename kvm_irqchip_[add, remove]_irqfd_notifier with gsi suffix
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (4 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 05/12] hw/arm/sysbus-fdt: enable vfio-calxeda-xgmac dynamic instantiation Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 07/12] kvm-all.c: add qemu_irq/gsi hash table and utility routines Eric Auger
` (5 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
Anticipating for the introduction of new add/remove functions taking
a qemu_irq parameter, let's rename existing ones with a gsi suffix.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
hw/s390x/virtio-ccw.c | 8 ++++----
hw/vfio/pci.c | 6 +++---
hw/virtio/virtio-pci.c | 4 ++--
include/sysemu/kvm.h | 7 ++++---
kvm-all.c | 7 ++++---
kvm-stub.c | 7 ++++---
6 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index ed75c63..55a74fa 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1238,8 +1238,8 @@ static int virtio_ccw_add_irqfd(VirtioCcwDevice *dev, int n)
VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
- return kvm_irqchip_add_irqfd_notifier(kvm_state, notifier, NULL,
- dev->routes.gsi[n]);
+ return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, notifier, NULL,
+ dev->routes.gsi[n]);
}
static void virtio_ccw_remove_irqfd(VirtioCcwDevice *dev, int n)
@@ -1249,8 +1249,8 @@ static void virtio_ccw_remove_irqfd(VirtioCcwDevice *dev, int n)
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
int ret;
- ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, notifier,
- dev->routes.gsi[n]);
+ ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, notifier,
+ dev->routes.gsi[n]);
assert(ret == 0);
}
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index cd15b20..938f584 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -596,7 +596,7 @@ static void vfio_add_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage *msg,
return;
}
- if (kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->kvm_interrupt,
+ if (kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &vector->kvm_interrupt,
NULL, virq) < 0) {
kvm_irqchip_release_virq(kvm_state, virq);
event_notifier_cleanup(&vector->kvm_interrupt);
@@ -608,8 +608,8 @@ static void vfio_add_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage *msg,
static void vfio_remove_kvm_msi_virq(VFIOMSIVector *vector)
{
- kvm_irqchip_remove_irqfd_notifier(kvm_state, &vector->kvm_interrupt,
- vector->virq);
+ kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &vector->kvm_interrupt,
+ vector->virq);
kvm_irqchip_release_virq(kvm_state, vector->virq);
vector->virq = -1;
event_notifier_cleanup(&vector->kvm_interrupt);
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index c7c3f72..3be7fad 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -477,7 +477,7 @@ static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
int ret;
- ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq);
+ ret = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq);
return ret;
}
@@ -491,7 +491,7 @@ static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
int ret;
- ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq);
+ ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq);
assert(ret == 0);
}
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 197e6c0..0f28d6f 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -413,9 +413,10 @@ void kvm_irqchip_release_virq(KVMState *s, int virq);
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
-int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
- EventNotifier *rn, int virq);
-int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
+int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
+ EventNotifier *rn, int virq);
+int kvm_irqchip_remove_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
+ int virq);
void kvm_pc_gsi_handler(void *opaque, int n, int level);
void kvm_pc_setup_irq_routing(bool pci_enabled);
void kvm_init_irq_routing(KVMState *s);
diff --git a/kvm-all.c b/kvm-all.c
index 4ec153d..42bb923 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1368,14 +1368,15 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
}
#endif /* !KVM_CAP_IRQ_ROUTING */
-int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
- EventNotifier *rn, int virq)
+int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
+ EventNotifier *rn, int virq)
{
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n),
rn ? event_notifier_get_fd(rn) : -1, virq, true);
}
-int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
+int kvm_irqchip_remove_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
+ int virq)
{
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), -1, virq,
false);
diff --git a/kvm-stub.c b/kvm-stub.c
index 7ba90c5..977de21 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -137,13 +137,14 @@ int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
return -ENOSYS;
}
-int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
- EventNotifier *rn, int virq)
+int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
+ EventNotifier *rn, int virq)
{
return -ENOSYS;
}
-int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
+int kvm_irqchip_remove_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
+ int virq)
{
return -ENOSYS;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 07/12] kvm-all.c: add qemu_irq/gsi hash table and utility routines
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (5 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 06/12] kvm: rename kvm_irqchip_[add, remove]_irqfd_notifier with gsi suffix Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 08/12] intc: arm_gic_kvm: set the qemu_irq/gsi mapping Eric Auger
` (4 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
VFIO platform device needs to setup irqfd but it does not know the
gsi corresponding to the device qemu_irq. This series proposes to
store a hash table in kvm_state using the qemu_irq as key and the gsi
as a value.
kvm_irqchip_set_qemuirq_gsi allows to insert such a pair. The interrupt
controller is supposed to use it.
kvm_irqchip_[add, remove]_irqfd_notifier allows to setup/tear down
irqfd directly from the qemu_irq.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v2 -> v3:
- rename kvm_irqchip_[add, remove]_qemuirq_irqfd_notifier into
kvm_irqchip_[add, remove]_irqfd_notifier. Possible since legacy
functions were also renamed with _gsi suffix.
V1 -> v2:
- qemu_irq get_gsi callback replaced by hash table stored in kvm
---
include/sysemu/kvm.h | 6 ++++++
kvm-all.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 0f28d6f..bc3f230 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -18,6 +18,7 @@
#include "config-host.h"
#include "qemu/queue.h"
#include "qom/cpu.h"
+#include "hw/irq.h"
#ifdef CONFIG_KVM
#include <linux/kvm.h>
@@ -417,6 +418,11 @@ int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
EventNotifier *rn, int virq);
int kvm_irqchip_remove_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
int virq);
+int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
+ EventNotifier *rn, qemu_irq irq);
+int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n,
+ qemu_irq irq);
+void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi);
void kvm_pc_gsi_handler(void *opaque, int n, int level);
void kvm_pc_setup_irq_routing(bool pci_enabled);
void kvm_init_irq_routing(KVMState *s);
diff --git a/kvm-all.c b/kvm-all.c
index 42bb923..6531062 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -37,6 +37,7 @@
#include "exec/address-spaces.h"
#include "qemu/event_notifier.h"
#include "trace.h"
+#include "hw/irq.h"
#include "hw/boards.h"
@@ -99,6 +100,7 @@ struct KVMState
* unsigned, and treating them as signed here can break things */
unsigned irq_set_ioctl;
unsigned int sigmask_len;
+ GHashTable *gsimap;
#ifdef KVM_CAP_IRQ_ROUTING
struct kvm_irq_routing *irq_routes;
int nr_allocated_irq_routes;
@@ -1382,6 +1384,37 @@ int kvm_irqchip_remove_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
false);
}
+int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
+ EventNotifier *rn, qemu_irq irq)
+{
+ gpointer key, gsi;
+ gboolean found = g_hash_table_lookup_extended(s->gsimap, irq, &key, &gsi);
+
+ if (!found) {
+ return -ENXIO;
+ } else {
+ return kvm_irqchip_add_irqfd_notifier_gsi(s, n, rn, GPOINTER_TO_UINT(gsi));
+ }
+}
+
+int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n,
+ qemu_irq irq)
+{
+ gpointer key, gsi;
+ gboolean found = g_hash_table_lookup_extended(s->gsimap, irq, &key, &gsi);
+
+ if (!found) {
+ return -ENXIO;
+ } else {
+ return kvm_irqchip_remove_irqfd_notifier_gsi(s, n, GPOINTER_TO_INT(gsi));
+ }
+}
+
+void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi)
+{
+ g_hash_table_insert(s->gsimap, irq, GINT_TO_POINTER(gsi));
+}
+
static int kvm_irqchip_create(MachineState *machine, KVMState *s)
{
int ret;
@@ -1414,6 +1447,8 @@ static int kvm_irqchip_create(MachineState *machine, KVMState *s)
kvm_init_irq_routing(s);
+ s->gsimap = g_hash_table_new(g_direct_hash, g_direct_equal);
+
return 0;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 08/12] intc: arm_gic_kvm: set the qemu_irq/gsi mapping
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (6 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 07/12] kvm-all.c: add qemu_irq/gsi hash table and utility routines Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 09/12] qdev: pass the check callback to qdev_init_gpio_out_named Eric Auger
` (3 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
The arm_gic_kvm now calls kvm_irqchip_set_qemuirq_gsi to build
the hash table storing qemu_irq/gsi mappings. From that point on
irqfd can be setup directly from the qemu_irq using
kvm_irqchip_add_irqfd_notifier.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v2 -> v3:
- kvm_irqchip_add_qemuirq_irqfd_notifier renamed into
kvm_irqchip_add_irqfd_notifier
---
hw/intc/arm_gic_kvm.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index e1952ad..28506e3 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -554,6 +554,11 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
*/
i += (GIC_INTERNAL * s->num_cpu);
qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i);
+
+ for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
+ qemu_irq irq = qdev_get_gpio_in(dev, i);
+ kvm_irqchip_set_qemuirq_gsi(kvm_state, irq, i);
+ }
/* We never use our outbound IRQ lines but provide them so that
* we maintain the same interface as the non-KVM GIC.
*/
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 09/12] qdev: pass the check callback to qdev_init_gpio_out_named
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (7 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 08/12] intc: arm_gic_kvm: set the qemu_irq/gsi mapping Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 10/12] qdev: check callback takes the property child as third argument Eric Auger
` (2 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
qdev_init_gpio_out_named takes a new argument corresponding to the
check callback passed to object_property_add_link. In qdev_init_gpio_out
and sysbus_init_irq, this callback is currently set to the dummy
object_property_allow_set_link.
This will allow qdev_init_gpio_out_named callers to specialize this
callback. A subsequent patch will implement that for sysbus.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v1 -> v2:
- fix qdev_init_gpio_out_named call in sysbus_init_irq
- rewording of commit message
---
hw/core/qdev.c | 8 +++++---
hw/core/sysbus.c | 3 ++-
include/hw/qdev-core.h | 3 ++-
include/qom/object.h | 6 ++++--
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 6e6a65d..857217d 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -452,7 +452,8 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
}
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
- const char *name, int n)
+ const char *name, int n,
+ LinkPropertySetter check_cb)
{
int i;
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
@@ -465,7 +466,7 @@ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
memset(&pins[i], 0, sizeof(*pins));
object_property_add_link(OBJECT(dev), propname, TYPE_IRQ,
(Object **)&pins[i],
- object_property_allow_set_link,
+ check_cb,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
}
@@ -474,7 +475,8 @@ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
{
- qdev_init_gpio_out_named(dev, pins, NULL, n);
+ qdev_init_gpio_out_named(dev, pins, NULL, n,
+ object_property_allow_set_link);
}
qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n)
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index b53c351..1bcb64d 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -159,7 +159,8 @@ void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
/* Request an IRQ source. The actual IRQ object may be populated later. */
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
{
- qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1);
+ qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1,
+ object_property_allow_set_link);
}
/* Pass IRQs from a target device. */
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 4e673f9..0885f39 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -293,7 +293,8 @@ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
const char *name, int n);
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
- const char *name, int n);
+ const char *name, int n,
+ LinkPropertySetter fn);
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
const char *name);
diff --git a/include/qom/object.h b/include/qom/object.h
index d2d7748..95d1a1d 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -33,6 +33,9 @@ typedef struct TypeInfo TypeInfo;
typedef struct InterfaceClass InterfaceClass;
typedef struct InterfaceInfo InterfaceInfo;
+typedef void (*LinkPropertySetter)(Object *, const char *,
+ Object *, Error **);
+
#define TYPE_OBJECT "object"
/**
@@ -1165,8 +1168,7 @@ void object_property_allow_set_link(Object *, const char *,
*/
void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child,
- void (*check)(Object *obj, const char *name,
- Object *val, Error **errp),
+ LinkPropertySetter check,
ObjectPropertyLinkFlags flags,
Error **errp);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 10/12] qdev: check callback takes the property child as third argument
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (8 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 09/12] qdev: pass the check callback to qdev_init_gpio_out_named Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-29 8:22 ` Paolo Bonzini
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 11/12] sysbus: add irq_set_hook Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 12/12] hw/vfio/platform: add irqfd support Eric Auger
11 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
Check callback now takes as third argument an Object * const*. In
object_set_link_property, we pass the property child as argument.
We also assign the *child before the check call so that enhanced
check can be performed in the callback. In case the check fails,
the old value is restored and ref count is left unchanged.
This typically makes possible to do checks both on the *child
content (for instance a qemu_irq) and also perform some actions/
checks on its container, which was not possible before.
This is for example useful for starting irqfd setup in vfio platform
use case.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v1 -> v2:
- Object ** becomes Object * const*
- rename patch title
---
hw/core/qdev-properties.c | 3 ++-
include/hw/qdev-properties.h | 3 ++-
include/qom/object.h | 4 ++--
qom/object.c | 16 +++++++++-------
4 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 570d5f0..7e00cd2 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -22,7 +22,8 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
}
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
- Object *val, Error **errp)
+ Object * const *target,
+ Error **errp)
{
DeviceState *dev = DEVICE(obj);
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index d67dad5..67ac457 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -213,6 +213,7 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
* object_property_add_link().
*/
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
- Object *val, Error **errp);
+ Object * const *target,
+ Error **errp);
#endif
diff --git a/include/qom/object.h b/include/qom/object.h
index 95d1a1d..ab60c16 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -34,7 +34,7 @@ typedef struct InterfaceClass InterfaceClass;
typedef struct InterfaceInfo InterfaceInfo;
typedef void (*LinkPropertySetter)(Object *, const char *,
- Object *, Error **);
+ Object * const *, Error **);
#define TYPE_OBJECT "object"
@@ -1136,7 +1136,7 @@ typedef enum {
* an error.
*/
void object_property_allow_set_link(Object *, const char *,
- Object *, Error **);
+ Object * const *, Error **);
/**
* object_property_add_link:
diff --git a/qom/object.c b/qom/object.c
index b8dff43..ed286e7 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1112,14 +1112,14 @@ out:
}
void object_property_allow_set_link(Object *obj, const char *name,
- Object *val, Error **errp)
+ Object * const *target, Error **errp)
{
/* Allow the link to be set, always */
}
typedef struct {
Object **child;
- void (*check)(Object *, const char *, Object *, Error **);
+ LinkPropertySetter check;
ObjectPropertyLinkFlags flags;
} LinkProperty;
@@ -1201,14 +1201,17 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
return;
}
- prop->check(obj, name, new_target, &local_err);
+ object_ref(new_target);
+ *child = new_target;
+
+ prop->check(obj, name, child, &local_err);
if (local_err) {
error_propagate(errp, local_err);
+ *child = old_target;
+ object_ref(new_target);
return;
}
- object_ref(new_target);
- *child = new_target;
object_unref(old_target);
}
@@ -1232,8 +1235,7 @@ static void object_release_link_property(Object *obj, const char *name,
void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child,
- void (*check)(Object *, const char *,
- Object *, Error **),
+ LinkPropertySetter check,
ObjectPropertyLinkFlags flags,
Error **errp)
{
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v13 10/12] qdev: check callback takes the property child as third argument
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 10/12] qdev: check callback takes the property child as third argument Eric Auger
@ 2015-04-29 8:22 ` Paolo Bonzini
2015-04-29 8:37 ` Eric Auger
0 siblings, 1 reply; 19+ messages in thread
From: Paolo Bonzini @ 2015-04-29 8:22 UTC (permalink / raw)
To: Eric Auger, eric.auger, qemu-devel, alex.williamson, agraf,
peter.crosthwaite
Cc: kvmarm, patches
On 28/04/2015 18:51, Eric Auger wrote:
> - prop->check(obj, name, new_target, &local_err);
> + object_ref(new_target);
> + *child = new_target;
> +
> + prop->check(obj, name, child, &local_err);
> if (local_err) {
> error_propagate(errp, local_err);
> + *child = old_target;
> + object_ref(new_target);
This should be an unref.
Paolo
> return;
> }
>
> - object_ref(new_target);
> - *child = new_target;
> object_unref(old_target);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v13 10/12] qdev: check callback takes the property child as third argument
2015-04-29 8:22 ` Paolo Bonzini
@ 2015-04-29 8:37 ` Eric Auger
2015-04-29 11:12 ` Paolo Bonzini
0 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2015-04-29 8:37 UTC (permalink / raw)
To: Paolo Bonzini, eric.auger, qemu-devel, alex.williamson, agraf,
peter.crosthwaite
Cc: kvmarm, patches
On 04/29/2015 10:22 AM, Paolo Bonzini wrote:
>
>
> On 28/04/2015 18:51, Eric Auger wrote:
>> - prop->check(obj, name, new_target, &local_err);
>> + object_ref(new_target);
>> + *child = new_target;
>> +
>> + prop->check(obj, name, child, &local_err);
>> if (local_err) {
>> error_propagate(errp, local_err);
>> + *child = old_target;
>> + object_ref(new_target);
>
> This should be an unref.
oups yes.
Thanks! Do I keep this series or do I revert to sysbus irq connect irq
temporary patch as per Peter's last email?
Eric
>
> Paolo
>
>> return;
>> }
>>
>> - object_ref(new_target);
>> - *child = new_target;
>> object_unref(old_target);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v13 10/12] qdev: check callback takes the property child as third argument
2015-04-29 8:37 ` Eric Auger
@ 2015-04-29 11:12 ` Paolo Bonzini
2015-04-29 11:10 ` Eric Auger
0 siblings, 1 reply; 19+ messages in thread
From: Paolo Bonzini @ 2015-04-29 11:12 UTC (permalink / raw)
To: Eric Auger, eric.auger, qemu-devel, alex.williamson, agraf,
peter.crosthwaite
Cc: kvmarm, patches
On 29/04/2015 10:37, Eric Auger wrote:
>> > This should be an unref.
> oups yes.
>
> Thanks! Do I keep this series or do I revert to sysbus irq connect irq
> temporary patch as per Peter's last email?
I think reverting is better since you need a respin and Peter offered to
touch the code later.
Paolo
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 11/12] sysbus: add irq_set_hook
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (9 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 10/12] qdev: check callback takes the property child as third argument Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 12/12] hw/vfio/platform: add irqfd support Eric Auger
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
Add a new callback in the SysBusDeviceClass. This callback now can
be overriden by devices inheriting from sysbus. By default the callback
is set to the dummy object_property_allow_set_link callback.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
v1 -> v2:
- use new LinkPropertySetter type
---
hw/core/sysbus.c | 7 ++++++-
include/hw/sysbus.h | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index 1bcb64d..ee573b4 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -159,8 +159,10 @@ void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
/* Request an IRQ source. The actual IRQ object may be populated later. */
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(dev);
+
qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1,
- object_property_allow_set_link);
+ sbc->irq_set_hook);
}
/* Pass IRQs from a target device. */
@@ -311,8 +313,11 @@ MemoryRegion *sysbus_address_space(SysBusDevice *dev)
static void sysbus_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
k->init = sysbus_device_init;
k->bus_type = TYPE_SYSTEM_BUS;
+ sbc->irq_set_hook = object_property_allow_set_link;
}
static const TypeInfo sysbus_device_type_info = {
diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h
index d1f3f00..b8dde79 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -41,6 +41,7 @@ typedef struct SysBusDeviceClass {
/*< public >*/
int (*init)(SysBusDevice *dev);
+ LinkPropertySetter irq_set_hook;
} SysBusDeviceClass;
struct SysBusDevice {
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v13 12/12] hw/vfio/platform: add irqfd support
2015-04-28 16:51 [Qemu-devel] [PATCH v13 00/12] KVM platform device passthrough Eric Auger
` (10 preceding siblings ...)
2015-04-28 16:51 ` [Qemu-devel] [PATCH v13 11/12] sysbus: add irq_set_hook Eric Auger
@ 2015-04-28 16:51 ` Eric Auger
11 siblings, 0 replies; 19+ messages in thread
From: Eric Auger @ 2015-04-28 16:51 UTC (permalink / raw)
To: eric.auger, eric.auger, qemu-devel, alex.williamson, agraf,
pbonzini, peter.crosthwaite
Cc: peter.maydell, kim.phillips, b.reynal, vikrams, patches,
Bharat.Bhushan, alex.bennee, kvmarm, christoffer.dall
This patch aims at optimizing IRQ handling using irqfd framework.
Instead of handling the eventfds on user-side they are handled on
kernel side using
- the KVM irqfd framework,
- the VFIO driver virqfd framework.
the virtual IRQ completion is trapped at interrupt controller
This removes the need for fast/slow path swap.
Overall this brings significant performance improvements.
Signed-off-by: Alvise Rigo <a.rigo@virtualopensystems.com>
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Alex Bennee<alex.bennee@linaro.org>
---
v12 -> v13:
- setup the new mechanism for starting irqfd, based on
LinkPropertySetter override
- use kvm_irqchip_[add,remove]_irqfd_notifier new functions: no need
to bother about gsi (hence virtualID could be removed with small
change in trace-events)
v10 -> v11:
- Add Alex' Reviewed-by
- introduce kvm_accel in this patch and initialize it
v5 -> v6
- rely on kvm_irqfds_enabled() and kvm_resamplefds_enabled()
- guard KVM code with #ifdef CONFIG_KVM
v3 -> v4:
[Alvise Rigo]
Use of VFIO Platform driver v6 unmask/virqfd feature and removal
of resamplefd handler. Physical IRQ unmasking is now done in
VFIO driver.
v3:
[Eric Auger]
initial support with resamplefd handled on QEMU side since the
unmask was not supported on VFIO platform driver v5.
Conflicts:
hw/vfio/platform.c
---
hw/vfio/platform.c | 107 ++++++++++++++++++++++++++++++++++++++++
include/hw/vfio/vfio-platform.h | 3 +-
trace-events | 2 +
3 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index f484764..376f865 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -26,6 +26,7 @@
#include "hw/sysbus.h"
#include "trace.h"
#include "hw/platform-bus.h"
+#include "sysemu/kvm.h"
/*
* Functions used whatever the injection method
@@ -51,6 +52,7 @@ static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev,
intp->pin = info.index;
intp->flags = info.flags;
intp->state = VFIO_IRQ_INACTIVE;
+ intp->kvm_accel = false;
sysbus_init_irq(sbdev, &intp->qemuirq);
@@ -61,6 +63,13 @@ static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev,
error_report("vfio: Error: trigger event_notifier_init failed ");
return NULL;
}
+ /* Get an eventfd for resample/unmask */
+ ret = event_notifier_init(&intp->unmask, 0);
+ if (ret) {
+ g_free(intp);
+ error_report("vfio: Error: resample event_notifier_init failed eoi");
+ return NULL;
+ }
QLIST_INSERT_HEAD(&vdev->intp_list, intp, next);
return intp;
@@ -315,6 +324,95 @@ static int vfio_start_eventfd_injection(VFIOINTp *intp)
return ret;
}
+/*
+ * Functions used for irqfd
+ */
+
+#ifdef CONFIG_KVM
+
+/**
+ * vfio_set_resample_eventfd - sets the resamplefd for an IRQ
+ * @intp: the IRQ struct handle
+ * programs the VFIO driver to unmask this IRQ when the
+ * intp->unmask eventfd is triggered
+ */
+static int vfio_set_resample_eventfd(VFIOINTp *intp)
+{
+ VFIODevice *vbasedev = &intp->vdev->vbasedev;
+ struct vfio_irq_set *irq_set;
+ int argsz, ret;
+ int32_t *pfd;
+
+ argsz = sizeof(*irq_set) + sizeof(*pfd);
+ irq_set = g_malloc0(argsz);
+ irq_set->argsz = argsz;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_UNMASK;
+ irq_set->index = intp->pin;
+ irq_set->start = 0;
+ irq_set->count = 1;
+ pfd = (int32_t *)&irq_set->data;
+ *pfd = event_notifier_get_fd(&intp->unmask);
+ qemu_set_fd_handler(*pfd, NULL, NULL, NULL);
+ ret = ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ g_free(irq_set);
+ if (ret < 0) {
+ error_report("vfio: Failed to set resample eventfd: %m");
+ }
+ return ret;
+}
+
+static void vfio_start_irqfd_injection(DeviceState *dev, qemu_irq *pirq)
+{
+ VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
+ struct VFIOINTp *intp = container_of(pirq, struct VFIOINTp, qemuirq);
+
+ /* Get to a known interrupt state */
+ qemu_set_fd_handler(event_notifier_get_fd(&intp->interrupt),
+ NULL, NULL, vdev);
+
+ vfio_mask_single_irqindex(&vdev->vbasedev, intp->pin);
+ qemu_set_irq(intp->qemuirq, 0);
+
+ if (kvm_irqchip_add_irqfd_notifier(kvm_state, &intp->interrupt,
+ &intp->unmask, *pirq) < 0) {
+ goto fail_irqfd;
+ }
+
+ if (vfio_set_trigger_eventfd(intp, NULL) < 0) {
+ goto fail_vfio;
+ }
+ if (vfio_set_resample_eventfd(intp) < 0) {
+ goto fail_vfio;
+ }
+
+ /* Let'em rip */
+ vfio_unmask_single_irqindex(&vdev->vbasedev, intp->pin);
+
+ intp->kvm_accel = true;
+
+ trace_vfio_platform_start_irqfd_injection(intp->pin,
+ event_notifier_get_fd(&intp->interrupt),
+ event_notifier_get_fd(&intp->unmask));
+ return;
+fail_vfio:
+ kvm_irqchip_remove_irqfd_notifier(kvm_state, &intp->interrupt, *pirq);
+fail_irqfd:
+ vfio_start_eventfd_injection(intp);
+ vfio_unmask_single_irqindex(&vdev->vbasedev, intp->pin);
+ return;
+}
+
+static void vfio_start_irqfd(Object *obj, const char *name,
+ Object * const *irqp, Error ** err)
+{
+ OBJECT_CHECK(struct IRQState, (*irqp), TYPE_IRQ);
+
+ vfio_start_irqfd_injection(DEVICE(obj), (qemu_irq *)irqp);
+
+}
+
+#endif /* CONFIG_KVM */
+
/* VFIO skeleton */
/* not implemented yet */
@@ -550,6 +648,7 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
{
VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(dev);
VFIODevice *vbasedev = &vdev->vbasedev;
VFIOINTp *intp;
int i, ret;
@@ -557,6 +656,13 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
vbasedev->ops = &vfio_platform_ops;
+#ifdef CONFIG_KVM
+ if (kvm_irqfds_enabled() && kvm_resamplefds_enabled() &&
+ vdev->irqfd_allowed) {
+ sbc->irq_set_hook = vfio_start_irqfd;
+ }
+#endif
+
trace_vfio_platform_realize(vbasedev->name, vdev->compat);
ret = vfio_base_device_init(vbasedev);
@@ -586,6 +692,7 @@ static Property vfio_platform_dev_properties[] = {
DEFINE_PROP_BOOL("x-mmap", VFIOPlatformDevice, vbasedev.allow_mmap, true),
DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
mmap_timeout, 1100),
+ DEFINE_PROP_BOOL("x-irqfd", VFIOPlatformDevice, irqfd_allowed, true),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index ec97e97..c5cf1d7 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -40,8 +40,8 @@ typedef struct VFIOINTp {
struct VFIOPlatformDevice *vdev; /* back pointer to device */
int state; /* inactive, pending, active */
uint8_t pin; /* index */
- uint32_t virtualID; /* virtual IRQ */
uint32_t flags; /* IRQ info flags */
+ bool kvm_accel; /* set when QEMU bypass through KVM enabled */
} VFIOINTp;
/* function type for user side eventfd handler */
@@ -58,6 +58,7 @@ typedef struct VFIOPlatformDevice {
uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */
QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
QemuMutex intp_mutex; /* protect the intp_list IRQ state */
+ bool irqfd_allowed; /* debug option to force irqfd on/off */
} VFIOPlatformDevice;
typedef struct VFIOPlatformDeviceClass {
diff --git a/trace-events b/trace-events
index ed8ed90..a378b78 100644
--- a/trace-events
+++ b/trace-events
@@ -1571,6 +1571,8 @@ vfio_platform_intp_interrupt(int pin, int fd) "Inject IRQ #%d (fd = %d)"
vfio_platform_intp_inject_pending_lockheld(int pin, int fd) "Inject pending IRQ #%d (fd = %d)"
vfio_platform_populate_interrupts(int pin, int count, int flags) "- IRQ index %d: count %d, flags=0x%x"
vfio_intp_interrupt_set_pending(int index) "irq %d is set PENDING"
+vfio_start_eventfd_injection(int index, int fd) "IRQ index=%d, fd = %d"
+vfio_platform_start_irqfd_injection(int index, int fd, int resamplefd) "IRQ index=%d, fd = %d, resamplefd = %d"
#hw/acpi/memory_hotplug.c
mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
--
1.8.3.2
^ permalink raw reply related [flat|nested] 19+ messages in thread