Skip to contentSkip to conversation

In-kernel XICS interrupt controller emulation

PATCH In review Paul Mackerras 3 participants 17 messages Apr 18, 2013 – Apr 30, 2013

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

v5 cover In-kernel XICS interrupt controller emulation

This is a repost of my patch series implementing in-kernel emulation of the XICS interrupt controller architecture defined in PAPR (Power Architecture Platform Requirements, the document that defines IBM's pSeries platform architecture). This version of the patch series uses the latest device API as posted by Scott Wood, that is, i.e., the version where the core device code provides the file descriptor and ioctl handler. I have structured the series so that the API is added by the last two patches, so as to be able to accommodate any future revisions to the device API with minimal changes.

The series is based on Alex Graf's kvm-ppc-queue branch with Scott Wood's recent patch series applied on top, together with the patch below to allow it to build with CONFIG_KVM_MPIC=n.

The API defined here uses KVM_CREATE_DEVICE to create the XICS, KVM_DEVICE_SET_ATTR/KVM_DEVICE_GET_ATTR to manipulate the interrupt sources (for initialization and migration), a new KVM_CAP_IRQ_XICS capability to connect vcpus to the XICS, a new identifier KVM_REG_PPC_ICP_STATE for the one-reg interface to get and set per-vcpu state, and the existing KVM_IRQ_LINE ioctl to assert and deassert interrupt sources.

This version also cleans up some checkpatch.pl errors and clarifies the lifetime rules for the various objects. There are two checkpatch warnings for long lines, but they are long because they have long strings in them, and if I break the strings over two lines then checkpatch warns about that.

Paul.

arch/powerpc/kvm/powerpc.c +2 -0
index 1d3888b..bd41eea 100644
@@ -466,9 +466,11 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 	kvmppc_remove_vcpu_debugfs(vcpu);
 
 	switch (vcpu->arch.irq_type) {
+#ifdef CONFIG_KVM_MPIC
 	case KVMPPC_IRQ_MPIC:
 		kvmppc_mpic_disconnect_vcpu(vcpu->arch.mpic, vcpu);
 		break;
+#endif
 	}
 
 	kvmppc_core_vcpu_free(vcpu);
#1 lore raw

PATCH v5 1/8 KVM: PPC: Book3S: Add infrastructure to implement kernel-side RTAS calls

From: Michael Ellerman <[email protected]>

For pseries machine emulation, in order to move the interrupt controller code to the kernel, we need to intercept some RTAS calls in the kernel itself. This adds an infrastructure to allow in-kernel handlers to be registered for RTAS services by name. A new ioctl, KVM_PPC_RTAS_DEFINE_TOKEN, then allows userspace to associate token values with those service names. Then, when the guest requests an RTAS service with one of those token values, it will be handled by the relevant in-kernel handler rather than being passed up to userspace as at present.

---
 Documentation/virtual/kvm/api.txt   |   19 ++++
 arch/powerpc/include/asm/hvcall.h   |    3 +
 arch/powerpc/include/asm/kvm_host.h |    1 +
 arch/powerpc/include/asm/kvm_ppc.h  |    4 +
 arch/powerpc/include/uapi/asm/kvm.h |    6 ++
 arch/powerpc/kvm/Makefile           |    1 +
 arch/powerpc/kvm/book3s_hv.c        |   18 +++-
 arch/powerpc/kvm/book3s_pr.c        |    1 +
 arch/powerpc/kvm/book3s_pr_papr.c   |    7 ++
 arch/powerpc/kvm/book3s_rtas.c      |  182 +++++++++++++++++++++++++++++++++++
 arch/powerpc/kvm/powerpc.c          |    8 ++
 include/uapi/linux/kvm.h            |    3 +
 12 files changed, 252 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/kvm/book3s_rtas.c
Documentation/virtual/kvm/api.txt +19 -0
index 4c326ae..4247d65 100644
@@ -2325,6 +2325,25 @@ and distributor interface, the ioctl must be called after calling
 KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs.  Calling
 this ioctl twice for any of the base addresses will return -EEXIST.
 
+4.82 KVM_PPC_RTAS_DEFINE_TOKEN
+
+Capability: KVM_CAP_PPC_RTAS
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_rtas_token_args
+Returns: 0 on success, -1 on error
+
+Defines a token value for a RTAS (Run Time Abstraction Services)
+service in order to allow it to be handled in the kernel.  The
+argument struct gives the name of the service, which must be the name
+of a service that has a kernel-side implementation.  If the token
+value is non-zero, it will be associated with that service, and
+subsequent RTAS calls by the guest specifying that token will be
+handled by the kernel.  If the token value is 0, then any token
+associated with the service will be forgotten, and subsequent RTAS
+calls by the guest for that service will be passed to userspace to be
+handled.
+
 
 5. The kvm_run structure
 ------------------------
arch/powerpc/include/asm/hvcall.h +3 -0
index 4bc2c3d..cf4df8e 100644
@@ -270,6 +270,9 @@
 #define H_SET_MODE		0x31C
 #define MAX_HCALL_OPCODE	H_SET_MODE
 
+/* Platform specific hcalls, used by KVM */
+#define H_RTAS			0xf000
+
 #ifndef __ASSEMBLY__
 
 /**
arch/powerpc/include/asm/kvm_host.h +1 -0
index 36368c9..1650e26 100644
@@ -255,6 +255,7 @@ struct kvm_arch {
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 #ifdef CONFIG_PPC_BOOK3S_64
 	struct list_head spapr_tce_tables;
+	struct list_head rtas_tokens;
 #endif
 };
 
arch/powerpc/include/asm/kvm_ppc.h +4 -0
index b25d475..948b4c2 100644
@@ -166,6 +166,10 @@ extern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *);
 
 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
 
+extern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp);
+extern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu);
+extern void kvmppc_rtas_tokens_free(struct kvm *kvm);
+
 /*
  * Cuts out inst bits with ordering according to spec.
  * That means the leftmost bit is zero. All given bits are included.
arch/powerpc/include/uapi/asm/kvm.h +6 -0
index 36be2fe..18be86c 100644
@@ -299,6 +299,12 @@ struct kvm_allocate_rma {
 	__u64 rma_size;
 };
 
+/* for KVM_CAP_PPC_RTAS */
+struct kvm_rtas_token_args {
+	char name[120];
+	__u64 token;	/* Use a token of 0 to undefine a mapping */
+};
+
 struct kvm_book3e_206_tlb_entry {
 	__u32 mas8;
 	__u32 mas1;
arch/powerpc/kvm/Makefile +1 -0
index 4a2277a..d2c8a88 100644
@@ -86,6 +86,7 @@ kvm-book3s_64-module-objs := \
 	emulate.o \
 	book3s.o \
 	book3s_64_vio.o \
+	book3s_rtas.o \
 	$(kvm-book3s_64-objs-y)
 
 kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs)
arch/powerpc/kvm/book3s_hv.c +17 -1
index 1e521ba..c445a3d 100644
@@ -479,7 +479,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 	unsigned long req = kvmppc_get_gpr(vcpu, 3);
 	unsigned long target, ret = H_SUCCESS;
 	struct kvm_vcpu *tvcpu;
-	int idx;
+	int idx, rc;
 
 	switch (req) {
 	case H_ENTER:
@@ -515,6 +515,19 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 					kvmppc_get_gpr(vcpu, 5),
 					kvmppc_get_gpr(vcpu, 6));
 		break;
+	case H_RTAS:
+		if (list_empty(&vcpu->kvm->arch.rtas_tokens))
+			return RESUME_HOST;
+
+		rc = kvmppc_rtas_hcall(vcpu);
+
+		if (rc = -ENOENT)
+			return RESUME_HOST;
+		else if (rc = 0)
+			break;
+
+		/* Send the error out to userspace via KVM_RUN */
+		return rc;
 	default:
 		return RESUME_HOST;
 	}
@@ -1821,6 +1834,7 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 	cpumask_setall(&kvm->arch.need_tlb_flush);
 
 	INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
+	INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
 
 	kvm->arch.rma = NULL;
 
@@ -1866,6 +1880,8 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 		kvm->arch.rma = NULL;
 	}
 
+	kvmppc_rtas_tokens_free(kvm);
+
 	kvmppc_free_hpt(kvm);
 	WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
 }
