aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-02-02 19:56:21 -0500
committerAvi Kivity <avi@redhat.com>2012-04-08 07:01:29 -0400
commit0456ec4ff2b832ab9ff476ed687fea704500f1cd (patch)
treecfc0113c6f910fb51fd5b35c90653e7d17a321e1 /arch/powerpc
parent2e25aa5f64b18a97f35266e51c71ff4dc644db0c (diff)
KVM: PPC: Book3S HV: Report stolen time to guest through dispatch trace log
This adds code to measure "stolen" time per virtual core in units of timebase ticks, and to report the stolen time to the guest using the dispatch trace log (DTL). The guest can register an area of memory for the DTL for a given vcpu. The DTL is a ring buffer where KVM fills in one entry every time it enters the guest for that vcpu. Stolen time is measured as time when the virtual core is not running, either because the vcore is not runnable (e.g. some of its vcpus are executing elsewhere in the kernel or in userspace), or when the vcpu thread that is running the vcore is preempted. This includes time when all the vcpus are idle (i.e. have executed the H_CEDE hypercall), which is OK because the guest accounts stolen time while idle as idle time. Each vcpu keeps a record of how much stolen time has been reported to the guest for that vcpu so far. When we are about to enter the guest, we create a new DTL entry (if the guest vcpu has a DTL) and report the difference between total stolen time for the vcore and stolen time reported so far for the vcpu as the "enqueue to dispatch" time in the DTL entry. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_host.h4
-rw-r--r--arch/powerpc/kvm/book3s_hv.c46
2 files changed, 49 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 93ffd8dd8554..014eaf27a239 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -268,6 +268,9 @@ struct kvmppc_vcore {
268 struct list_head runnable_threads; 268 struct list_head runnable_threads;
269 spinlock_t lock; 269 spinlock_t lock;
270 wait_queue_head_t wq; 270 wait_queue_head_t wq;
271 u64 stolen_tb;
272 u64 preempt_tb;
273 struct kvm_vcpu *runner;
271}; 274};
272 275
273#define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff) 276#define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff)
@@ -516,6 +519,7 @@ struct kvm_vcpu_arch {
516 struct kvmppc_vpa dtl; 519 struct kvmppc_vpa dtl;
517 struct dtl_entry *dtl_ptr; 520 struct dtl_entry *dtl_ptr;
518 unsigned long dtl_index; 521 unsigned long dtl_index;
522 u64 stolen_logged;
519 struct kvmppc_vpa slb_shadow; 523 struct kvmppc_vpa slb_shadow;
520#endif 524#endif
521}; 525};
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 2444a9ce781f..907935764de0 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -60,12 +60,20 @@ static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu);
60 60
61void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 61void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
62{ 62{
63 struct kvmppc_vcore *vc = vcpu->arch.vcore;
64
63 local_paca->kvm_hstate.kvm_vcpu = vcpu; 65 local_paca->kvm_hstate.kvm_vcpu = vcpu;
64 local_paca->kvm_hstate.kvm_vcore = vcpu->arch.vcore; 66 local_paca->kvm_hstate.kvm_vcore = vc;
67 if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
68 vc->stolen_tb += mftb() - vc->preempt_tb;
65} 69}
66 70
67void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) 71void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
68{ 72{
73 struct kvmppc_vcore *vc = vcpu->arch.vcore;
74
75 if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
76 vc->preempt_tb = mftb();
69} 77}
70 78
71void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) 79void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
@@ -305,6 +313,35 @@ static void kvmppc_update_vpas(struct kvm_vcpu *vcpu)
305 spin_unlock(&vcpu->arch.vpa_update_lock); 313 spin_unlock(&vcpu->arch.vpa_update_lock);
306} 314}
307 315
316static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
317 struct kvmppc_vcore *vc)
318{
319 struct dtl_entry *dt;
320 struct lppaca *vpa;
321 unsigned long old_stolen;
322
323 dt = vcpu->arch.dtl_ptr;
324 vpa = vcpu->arch.vpa.pinned_addr;
325 old_stolen = vcpu->arch.stolen_logged;
326 vcpu->arch.stolen_logged = vc->stolen_tb;
327 if (!dt || !vpa)
328 return;
329 memset(dt, 0, sizeof(struct dtl_entry));
330 dt->dispatch_reason = 7;
331 dt->processor_id = vc->pcpu + vcpu->arch.ptid;
332 dt->timebase = mftb();
333 dt->enqueue_to_dispatch_time = vc->stolen_tb - old_stolen;
334 dt->srr0 = kvmppc_get_pc(vcpu);
335 dt->srr1 = vcpu->arch.shregs.msr;
336 ++dt;
337 if (dt == vcpu->arch.dtl.pinned_end)
338 dt = vcpu->arch.dtl.pinned_addr;
339 vcpu->arch.dtl_ptr = dt;
340 /* order writing *dt vs. writing vpa->dtl_idx */
341 smp_wmb();
342 vpa->dtl_idx = ++vcpu->arch.dtl_index;
343}
344
308int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) 345int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
309{ 346{
310 unsigned long req = kvmppc_get_gpr(vcpu, 3); 347 unsigned long req = kvmppc_get_gpr(vcpu, 3);
@@ -568,6 +605,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
568 INIT_LIST_HEAD(&vcore->runnable_threads); 605 INIT_LIST_HEAD(&vcore->runnable_threads);
569 spin_lock_init(&vcore->lock); 606 spin_lock_init(&vcore->lock);
570 init_waitqueue_head(&vcore->wq); 607 init_waitqueue_head(&vcore->wq);
608 vcore->preempt_tb = mftb();
571 } 609 }
572 kvm->arch.vcores[core] = vcore; 610 kvm->arch.vcores[core] = vcore;
573 } 611 }
@@ -580,6 +618,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
580 ++vcore->num_threads; 618 ++vcore->num_threads;
581 spin_unlock(&vcore->lock); 619 spin_unlock(&vcore->lock);
582 vcpu->arch.vcore = vcore; 620 vcpu->arch.vcore = vcore;
621 vcpu->arch.stolen_logged = vcore->stolen_tb;
583 622
584 vcpu->arch.cpu_type = KVM_CPU_3S_64; 623 vcpu->arch.cpu_type = KVM_CPU_3S_64;
585 kvmppc_sanity_check(vcpu); 624 kvmppc_sanity_check(vcpu);
@@ -803,6 +842,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
803 vc->nap_count = 0; 842 vc->nap_count = 0;
804 vc->entry_exit_count = 0; 843 vc->entry_exit_count = 0;
805 vc->vcore_state = VCORE_RUNNING; 844 vc->vcore_state = VCORE_RUNNING;
845 vc->stolen_tb += mftb() - vc->preempt_tb;
806 vc->in_guest = 0; 846 vc->in_guest = 0;
807 vc->pcpu = smp_processor_id(); 847 vc->pcpu = smp_processor_id();
808 vc->napping_threads = 0; 848 vc->napping_threads = 0;
@@ -812,6 +852,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
812 vcpu->arch.slb_shadow.update_pending || 852 vcpu->arch.slb_shadow.update_pending ||
813 vcpu->arch.dtl.update_pending) 853 vcpu->arch.dtl.update_pending)
814 kvmppc_update_vpas(vcpu); 854 kvmppc_update_vpas(vcpu);
855 kvmppc_create_dtl_entry(vcpu, vc);
815 } 856 }
816 /* Grab any remaining hw threads so they can't go into the kernel */ 857 /* Grab any remaining hw threads so they can't go into the kernel */
817 for (i = ptid; i < threads_per_core; ++i) 858 for (i = ptid; i < threads_per_core; ++i)
@@ -869,6 +910,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
869 spin_lock(&vc->lock); 910 spin_lock(&vc->lock);
870 out: 911 out:
871 vc->vcore_state = VCORE_INACTIVE; 912 vc->vcore_state = VCORE_INACTIVE;
913 vc->preempt_tb = mftb();
872 list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads, 914 list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
873 arch.run_list) { 915 arch.run_list) {
874 if (vcpu->arch.ret != RESUME_GUEST) { 916 if (vcpu->arch.ret != RESUME_GUEST) {
@@ -967,6 +1009,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
967 spin_lock(&vc->lock); 1009 spin_lock(&vc->lock);
968 continue; 1010 continue;
969 } 1011 }
1012 vc->runner = vcpu;
970 n_ceded = 0; 1013 n_ceded = 0;
971 list_for_each_entry(v, &vc->runnable_threads, arch.run_list) 1014 list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
972 n_ceded += v->arch.ceded; 1015 n_ceded += v->arch.ceded;
@@ -986,6 +1029,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
986 wake_up(&v->arch.cpu_run); 1029 wake_up(&v->arch.cpu_run);
987 } 1030 }
988 } 1031 }
1032 vc->runner = NULL;
989 } 1033 }
990 1034
991 if (signal_pending(current)) { 1035 if (signal_pending(current)) {