From: Marc Zyngier <maz@kernel.org>
To: James Morse <james.morse@arm.com>
Cc: kvmarm@lists.cs.columbia.edu,
linux-arm-kernel@lists.infradead.org,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Anshuman Khandual <anshuman.khandual@arm.com>
Subject: Re: [PATCH 4/4] KVM: arm64: Workaround Cortex-A510's single-step and PAC trap errata
Date: Tue, 25 Jan 2022 18:36:47 +0000 [thread overview]
Message-ID: <87k0en7jcw.wl-maz@kernel.org> (raw)
In-Reply-To: <711e16a1-c853-10e8-43d5-31890f0d4c7c@arm.com>
On Tue, 25 Jan 2022 18:19:45 +0000,
James Morse <james.morse@arm.com> wrote:
>
> Hi Marc,
>
> On 25/01/2022 16:51, Marc Zyngier wrote:
> > On Tue, 25 Jan 2022 15:38:03 +0000,
> > James Morse <james.morse@arm.com> wrote:
> >>
> >> Cortex-A510's erratum #2077057 causes SPSR_EL2 to be corrupted when
> >> single-stepping authenticated ERET instructions. A single step is
> >> expected, but a pointer authentication trap is taken instead. The
> >> erratum causes SPSR_EL1 to be copied to SPSR_EL2, which could allow
> >> EL1 to cause a return to EL2 with a guest controlled ELR_EL2.
> >>
> >> Because the conditions require an ERET into active-not-pending state,
> >> this is only a problem for the EL2 when EL2 is stepping EL1. In this case
> >> the previous SPSR_EL2 value is preserved in struct kvm_vcpu, and can be
> >> restored.
>
> > Urgh. That's pretty nasty :-(.
>
> >> diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
> >> index 331dd10821df..93bf140cc972 100644
> >> --- a/arch/arm64/kvm/hyp/include/hyp/switch.h
> >> +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
> >> @@ -440,6 +442,22 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> >> write_sysreg_el2(read_sysreg_el2(SYS_ELR) - 4, SYS_ELR);
> >> }
> >>
> >> + /*
> >> + * Check for the conditions of Cortex-A510's #2077057. When these occur
> >> + * SPSR_EL2 can't be trusted, but isn't needed either as it is
> >> + * unchanged from the value in vcpu_gp_regs(vcpu)->pstate.
> >> + * Did we just take a PAC exception when a step exception was expected?
> >> + */
> >> + if (IS_ENABLED(CONFIG_ARM64_ERRATUM_2077057) &&
> >
> > nit: we can drop this IS_ENABLED()...
>
> Hmmm, I thought dead code elimination was a good thing!
> Without the cpu_errata.c match, (which is also guarded by #ifdef),
> the cap will never be true, even if an affected CPU showed up. This
> way the compiler knows it can remove all this.
I don't dispute that. However, experience shows that the more of these
we sprinkle around, the quicker this code bitrots as we don't build
for all the possible configurations. In general, we hardly have any
dependency on configuration symbols, and rely on static keys got
things not be terribly sucky.
>
>
> >> + cpus_have_const_cap(ARM64_WORKAROUND_2077057) &&
> >
> > and make this a final cap. Being a ARM64_CPUCAP_LOCAL_CPU_ERRATUM, we
> > won't accept late CPUs on a system that wasn't affected until then.
> >
> >> + ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ &&
> >> + esr_ec == ESR_ELx_EC_PAC &&
> >> + vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
> >> + /* Active-not-pending? */
> >> + if (*vcpu_cpsr(vcpu) & DBG_SPSR_SS)
> >> + write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
> >
> > Err... Isn't this way too late? The function starts with:
> >
> > vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR);
> >
> > which is just another way to write:
> >
> > *vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);
> >
> > By that time, the vcpu's PSTATE is terminally corrupted.
>
> Yes - bother. Staring at it didn't let me spot that!
> I can hit the conditions to test this, but due to lack of
> imagination the model doesn't corrupt the SPSR.
Bad model. ;-)
>
>
> > I think you need to hoist this workaround way up, before we call into
> > early_exit_filter() as it will assume that the guest pstate is correct
> > (this is used by both pKVM and the NV code).
> >
> > Something like this (untested):
> >
> > diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
> > index 93bf140cc972..a8a1502db237 100644
> > --- a/arch/arm64/kvm/hyp/include/hyp/switch.h
> > +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
> > @@ -402,6 +402,26 @@ static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> > return false;
> > }
> >
> > +static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu,
> > + u64 *exit_code)
> > +{
> > + /*
> > + * Check for the conditions of Cortex-A510's #2077057. When these occur
> > + * SPSR_EL2 can't be trusted, but isn't needed either as it is
> > + * unchanged from the value in vcpu_gp_regs(vcpu)->pstate.
> > + * Did we just take a PAC exception when a step exception (being in the
> > + * Active-not-pending state) was expected?
> > + */
> > + if (cpus_have_final_cap(ARM64_WORKAROUND_2077057) &&
> > + ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ &&
>
> > + kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_PAC &&
>
> The vcpu's esr_el2 isn't yet set:
> | ESR_ELx_EC(read_sysreg_el2(SYS_ESR)) == ESR_ELx_EC_PAC
Ah, well spotted!
>
> (and I'll shuffle the order so this is last as its an extra sysreg read)
>
>
> > + vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP &&
> > + *vcpu_cpsr(vcpu) & DBG_SPSR_SS)
> > + write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
> > +
> > + *vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);
> > +}
> > +
> > /*
> > * Return true when we were able to fixup the guest exit and should return to
> > * the guest, false when we should restore the host state and return to the
> > @@ -415,7 +435,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> > * Save PSTATE early so that we can evaluate the vcpu mode
> > * early on.
> > */
> > - vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR);
> > + synchronize_vcpu_pstate(vcpu, exit_code);
>
> Even better, that saves the noise from moving esr_ec around!
Yup, the patch becomes marginally smaller.
>
>
> > Other than that, I'm happy to take the series as a whole ASAP, if only
> > for the two pretty embarrassing bug fixes. If you can respin it
> > shortly and address the comments above, I'd like it into -rc2.
>
> Will do. Shout if you strongly care about the IS_ENABLED().
I'd really like it gone. Otherwise, I'll never compile that code.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2022-01-25 18:40 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-25 15:37 [PATCH 0/4] KVM: arm64: A510 errata workaround and fixes for fixup_guest_exit() James Morse
2022-01-25 15:38 ` [PATCH 1/4] arm64: Add Cortex-A510 CPU part definition James Morse
2022-01-25 15:38 ` [PATCH 2/4] KVM: arm64: Avoid consuming a stale esr value when SError occur James Morse
2022-01-25 15:38 ` [PATCH 3/4] KVM: arm64: Stop handle_exit() from handling HVC twice when an SError occurs James Morse
2022-01-25 15:38 ` [PATCH 4/4] KVM: arm64: Workaround Cortex-A510's single-step and PAC trap errata James Morse
2022-01-25 16:51 ` Marc Zyngier
2022-01-25 18:19 ` James Morse
2022-01-25 18:36 ` Marc Zyngier [this message]
2022-01-26 16:49 ` James Morse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87k0en7jcw.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=alexandru.elisei@arm.com \
--cc=anshuman.khandual@arm.com \
--cc=catalin.marinas@arm.com \
--cc=james.morse@arm.com \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=suzuki.poulose@arm.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).