aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2013-09-05 23:11:18 -0400
committerAlexander Graf <agraf@suse.de>2013-10-17 08:44:59 -0400
commit14941789f2a13cd89e2dd567c4f708e571ab714e (patch)
tree71149df5b0ab4e2790c368d7addf90fb920b0caa /arch/powerpc
parent3b7834743f9492e3509930feb4ca47135905e640 (diff)
KVM: PPC: Book3S HV: Save/restore SIAR and SDAR along with other PMU registers
Currently we are not saving and restoring the SIAR and SDAR registers in the PMU (performance monitor unit) on guest entry and exit. The result is that performance monitoring tools in the guest could get false information about where a program was executing and what data it was accessing at the time of a performance monitor interrupt. This fixes it by saving and restoring these registers along with the other PMU registers on guest entry/exit. This also provides a way for userspace to access these values for a vcpu via the one_reg interface. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c2
-rw-r--r--arch/powerpc/kvm/book3s_hv.c12
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S8
4 files changed, 24 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 0866230b7c2d..d9b21af62610 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -493,6 +493,8 @@ struct kvm_vcpu_arch {
493 493
494 u64 mmcr[3]; 494 u64 mmcr[3];
495 u32 pmc[8]; 495 u32 pmc[8];
496 u64 siar;
497 u64 sdar;
496 498
497#ifdef CONFIG_KVM_EXIT_TIMING 499#ifdef CONFIG_KVM_EXIT_TIMING
498 struct mutex exit_timing_lock; 500 struct mutex exit_timing_lock;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index d8958be5f31a..19e699d747b7 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -508,6 +508,8 @@ int main(void)
508 DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded)); 508 DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded));
509 DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr)); 509 DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr));
510 DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc)); 510 DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc));
511 DEFINE(VCPU_SIAR, offsetof(struct kvm_vcpu, arch.siar));
512 DEFINE(VCPU_SDAR, offsetof(struct kvm_vcpu, arch.sdar));
511 DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb)); 513 DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb));
512 DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max)); 514 DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max));
513 DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr)); 515 DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 62a2b5ab08ed..45a9b876b0a0 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -749,6 +749,12 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
749 i = id - KVM_REG_PPC_PMC1; 749 i = id - KVM_REG_PPC_PMC1;
750 *val = get_reg_val(id, vcpu->arch.pmc[i]); 750 *val = get_reg_val(id, vcpu->arch.pmc[i]);
751 break; 751 break;
752 case KVM_REG_PPC_SIAR:
753 *val = get_reg_val(id, vcpu->arch.siar);
754 break;
755 case KVM_REG_PPC_SDAR:
756 *val = get_reg_val(id, vcpu->arch.sdar);
757 break;
752#ifdef CONFIG_VSX 758#ifdef CONFIG_VSX
753 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: 759 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
754 if (cpu_has_feature(CPU_FTR_VSX)) { 760 if (cpu_has_feature(CPU_FTR_VSX)) {
@@ -833,6 +839,12 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
833 i = id - KVM_REG_PPC_PMC1; 839 i = id - KVM_REG_PPC_PMC1;
834 vcpu->arch.pmc[i] = set_reg_val(id, *val); 840 vcpu->arch.pmc[i] = set_reg_val(id, *val);
835 break; 841 break;
842 case KVM_REG_PPC_SIAR:
843 vcpu->arch.siar = set_reg_val(id, *val);
844 break;
845 case KVM_REG_PPC_SDAR:
846 vcpu->arch.sdar = set_reg_val(id, *val);
847 break;
836#ifdef CONFIG_VSX 848#ifdef CONFIG_VSX
837 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: 849 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
838 if (cpu_has_feature(CPU_FTR_VSX)) { 850 if (cpu_has_feature(CPU_FTR_VSX)) {
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 294b7af28cdd..541aea0ce91a 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -200,8 +200,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
200 ld r3, VCPU_MMCR(r4) 200 ld r3, VCPU_MMCR(r4)
201 ld r5, VCPU_MMCR + 8(r4) 201 ld r5, VCPU_MMCR + 8(r4)
202 ld r6, VCPU_MMCR + 16(r4) 202 ld r6, VCPU_MMCR + 16(r4)
203 ld r7, VCPU_SIAR(r4)
204 ld r8, VCPU_SDAR(r4)
203 mtspr SPRN_MMCR1, r5 205 mtspr SPRN_MMCR1, r5
204 mtspr SPRN_MMCRA, r6 206 mtspr SPRN_MMCRA, r6
207 mtspr SPRN_SIAR, r7
208 mtspr SPRN_SDAR, r8
205 mtspr SPRN_MMCR0, r3 209 mtspr SPRN_MMCR0, r3
206 isync 210 isync
207 211
@@ -1134,9 +1138,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
1134 std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */ 1138 std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */
1135 b 22f 1139 b 22f
113621: mfspr r5, SPRN_MMCR1 114021: mfspr r5, SPRN_MMCR1
1141 mfspr r7, SPRN_SIAR
1142 mfspr r8, SPRN_SDAR
1137 std r4, VCPU_MMCR(r9) 1143 std r4, VCPU_MMCR(r9)
1138 std r5, VCPU_MMCR + 8(r9) 1144 std r5, VCPU_MMCR + 8(r9)
1139 std r6, VCPU_MMCR + 16(r9) 1145 std r6, VCPU_MMCR + 16(r9)
1146 std r7, VCPU_SIAR(r9)
1147 std r8, VCPU_SDAR(r9)
1140 mfspr r3, SPRN_PMC1 1148 mfspr r3, SPRN_PMC1
1141 mfspr r4, SPRN_PMC2 1149 mfspr r4, SPRN_PMC2
1142 mfspr r5, SPRN_PMC3 1150 mfspr r5, SPRN_PMC3