arch/powerpc/kvm/book3s_pr.c +1 -0
index 286e23e..88790b8 100644
@@ -1298,6 +1298,7 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 {
 #ifdef CONFIG_PPC64
 	INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
+	INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
 #endif
 
 	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
arch/powerpc/kvm/book3s_pr_papr.c +7 -0
index ee02b30..4efa4a4 100644
@@ -246,6 +246,13 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
 		clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
 		vcpu->stat.halt_wakeup++;
 		return EMULATE_DONE;
+	case H_RTAS:
+		if (list_empty(&vcpu->kvm->arch.rtas_tokens))
+			return RESUME_HOST;
+		if (kvmppc_rtas_hcall(vcpu))
+			break;
+		kvmppc_set_gpr(vcpu, 3, 0);
+		return EMULATE_DONE;
 	}
 
 	return EMULATE_FAIL;
arch/powerpc/kvm/book3s_rtas.c new file +182 -0

182 lines not on this page · raw message

arch/powerpc/kvm/powerpc.c +8 -0
index d282164..51e8420 100644
@@ -340,6 +340,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 #ifdef CONFIG_PPC_BOOK3S_64
 	case KVM_CAP_SPAPR_TCE:
 	case KVM_CAP_PPC_ALLOC_HTAB:
+	case KVM_CAP_PPC_RTAS:
 		r = 1;
 		break;
 #endif /* CONFIG_PPC_BOOK3S_64 */
@@ -981,6 +982,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	case KVM_ALLOCATE_RMA: {
 		struct kvm_allocate_rma rma;
+		struct kvm *kvm = filp->private_data;
 
 		r = kvm_vm_ioctl_allocate_rma(kvm, &rma);
 		if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma)))
@@ -1025,6 +1027,12 @@ long kvm_arch_vm_ioctl(struct file *filp,
 			r = -EFAULT;
 		break;
 	}
+	case KVM_PPC_RTAS_DEFINE_TOKEN: {
+		struct kvm *kvm = filp->private_data;
+
+		r = kvm_vm_ioctl_rtas_define_token(kvm, argp);
+		break;
+	}
 #endif /* CONFIG_PPC_BOOK3S_64 */
 	default:
 		r = -ENOTTY;
include/uapi/linux/kvm.h +3 -0
index 5b3248a..d100ac6 100644
@@ -670,6 +670,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_ARM_SET_DEVICE_ADDR 88
 #define KVM_CAP_DEVICE_CTRL 89
 #define KVM_CAP_IRQ_MPIC 90
+#define KVM_CAP_PPC_RTAS 91
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -909,6 +910,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_HTAB_FD	  _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
 /* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
 #define KVM_ARM_SET_DEVICE_ADDR	  _IOW(KVMIO,  0xab, struct kvm_arm_device_addr)
+/* Available with KVM_CAP_PPC_RTAS */
+#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO,  0xac, struct kvm_rtas_token_args)
 
 /*
  * Device control API, available with KVM_CAP_DEVICE_CTRL
Signature · 1 line
1.7.10.4
#2 lore raw

PATCH v5 2/8 KVM: PPC: Book3S: Add kernel emulation for the XICS interrupt controller

In reply to Paul Mackerras

From: Benjamin Herrenschmidt <[email protected]>

This adds in-kernel emulation of the XICS (eXternal Interrupt Controller Specification) interrupt controller specified by PAPR, for both HV and PR KVM guests.

The XICS emulation supports up to 1048560 interrupt sources. Interrupt source numbers below 16 are reserved; 0 is used to mean no interrupt and 2 is used for IPIs. Internally these are represented in blocks of 1024, called ICS (interrupt controller source) entities, but that is not visible to userspace.

Each vcpu gets one ICP (interrupt controller presentation) entity, used to store the per-vcpu state such as vcpu priority, pending interrupt state, IPI request, etc.

This does not include any API or any way to connect vcpus to their ICP state; that will be added in later patches.

This is based on an initial implementation by Michael Ellerman <[email protected]> reworked by Benjamin Herrenschmidt and Paul Mackerras.

---
 arch/powerpc/include/asm/kvm_book3s.h |    2 +
 arch/powerpc/include/asm/kvm_host.h   |   11 +
 arch/powerpc/include/asm/kvm_ppc.h    |   29 +
 arch/powerpc/kvm/Kconfig              |    8 +
 arch/powerpc/kvm/Makefile             |    3 +
 arch/powerpc/kvm/book3s.c             |    2 +-
 arch/powerpc/kvm/book3s_hv.c          |    9 +
 arch/powerpc/kvm/book3s_pr_papr.c     |   14 +
 arch/powerpc/kvm/book3s_rtas.c        |   54 +-
 arch/powerpc/kvm/book3s_xics.c        |  946 +++++++++++++++++++++++++++++++++
 arch/powerpc/kvm/book3s_xics.h        |  113 ++++
 arch/powerpc/kvm/powerpc.c            |    3 +
 12 files changed, 1192 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/kvm/book3s_xics.c
 create mode 100644 arch/powerpc/kvm/book3s_xics.h
arch/powerpc/include/asm/kvm_book3s.h +2 -0
index bc81842..0d9b32c 100644
@@ -142,6 +142,8 @@ extern int kvmppc_mmu_hv_init(void);
 extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
 extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
 extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
+extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
+					  unsigned int vec);
 extern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags);
 extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
 			   bool upper, u32 val);
arch/powerpc/include/asm/kvm_host.h +11 -0
index 1650e26..3d34570 100644
@@ -188,6 +188,10 @@ struct kvmppc_linear_info {
 	int		 type;
 };
 
+/* XICS components, defined in boo3s_xics.c */
+struct kvmppc_xics;
+struct kvmppc_icp;
+
 /*
  * The reverse mapping array has one entry for each HPTE,
  * which stores the guest's view of the second word of the HPTE
@@ -257,6 +261,9 @@ struct kvm_arch {
 	struct list_head spapr_tce_tables;
 	struct list_head rtas_tokens;
 #endif
+#ifdef CONFIG_KVM_XICS
+	struct kvmppc_xics *xics;
+#endif
 };
 
 /*
@@ -378,6 +385,7 @@ struct kvmppc_booke_debug_reg {
 
 #define KVMPPC_IRQ_DEFAULT	0
 #define KVMPPC_IRQ_MPIC		1
+#define KVMPPC_IRQ_XICS		2
 
 struct openpic;
 
@@ -563,6 +571,9 @@ struct kvm_vcpu_arch {
 	int irq_type;		/* one of KVM_IRQ_* */
 	int irq_cpu_id;
 	struct openpic *mpic;	/* KVM_IRQ_MPIC */
+#ifdef CONFIG_KVM_XICS
+	struct kvmppc_icp *icp; /* XICS presentation controller */
+#endif
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	struct kvm_vcpu_arch_shared shregs;
arch/powerpc/include/asm/kvm_ppc.h +29 -0
index 948b4c2..7cb8a71 100644
@@ -130,6 +130,7 @@ extern long kvmppc_prepare_vrma(struct kvm *kvm,
 extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
 			struct kvm_memory_slot *memslot, unsigned long porder);
 extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
+
 extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
 				struct kvm_create_spapr_tce *args);
 extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
@@ -169,6 +170,10 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
 extern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp);
 extern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu);
 extern void kvmppc_rtas_tokens_free(struct kvm *kvm);
