[PATCH 2/2] powerpc/pseries/svm: Disable BHRB/EBB/PMU access
maddy
maddy at linux.ibm.com
Tue Jan 7 15:08:45 AEDT 2020
On 12/27/19 10:59 AM, Sukadev Bhattiprolu wrote:
> Sukadev Bhattiprolu [sukadev at linux.ibm.com] wrote:
>> Ultravisor disables some CPU features like BHRB, EBB and PMU in
>> secure virtual machines (SVMs). Skip accessing those registers
>> in SVMs to avoid getting a Program Interrupt.
> Here is an updated patch that explicitly includes <asm/svm.h> in
> in some files to fix build errors reported by <lkp at intel.org>.
> ---
>
> From: Sukadev Bhattiprolu <sukadev at linux.vnet.ibm.com>
> Date: Thu, 16 May 2019 20:57:12 -0500
> Subject: [PATCH 2/2] powerpc/pseries/svm: Disable BHRB/EBB/PMU access
>
> Ultravisor disables some CPU features like BHRB, EBB and PMU in
> secure virtual machines (SVMs). Skip accessing those registers
> in SVMs to avoid getting a Program Interrupt.
>
> Signed-off-by: Sukadev Bhattiprolu <sukadev at linux.ibm.com>
> ---
> Changelog[v2]
> - [Michael Ellerman] Optimize the code using FW_FEATURE_SVM
> - Merged EBB/BHRB and PMU patches into one and reorganized code.
> - Fix some build errors reported by <lkp at intel.org>
> ---
> arch/powerpc/kernel/cpu_setup_power.S | 21 ++++++++++++++++
> arch/powerpc/kernel/process.c | 23 ++++++++++-------
> arch/powerpc/kvm/book3s_hv.c | 33 ++++++++++++++++---------
> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 32 +++++++++++++++---------
> arch/powerpc/kvm/book3s_hv_tm_builtin.c | 21 ++++++++++------
> arch/powerpc/perf/core-book3s.c | 6 +++++
> arch/powerpc/xmon/xmon.c | 30 +++++++++++++---------
> 7 files changed, 114 insertions(+), 52 deletions(-)
>
> diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
> index a460298c7ddb..9e895d8db468 100644
> --- a/arch/powerpc/kernel/cpu_setup_power.S
> +++ b/arch/powerpc/kernel/cpu_setup_power.S
> @@ -206,14 +206,35 @@ __init_PMU_HV_ISA207:
> blr
>
> __init_PMU:
> +#ifdef CONFIG_PPC_SVM
> + /*
> + * SVM's are restricted from accessing PMU, so skip.
> + */
> + mfmsr r5
> + rldicl r5, r5, 64-MSR_S_LG, 62
> + cmpwi r5,1
> + beq skip1
I know all MMCR* are loaded with 0. But
it is better if PEF code load the MMCR0
with freeze bits on. I will send a separate
patch to handle in the non-svm case.
Rest looks good.
Acked-by: Madhavan Srinivasan <maddy at linux.ibm.com>
> +#endif
> li r5,0
> mtspr SPRN_MMCRA,r5
> mtspr SPRN_MMCR0,r5
> mtspr SPRN_MMCR1,r5
> mtspr SPRN_MMCR2,r5
> +skip1:
> blr
>
> __init_PMU_ISA207:
> +
> +#ifdef CONFIG_PPC_SVM
> + /*
> + * SVM's are restricted from accessing PMU, so skip.
> + */
> + mfmsr r5
> + rldicl r5, r5, 64-MSR_S_LG, 62
> + cmpwi r5,1
> + beq skip2
> +#endif
> li r5,0
> mtspr SPRN_MMCRS,r5
> +skip2:
> blr
> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
> index 639ceae7da9d..83c7c4119305 100644
> --- a/arch/powerpc/kernel/process.c
> +++ b/arch/powerpc/kernel/process.c
> @@ -64,6 +64,7 @@
> #include <asm/asm-prototypes.h>
> #include <asm/stacktrace.h>
> #include <asm/hw_breakpoint.h>
> +#include <asm/svm.h>
>
> #include <linux/kprobes.h>
> #include <linux/kdebug.h>
> @@ -1059,9 +1060,11 @@ static inline void save_sprs(struct thread_struct *t)
> t->dscr = mfspr(SPRN_DSCR);
>
> if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
> - t->bescr = mfspr(SPRN_BESCR);
> - t->ebbhr = mfspr(SPRN_EBBHR);
> - t->ebbrr = mfspr(SPRN_EBBRR);
> + if (!is_secure_guest()) {
> + t->bescr = mfspr(SPRN_BESCR);
> + t->ebbhr = mfspr(SPRN_EBBHR);
> + t->ebbrr = mfspr(SPRN_EBBRR);
> + }
>
> t->fscr = mfspr(SPRN_FSCR);
>
> @@ -1097,12 +1100,14 @@ static inline void restore_sprs(struct thread_struct *old_thread,
> }
>
> if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
> - if (old_thread->bescr != new_thread->bescr)
> - mtspr(SPRN_BESCR, new_thread->bescr);
> - if (old_thread->ebbhr != new_thread->ebbhr)
> - mtspr(SPRN_EBBHR, new_thread->ebbhr);
> - if (old_thread->ebbrr != new_thread->ebbrr)
> - mtspr(SPRN_EBBRR, new_thread->ebbrr);
> + if (!is_secure_guest()) {
> + if (old_thread->bescr != new_thread->bescr)
> + mtspr(SPRN_BESCR, new_thread->bescr);
> + if (old_thread->ebbhr != new_thread->ebbhr)
> + mtspr(SPRN_EBBHR, new_thread->ebbhr);
> + if (old_thread->ebbrr != new_thread->ebbrr)
> + mtspr(SPRN_EBBRR, new_thread->ebbrr);
> + }
>
> if (old_thread->fscr != new_thread->fscr)
> mtspr(SPRN_FSCR, new_thread->fscr);
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index 709cf1fd4cf4..29a2640108d1 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -42,6 +42,7 @@
> #include <linux/module.h>
> #include <linux/compiler.h>
> #include <linux/of.h>
> +#include <asm/svm.h>
>
> #include <asm/ftrace.h>
> #include <asm/reg.h>
> @@ -3568,9 +3569,11 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
> mtspr(SPRN_PSPB, vcpu->arch.pspb);
> mtspr(SPRN_FSCR, vcpu->arch.fscr);
> mtspr(SPRN_TAR, vcpu->arch.tar);
> - mtspr(SPRN_EBBHR, vcpu->arch.ebbhr);
> - mtspr(SPRN_EBBRR, vcpu->arch.ebbrr);
> - mtspr(SPRN_BESCR, vcpu->arch.bescr);
> + if (!is_secure_guest()) {
> + mtspr(SPRN_EBBHR, vcpu->arch.ebbhr);
> + mtspr(SPRN_EBBRR, vcpu->arch.ebbrr);
> + mtspr(SPRN_BESCR, vcpu->arch.bescr);
> + }
> mtspr(SPRN_WORT, vcpu->arch.wort);
> mtspr(SPRN_TIDR, vcpu->arch.tid);
> mtspr(SPRN_DAR, vcpu->arch.shregs.dar);
> @@ -3641,9 +3644,11 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
> vcpu->arch.pspb = mfspr(SPRN_PSPB);
> vcpu->arch.fscr = mfspr(SPRN_FSCR);
> vcpu->arch.tar = mfspr(SPRN_TAR);
> - vcpu->arch.ebbhr = mfspr(SPRN_EBBHR);
> - vcpu->arch.ebbrr = mfspr(SPRN_EBBRR);
> - vcpu->arch.bescr = mfspr(SPRN_BESCR);
> + if (!is_secure_guest()) {
> + vcpu->arch.ebbhr = mfspr(SPRN_EBBHR);
> + vcpu->arch.ebbrr = mfspr(SPRN_EBBRR);
> + vcpu->arch.bescr = mfspr(SPRN_BESCR);
> + }
> vcpu->arch.wort = mfspr(SPRN_WORT);
> vcpu->arch.tid = mfspr(SPRN_TIDR);
> vcpu->arch.amr = mfspr(SPRN_AMR);
> @@ -4272,9 +4277,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
>
> /* Save userspace EBB and other register values */
> if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
> - ebb_regs[0] = mfspr(SPRN_EBBHR);
> - ebb_regs[1] = mfspr(SPRN_EBBRR);
> - ebb_regs[2] = mfspr(SPRN_BESCR);
> + if (!is_secure_guest()) {
> + ebb_regs[0] = mfspr(SPRN_EBBHR);
> + ebb_regs[1] = mfspr(SPRN_EBBRR);
> + ebb_regs[2] = mfspr(SPRN_BESCR);
> + }
> user_tar = mfspr(SPRN_TAR);
> }
> user_vrsave = mfspr(SPRN_VRSAVE);
> @@ -4320,9 +4327,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
>
> /* Restore userspace EBB and other register values */
> if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
> - mtspr(SPRN_EBBHR, ebb_regs[0]);
> - mtspr(SPRN_EBBRR, ebb_regs[1]);
> - mtspr(SPRN_BESCR, ebb_regs[2]);
> + if (!is_secure_guest()) {
> + mtspr(SPRN_EBBHR, ebb_regs[0]);
> + mtspr(SPRN_EBBRR, ebb_regs[1]);
> + mtspr(SPRN_BESCR, ebb_regs[2]);
> + }
> mtspr(SPRN_TAR, user_tar);
> mtspr(SPRN_FSCR, current->thread.fscr);
> }
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index faebcbb8c4db..7cc73c832482 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -810,15 +810,19 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
> mtspr SPRN_CIABR, r7
> mtspr SPRN_TAR, r8
> ld r5, VCPU_IC(r4)
> - ld r8, VCPU_EBBHR(r4)
> mtspr SPRN_IC, r5
> - mtspr SPRN_EBBHR, r8
> - ld r5, VCPU_EBBRR(r4)
> - ld r6, VCPU_BESCR(r4)
> +
> +BEGIN_FTR_SECTION
> + ld r5, VCPU_EBBHR(r4)
> + ld r6, VCPU_EBBRR(r4)
> + ld r7, VCPU_BESCR(r4)
> + mtspr SPRN_EBBHR, r5
> + mtspr SPRN_EBBRR, r6
> + mtspr SPRN_BESCR, r7
> +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_SVM)
> +
> lwz r7, VCPU_GUEST_PID(r4)
> ld r8, VCPU_WORT(r4)
> - mtspr SPRN_EBBRR, r5
> - mtspr SPRN_BESCR, r6
> mtspr SPRN_PID, r7
> mtspr SPRN_WORT, r8
> BEGIN_FTR_SECTION
> @@ -1615,14 +1619,18 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
> mfspr r7, SPRN_TAR
> std r5, VCPU_IC(r9)
> std r7, VCPU_TAR(r9)
> - mfspr r8, SPRN_EBBHR
> - std r8, VCPU_EBBHR(r9)
> - mfspr r5, SPRN_EBBRR
> - mfspr r6, SPRN_BESCR
> +
> +BEGIN_FTR_SECTION
> + mfspr r5, SPRN_EBBHR
> + mfspr r6, SPRN_EBBRR
> + mfspr r7, SPRN_BESCR
> + std r5, VCPU_EBBHR(r9)
> + std r6, VCPU_EBBRR(r9)
> + std r7, VCPU_BESCR(r9)
> +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_SVM)
> +
> mfspr r7, SPRN_PID
> mfspr r8, SPRN_WORT
> - std r5, VCPU_EBBRR(r9)
> - std r6, VCPU_BESCR(r9)
> stw r7, VCPU_GUEST_PID(r9)
> std r8, VCPU_WORT(r9)
> BEGIN_FTR_SECTION
> diff --git a/arch/powerpc/kvm/book3s_hv_tm_builtin.c b/arch/powerpc/kvm/book3s_hv_tm_builtin.c
> index 217246279dfa..46257a464f99 100644
> --- a/arch/powerpc/kvm/book3s_hv_tm_builtin.c
> +++ b/arch/powerpc/kvm/book3s_hv_tm_builtin.c
> @@ -10,6 +10,7 @@
> #include <asm/kvm_book3s_64.h>
> #include <asm/reg.h>
> #include <asm/ppc-opcode.h>
> +#include <asm/svm.h>
>
> /*
> * This handles the cases where the guest is in real suspend mode
> @@ -45,14 +46,18 @@ int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu)
> if (!(vcpu->arch.hfscr & HFSCR_EBB) ||
> ((msr & MSR_PR) && !(mfspr(SPRN_FSCR) & FSCR_EBB)))
> return 0;
> - bescr = mfspr(SPRN_BESCR);
> - /* expect to see a S->T transition requested */
> - if (((bescr >> 30) & 3) != 2)
> - return 0;
> - bescr &= ~BESCR_GE;
> - if (instr & (1 << 11))
> - bescr |= BESCR_GE;
> - mtspr(SPRN_BESCR, bescr);
> +
> + if (!is_secure_guest()) {
> + bescr = mfspr(SPRN_BESCR);
> + /* expect to see a S->T transition requested */
> + if (((bescr >> 30) & 3) != 2)
> + return 0;
> + bescr &= ~BESCR_GE;
> + if (instr & (1 << 11))
> + bescr |= BESCR_GE;
> + mtspr(SPRN_BESCR, bescr);
> + }
> +
> msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
> vcpu->arch.shregs.msr = msr;
> vcpu->arch.cfar = vcpu->arch.regs.nip - 4;
> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
> index ca92e01d0bd1..52384b4c2bd6 100644
> --- a/arch/powerpc/perf/core-book3s.c
> +++ b/arch/powerpc/perf/core-book3s.c
> @@ -17,6 +17,7 @@
> #include <asm/firmware.h>
> #include <asm/ptrace.h>
> #include <asm/code-patching.h>
> +#include <asm/svm.h>
>
> #ifdef CONFIG_PPC64
> #include "internal.h"
> @@ -813,6 +814,11 @@ void perf_event_print_debug(void)
> return;
> }
>
> + if (is_secure_guest()) {
> + pr_info("Performance monitor access disabled in SVM.\n");
> + return;
> + }
> +
> if (!ppmu->n_counter)
> return;
>
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index d83364ebc5c5..35fd3edb1949 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -53,6 +53,7 @@
> #include <asm/firmware.h>
> #include <asm/code-patching.h>
> #include <asm/sections.h>
> +#include <asm/svm.h>
>
> #ifdef CONFIG_PPC64
> #include <asm/hvcall.h>
> @@ -1861,17 +1862,24 @@ static void dump_207_sprs(void)
> mfspr(SPRN_TEXASR));
> }
>
> - printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n",
> - mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCR2));
> - printf("pmc1 = %.8lx pmc2 = %.8lx pmc3 = %.8lx pmc4 = %.8lx\n",
> - mfspr(SPRN_PMC1), mfspr(SPRN_PMC2),
> - mfspr(SPRN_PMC3), mfspr(SPRN_PMC4));
> - printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8lx\n",
> - mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5));
> - printf("sdar = %.16lx sier = %.16lx pmc6 = %.8lx\n",
> - mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6));
> - printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n",
> - mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR));
> + if (!is_secure_guest()) {
> + printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n",
> + mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1),
> + mfspr(SPRN_MMCR2));
> + printf("pmc1 = %.8lx pmc2 = %.8lx pmc3 = %.8lx pmc4 = %.8lx\n",
> + mfspr(SPRN_PMC1), mfspr(SPRN_PMC2),
> + mfspr(SPRN_PMC3), mfspr(SPRN_PMC4));
> + printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8lx\n",
> + mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5));
> + printf("sdar = %.16lx sier = %.16lx pmc6 = %.8lx\n",
> + mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6));
> +
> + printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n",
> + mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR),
> + mfspr(SPRN_BESCR));
> + }
> +
> +
> printf("iamr = %.16lx\n", mfspr(SPRN_IAMR));
>
> if (!(msr & MSR_HV))
More information about the Linuxppc-dev
mailing list