In-kernel XICS interrupt controller emulation
Subsystems (4)
v4 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 device API as posted by Scott Wood. 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-next branch with Scott Wood's recent patch series applied on top, together with the patch below to allow it to compile 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.
Paul.
PATCH v4 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
@@ -980,6 +981,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 &©_to_user (argp, &rma,sizeof (rma)))
@@ -1024,6 +1026,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
@@ -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
PATCH v4 2/8 KVM: PPC: Book3S: Add kernel emulation for the XICS interrupt controller
In reply to Paul MackerrasFrom: 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 | 1 + arch/powerpc/include/asm/kvm_host.h | 9 + arch/powerpc/include/asm/kvm_ppc.h | 27 + arch/powerpc/include/uapi/asm/kvm.h | 1 + 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 | 16 + arch/powerpc/kvm/book3s_rtas.c | 51 +- arch/powerpc/kvm/book3s_xics.c | 942 +++++++++++++++++++++++++++++++++ arch/powerpc/kvm/book3s_xics.h | 113 ++++ arch/powerpc/kvm/powerpc.c | 5 + 13 files changed, 1185 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 +1 -0
@@ -142,6 +142,7 @@ 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 +9 -0
@@ -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
@@ -256,6 +260,7 @@ struct kvm_arch {#ifdef CONFIG_PPC_BOOK3S_64 struct list_head spapr_tce_tables;struct list_head rtas_tokens; +struct kvmppc_xics *xics;#endif };
@@ -378,6 +383,7 @@ struct kvmppc_booke_debug_reg {#define KVMPPC_IRQ_DEFAULT 0#define KVMPPC_IRQ_MPIC 1 +#define KVMPPC_IRQ_XICS 2struct openpic ;
@@ -562,6 +568,9 @@ struct kvm_vcpu_arch {int irq_type;/* one of KVM_IRQ_* */ 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 +27 -0
@@ -130,6 +130,8 @@ 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 int kvmppc_xics_hcall (struct kvm_vcpu *vcpu,u32 cmd); +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 +171,8 @@ 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.
@@ -268,6 +272,27 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)static inline void kvm_linear_init (void ) {} + +#endif + +#ifdef CONFIG_PPC_BOOK3S_64 +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); +#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 ; }#endif static inline void kvmppc_set_epr (struct kvm_vcpu *vcpu,u32 epr)
@@ -282,6 +307,8 @@ static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)void kvmppc_mpic_set_epr (struct kvm_vcpu *vcpu);int kvmppc_mpic_connect_vcpu (struct file *mpic_filp,struct kvm_vcpu *vcpu,u32 cpu); +int kvmppc_xics_connect_vcpu (struct file *xics_filp,struct kvm_vcpu *vcpu, +u32 cpu);int kvm_vcpu_ioctl_config_tlb (struct kvm_vcpu *vcpu,struct kvm_config_tlb *cfg);
arch/powerpc/include/uapi/asm/kvm.h +1 -0
@@ -428,4 +428,5 @@ struct kvm_get_htab_header {#define KVM_REG_PPC_CLEAR_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88)#define KVM_REG_PPC_TCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89)#define KVM_REG_PPC_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a) +#endif /* __LINUX_KVM_POWERPC_H */
arch/powerpc/kvm/Kconfig +8 -0
@@ -155,6 +155,14 @@ config KVM_MPIC bool "KVM in-kernel MPIC emulation" depends on KVM +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
arch/powerpc/kvm/Makefile +3 -0
@@ -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
@@ -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
@@ -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 +16 -0
@@ -227,6 +227,15 @@ 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); +if (rc =H_TOO_HARD ) +return EMULATE_FAIL ; +kvmppc_set_gpr (vcpu,3 , rc); +return EMULATE_DONE ; +} +int kvmppc_h_pr (struct kvm_vcpu *vcpu,unsigned long cmd) {switch (cmd) {
@@ -246,6 +255,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 +50 -1
62 lines not on this page · raw message
arch/powerpc/kvm/book3s_xics.c new file +941 -0
941 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 +5 -0
@@ -472,6 +472,11 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)kvmppc_mpic_put (vcpu->arch.mpic);break ;#endif +#ifdef CONFIG_KVM_XICS +case KVMPPC_IRQ_XICS : +kvmppc_xics_free_icp (vcpu); +break ; +#endif default :break ; }
Signature · 1 line
1.7.10.4
PATCH v4 3/8 KVM: PPC: Book3S HV: Speed up wakeups of CPUs on HV KVM
In reply to Paul MackerrasFrom: 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
@@ -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
@@ -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_PPC_BOOK3S_64
@@ -363,4 +390,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
@@ -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
@@ -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
@@ -224,7 +224,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
@@ -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
PATCH v4 4/8 KVM: PPC: Book3S HV: Add support for real mode ICP in XICS emulation
In reply to Paul MackerrasFrom: 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 | 1 + arch/powerpc/kvm/book3s_hv_rm_xics.c | 402 +++++++++++++++++++++++++++++++ arch/powerpc/kvm/book3s_hv_rmhandlers.S | 10 +- arch/powerpc/kvm/book3s_xics.c | 64 ++++- arch/powerpc/kvm/book3s_xics.h | 16 ++ 5 files changed, 475 insertions(+), 18 deletions(-) create mode 100644 arch/powerpc/kvm/book3s_hv_rm_xics.c
arch/powerpc/kvm/Makefile +1 -0
@@ -77,6 +77,7 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \ book3s_hv_rm_mmu.o \ book3s_64_vio_hv.o \ book3s_hv_ras.o \ + book3s_hv_rm_xics.o \ book3s_hv_builtin.o kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
arch/powerpc/kvm/book3s_hv_rm_xics.c new file +402 -0
402 lines not on this page · raw message
arch/powerpc/kvm/book3s_hv_rmhandlers.S +5 -5
@@ -1420,11 +1420,11 @@ 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 */ + .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 .long 0 /* 0x78 */ .long 0 /* 0x7c */ .long 0 /* 0x80 */
arch/powerpc/kvm/book3s_xics.c +3 -0
@@ -27,6 +27,9 @@ #define XICS_DBG(fmt...) do { } while (0)//#define XICS_DBG(fmt...) do { trace_printk(fmt); } while (0) +#define ENABLE_REALMODE true +#define DEBUG_REALMODE false +/* * LOCKING * ===@@ -217,8 +220,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,
@@ -480,7 +485,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;
@@ -514,8 +519,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;
@@ -583,7 +588,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;
@@ -640,7 +645,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;
@@ -690,29 +695,54 @@ static noinline int h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
return H_SUCCESS;
}
+static int noinline 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;
}
@@ -928,6 +958,14 @@ int kvm_create_xics(struct kvm *kvm, u32 type)
kvm->arch.xics = xics;
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 */
+
kvm_get_kvm(kvm);
return 0;
}
arch/powerpc/kvm/book3s_xics.h +16 -0
@@ -63,6 +63,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 dentry *dentry;u32 max_icsid;atomic_t usecount; +bool real_mode; +bool real_mode_dbg;struct kvmppc_ics *ics[KVMPPC_XICS_MAX_ICS_ID +1 ]; };
Signature · 1 line
1.7.10.4
PATCH v4 5/8 KVM: PPC: Book3S HV: Improve real-mode handling of external interrupts
In reply to Paul MackerrasThis 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 | 140 +++++++++++++++++-------------- 3 files changed, 81 insertions(+), 65 deletions(-)
arch/powerpc/include/asm/reg.h +1 -0
@@ -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
@@ -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 +76 -64
234 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH v4 6/8 KVM: PPC: Book3S: Add support for ibm,int-on/off RTAS calls
In reply to Paul MackerrasThis 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 | 86 +++++++++++++++++++++++++++++------- arch/powerpc/kvm/book3s_xics.h | 2 +- 4 files changed, 114 insertions(+), 16 deletions(-)
arch/powerpc/include/asm/kvm_ppc.h +2 -0
@@ -173,6 +173,8 @@ 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); +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
@@ -64,6 +64,44 @@ 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; +} +struct rtas_handler {void (*handler)(struct kvm_vcpu *vcpu,struct rtas_args *args);char *name;
@@ -72,6 +110,8 @@ struct rtas_handler {static struct rtas_handler rtas_handlers[] = { { .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 }, };struct rtas_token_definition {
arch/powerpc/kvm/book3s_xics.c +71 -15
120 lines not on this page · raw message
arch/powerpc/kvm/book3s_xics.h +1 -1
@@ -35,7 +35,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
PATCH v4 7/8 KVM: PPC: Book3S: Facilities to save/restore XICS presentation ctrler state
In reply to Paul MackerrasThis 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 | 13 +++++ arch/powerpc/kvm/book3s.c | 19 ++++++++ arch/powerpc/kvm/book3s_xics.c | 90 +++++++++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+)
Documentation/virtual/kvm/api.txt +1 -0
@@ -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
@@ -312,6 +312,8 @@ static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)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 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 +13 -0
@@ -429,4 +429,17 @@ struct kvm_get_htab_header {#define KVM_REG_PPC_TCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89)#define KVM_REG_PPC_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a) +/* Per-vcpu interrupt controller state */ +#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8b) + +/* Layout of above for XICS */ +#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 +#endif /* __LINUX_KVM_POWERPC_H */
arch/powerpc/kvm/book3s.c +19 -0
@@ -529,6 +529,15 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) val =get_reg_val (reg->id, vcpu->arch.vscr.u[3 ]);break ;#endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_KVM_BOOK3S_64 +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_BOOK3S_64 */ default : r = -EINVAL ;break ;
@@ -591,6 +600,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_BOOK3S_64 +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_BOOK3S_64 */ 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
PATCH v4 8/8 KVM: PPC: Book 3S: Add API for in-kernel XICS emulation
In reply to Paul MackerrasThis 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/kvm/book3s_xics.c | 206 +++++++++++++++++++++++++++- arch/powerpc/kvm/powerpc.c | 31 +++++ include/linux/kvm_host.h | 1 + include/uapi/linux/kvm.h | 14 ++ virt/kvm/kvm_main.c | 14 ++ 7 files changed, 335 insertions(+), 5 deletions(-) create mode 100644 Documentation/virtual/kvm/devices/xics.txt
Documentation/virtual/kvm/api.txt +8 -0
@@ -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/kvm/book3s_xics.c +201 -5
262 lines not on this page · raw message
arch/powerpc/kvm/powerpc.c +31 -0
@@ -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 */
@@ -830,6 +833,21 @@ 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; + + r = -EBADF ; + filp =fget (cap->args[0 ]); +if (!filp) +break ; + + r =kvmppc_xics_connect_vcpu (filp, vcpu, cap->args[1 ]); + +fput (filp); +break ; + } +#endif /* CONFIG_KVM_XICS */ default : r = -EINVAL ;break ;
@@ -1038,6 +1056,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
@@ -1085,6 +1085,7 @@ static inline bool kvm_vcpu_eligible_for_directed_yield(struct kvm_vcpu *vcpu) }int kvm_create_mpic (struct kvm *kvm,u32 type); +extern int kvm_create_xics (struct kvm *kvm,u32 type);#endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */ #else
include/uapi/linux/kvm.h +14 -0
@@ -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
@@ -940,6 +941,19 @@ struct kvm_device_attr {#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_TYPE_XICS 3 +#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) +/* ioctl for vm fd */ #define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
virt/kvm/kvm_main.c +14 -0
@@ -2171,6 +2171,20 @@ static int kvm_ioctl_create_device(struct kvm *kvm, return kvm_create_mpic(kvm, cd->type); }#endif +#ifdef CONFIG_KVM_XICS +case KVM_DEV_TYPE_XICS : { +int fd; + +if (cd->flags &KVM_CREATE_DEVICE_TEST ) +return 0 ; + + fd =kvm_create_xics (kvm, cd->type); +if (fd <0 ) +return fd; + cd->fd = fd; +return 0 ; + } +#endif default :return -ENODEV ; }
Signature · 1 line
1.7.10.4
Quoted 3 lines · I wrote:
The series is based on Alex Graf's kvm-ppc-next branch with Scott Wood's recent patch series applied on top, together with the patch below to allow it to compile with
CONFIG_KVM_MPIC=n.
And of course I forgot to include the patch. Here it is.
Paul.
arch/powerpc/kvm/powerpc.c +4 -0
@@ -466,9 +466,13 @@ 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_put (vcpu->arch.mpic);break ; +#endif +default : +break ; }kvmppc_core_vcpu_free (vcpu);
virt/kvm/kvm_main.c +1 -3
@@ -2161,13 +2161,11 @@ out:static int kvm_ioctl_create_device (struct kvm *kvm,struct kvm_create_device *cd) { -bool test = cd->flags &KVM_CREATE_DEVICE_TEST ; -switch (cd->type) {#ifdef CONFIG_KVM_MPIC case KVM_DEV_TYPE_FSL_MPIC_20 :case KVM_DEV_TYPE_FSL_MPIC_42 : { -if (test) +if (cd->flags &KVM_CREATE_DEVICE_TEST )return 0 ;return kvm_create_mpic (kvm, cd->type);