aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2011-06-28 20:23:08 -0400
committerAvi Kivity <avi@redhat.com>2011-07-12 06:16:57 -0400
commit371fefd6f2dc46668e00871930dde613b88d4bde (patch)
tree35fe799343861405914d27873eb175eb04d6dce5 /arch/powerpc/include
parent54738c097163c3f01e67ccc85462b78d4d4f495f (diff)
KVM: PPC: Allow book3s_hv guests to use SMT processor modes
This lifts the restriction that book3s_hv guests can only run one hardware thread per core, and allows them to use up to 4 threads per core on POWER7. The host still has to run single-threaded. This capability is advertised to qemu through a new KVM_CAP_PPC_SMT capability. The return value of the ioctl querying this capability is the number of vcpus per virtual CPU core (vcore), currently 4. To use this, the host kernel should be booted with all threads active, and then all the secondary threads should be offlined. This will put the secondary threads into nap mode. KVM will then wake them from nap mode and use them for running guest code (while they are still offline). To wake the secondary threads, we send them an IPI using a new xics_wake_cpu() function, implemented in arch/powerpc/sysdev/xics/icp-native.c. In other words, at this stage we assume that the platform has a XICS interrupt controller and we are using icp-native.c to drive it. Since the woken thread will need to acknowledge and clear the IPI, we also export the base physical address of the XICS registers using kvmppc_set_xics_phys() for use in the low-level KVM book3s code. When a vcpu is created, it is assigned to a virtual CPU core. The vcore number is obtained by dividing the vcpu number by the number of threads per core in the host. This number is exported to userspace via the KVM_CAP_PPC_SMT capability. If qemu wishes to run the guest in single-threaded mode, it should make all vcpu numbers be multiples of the number of threads per core. We distinguish three states of a vcpu: runnable (i.e., ready to execute the guest), blocked (that is, idle), and busy in host. We currently implement a policy that the vcore can run only when all its threads are runnable or blocked. This way, if a vcpu needs to execute elsewhere in the kernel or in qemu, it can do so without being starved of CPU by the other vcpus. When a vcore starts to run, it executes in the context of one of the vcpu threads. The other vcpu threads all go to sleep and stay asleep until something happens requiring the vcpu thread to return to qemu, or to wake up to run the vcore (this can happen when another vcpu thread goes from busy in host state to blocked). It can happen that a vcpu goes from blocked to runnable state (e.g. because of an interrupt), and the vcore it belongs to is already running. In that case it can start to run immediately as long as the none of the vcpus in the vcore have started to exit the guest. We send the next free thread in the vcore an IPI to get it to start to execute the guest. It synchronizes with the other threads via the vcore->entry_exit_count field to make sure that it doesn't go into the guest if the other vcpus are exiting by the time that it is ready to actually enter the guest. Note that there is no fixed relationship between the hardware thread number and the vcpu number. Hardware threads are assigned to vcpus as they become runnable, so we will always use the lower-numbered hardware threads in preference to higher-numbered threads if not all the vcpus in the vcore are runnable, regardless of which vcpus are runnable. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/include')
-rw-r--r--arch/powerpc/include/asm/kvm.h1
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_asm.h2
-rw-r--r--arch/powerpc/include/asm/kvm_host.h46
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h13
4 files changed, 61 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index c3ec990daf45..471bb3d85e0b 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -24,6 +24,7 @@
24 24
25/* Select powerpc specific features in <linux/kvm.h> */ 25/* Select powerpc specific features in <linux/kvm.h> */
26#define __KVM_HAVE_SPAPR_TCE 26#define __KVM_HAVE_SPAPR_TCE
27#define __KVM_HAVE_PPC_SMT
27 28
28struct kvm_regs { 29struct kvm_regs {
29 __u64 pc; 30 __u64 pc;
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index b7b039532fbc..9cfd5436782d 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -78,6 +78,8 @@ struct kvmppc_host_state {
78 78
79#ifdef CONFIG_KVM_BOOK3S_64_HV 79#ifdef CONFIG_KVM_BOOK3S_64_HV
80 struct kvm_vcpu *kvm_vcpu; 80 struct kvm_vcpu *kvm_vcpu;
81 struct kvmppc_vcore *kvm_vcore;
82 unsigned long xics_phys;
81 u64 dabr; 83 u64 dabr;
82 u64 host_mmcr[3]; 84 u64 host_mmcr[3];
83 u32 host_pmc[6]; 85 u32 host_pmc[6];
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 5616e39a7fa4..0d6d569e19c7 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -25,10 +25,14 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/kvm_types.h> 27#include <linux/kvm_types.h>
28#include <linux/threads.h>
29#include <linux/spinlock.h>
28#include <linux/kvm_para.h> 30#include <linux/kvm_para.h>
29#include <asm/kvm_asm.h> 31#include <asm/kvm_asm.h>
32#include <asm/processor.h>
30 33
31#define KVM_MAX_VCPUS 1 34#define KVM_MAX_VCPUS NR_CPUS
35#define KVM_MAX_VCORES NR_CPUS
32#define KVM_MEMORY_SLOTS 32 36#define KVM_MEMORY_SLOTS 32
33/* memory slots that does not exposed to userspace */ 37/* memory slots that does not exposed to userspace */
34#define KVM_PRIVATE_MEM_SLOTS 4 38#define KVM_PRIVATE_MEM_SLOTS 4
@@ -167,9 +171,34 @@ struct kvm_arch {
167 int tlbie_lock; 171 int tlbie_lock;
168 struct list_head spapr_tce_tables; 172 struct list_head spapr_tce_tables;
169 unsigned short last_vcpu[NR_CPUS]; 173 unsigned short last_vcpu[NR_CPUS];
174 struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
170#endif /* CONFIG_KVM_BOOK3S_64_HV */ 175#endif /* CONFIG_KVM_BOOK3S_64_HV */
171}; 176};
172 177
178/*
179 * Struct for a virtual core.
180 * Note: entry_exit_count combines an entry count in the bottom 8 bits
181 * and an exit count in the next 8 bits. This is so that we can
182 * atomically increment the entry count iff the exit count is 0
183 * without taking the lock.
184 */
185struct kvmppc_vcore {
186 int n_runnable;
187 int n_blocked;
188 int num_threads;
189 int entry_exit_count;
190 int n_woken;
191 int nap_count;
192 u16 pcpu;
193 u8 vcore_running;
194 u8 in_guest;
195 struct list_head runnable_threads;
196 spinlock_t lock;
197};
198
199#define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff)
200#define VCORE_EXIT_COUNT(vc) ((vc)->entry_exit_count >> 8)
201
173struct kvmppc_pte { 202struct kvmppc_pte {
174 ulong eaddr; 203 ulong eaddr;
175 u64 vpage; 204 u64 vpage;
@@ -365,14 +394,29 @@ struct kvm_vcpu_arch {
365 struct slb_shadow *slb_shadow; 394 struct slb_shadow *slb_shadow;
366 struct dtl *dtl; 395 struct dtl *dtl;
367 struct dtl *dtl_end; 396 struct dtl *dtl_end;
397
398 struct kvmppc_vcore *vcore;
399 int ret;
368 int trap; 400 int trap;
401 int state;
402 int ptid;
403 wait_queue_head_t cpu_run;
404
369 struct kvm_vcpu_arch_shared *shared; 405 struct kvm_vcpu_arch_shared *shared;
370 unsigned long magic_page_pa; /* phys addr to map the magic page to */ 406 unsigned long magic_page_pa; /* phys addr to map the magic page to */
371 unsigned long magic_page_ea; /* effect. addr to map the magic page to */ 407 unsigned long magic_page_ea; /* effect. addr to map the magic page to */
372 408
373#ifdef CONFIG_KVM_BOOK3S_64_HV 409#ifdef CONFIG_KVM_BOOK3S_64_HV
374 struct kvm_vcpu_arch_shared shregs; 410 struct kvm_vcpu_arch_shared shregs;
411
412 struct list_head run_list;
413 struct task_struct *run_task;
414 struct kvm_run *kvm_run;
375#endif 415#endif
376}; 416};
377 417
418#define KVMPPC_VCPU_BUSY_IN_HOST 0
419#define KVMPPC_VCPU_BLOCKED 1
420#define KVMPPC_VCPU_RUNNABLE 2
421
378#endif /* __POWERPC_KVM_HOST_H__ */ 422#endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 99f6fcf4cf88..6ef734428634 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -33,6 +33,9 @@
33#else 33#else
34#include <asm/kvm_booke.h> 34#include <asm/kvm_booke.h>
35#endif 35#endif
36#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
37#include <asm/paca.h>
38#endif
36 39
37enum emulation_result { 40enum emulation_result {
38 EMULATE_DONE, /* no further processing */ 41 EMULATE_DONE, /* no further processing */
@@ -169,4 +172,14 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
169 172
170void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid); 173void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
171 174
175#ifdef CONFIG_KVM_BOOK3S_64_HV
176static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
177{
178 paca[cpu].kvm_hstate.xics_phys = addr;
179}
180#else
181static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
182{}
183#endif
184
172#endif /* __POWERPC_KVM_PPC_H__ */ 185#endif /* __POWERPC_KVM_PPC_H__ */