+extern int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server,
+				u32 priority);
+extern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server,
+				u32 *priority);
 
 /*
  * Cuts out inst bits with ordering according to spec.
@@ -267,6 +272,30 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
 
 static inline void kvm_linear_init(void)
 {}
+
+#endif
+
+#ifdef CONFIG_KVM_XICS
+static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.irq_type = KVMPPC_IRQ_XICS;
+}
+extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu);
+extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu, unsigned long server);
+extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args);
+extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd);
+#else
+static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
+	{ return 0; }
+static inline void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { }
+static inline int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu,
+					 unsigned long server)
+	{ return -EINVAL; }
+static inline int kvm_vm_ioctl_xics_irq(struct kvm *kvm,
+					struct kvm_irq_level *args)
+	{ return -ENOTTY; }
+static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
+	{ return 0; }
 #endif
 
 static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)
arch/powerpc/kvm/Kconfig +8 -0
index 938a729..52e714c 100644
@@ -160,6 +160,14 @@ config KVM_MPIC
           Currently, support is limited to certain versions of
           Freescale's MPIC implementation.
 
+config KVM_XICS
+	bool "KVM in-kernel XICS emulation"
+	depends on KVM_BOOK3S_64
+	---help---
+	  Include support for the XICS (eXternal Interrupt Controller
+	  Specification) interrupt controller architecture used on
+	  IBM POWER (pSeries) servers.
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
arch/powerpc/kvm/Makefile +3 -0
index d2c8a88..cccd85f 100644
@@ -79,6 +79,9 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
 	book3s_hv_ras.o \
 	book3s_hv_builtin.o
 
+kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
+	book3s_xics.o
+
 kvm-book3s_64-module-objs := \
 	../../../virt/kvm/kvm_main.o \
 	../../../virt/kvm/eventfd.o \
arch/powerpc/kvm/book3s.c +1 -1
index 2d32ae4..10cd398 100644
@@ -104,7 +104,7 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
 	return prio;
 }
 
-static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
+void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
 					  unsigned int vec)
 {
 	unsigned long old_pending = vcpu->arch.pending_exceptions;
arch/powerpc/kvm/book3s_hv.c +9 -0
index c445a3d..506b5ea 100644
@@ -528,6 +528,15 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 
 		/* Send the error out to userspace via KVM_RUN */
 		return rc;
+
+	case H_XIRR:
+	case H_CPPR:
+	case H_EOI:
+	case H_IPI:
+		if (kvmppc_xics_enabled(vcpu)) {
+			ret = kvmppc_xics_hcall(vcpu, req);
+			break;
+		} /* fallthrough */
 	default:
 		return RESUME_HOST;
 	}
arch/powerpc/kvm/book3s_pr_papr.c +14 -0
index 4efa4a4..b24309c 100644
@@ -227,6 +227,13 @@ static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
 	return EMULATE_DONE;
 }
 
+static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
+{
+	long rc = kvmppc_xics_hcall(vcpu, cmd);
+	kvmppc_set_gpr(vcpu, 3, rc);
+	return EMULATE_DONE;
+}
+
 int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
 {
 	switch (cmd) {
@@ -246,6 +253,13 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
 		clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
 		vcpu->stat.halt_wakeup++;
 		return EMULATE_DONE;
+	case H_XIRR:
+	case H_CPPR:
+	case H_EOI:
+	case H_IPI:
+		if (kvmppc_xics_enabled(vcpu))
+			return kvmppc_h_pr_xics_hcall(vcpu, cmd);
+		break;
 	case H_RTAS:
 		if (list_empty(&vcpu->kvm->arch.rtas_tokens))
 			return RESUME_HOST;
arch/powerpc/kvm/book3s_rtas.c +53 -1

66 lines not on this page · raw message

arch/powerpc/kvm/book3s_xics.c new file +945 -0

945 lines not on this page · raw message

arch/powerpc/kvm/book3s_xics.h new file +113 -0

113 lines not on this page · raw message

arch/powerpc/kvm/powerpc.c +3 -0
index 51e8420..2441b81 100644
@@ -472,6 +472,9 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 		kvmppc_mpic_disconnect_vcpu(vcpu->arch.mpic, vcpu);
 		break;
 #endif
+	case KVMPPC_IRQ_XICS:
+		kvmppc_xics_free_icp(vcpu);
+		break;
 	}
 
 	kvmppc_core_vcpu_free(vcpu);
Signature · 1 line
1.7.10.4
#3 lore raw

PATCH v5 3/8 KVM: PPC: Book3S HV: Speed up wakeups of CPUs on HV KVM

In reply to Paul Mackerras

From: Benjamin Herrenschmidt <[email protected]>

Currently, we wake up a CPU by sending a host IPI with smp_send_reschedule() to thread 0 of that core, which will take all threads out of the guest, and cause them to re-evaluate their interrupt status on the way back in.

This adds a mechanism to differentiate real host IPIs from IPIs sent by KVM for guest threads to poke each other, in order to target the guest threads precisely when possible and avoid that global switch of the core to host state.

We then use this new facility in the in-kernel XICS code.

---
 arch/powerpc/include/asm/kvm_book3s_asm.h |    8 ++-
 arch/powerpc/include/asm/kvm_ppc.h        |   29 ++++++++
 arch/powerpc/kernel/asm-offsets.c         |    2 +
 arch/powerpc/kvm/book3s_hv.c              |   26 +++++++-
 arch/powerpc/kvm/book3s_hv_rmhandlers.S   |  102 ++++++++++++++++++++++++-----
 arch/powerpc/kvm/book3s_xics.c            |    2 +-
 arch/powerpc/sysdev/xics/icp-native.c     |    8 +++
 7 files changed, 158 insertions(+), 19 deletions(-)
arch/powerpc/include/asm/kvm_book3s_asm.h +7 -1
index cdc3d27..9039d3c 100644
@@ -20,6 +20,11 @@
 #ifndef __ASM_KVM_BOOK3S_ASM_H__
 #define __ASM_KVM_BOOK3S_ASM_H__
 
+/* XICS ICP register offsets */
+#define XICS_XIRR		4
+#define XICS_MFRR		0xc
+#define XICS_IPI		2	/* interrupt source # for IPIs */
+
 #ifdef __ASSEMBLY__
 
 #ifdef CONFIG_KVM_BOOK3S_HANDLER
@@ -81,10 +86,11 @@ struct kvmppc_host_state {
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	u8 hwthread_req;
 	u8 hwthread_state;
-
+	u8 host_ipi;
 	struct kvm_vcpu *kvm_vcpu;
 	struct kvmppc_vcore *kvm_vcore;
 	unsigned long xics_phys;
+	u32 saved_xirr;
 	u64 dabr;
 	u64 host_mmcr[3];
 	u32 host_pmc[8];
arch/powerpc/include/asm/kvm_ppc.h +29 -0
index 7cb8a71..95a44a6 100644
@@ -264,6 +264,21 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
 	paca[cpu].kvm_hstate.xics_phys = addr;
 }
 
+static inline u32 kvmppc_get_xics_latch(void)
+{
+	u32 xirr = get_paca()->kvm_hstate.saved_xirr;
+
+	get_paca()->kvm_hstate.saved_xirr = 0;
+
+	return xirr;
+}
+
+static inline void kvmppc_set_host_ipi(int cpu, u8 host_ipi)
+{
+	paca[cpu].kvm_hstate.host_ipi = host_ipi;
+}
+
+extern void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu);
 extern void kvm_linear_init(void);
 
 #else
@@ -273,6 +288,18 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
 static inline void kvm_linear_init(void)
 {}
 
+static inline u32 kvmppc_get_xics_latch(void)
+{
+	return 0;
+}
+
+static inline void kvmppc_set_host_ipi(int cpu, u8 host_ipi)
+{}
+
+static inline void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
+{
+	kvm_vcpu_kick(vcpu);
+}
 #endif
 
 #ifdef CONFIG_KVM_XICS
@@ -365,4 +392,6 @@ static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
 	return ea;
 }
 
+extern void xics_wake_cpu(int cpu);
+
 #endif /* __POWERPC_KVM_PPC_H__ */
arch/powerpc/kernel/asm-offsets.c +2 -0
index d87c908..75e31ac 100644
@@ -573,6 +573,8 @@ int main(void)
 	HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu);
 	HSTATE_FIELD(HSTATE_KVM_VCORE, kvm_vcore);
 	HSTATE_FIELD(HSTATE_XICS_PHYS, xics_phys);
+	HSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr);
+	HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi);
 	HSTATE_FIELD(HSTATE_MMCR, host_mmcr);
 	HSTATE_FIELD(HSTATE_PMC, host_pmc);
 	HSTATE_FIELD(HSTATE_PURR, host_purr);
