aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Warrier <warrier@linux.vnet.ibm.com>2015-12-17 15:59:06 -0500
committerPaul Mackerras <paulus@samba.org>2016-02-29 00:25:06 -0500
commit79b6c247e9afe35714c1f83cfcecf40a438ca4a4 (patch)
tree00b79733eed9922728d9b9bcbb245c0dd2908cb4
parentec13e9b6b13d66c54951fec7f1158bf85f68fecd (diff)
KVM: PPC: Book3S HV: Host-side RM data structures
This patch defines the data structures to support the setting up of host side operations while running in real mode in the guest, and also the functions to allocate and free it. The operations are for now limited to virtual XICS operations. Currently, we have only defined one operation in the data structure: - Wake up a VCPU sleeping in the host when it receives a virtual interrupt The operations are assigned at the core level because PowerKVM requires that the host run in SMT off mode. For each core, we will need to manage its state atomically - where the state is defined by: 1. Is the core running in the host? 2. Is there a Real Mode (RM) operation pending on the host? Currently, core state is only managed at the whole-core level even when the system is in split-core mode. This just limits the number of free or "available" cores in the host to perform any host-side operations. The kvmppc_host_rm_core.rm_data allows any data to be passed by KVM in real mode to the host core along with the operation to be performed. The kvmppc_host_rm_ops structure is allocated the very first time a guest VM is started. Initial core state is also set - all online cores are in the host. This structure is never deleted, not even when there are no active guests. However, it needs to be freed when the module is unloaded because the kvmppc_host_rm_ops_hv can contain function pointers to kvm-hv.ko functions for the different supported host operations. Signed-off-by: Suresh Warrier <warrier@linux.vnet.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h31
-rw-r--r--arch/powerpc/kvm/book3s_hv.c70
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c3
3 files changed, 104 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 4cadee590deb..ded8ddac7dcf 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -453,6 +453,8 @@ static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
453{ 453{
454 return vcpu->arch.irq_type == KVMPPC_IRQ_XICS; 454 return vcpu->arch.irq_type == KVMPPC_IRQ_XICS;
455} 455}
456extern void kvmppc_alloc_host_rm_ops(void);
457extern void kvmppc_free_host_rm_ops(void);
456extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu); 458extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu);
457extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu, unsigned long server); 459extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu, unsigned long server);
458extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args); 460extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args);
@@ -462,6 +464,8 @@ extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
462extern int kvmppc_xics_connect_vcpu(struct kvm_device *dev, 464extern int kvmppc_xics_connect_vcpu(struct kvm_device *dev,
463 struct kvm_vcpu *vcpu, u32 cpu); 465 struct kvm_vcpu *vcpu, u32 cpu);
464#else 466#else
467static inline void kvmppc_alloc_host_rm_ops(void) {};
468static inline void kvmppc_free_host_rm_ops(void) {};
465static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu) 469static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
466 { return 0; } 470 { return 0; }
467static inline void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { } 471static inline void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { }
@@ -475,6 +479,33 @@ static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
475 { return 0; } 479 { return 0; }
476#endif 480#endif
477 481
482/*
483 * Host-side operations we want to set up while running in real
484 * mode in the guest operating on the xics.
485 * Currently only VCPU wakeup is supported.
486 */
487
488union kvmppc_rm_state {
489 unsigned long raw;
490 struct {
491 u32 in_host;
492 u32 rm_action;
493 };
494};
495
496struct kvmppc_host_rm_core {
497 union kvmppc_rm_state rm_state;
498 void *rm_data;
499 char pad[112];
500};
501
502struct kvmppc_host_rm_ops {
503 struct kvmppc_host_rm_core *rm_core;
504 void (*vcpu_kick)(struct kvm_vcpu *vcpu);
505};
506
507extern struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv;
508
478static inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu) 509static inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu)
479{ 510{
480#ifdef CONFIG_KVM_BOOKE_HV 511#ifdef CONFIG_KVM_BOOKE_HV
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 33b491e6f666..8b3332fb9ed2 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -3008,6 +3008,73 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
3008 goto out_srcu; 3008 goto out_srcu;
3009} 3009}
3010 3010
3011#ifdef CONFIG_KVM_XICS
3012/*
3013 * Allocate a per-core structure for managing state about which cores are
3014 * running in the host versus the guest and for exchanging data between
3015 * real mode KVM and CPU running in the host.
3016 * This is only done for the first VM.
3017 * The allocated structure stays even if all VMs have stopped.
3018 * It is only freed when the kvm-hv module is unloaded.
3019 * It's OK for this routine to fail, we just don't support host
3020 * core operations like redirecting H_IPI wakeups.
3021 */
3022void kvmppc_alloc_host_rm_ops(void)
3023{
3024 struct kvmppc_host_rm_ops *ops;
3025 unsigned long l_ops;
3026 int cpu, core;
3027 int size;
3028
3029 /* Not the first time here ? */
3030 if (kvmppc_host_rm_ops_hv != NULL)
3031 return;
3032
3033 ops = kzalloc(sizeof(struct kvmppc_host_rm_ops), GFP_KERNEL);
3034 if (!ops)
3035 return;
3036
3037 size = cpu_nr_cores() * sizeof(struct kvmppc_host_rm_core);
3038 ops->rm_core = kzalloc(size, GFP_KERNEL);
3039
3040 if (!ops->rm_core) {
3041 kfree(ops);
3042 return;
3043 }
3044
3045 for (cpu = 0; cpu < nr_cpu_ids; cpu += threads_per_core) {
3046 if (!cpu_online(cpu))
3047 continue;
3048
3049 core = cpu >> threads_shift;
3050 ops->rm_core[core].rm_state.in_host = 1;
3051 }
3052
3053 /*
3054 * Make the contents of the kvmppc_host_rm_ops structure visible
3055 * to other CPUs before we assign it to the global variable.
3056 * Do an atomic assignment (no locks used here), but if someone
3057 * beats us to it, just free our copy and return.
3058 */
3059 smp_wmb();
3060 l_ops = (unsigned long) ops;
3061
3062 if (cmpxchg64((unsigned long *)&kvmppc_host_rm_ops_hv, 0, l_ops)) {
3063 kfree(ops->rm_core);
3064 kfree(ops);
3065 }
3066}
3067
3068void kvmppc_free_host_rm_ops(void)
3069{
3070 if (kvmppc_host_rm_ops_hv) {
3071 kfree(kvmppc_host_rm_ops_hv->rm_core);
3072 kfree(kvmppc_host_rm_ops_hv);
3073 kvmppc_host_rm_ops_hv = NULL;
3074 }
3075}
3076#endif
3077
3011static int kvmppc_core_init_vm_hv(struct kvm *kvm) 3078static int kvmppc_core_init_vm_hv(struct kvm *kvm)
3012{ 3079{
3013 unsigned long lpcr, lpid; 3080 unsigned long lpcr, lpid;
@@ -3020,6 +3087,8 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
3020 return -ENOMEM; 3087 return -ENOMEM;
3021 kvm->arch.lpid = lpid; 3088 kvm->arch.lpid = lpid;
3022 3089
3090 kvmppc_alloc_host_rm_ops();
3091
3023 /* 3092 /*
3024 * Since we don't flush the TLB when tearing down a VM, 3093 * Since we don't flush the TLB when tearing down a VM,
3025 * and this lpid might have previously been used, 3094 * and this lpid might have previously been used,
@@ -3253,6 +3322,7 @@ static int kvmppc_book3s_init_hv(void)
3253 3322
3254static void kvmppc_book3s_exit_hv(void) 3323static void kvmppc_book3s_exit_hv(void)
3255{ 3324{
3325 kvmppc_free_host_rm_ops();
3256 kvmppc_hv_ops = NULL; 3326 kvmppc_hv_ops = NULL;
3257} 3327}
3258 3328
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index fd7006bf6b1a..5f0380db3eab 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -283,3 +283,6 @@ void kvmhv_commence_exit(int trap)
283 kvmhv_interrupt_vcore(vc, ee); 283 kvmhv_interrupt_vcore(vc, ee);
284 } 284 }
285} 285}
286
287struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv;
288EXPORT_SYMBOL_GPL(kvmppc_host_rm_ops_hv);