* [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API
@ 2014-02-18 1:41 Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 1/4] linux-headers: Update from v3.14-rc3 Christoffer Dall
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Christoffer Dall @ 2014-02-18 1:41 UTC (permalink / raw)
To: qemu-devel; +Cc: kvmarm, Christoffer Dall
This patch series adds generic support for issuing device control
related ioctls and supports creating the ARM KVM-accelerated VGIC using
the device control API while maintaining backwards compatibility for
older kernels.
Changelogs in the individual patches. This last series is identical to
v5, but is using an updated Linux kerned header update, which includes
arm64 device control header support, avoiding to completely break arm64
QEMU support.
The patch series based on qemu/master can be found here:
git://git.linaro.org/people/cdall/qemu-arm.git migration/device-ctrl-v6
Christoffer Dall (4):
linux-headers: Update from v3.14-rc3
kvm: Introduce kvm_arch_irqchip_create
kvm: Common device control API functions
arm: vgic device control api support
hw/intc/arm_gic_kvm.c | 22 ++++++++++++++--
include/hw/intc/arm_gic_common.h | 1 +
include/sysemu/kvm.h | 34 +++++++++++++++++++++++++
kvm-all.c | 50 ++++++++++++++++++++++++++++++++++--
linux-headers/asm-arm/kvm.h | 28 ++++++++++++++++++++
linux-headers/asm-arm64/kvm.h | 30 +++++++++++++++++++++-
linux-headers/asm-powerpc/kvm.h | 3 +++
linux-headers/asm-x86/hyperv.h | 16 +++++++++---
linux-headers/linux/kvm.h | 1 +
stubs/Makefile.objs | 1 +
stubs/kvm.c | 7 +++++
target-arm/kvm.c | 55 +++++++++++++++++++++++++++++++++++-----
target-arm/kvm_arm.h | 17 ++++++++-----
trace-events | 1 +
14 files changed, 245 insertions(+), 21 deletions(-)
create mode 100644 stubs/kvm.c
--
1.8.5.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 1/4] linux-headers: Update from v3.14-rc3
2014-02-18 1:41 [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Christoffer Dall
@ 2014-02-18 1:41 ` Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 2/4] kvm: Introduce kvm_arch_irqchip_create Christoffer Dall
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Christoffer Dall @ 2014-02-18 1:41 UTC (permalink / raw)
To: qemu-devel; +Cc: kvmarm, Christoffer Dall
Update to tag v3.14-rc3 (6d0abeca3242a88cab8232e4acd7e2bf088f3bc2)
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
| 28 ++++++++++++++++++++++++++++
| 30 +++++++++++++++++++++++++++++-
| 3 +++
| 16 +++++++++++++---
| 1 +
5 files changed, 74 insertions(+), 4 deletions(-)
--git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
index c498b60..ef0c878 100644
--- a/linux-headers/asm-arm/kvm.h
+++ b/linux-headers/asm-arm/kvm.h
@@ -119,6 +119,26 @@ struct kvm_arch_memory_slot {
#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800
#define KVM_REG_ARM_32_CRN_SHIFT 11
+#define ARM_CP15_REG_SHIFT_MASK(x,n) \
+ (((x) << KVM_REG_ARM_ ## n ## _SHIFT) & KVM_REG_ARM_ ## n ## _MASK)
+
+#define __ARM_CP15_REG(op1,crn,crm,op2) \
+ (KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT) | \
+ ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
+ ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
+ ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
+ ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
+
+#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
+
+#define __ARM_CP15_REG64(op1,crm) \
+ (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
+#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
+
+#define KVM_REG_ARM_TIMER_CTL ARM_CP15_REG32(0, 14, 3, 1)
+#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
+#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
+
/* Normal registers are mapped as coprocessor 16. */
#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
@@ -143,6 +163,14 @@ struct kvm_arch_memory_slot {
#define KVM_REG_ARM_VFP_FPINST 0x1009
#define KVM_REG_ARM_VFP_FPINST2 0x100A
+/* Device Control API: ARM VGIC */
+#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
+#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
+#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
+#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
+#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
+#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
/* KVM_IRQ_LINE irq field index values */
#define KVM_ARM_IRQ_TYPE_SHIFT 24
--git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
index 5031f42..eaf54a3 100644
--- a/linux-headers/asm-arm64/kvm.h
+++ b/linux-headers/asm-arm64/kvm.h
@@ -55,8 +55,9 @@ struct kvm_regs {
#define KVM_ARM_TARGET_AEM_V8 0
#define KVM_ARM_TARGET_FOUNDATION_V8 1
#define KVM_ARM_TARGET_CORTEX_A57 2
+#define KVM_ARM_TARGET_XGENE_POTENZA 3
-#define KVM_ARM_NUM_TARGETS 3
+#define KVM_ARM_NUM_TARGETS 4
/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
#define KVM_ARM_DEVICE_TYPE_SHIFT 0
@@ -129,6 +130,33 @@ struct kvm_arch_memory_slot {
#define KVM_REG_ARM64_SYSREG_OP2_MASK 0x0000000000000007
#define KVM_REG_ARM64_SYSREG_OP2_SHIFT 0
+#define ARM64_SYS_REG_SHIFT_MASK(x,n) \
+ (((x) << KVM_REG_ARM64_SYSREG_ ## n ## _SHIFT) & \
+ KVM_REG_ARM64_SYSREG_ ## n ## _MASK)
+
+#define __ARM64_SYS_REG(op0,op1,crn,crm,op2) \
+ (KVM_REG_ARM64 | KVM_REG_ARM64_SYSREG | \
+ ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \
+ ARM64_SYS_REG_SHIFT_MASK(op1, OP1) | \
+ ARM64_SYS_REG_SHIFT_MASK(crn, CRN) | \
+ ARM64_SYS_REG_SHIFT_MASK(crm, CRM) | \
+ ARM64_SYS_REG_SHIFT_MASK(op2, OP2))
+
+#define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
+
+#define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1)
+#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
+#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)
+
+/* Device Control API: ARM VGIC */
+#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
+#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
+#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
+#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
+#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
+#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
+
/* KVM_IRQ_LINE irq field index values */
#define KVM_ARM_IRQ_TYPE_SHIFT 24
#define KVM_ARM_IRQ_TYPE_MASK 0xff
--git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 6836ec7..a6665be 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -545,6 +545,7 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_TCSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1)
#define KVM_REG_PPC_PID (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2)
#define KVM_REG_PPC_ACOP (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3)
+#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb4)
#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
@@ -553,6 +554,8 @@ struct kvm_get_htab_header {
/* Architecture compatibility level */
#define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7)
+#define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
+
/* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs
*/
--git a/linux-headers/asm-x86/hyperv.h b/linux-headers/asm-x86/hyperv.h
index 3b400ee..462efe7 100644
--- a/linux-headers/asm-x86/hyperv.h
+++ b/linux-headers/asm-x86/hyperv.h
@@ -28,6 +28,9 @@
/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
+/* A partition's reference time stamp counter (TSC) page */
+#define HV_X64_MSR_REFERENCE_TSC 0x40000021
+
/*
* There is a single feature flag that signifies the presence of the MSR
* that can be used to retrieve both the local APIC Timer frequency as
@@ -149,9 +152,6 @@
/* MSR used to read the per-partition time reference counter */
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
-/* A partition's reference time stamp counter (TSC) page */
-#define HV_X64_MSR_REFERENCE_TSC 0x40000021
-
/* MSR used to retrieve the TSC frequency */
#define HV_X64_MSR_TSC_FREQUENCY 0x40000022
@@ -201,6 +201,9 @@
#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK \
(~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
+#define HV_X64_MSR_TSC_REFERENCE_ENABLE 0x00000001
+#define HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT 12
+
#define HV_PROCESSOR_POWER_STATE_C0 0
#define HV_PROCESSOR_POWER_STATE_C1 1
#define HV_PROCESSOR_POWER_STATE_C2 2
@@ -213,4 +216,11 @@
#define HV_STATUS_INVALID_ALIGNMENT 4
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
+typedef struct _HV_REFERENCE_TSC_PAGE {
+ __u32 tsc_sequence;
+ __u32 res1;
+ __u64 tsc_scale;
+ __s64 tsc_offset;
+} HV_REFERENCE_TSC_PAGE, *PHV_REFERENCE_TSC_PAGE;
+
#endif
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 999fb13..77ad35c 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -854,6 +854,7 @@ struct kvm_device_attr {
#define KVM_DEV_VFIO_GROUP 1
#define KVM_DEV_VFIO_GROUP_ADD 1
#define KVM_DEV_VFIO_GROUP_DEL 2
+#define KVM_DEV_TYPE_ARM_VGIC_V2 5
/*
* ioctls for VM fds
--
1.8.5.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 2/4] kvm: Introduce kvm_arch_irqchip_create
2014-02-18 1:41 [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 1/4] linux-headers: Update from v3.14-rc3 Christoffer Dall
@ 2014-02-18 1:41 ` Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 3/4] kvm: Common device control API functions Christoffer Dall
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Christoffer Dall @ 2014-02-18 1:41 UTC (permalink / raw)
To: qemu-devel; +Cc: kvmarm, Christoffer Dall
Introduce kvm_arch_irqchip_create an arch-specific hook in preparation
for architecture-specific use of the device control API to create IRQ
chips.
Following patches will implement the ARM irqchip create method to prefer
the device control API over the older KVM_CREATE_IRQCHIP API.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
Changelog[v1 -> v2]:
- Proper formatted function comments
- Use QEMU's stubs mechanism for KVM stubs
include/sysemu/kvm.h | 12 ++++++++++++
kvm-all.c | 11 +++++++++--
stubs/Makefile.objs | 1 +
stubs/kvm.c | 7 +++++++
4 files changed, 29 insertions(+), 2 deletions(-)
create mode 100644 stubs/kvm.c
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 3b25f27..e4e43b8 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -319,4 +319,16 @@ int kvm_irqchip_remove_irqfd_notifier(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);
+
+/**
+ * kvm_arch_irqchip_create:
+ * @KVMState: The KVMState pointer
+ *
+ * Allow architectures to create an in-kernel irq chip themselves.
+ *
+ * Returns: < 0: error
+ * 0: irq chip was not created
+ * > 0: irq chip was created
+ */
+int kvm_arch_irqchip_create(KVMState *s);
#endif
diff --git a/kvm-all.c b/kvm-all.c
index 2ca9143..8670878 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1298,10 +1298,17 @@ static int kvm_irqchip_create(KVMState *s)
return 0;
}
- ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
+ /* First probe and see if there's a arch-specific hook to create the
+ * in-kernel irqchip for us */
+ ret = kvm_arch_irqchip_create(s);
if (ret < 0) {
- fprintf(stderr, "Create kernel irqchip failed\n");
return ret;
+ } else if (ret == 0) {
+ ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
+ if (ret < 0) {
+ fprintf(stderr, "Create kernel irqchip failed\n");
+ return ret;
+ }
}
kvm_kernel_irqchip = true;
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index df92fe5..df3aa7a 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -27,3 +27,4 @@ stub-obj-y += vm-stop.o
stub-obj-y += vmstate.o
stub-obj-$(CONFIG_WIN32) += fd-register.o
stub-obj-y += cpus.o
+stub-obj-y += kvm.o
diff --git a/stubs/kvm.c b/stubs/kvm.c
new file mode 100644
index 0000000..e7c60b6
--- /dev/null
+++ b/stubs/kvm.c
@@ -0,0 +1,7 @@
+#include "qemu-common.h"
+#include "sysemu/kvm.h"
+
+int kvm_arch_irqchip_create(KVMState *s)
+{
+ return 0;
+}
--
1.8.5.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 3/4] kvm: Common device control API functions
2014-02-18 1:41 [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 1/4] linux-headers: Update from v3.14-rc3 Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 2/4] kvm: Introduce kvm_arch_irqchip_create Christoffer Dall
@ 2014-02-18 1:41 ` Christoffer Dall
2014-02-18 1:42 ` [Qemu-devel] [PATCH v6 4/4] arm: vgic device control api support Christoffer Dall
2014-02-25 15:32 ` [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Peter Maydell
4 siblings, 0 replies; 6+ messages in thread
From: Christoffer Dall @ 2014-02-18 1:41 UTC (permalink / raw)
To: qemu-devel; +Cc: kvmarm, Christoffer Dall
Introduces two simple functions:
int kvm_device_ioctl(int fd, int type, ...);
int kvm_create_device(KVMState *s, uint64_t type, bool test);
These functions wrap the basic ioctl-based interactions with KVM in a
way similar to other KVM ioctl wrappers.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
Changelog[v2 -> v3]:
- Changed format for trace-events according to upstream changes
Changelog[v1 -> v2]:
- Added function docs and adjust code formatting
- Return proper error value from kvm_create_device
include/sysemu/kvm.h | 22 ++++++++++++++++++++++
kvm-all.c | 39 +++++++++++++++++++++++++++++++++++++++
trace-events | 1 +
3 files changed, 62 insertions(+)
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index e4e43b8..a02d67c 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -194,6 +194,28 @@ int kvm_vm_ioctl(KVMState *s, int type, ...);
int kvm_vcpu_ioctl(CPUState *cpu, int type, ...);
+/**
+ * kvm_device_ioctl - call an ioctl on a kvm device
+ * @fd: The KVM device file descriptor as returned from KVM_CREATE_DEVICE
+ * @type: The device-ctrl ioctl number
+ *
+ * Returns: -errno on error, nonnegative on success
+ */
+int kvm_device_ioctl(int fd, int type, ...);
+
+/**
+ * kvm_create_device - create a KVM device for the device control API
+ * @KVMState: The KVMState pointer
+ * @type: The KVM device type (see Documentation/virtual/kvm/devices in the
+ * kernel source)
+ * @test: If true, only test if device can be created, but don't actually
+ * create the device.
+ *
+ * Returns: -errno on error, nonnegative on success: @test ? 0 : device fd;
+ */
+int kvm_create_device(KVMState *s, uint64_t type, bool test);
+
+
/* Arch specific hooks */
extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
diff --git a/kvm-all.c b/kvm-all.c
index 8670878..290e726 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1784,6 +1784,24 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
return ret;
}
+int kvm_device_ioctl(int fd, int type, ...)
+{
+ int ret;
+ void *arg;
+ va_list ap;
+
+ va_start(ap, type);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ trace_kvm_device_ioctl(fd, type, arg);
+ ret = ioctl(fd, type, arg);
+ if (ret == -1) {
+ ret = -errno;
+ }
+ return ret;
+}
+
int kvm_has_sync_mmu(void)
{
return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
@@ -2065,3 +2083,24 @@ int kvm_on_sigbus(int code, void *addr)
{
return kvm_arch_on_sigbus(code, addr);
}
+
+int kvm_create_device(KVMState *s, uint64_t type, bool test)
+{
+ int ret;
+ struct kvm_create_device create_dev;
+
+ create_dev.type = type;
+ create_dev.fd = -1;
+ create_dev.flags = test ? KVM_CREATE_DEVICE_TEST : 0;
+
+ if (!kvm_check_extension(s, KVM_CAP_DEVICE_CTRL)) {
+ return -ENOTSUP;
+ }
+
+ ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, &create_dev);
+ if (ret) {
+ return ret;
+ }
+
+ return test ? 0 : create_dev.fd;
+}
diff --git a/trace-events b/trace-events
index ab11f97..1d5f5aa 100644
--- a/trace-events
+++ b/trace-events
@@ -1170,6 +1170,7 @@ kvm_ioctl(int type, void *arg) "type 0x%x, arg %p"
kvm_vm_ioctl(int type, void *arg) "type 0x%x, arg %p"
kvm_vcpu_ioctl(int cpu_index, int type, void *arg) "cpu_index %d, type 0x%x, arg %p"
kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d"
+kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p"
# memory.c
memory_region_ops_read(void *mr, uint64_t addr, uint64_t value, unsigned size) "mr %p addr %#"PRIx64" value %#"PRIx64" size %u"
--
1.8.5.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 4/4] arm: vgic device control api support
2014-02-18 1:41 [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Christoffer Dall
` (2 preceding siblings ...)
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 3/4] kvm: Common device control API functions Christoffer Dall
@ 2014-02-18 1:42 ` Christoffer Dall
2014-02-25 15:32 ` [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Peter Maydell
4 siblings, 0 replies; 6+ messages in thread
From: Christoffer Dall @ 2014-02-18 1:42 UTC (permalink / raw)
To: qemu-devel; +Cc: kvmarm, Christoffer Dall
Support creating the ARM vgic device through the device control API and
setting the base address for the distributor and cpu interfaces in KVM
VMs using this API.
Because the older KVM_CREATE_IRQCHIP interface needs the irq chip to be
created prior to creating the VCPUs, we first test if we can use the
device control API in kvm_arch_irqchip_create (using the test flag from
the device control API). If we cannot, it means we have to fall back to
KVM_CREATE_IRQCHIP and use the older ioctl at this point in time. If
however, we can use the device control API, we don't do anything and
wait until the arm_gic_kvm driver initializes and let that use the
device control API.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
Changelog[v3 -> v4]:
- Support creating the gic-kvm with kernels that do not even support
the device control API, by checking for -ENOTSUP returns from
kvm_create_device().
Changelog[v2 -> v3]:
- Fixed indentation
- Fixed number of parameters in kvm_arm_register_device documentation
Changelog[v1 -> v2]:
- Moved dev_fd into GICState
- Proper error handling in kvm_arm_gic_realize
- Coding style and other minor fixes
hw/intc/arm_gic_kvm.c | 22 ++++++++++++++--
include/hw/intc/arm_gic_common.h | 1 +
target-arm/kvm.c | 55 +++++++++++++++++++++++++++++++++++-----
target-arm/kvm_arm.h | 17 ++++++++-----
4 files changed, 80 insertions(+), 15 deletions(-)
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 59a3da5..964d4d7 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -97,6 +97,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
GICState *s = KVM_ARM_GIC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
+ int ret;
kgc->parent_realize(dev, errp);
if (error_is_set(errp)) {
@@ -119,13 +120,27 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->parent_irq[i]);
}
+
+ /* Try to create the device via the device control API */
+ s->dev_fd = -1;
+ ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
+ if (ret >= 0) {
+ s->dev_fd = ret;
+ } else if (ret != -ENODEV && ret != -ENOTSUP) {
+ error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
+ return;
+ }
+
/* Distributor */
memory_region_init_reservation(&s->iomem, OBJECT(s),
"kvm-gic_dist", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
kvm_arm_register_device(&s->iomem,
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
- | KVM_VGIC_V2_ADDR_TYPE_DIST);
+ | KVM_VGIC_V2_ADDR_TYPE_DIST,
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V2_ADDR_TYPE_DIST,
+ s->dev_fd);
/* CPU interface for current core. Unlike arm_gic, we don't
* provide the "interface for core #N" memory regions, because
* cores with a VGIC don't have those.
@@ -135,7 +150,10 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->cpuiomem[0]);
kvm_arm_register_device(&s->cpuiomem[0],
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
- | KVM_VGIC_V2_ADDR_TYPE_CPU);
+ | KVM_VGIC_V2_ADDR_TYPE_CPU,
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V2_ADDR_TYPE_CPU,
+ s->dev_fd);
}
static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 89384c2..f6887ed 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -104,6 +104,7 @@ typedef struct GICState {
MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
uint32_t num_irq;
uint32_t revision;
+ int dev_fd; /* kvm device fd if backed by kvm vgic support */
} GICState;
#define TYPE_ARM_GIC_COMMON "arm_gic_common"
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 1d2688d..39202d7 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -165,8 +165,10 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
*/
typedef struct KVMDevice {
struct kvm_arm_device_addr kda;
+ struct kvm_device_attr kdattr;
MemoryRegion *mr;
QSLIST_ENTRY(KVMDevice) entries;
+ int dev_fd;
} KVMDevice;
static QSLIST_HEAD(kvm_devices_head, KVMDevice) kvm_devices_head;
@@ -200,6 +202,29 @@ static MemoryListener devlistener = {
.region_del = kvm_arm_devlistener_del,
};
+static void kvm_arm_set_device_addr(KVMDevice *kd)
+{
+ struct kvm_device_attr *attr = &kd->kdattr;
+ int ret;
+
+ /* If the device control API is available and we have a device fd on the
+ * KVMDevice struct, let's use the newer API
+ */
+ if (kd->dev_fd >= 0) {
+ uint64_t addr = kd->kda.addr;
+ attr->addr = (uintptr_t)&addr;
+ ret = kvm_device_ioctl(kd->dev_fd, KVM_SET_DEVICE_ATTR, attr);
+ } else {
+ ret = kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR, &kd->kda);
+ }
+
+ if (ret < 0) {
+ fprintf(stderr, "Failed to set device address: %s\n",
+ strerror(-ret));
+ abort();
+ }
+}
+
static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
{
KVMDevice *kd, *tkd;
@@ -207,12 +232,7 @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
memory_listener_unregister(&devlistener);
QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) {
if (kd->kda.addr != -1) {
- if (kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR,
- &kd->kda) < 0) {
- fprintf(stderr, "KVM_ARM_SET_DEVICE_ADDRESS failed: %s\n",
- strerror(errno));
- abort();
- }
+ kvm_arm_set_device_addr(kd);
}
memory_region_unref(kd->mr);
g_free(kd);
@@ -223,7 +243,8 @@ static Notifier notify = {
.notify = kvm_arm_machine_init_done,
};
-void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid)
+void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
+ uint64_t attr, int dev_fd)
{
KVMDevice *kd;
@@ -239,6 +260,10 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid)
kd->mr = mr;
kd->kda.id = devid;
kd->kda.addr = -1;
+ kd->kdattr.flags = 0;
+ kd->kdattr.group = group;
+ kd->kdattr.attr = attr;
+ kd->dev_fd = dev_fd;
QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
memory_region_ref(kd->mr);
}
@@ -389,3 +414,19 @@ void kvm_arch_remove_all_hw_breakpoints(void)
void kvm_arch_init_irq_routing(KVMState *s)
{
}
+
+int kvm_arch_irqchip_create(KVMState *s)
+{
+ int ret;
+
+ /* If we can create the VGIC using the newer device control API, we
+ * let the device do this when it initializes itself, otherwise we
+ * fall back to the old API */
+
+ ret = kvm_create_device(s, KVM_DEV_TYPE_ARM_VGIC_V2, true);
+ if (ret == 0) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index cd3d13c..137c567 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -18,16 +18,21 @@
* kvm_arm_register_device:
* @mr: memory region for this device
* @devid: the KVM device ID
+ * @group: device control API group for setting addresses
+ * @attr: device control API address type
+ * @dev_fd: device control device file descriptor (or -1 if not supported)
*
* Remember the memory region @mr, and when it is mapped by the
* machine model, tell the kernel that base address using the
- * KVM_SET_DEVICE_ADDRESS ioctl. @devid should be the ID of
- * the device as defined by KVM_SET_DEVICE_ADDRESS.
- * The machine model may map and unmap the device multiple times;
- * the kernel will only be told the final address at the point
- * where machine init is complete.
+ * KVM_ARM_SET_DEVICE_ADDRESS ioctl or the newer device control API. @devid
+ * should be the ID of the device as defined by KVM_ARM_SET_DEVICE_ADDRESS or
+ * the arm-vgic device in the device control API.
+ * The machine model may map
+ * and unmap the device multiple times; the kernel will only be told the final
+ * address at the point where machine init is complete.
*/
-void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid);
+void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
+ uint64_t attr, int dev_fd);
/**
* write_list_to_kvmstate:
--
1.8.5.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API
2014-02-18 1:41 [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Christoffer Dall
` (3 preceding siblings ...)
2014-02-18 1:42 ` [Qemu-devel] [PATCH v6 4/4] arm: vgic device control api support Christoffer Dall
@ 2014-02-25 15:32 ` Peter Maydell
4 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2014-02-25 15:32 UTC (permalink / raw)
To: Christoffer Dall; +Cc: QEMU Developers, kvmarm@lists.cs.columbia.edu
On 18 February 2014 01:41, Christoffer Dall <christoffer.dall@linaro.org> wrote:
> This patch series adds generic support for issuing device control
> related ioctls and supports creating the ARM KVM-accelerated VGIC using
> the device control API while maintaining backwards compatibility for
> older kernels.
>
> Changelogs in the individual patches. This last series is identical to
> v5, but is using an updated Linux kerned header update, which includes
> arm64 device control header support, avoiding to completely break arm64
> QEMU support.
>
> The patch series based on qemu/master can be found here:
> git://git.linaro.org/people/cdall/qemu-arm.git migration/device-ctrl-v6
>
> Christoffer Dall (4):
> linux-headers: Update from v3.14-rc3
> kvm: Introduce kvm_arch_irqchip_create
> kvm: Common device control API functions
> arm: vgic device control api support
Applied to target-arm.next, thanks.
-- PMM
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-02-25 15:32 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-18 1:41 [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 1/4] linux-headers: Update from v3.14-rc3 Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 2/4] kvm: Introduce kvm_arch_irqchip_create Christoffer Dall
2014-02-18 1:41 ` [Qemu-devel] [PATCH v6 3/4] kvm: Common device control API functions Christoffer Dall
2014-02-18 1:42 ` [Qemu-devel] [PATCH v6 4/4] arm: vgic device control api support Christoffer Dall
2014-02-25 15:32 ` [Qemu-devel] [PATCH v6 0/4] Create ARM KVM VGIC with device control API Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).