arch/powerpc/kvm/book3s_hv.c +25 -1
index 506b5ea..0423c81 100644
@@ -66,6 +66,31 @@
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
+void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
+{
+	int me;
+	int cpu = vcpu->cpu;
+	wait_queue_head_t *wqp;
+
+	wqp = kvm_arch_vcpu_wq(vcpu);
+	if (waitqueue_active(wqp)) {
+		wake_up_interruptible(wqp);
+		++vcpu->stat.halt_wakeup;
+	}
+
+	me = get_cpu();
+
+	/* CPU points to the first thread of the core */
+	if (cpu != me && cpu >= 0 && cpu < nr_cpu_ids) {
+		int real_cpu = cpu + vcpu->arch.ptid;
+		if (paca[real_cpu].kvm_hstate.xics_phys)
+			xics_wake_cpu(real_cpu);
+		else if (cpu_online(cpu))
+			smp_send_reschedule(cpu);
+	}
+	put_cpu();
+}
+
 /*
  * We use the vcpu_load/put functions to measure stolen time.
  * Stolen time is counted as time when either the vcpu is able to
@@ -977,7 +1002,6 @@ static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
 }
 
 extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
-extern void xics_wake_cpu(int cpu);
 
 static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
 				   struct kvm_vcpu *vcpu)
arch/powerpc/kvm/book3s_hv_rmhandlers.S +86 -16

134 lines not on this page · raw message

arch/powerpc/kvm/book3s_xics.c +1 -1
index 53af848..1417e65 100644
@@ -227,7 +227,7 @@ static inline bool icp_try_update(struct kvmppc_icp *icp,
 		kvmppc_book3s_queue_irqprio(icp->vcpu,
 					    BOOK3S_INTERRUPT_EXTERNAL_LEVEL);
 		if (!change_self)
-			kvm_vcpu_kick(icp->vcpu);
+			kvmppc_fast_vcpu_kick(icp->vcpu);
 	}
  bail:
 	return success;
arch/powerpc/sysdev/xics/icp-native.c +8 -0
index 48861d3..20b328b 100644
@@ -51,6 +51,12 @@ static struct icp_ipl __iomem *icp_native_regs[NR_CPUS];
 static inline unsigned int icp_native_get_xirr(void)
 {
 	int cpu = smp_processor_id();
+	unsigned int xirr;
+
+	/* Handled an interrupt latched by KVM */
+	xirr = kvmppc_get_xics_latch();
+	if (xirr)
+		return xirr;
 
 	return in_be32(&icp_native_regs[cpu]->xirr.word);
 }
@@ -138,6 +144,7 @@ static unsigned int icp_native_get_irq(void)
 
 static void icp_native_cause_ipi(int cpu, unsigned long data)
 {
+	kvmppc_set_host_ipi(cpu, 1);
 	icp_native_set_qirr(cpu, IPI_PRIORITY);
 }
 
@@ -151,6 +158,7 @@ static irqreturn_t icp_native_ipi_action(int irq, void *dev_id)
 {
 	int cpu = smp_processor_id();
 
+	kvmppc_set_host_ipi(cpu, 0);
 	icp_native_set_qirr(cpu, 0xff);
 
 	return smp_ipi_demux();
Signature · 1 line
1.7.10.4
#4 lore raw

PATCH v5 4/8 KVM: PPC: Book3S HV: Add support for real mode ICP in XICS emulation

In reply to Paul Mackerras

From: Benjamin Herrenschmidt <[email protected]>

This adds an implementation of the XICS hypercalls in real mode for HV KVM, which allows us to avoid exiting the guest MMU context on all threads for a variety of operations such as fetching a pending interrupt, EOI of messages, IPIs, etc.

---
 arch/powerpc/kvm/Makefile               |    5 +-
 arch/powerpc/kvm/book3s_hv_rm_xics.c    |  406 +++++++++++++++++++++++++++++++
 arch/powerpc/kvm/book3s_hv_rmhandlers.S |   18 +-
 arch/powerpc/kvm/book3s_xics.c          |   64 ++++-
 arch/powerpc/kvm/book3s_xics.h          |   16 ++
 5 files changed, 490 insertions(+), 19 deletions(-)
 create mode 100644 arch/powerpc/kvm/book3s_hv_rm_xics.c
arch/powerpc/kvm/Makefile +4 -1
index cccd85f..7f85a6c 100644
@@ -72,12 +72,15 @@ kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
 	book3s_hv.o \
 	book3s_hv_interrupts.o \
 	book3s_64_mmu_hv.o
+kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \
+	book3s_hv_rm_xics.o
 kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
 	book3s_hv_rmhandlers.o \
 	book3s_hv_rm_mmu.o \
 	book3s_64_vio_hv.o \
 	book3s_hv_ras.o \
-	book3s_hv_builtin.o
+	book3s_hv_builtin.o \
+	$(kvm-book3s_64-builtin-xics-objs-y)
 
 kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
 	book3s_xics.o
arch/powerpc/kvm/book3s_hv_rm_xics.c new file +406 -0

406 lines not on this page · raw message

arch/powerpc/kvm/book3s_hv_rmhandlers.S +13 -5
index 0c8fc51..c35ae06 100644
@@ -1420,11 +1420,19 @@ hcall_real_table:
 	.long	0		/* 0x58 */
 	.long	0		/* 0x5c */
 	.long	0		/* 0x60 */
-	.long	0		/* 0x64 */
-	.long	0		/* 0x68 */
-	.long	0		/* 0x6c */
-	.long	0		/* 0x70 */
-	.long	0		/* 0x74 */
+#ifdef CONFIG_KVM_XICS
+	.long	.kvmppc_rm_h_eoi - hcall_real_table
+	.long	.kvmppc_rm_h_cppr - hcall_real_table
+	.long	.kvmppc_rm_h_ipi - hcall_real_table
+	.long	0		/* 0x70 - H_IPOLL */
+	.long	.kvmppc_rm_h_xirr - hcall_real_table
+#else
+	.long	0		/* 0x64 - H_EOI */
+	.long	0		/* 0x68 - H_CPPR */
+	.long	0		/* 0x6c - H_IPI */
+	.long	0		/* 0x70 - H_IPOLL */
+	.long	0		/* 0x74 - H_XIRR */
+#endif
 	.long	0		/* 0x78 */
 	.long	0		/* 0x7c */
 	.long	0		/* 0x80 */
arch/powerpc/kvm/book3s_xics.c +3 -0
index 1417e65..7fd247c 100644
@@ -30,6 +30,9 @@
 #define XICS_DBG(fmt...) trace_printk(fmt)
 #endif
 
+#define ENABLE_REALMODE	true
+#define DEBUG_REALMODE	false
+
 /*
  * LOCKING
  * ===@@ -220,8 +223,10 @@ static inline bool icp_try_update(struct kvmppc_icp *icp,

* in Accept (H_XIRR) and Up_Cppr (H_XPPR).
*
* We also do not try to figure out whether the EE state has changed,
- * we unconditionally set it if the new state calls for it for the
- * same reason.
+ * we unconditionally set it if the new state calls for it. The reason
+ * for that is that we opportunistically remove the pending interrupt
+ * flag when raising CPPR, so we need to set it back here if an
+ * interrupt is still pending.
*/
if (new.out_ee) {
kvmppc_book3s_queue_irqprio(icp->vcpu,
@@ -483,7 +488,7 @@ static void icp_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
icp_check_resend(xics, icp);
}

-static noinline unsigned long h_xirr(struct kvm_vcpu *vcpu) +static noinline unsigned long kvmppc_h_xirr(struct kvm_vcpu *vcpu)
{
union kvmppc_icp_state old_state, new_state;
struct kvmppc_icp *icp = vcpu->arch.icp;
@@ -517,8 +522,8 @@ static noinline unsigned long h_xirr(struct kvm_vcpu *vcpu)
return xirr;
}

-static noinline int h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
- unsigned long mfrr)
+static noinline int kvmppc_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+ unsigned long mfrr)
{
union kvmppc_icp_state old_state, new_state;
struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
@@ -586,7 +591,7 @@ static noinline int h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
return H_SUCCESS;
}

-static noinline void h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) +static noinline void kvmppc_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
{
union kvmppc_icp_state old_state, new_state;
struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
@@ -643,7 +648,7 @@ static noinline void h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
icp_deliver_irq(xics, icp, reject);
}

-static noinline int h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) +static noinline int kvmppc_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
{
struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
struct kvmppc_icp *icp = vcpu->arch.icp;
@@ -693,29 +698,54 @@ static noinline int h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
return H_SUCCESS;
}

+static noinline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall) +{
+ struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
+ struct kvmppc_icp *icp = vcpu->arch.icp;
+
+ XICS_DBG("XICS_RM: H_%x completing, act: %x state: %lx tgt: %p\n",
+ hcall, icp->rm_action, icp->rm_dbgstate.raw, icp->rm_dbgtgt);
+
+ if (icp->rm_action & XICS_RM_KICK_VCPU)
+ kvmppc_fast_vcpu_kick(icp->rm_kick_target);
+ if (icp->rm_action & XICS_RM_CHECK_RESEND)
+ icp_check_resend(xics, icp);
+ if (icp->rm_action & XICS_RM_REJECT)
+ icp_deliver_irq(xics, icp, icp->rm_reject);
+
+ icp->rm_action = 0;
+
+ return H_SUCCESS;
+}
+
int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
{
+ struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
unsigned long res;
int rc = H_SUCCESS;

/* Check if we have an ICP */
- if (!vcpu->arch.icp || !vcpu->kvm->arch.xics)
+ if (!xics || !vcpu->arch.icp)
return H_HARDWARE;

+ /* Check for real mode returning too hard */
+ if (xics->real_mode)
+ return kvmppc_xics_rm_complete(vcpu, req);
+
switch (req) {
case H_XIRR:
- res = h_xirr(vcpu);
+ res = kvmppc_h_xirr(vcpu);
kvmppc_set_gpr(vcpu, 4, res);
break;
case H_CPPR:
- h_cppr(vcpu, kvmppc_get_gpr(vcpu, 4));
+ kvmppc_h_cppr(vcpu, kvmppc_get_gpr(vcpu, 4));
break;
case H_EOI:
- rc = h_eoi(vcpu, kvmppc_get_gpr(vcpu, 4));
+ rc = kvmppc_h_eoi(vcpu, kvmppc_get_gpr(vcpu, 4));
break;
case H_IPI:
- rc = h_ipi(vcpu, kvmppc_get_gpr(vcpu, 4),
- kvmppc_get_gpr(vcpu, 5));
+ rc = kvmppc_h_ipi(vcpu, kvmppc_get_gpr(vcpu, 4),
+ kvmppc_get_gpr(vcpu, 5));
break;
}

@@ -933,6 +963,14 @@ int kvm_xics_create(struct kvm *kvm, u32 type)

xics_debugfs_init(xics);

+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ if (cpu_has_feature(CPU_FTR_ARCH_206)) {
+ /* Enable real mode support */
+ xics->real_mode = ENABLE_REALMODE;
+ xics->real_mode_dbg = DEBUG_REALMODE;
+ }
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
return 0;
}

arch/powerpc/kvm/book3s_xics.h +16 -0
index 58ee190..c816c5a 100644
@@ -64,6 +64,20 @@ struct kvmppc_icp {
 	unsigned long server_num;
 	union kvmppc_icp_state state;
 	unsigned long resend_map[ICP_RESEND_MAP_SIZE];
+
+	/* Real mode might find something too hard, here's the action
+	 * it might request from virtual mode
+	 */
+#define XICS_RM_KICK_VCPU	0x1
+#define XICS_RM_CHECK_RESEND	0x2
+#define XICS_RM_REJECT		0x4
+	u32 rm_action;
+	struct kvm_vcpu *rm_kick_target;
+	u32  rm_reject;
+
+	/* Debug stuff for real mode */
+	union kvmppc_icp_state rm_dbgstate;
+	struct kvm_vcpu *rm_dbgtgt;
 };
 
 struct kvmppc_ics {
@@ -76,6 +90,8 @@ struct kvmppc_xics {
 	struct kvm *kvm;
 	struct dentry *dentry;
 	u32 max_icsid;
+	bool real_mode;
+	bool real_mode_dbg;
 	struct kvmppc_ics *ics[KVMPPC_XICS_MAX_ICS_ID + 1];
 };
 
Signature · 1 line
1.7.10.4
#5 lore raw

PATCH v5 5/8 KVM: PPC: Book3S HV: Improve real-mode handling of external interrupts

In reply to Paul Mackerras

This streamlines our handling of external interrupts that come in while we're in the guest. First, when waking up a hardware thread that was napping, we split off the "napping due to H_CEDE" case earlier, and use the code that handles an external interrupt (0x500) in the guest to handle that too. Secondly, the code that handles those external interrupts now checks if any other thread is exiting to the host before bouncing an external interrupt to the guest, and also checks that there is actually an external interrupt pending for the guest before setting the LPCR MER bit (mediated external request).

This also makes sure that we clear the "ceded" flag when we handle a wakeup from cede in real mode, and fixes a potential infinite loop in kvmppc_run_vcpu() which can occur if we ever end up with the ceded flag set but MSR[EE] off.

---
 arch/powerpc/include/asm/reg.h          |    1 +
 arch/powerpc/kvm/book3s_hv.c            |    5 +-
 arch/powerpc/kvm/book3s_hv_rmhandlers.S |  138 +++++++++++++++++--------------
 3 files changed, 80 insertions(+), 64 deletions(-)
arch/powerpc/include/asm/reg.h +1 -0
index c9c67fc..7993224 100644
@@ -290,6 +290,7 @@
 #define     LPCR_PECE1	0x00002000	/* decrementer can cause exit */
 #define     LPCR_PECE2	0x00001000	/* machine check etc can cause exit */
 #define   LPCR_MER	0x00000800	/* Mediated External Exception */
+#define   LPCR_MER_SH	11
 #define   LPCR_LPES    0x0000000c
 #define   LPCR_LPES0   0x00000008      /* LPAR Env selector 0 */
 #define   LPCR_LPES1   0x00000004      /* LPAR Env selector 1 */
arch/powerpc/kvm/book3s_hv.c +4 -1
index 0423c81..5e87599 100644
@@ -1376,9 +1376,12 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 			break;
 		vc->runner = vcpu;
 		n_ceded = 0;
-		list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
+		list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
 			if (!v->arch.pending_exceptions)
 				n_ceded += v->arch.ceded;
+			else
+				v->arch.ceded = 0;
+		}
 		if (n_ceded = vc->n_runnable)
 			kvmppc_vcore_blocked(vc);
 		else
arch/powerpc/kvm/book3s_hv_rmhandlers.S +75 -63

231 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#6 lore raw

PATCH v5 6/8 KVM: PPC: Book3S: Add support for ibm,int-on/off RTAS calls

In reply to Paul Mackerras

This adds support for the ibm,int-on and ibm,int-off RTAS calls to the in-kernel XICS emulation and corrects the handling of the saved priority by the ibm,set-xive RTAS call. With this, ibm,int-off sets the specified interrupt's priority in its saved_priority field and sets the priority to 0xff (the least favoured value). ibm,int-on restores the saved_priority to the priority field, and ibm,set-xive sets both the priority and the saved_priority to the specified priority value.

---
 arch/powerpc/include/asm/kvm_ppc.h |    2 +
 arch/powerpc/kvm/book3s_rtas.c     |   40 +++++++++++++++++
 arch/powerpc/kvm/book3s_xics.c     |   84 ++++++++++++++++++++++++++++++------
 arch/powerpc/kvm/book3s_xics.h     |    2 +-
 4 files changed, 113 insertions(+), 15 deletions(-)
arch/powerpc/include/asm/kvm_ppc.h +2 -0
index 95a44a6..962fcc6 100644
@@ -174,6 +174,8 @@ extern int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server,
 				u32 priority);
 extern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server,
 				u32 *priority);
+extern int kvmppc_xics_int_on(struct kvm *kvm, u32 irq);
+extern int kvmppc_xics_int_off(struct kvm *kvm, u32 irq);
 
 /*
  * Cuts out inst bits with ordering according to spec.
arch/powerpc/kvm/book3s_rtas.c +40 -0
index 44d652a..8e61156 100644
@@ -63,6 +63,44 @@ static void kvm_rtas_get_xive(struct kvm_vcpu *vcpu, struct rtas_args *args)
 out:
 	args->rets[0] = rc;
 }
+
+static void kvm_rtas_int_off(struct kvm_vcpu *vcpu, struct rtas_args *args)
+{
+	u32 irq;
+	int rc;
+
+	if (args->nargs != 1 || args->nret != 1) {
+		rc = -3;
+		goto out;
+	}
+
+	irq = args->args[0];
+
+	rc = kvmppc_xics_int_off(vcpu->kvm, irq);
+	if (rc)
+		rc = -3;
+out:
+	args->rets[0] = rc;
+}
+
+static void kvm_rtas_int_on(struct kvm_vcpu *vcpu, struct rtas_args *args)
+{
+	u32 irq;
+	int rc;
+
+	if (args->nargs != 1 || args->nret != 1) {
+		rc = -3;
+		goto out;
+	}
+
+	irq = args->args[0];
+
+	rc = kvmppc_xics_int_on(vcpu->kvm, irq);
+	if (rc)
+		rc = -3;
+out:
+	args->rets[0] = rc;
+}
 #endif /* CONFIG_KVM_XICS */
 
 struct rtas_handler {
@@ -74,6 +112,8 @@ static struct rtas_handler rtas_handlers[] = {
 #ifdef CONFIG_KVM_XICS
 	{ .name = "ibm,set-xive", .handler = kvm_rtas_set_xive },
 	{ .name = "ibm,get-xive", .handler = kvm_rtas_get_xive },
+	{ .name = "ibm,int-off",  .handler = kvm_rtas_int_off },
+	{ .name = "ibm,int-on",   .handler = kvm_rtas_int_on },
 #endif
 };
 
arch/powerpc/kvm/book3s_xics.c +70 -14

112 lines not on this page · raw message

arch/powerpc/kvm/book3s_xics.h +1 -1
index c816c5a..e4fdec3 100644
@@ -36,7 +36,7 @@ struct ics_irq_state {
 	u32 number;
 	u32 server;
 	u8  priority;
-	u8  saved_priority; /* currently unused */
+	u8  saved_priority;
 	u8  resend;
 	u8  masked_pending;
 	u8  asserted; /* Only for LSI */
Signature · 1 line
1.7.10.4
#7 lore raw

PATCH v5 7/8 KVM: PPC: Book3S: Facilities to save/restore XICS presentation ctrler state

In reply to Paul Mackerras

This adds the ability for userspace to save and restore the state of the XICS interrupt presentation controllers (ICPs) via the KVM_GET/SET_ONE_REG interface. Since there is one ICP per vcpu, we simply define a new 64-bit register in the ONE_REG space for the ICP state. The state includes the CPU priority setting, the pending IPI priority, and the priority and source number of any pending external interrupt.

---
 Documentation/virtual/kvm/api.txt   |    1 +
 arch/powerpc/include/asm/kvm_ppc.h  |    2 +
 arch/powerpc/include/uapi/asm/kvm.h |   12 +++++
 arch/powerpc/kvm/book3s.c           |   19 ++++++++
 arch/powerpc/kvm/book3s_xics.c      |   90 +++++++++++++++++++++++++++++++++++
 5 files changed, 124 insertions(+)
Documentation/virtual/kvm/api.txt +1 -0
index 4247d65..54bb6ad 100644
@@ -1792,6 +1792,7 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_TSR	| 32
   PPC   | KVM_REG_PPC_OR_TSR	| 32
   PPC   | KVM_REG_PPC_CLEAR_TSR	| 32
+  PPC   | KVM_REG_PPC_ICP_STATE | 64
 
 ARM registers are mapped using the lower 32 bits.  The upper 16 of that
 is the register group type, or coprocessor number:
arch/powerpc/include/asm/kvm_ppc.h +2 -0
index 962fcc6..44c8ea1 100644
@@ -313,6 +313,8 @@ extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu);
 extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu, unsigned long server);
 extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args);
 extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd);
+extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu);
+extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
 #else
 static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
 	{ return 0; }
arch/powerpc/include/uapi/asm/kvm.h +12 -0
index 18be86c..1388282 100644
@@ -432,6 +432,18 @@ struct kvm_get_htab_header {
 /* Debugging: Special instruction for software breakpoint */
 #define KVM_REG_PPC_DEBUG_INST	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8b)
 
+/* Per-vcpu XICS interrupt controller state */
+#define KVM_REG_PPC_ICP_STATE	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
+
+#define  KVM_REG_PPC_ICP_CPPR_SHIFT	56	/* current proc priority */
+#define  KVM_REG_PPC_ICP_CPPR_MASK	0xff
+#define  KVM_REG_PPC_ICP_XISR_SHIFT	32	/* interrupt status field */
+#define  KVM_REG_PPC_ICP_XISR_MASK	0xffffff
+#define  KVM_REG_PPC_ICP_MFRR_SHIFT	24	/* pending IPI priority */
+#define  KVM_REG_PPC_ICP_MFRR_MASK	0xff
+#define  KVM_REG_PPC_ICP_PPRI_SHIFT	16	/* pending irq priority */
+#define  KVM_REG_PPC_ICP_PPRI_MASK	0xff
+
 /* Device control API: PPC-specific devices */
 #define KVM_DEV_MPIC_GRP_MISC		1
 #define   KVM_DEV_MPIC_BASE_ADDR	0	/* 64-bit */
arch/powerpc/kvm/book3s.c +19 -0
index 10cd398..185c472 100644
@@ -535,6 +535,15 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 					 &opcode, sizeof(u32));
 			break;
 		}
+#ifdef CONFIG_KVM_XICS
+		case KVM_REG_PPC_ICP_STATE:
+			if (!vcpu->arch.icp) {
+				r = -ENXIO;
+				break;
+			}
+			val = get_reg_val(reg->id, kvmppc_xics_get_icp(vcpu));
+			break;
+#endif /* CONFIG_KVM_XICS */
 		default:
 			r = -EINVAL;
 			break;
@@ -597,6 +606,16 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 			vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val);
 			break;
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_KVM_XICS
+		case KVM_REG_PPC_ICP_STATE:
+			if (!vcpu->arch.icp) {
+				r = -ENXIO;
+				break;
+			}
+			r = kvmppc_xics_set_icp(vcpu,
+						set_reg_val(reg->id, val));
+			break;
+#endif /* CONFIG_KVM_XICS */
 		default:
 			r = -EINVAL;
 			break;
arch/powerpc/kvm/book3s_xics.c +90 -0

96 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#8 lore raw

PATCH v5 8/8 KVM: PPC: Book 3S: Add API for in-kernel XICS emulation

In reply to Paul Mackerras

This adds the API for userspace to instantiate an XICS device in a VM and connect VCPUs to it. The API consists of a new device type for the KVM_CREATE_DEVICE ioctl, a new capability KVM_CAP_IRQ_XICS, which functions similarly to KVM_CAP_IRQ_MPIC, and the KVM_IRQ_LINE ioctl, which is used to assert and deassert interrupt inputs of the XICS.

The XICS device has one attribute group, KVM_DEV_XICS_GRP_SOURCES. Each attribute within this group corresponds to the state of one interrupt source. The attribute number is the same as the interrupt source number.

---
 Documentation/virtual/kvm/api.txt          |    8 ++
 Documentation/virtual/kvm/devices/xics.txt |   66 +++++++++
 arch/powerpc/include/asm/kvm_ppc.h         |    2 +
 arch/powerpc/include/uapi/asm/kvm.h        |   12 ++
 arch/powerpc/kvm/book3s_xics.c             |  211 ++++++++++++++++++++++++++--
 arch/powerpc/kvm/book3s_xics.h             |    6 +
 arch/powerpc/kvm/powerpc.c                 |   35 +++++
 include/linux/kvm_host.h                   |    1 +
 include/uapi/linux/kvm.h                   |    2 +
 virt/kvm/kvm_main.c                        |    5 +
 10 files changed, 339 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/virtual/kvm/devices/xics.txt
Documentation/virtual/kvm/api.txt +8 -0
index 54bb6ad..db230f8 100644
@@ -2756,3 +2756,11 @@ Parameters: args[0] is the MPIC device fd
             args[1] is the MPIC CPU number for this vcpu
 
 This capability connects the vcpu to an in-kernel MPIC device.
+
+6.7 KVM_CAP_IRQ_XICS
+
+Architectures: ppc
+Parameters: args[0] is the XICS device fd
+            args[1] is the XICS CPU number (server ID) for this vcpu
+
+This capability connects the vcpu to an in-kernel XICS device.
Documentation/virtual/kvm/devices/xics.txt new file +66 -0

66 lines not on this page · raw message

arch/powerpc/include/asm/kvm_ppc.h +2 -0
index 44c8ea1..6041406 100644
@@ -315,6 +315,8 @@ extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args);
 extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd);
 extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu);
 extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
+extern int kvmppc_xics_connect_vcpu(struct kvm_device *dev,
+			struct kvm_vcpu *vcpu, u32 cpu);
 #else
 static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
 	{ return 0; }
arch/powerpc/include/uapi/asm/kvm.h +12 -0
index 1388282..ed5f6a2 100644
@@ -451,4 +451,16 @@ struct kvm_get_htab_header {
 #define KVM_DEV_MPIC_GRP_REGISTER	2	/* 32-bit */
 #define KVM_DEV_MPIC_GRP_IRQ_ACTIVE	3	/* 32-bit */
 
+/* PPC64 eXternal Interrupt Controller Specification */
+#define KVM_DEV_XICS_GRP_SOURCES	1	/* 64-bit source attributes */
+
+/* Layout of 64-bit source attribute values */
+#define  KVM_XICS_DESTINATION_SHIFT	0
+#define  KVM_XICS_DESTINATION_MASK	0xffffffffULL
+#define  KVM_XICS_PRIORITY_SHIFT	32
+#define  KVM_XICS_PRIORITY_MASK		0xff
+#define  KVM_XICS_LEVEL_SENSITIVE	(1ULL << 40)
+#define  KVM_XICS_MASKED		(1ULL << 41)
+#define  KVM_XICS_PENDING		(1ULL << 42)
+
 #endif /* __LINUX_KVM_POWERPC_H */
arch/powerpc/kvm/book3s_xics.c +201 -9

285 lines not on this page · raw message

arch/powerpc/kvm/book3s_xics.h +6 -0
index e4fdec3..939074c 100644
@@ -10,6 +10,9 @@
 #ifndef _KVM_PPC_BOOK3S_XICS_H
 #define _KVM_PPC_BOOK3S_XICS_H
 
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+
 /*
  * We use a two-level tree to store interrupt source information.
  * There are up to 1024 ICS nodes, each of which can represent
@@ -83,12 +86,15 @@ struct kvmppc_icp {
 struct kvmppc_ics {
 	struct mutex lock;
 	u16 icsid;
+	struct rcu_head rhead;
 	struct ics_irq_state irq_state[KVMPPC_XICS_IRQ_PER_ICS];
 };
 
 struct kvmppc_xics {
 	struct kvm *kvm;
+	struct kvm_device *dev;
 	struct dentry *dentry;
+	struct rcu_head rhead;
 	u32 max_icsid;
 	bool real_mode;
 	bool real_mode_dbg;
arch/powerpc/kvm/powerpc.c +35 -0
index 2441b81..232a174 100644
@@ -341,6 +341,9 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_SPAPR_TCE:
 	case KVM_CAP_PPC_ALLOC_HTAB:
 	case KVM_CAP_PPC_RTAS:
+#ifdef CONFIG_KVM_XICS
+	case KVM_CAP_IRQ_XICS:
+#endif
 		r = 1;
 		break;
 #endif /* CONFIG_PPC_BOOK3S_64 */
@@ -829,6 +832,25 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
 		break;
 	}
 #endif
+#ifdef CONFIG_KVM_XICS
+	case KVM_CAP_IRQ_XICS: {
+		struct file *filp;
+		struct kvm_device *dev;
+
+		r = -EBADF;
+		filp = fget(cap->args[0]);
+		if (!filp)
+			break;
+
+		r = -EPERM;
+		dev = kvm_device_from_filp(filp);
+		if (dev)
+			r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]);
+
+		fput(filp);
+		break;
+	}
+#endif /* CONFIG_KVM_XICS */
 	default:
 		r = -EINVAL;
 		break;
@@ -1037,6 +1059,19 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		break;
 	}
 #endif /* CONFIG_PPC_BOOK3S_64 */
+
+	case KVM_IRQ_LINE: {
+		struct kvm *kvm = filp->private_data;
+		struct kvm_irq_level args;
+
+		r = -EFAULT;
+		if (copy_from_user(&args, argp, sizeof(args)))
+			break;
+
+		/* Call all the interrupt controllers */
+		r = kvm_vm_ioctl_xics_irq(kvm, &args);
+		break;
+	}
 	default:
 		r = -ENOTTY;
 	}
include/linux/kvm_host.h +1 -0
index 55d3d9c..adfb42c 100644
@@ -1102,6 +1102,7 @@ void kvm_device_put(struct kvm_device *dev);
 struct kvm_device *kvm_device_from_filp(struct file *filp);
 
 extern struct kvm_device_ops kvm_mpic_ops;
+extern struct kvm_device_ops kvm_xics_ops;
 
 #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
 
include/uapi/linux/kvm.h +2 -0
index d100ac6..7189175 100644
@@ -671,6 +671,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_DEVICE_CTRL 89
 #define KVM_CAP_IRQ_MPIC 90
 #define KVM_CAP_PPC_RTAS 91
+#define KVM_CAP_IRQ_XICS 92
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -933,6 +934,7 @@ struct kvm_device_attr {
 
 #define KVM_DEV_TYPE_FSL_MPIC_20	1
 #define KVM_DEV_TYPE_FSL_MPIC_42	2
+#define KVM_DEV_TYPE_XICS		3
 
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE	  _IOWR(KVMIO,  0xe0, struct kvm_create_device)
virt/kvm/kvm_main.c +5 -0
index 5a51869..3ba2076 100644
@@ -2244,6 +2244,11 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
 		ops = &kvm_mpic_ops;
 		break;
 #endif
+#ifdef CONFIG_KVM_XICS
+	case KVM_DEV_TYPE_XICS:
+		ops = &kvm_xics_ops;
+		break;
+#endif
 	default:
 		return -ENODEV;
 	}
Signature · 1 line
1.7.10.4
#9 lore raw
In reply to Paul Mackerras
Quoted 22 lines · Paul Mackerras

This is a repost of my patch series implementing in-kernel emulation of the XICS interrupt controller architecture defined in PAPR (Power Architecture Platform Requirements, the document that defines IBM's pSeries platform architecture). This version of the patch series uses the latest device API as posted by Scott Wood, that is, i.e., the version where the core device code provides the file descriptor and ioctl handler. I have structured the series so that the API is added by the last two patches, so as to be able to accommodate any future revisions to the device API with minimal changes.

The series is based on Alex Graf's kvm-ppc-queue branch with Scott Wood's recent patch series applied on top, together with the patch below to allow it to build with CONFIG_KVM_MPIC=n.

The API defined here uses KVM_CREATE_DEVICE to create the XICS, KVM_DEVICE_SET_ATTR/KVM_DEVICE_GET_ATTR to manipulate the interrupt sources (for initialization and migration), a new KVM_CAP_IRQ_XICS capability to connect vcpus to the XICS, a new identifier KVM_REG_PPC_ICP_STATE for the one-reg interface to get and set per-vcpu state, and the existing KVM_IRQ_LINE ioctl to assert and deassert interrupt sources.

Quoted 5 lines

This version also cleans up some checkpatch.pl errors and clarifies the lifetime rules for the various objects. There are two checkpatch warnings for long lines, but they are long because they have long strings in them, and if I break the strings over two lines then checkpatch warns about that.

Very nice patch set. I've applie 1-7 of it to kvm-ppc-queue. So they will hopefully make it to 3.10.

Please check for 8/8 whether

a) You want to have a released kernel version without irq routing (irqfd) support. It makes user space's life harder, because you need to maintain backwards compatibility.

b) Please rebase on top of the current state of things, especially the changed lifecycle assumptions. Devices should now just live until the vm gets destroyed. It gives me way less headaches.

Alex

#10 lore raw
Quoted 39 lines · Alexander Graf
Quoted 4 lines · Paul Mackerras

This is a repost of my patch series implementing in-kernel emulation of the XICS interrupt controller architecture defined in PAPR (Power Architecture Platform Requirements, the document that defines IBM's pSeries platform architecture). This version of the patch series

uses

Quoted 3 lines

the latest device API as posted by Scott Wood, that is, i.e., the version where the core device code provides the file descriptor and ioctl handler. I have structured the series so that the API is

added

Quoted 15 lines

by the last two patches, so as to be able to accommodate any future revisions to the device API with minimal changes.

The series is based on Alex Graf's kvm-ppc-queue branch with Scott Wood's recent patch series applied on top, together with the patch below to allow it to build with CONFIG_KVM_MPIC=n.

The API defined here uses KVM_CREATE_DEVICE to create the XICS, KVM_DEVICE_SET_ATTR/KVM_DEVICE_GET_ATTR to manipulate the interrupt sources (for initialization and migration), a new KVM_CAP_IRQ_XICS capability to connect vcpus to the XICS, a new identifier KVM_REG_PPC_ICP_STATE for the one-reg interface to get and set per-vcpu state, and the existing KVM_IRQ_LINE ioctl to assert and deassert interrupt sources.

Quoted 2 lines

This version also cleans up some checkpatch.pl errors and clarifies the lifetime rules for the various objects. There are two

checkpatch

Quoted 3 lines

warnings for long lines, but they are long because they have long strings in them, and if I break the strings over two lines then checkpatch warns about that.

Very nice patch set. I've applie 1-7 of it to kvm-ppc-queue. So they will hopefully make it to 3.10.

Please check for 8/8 whether

Quoted 7 lines

a) You want to have a released kernel version without irq routing
(irqfd) support. It makes user space's life harder, because you need to maintain backwards compatibility.

b) Please rebase on top of the current state of things, especially
the changed lifecycle assumptions. Devices should now just live until the vm gets destroyed. It gives me way less headaches.

Also please note that we no longer hold kvm->lock during device creation, so your EEXIST check looks racy.

-Scott

#11 lore raw
Quoted 2 lines · Scott Wood

Also please note that we no longer hold kvm->lock during device creation, so your EEXIST check looks racy.

Huh? Patch 2/8 adds this code:

+ mutex_lock(&kvm->lock);
+ if (kvm->arch.xics)
+ ret = -EEXIST;
+ else
+ kvm->arch.xics = xics;
+ mutex_unlock(&kvm->lock);

How is that racy?

Paul.

#12 lore raw
Quoted 14 lines · Paul Mackerras
Quoted 2 lines · Scott Wood

Also please note that we no longer hold kvm->lock during device creation, so your EEXIST check looks racy.

Huh? Patch 2/8 adds this code:

(quoted diff) +6 -0
+       mutex_lock(&kvm->lock);
+       if (kvm->arch.xics)
+               ret = -EEXIST;
+       else
+               kvm->arch.xics = xics;
+       mutex_unlock(&kvm->lock);
Quoted 1 line

How is that racy?

Sorry, it's not -- I must have been looking at the previous version of the patchset by mistake. :-(

-Scott

#13 lore raw
In reply to Alexander Graf
Quoted 5 lines · Alexander Graf

Very nice patch set. I've applie 1-7 of it to kvm-ppc-queue. So they will hopefully make it to 3.10.

Please check for 8/8 whether

a) You want to have a released kernel version without irq routing (irqfd) support. It makes user space's life harder, because you need to maintain backwards compatibility.

If we do a version without irq routing and later add it, old userspace should still work, since KVM_IRQ_LINE still works, right? New userspace on an old kernel can test the KVM_CAP_IRQ_ROUTING capability to see if it can use irqfd. So on the whole, I would like to get it in, provided of course I can get it tested and sent out before the window closes.

Quoted 1 line

b) Please rebase on top of the current state of things, especially the changed lifecycle assumptions. Devices should now just live until the vm gets destroyed. It gives me way less headaches.

OK, I've done that, but I need to grab David Gibson to get a qemu that knows about the new API so I can test it.

Regards,
Paul.

#14 lore raw
Quoted 11 lines · Paul Mackerras
Quoted 5 lines · Alexander Graf

Very nice patch set. I've applie 1-7 of it to kvm-ppc-queue. So they will hopefully make it to 3.10.

Please check for 8/8 whether

a) You want to have a released kernel version without irq routing (irqfd) support. It makes user space's life harder, because you need to maintain backwards compatibility.

If we do a version without irq routing and later add it, old userspace should still work, since KVM_IRQ_LINE still works, right? New userspace on an old kernel can test the KVM_CAP_IRQ_ROUTING capability to see if it can use irqfd. So on the whole, I would like to get it

User space would have to know about 2 different ways of setting interrupts, one through IRQ_LINE and one through whatever XICS device specific ioctl you create :).

This really depends on how quickly you think you could have irqfd support working. If you think it's ready for 3.11, I'd be inclined to say that it's easier for everyone if we don't have to provide any backwards compatibility at all. Then QEMU doesn't need to learn about the irq line setting path that is only ever available on 3.10.

Quoted 7 lines

in, provided of course I can get it tested and sent out before the window closes.

Quoted 1 line

b) Please rebase on top of the current state of things, especially the changed lifecycle assumptions. Devices should now just live until the vm gets destroyed. It gives me way less headaches.

OK, I've done that, but I need to grab David Gibson to get a qemu that knows about the new API so I can test it.

Yeah, please sync with him on this whole thing too. Someone will have to write the compat code ;).

Alex

#15 lore raw
Quoted 8 lines · Alexander Graf
Quoted 5 lines · Paul Mackerras
Quoted 4 lines · Alexander Graf

Very nice patch set. I've applie 1-7 of it to kvm-ppc-queue. So they will hopefully make it to 3.10.

Please check for 8/8 whether

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

a) You want to have a released kernel version without irq routing (irqfd) support. It makes user space's life harder, because you need to maintain backwards compatibility.

If we do a version without irq routing and later add it, old userspace should still work, since KVM_IRQ_LINE still works, right? New userspace on an old kernel can test the KVM_CAP_IRQ_ROUTING capability to see if it can use irqfd. So on the whole, I would like to get it

User space would have to know about 2 different ways of setting interrupts, one through IRQ_LINE and one through whatever XICS device specific ioctl you create :).

Ummm, no, userspace uses KVM_IRQ_LINE either way. Since I don't define CONFIG_HAVE_KVM_IRQCHIP or CONFIG_HAVE_KVM_IRQ_ROUTING, we don't compile in virt/kvm/irqchip.c and thus we don't get a definition of kvm_set_irq() (note that in your tree as it stands, it's only by grace of gcc's optimizations that we don't get a link error when CONFIG_KVM_MPIC=n, since we have the code in arch/powerpc/kvm/powerpc.c that calls kvm_set_irq() unconditionally).

So I added a definition of kvm_set_irq() to book3s_xics.c in the patch I posted recently, meaning that userspace can in fact use KVM_IRQ_LINE even though I don't yet support irqfd or irq routing.

Quoted 4 lines
Quoted 2 lines

OK, I've done that, but I need to grab David Gibson to get a qemu that knows about the new API so I can test it.

Yeah, please sync with him on this whole thing too. Someone will have to write the compat code ;).

I have a version of qemu from him that uses KVM_CREATE_DEVICE to create the XICS and KVM_IRQ_LINE to control the interrupt inputs, and it all works just fine.

Regards,
Paul.

#16 lore raw
Quoted 26 lines · Paul Mackerras
Quoted 8 lines · Alexander Graf
Quoted 5 lines · Paul Mackerras
Quoted 4 lines · Alexander Graf

Very nice patch set. I've applie 1-7 of it to kvm-ppc-queue. So they will hopefully make it to 3.10.

Please check for 8/8 whether

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

a) You want to have a released kernel version without irq routing (irqfd) support. It makes user space's life harder, because you need to maintain backwards compatibility.

If we do a version without irq routing and later add it, old userspace should still work, since KVM_IRQ_LINE still works, right? New userspace on an old kernel can test the KVM_CAP_IRQ_ROUTING capability to see if it can use irqfd. So on the whole, I would like to get it

User space would have to know about 2 different ways of setting interrupts, one through IRQ_LINE and one through whatever XICS device specific ioctl you create :).

Ummm, no, userspace uses KVM_IRQ_LINE either way. Since I don't define CONFIG_HAVE_KVM_IRQCHIP or CONFIG_HAVE_KVM_IRQ_ROUTING, we don't compile in virt/kvm/irqchip.c and thus we don't get a definition of kvm_set_irq() (note that in your tree as it stands, it's only by grace of gcc's optimizations that we don't get a link error when CONFIG_KVM_MPIC=n, since we have the code in arch/powerpc/kvm/powerpc.c that calls kvm_set_irq() unconditionally).

Quoted 3 lines

So I added a definition of kvm_set_irq() to book3s_xics.c in the patch I posted recently, meaning that userspace can in fact use KVM_IRQ_LINE even though I don't yet support irqfd or irq routing.

That means you'll have to make your default map compatible with what you expose there now.

Quoted 9 lines
Quoted 5 lines
Quoted 3 lines

OK, I've done that, but I need to grab David Gibson to get a qemu that knows about the new API so I can test it.

Yeah, please sync with him on this whole thing too. Someone will have to write the compat code ;).

I have a version of qemu from him that uses KVM_CREATE_DEVICE to create the XICS and KVM_IRQ_LINE to control the interrupt inputs, and it all works just fine.

Please get him to ack the approach of getting 2 interfaces later. Of course what you wrote now works. I'm not concerned about that. I'm concerned about tomorrow :).

Alex