diff mbox series

[RFC,2/2] arm64: kvm: describe data or unified caches as having 1 set and 1 way

Message ID 20181217150205.27981-3-ard.biesheuvel@linaro.org (mailing list archive)
State RFC
Headers show
Series arm64: kvm: cache ID register trapping | expand

Commit Message

Ard Biesheuvel Dec. 17, 2018, 3:02 p.m. UTC
On SMP ARM systems, cache maintenance by set/way should only ever be
done in the context of onlining or offlining CPUs, which is typically
done by bare metal firmware and never in a virtual machine. For this
reason, we trap set/way cache maintenance operations and replace them
with conditional flushing of the entire guest address space.

Due to this trapping, the set/way arguments passed into the set/way
ops are completely ignored, and thus irrelevant. This also means that
the set/way geometry is equally irrelevant, and we can simply report
it as 1 set and 1 way, so that legacy 32-bit ARM system software (i.e.,
the kind that only receives odd fixes) doesn't take a performance hit
due to the trapping when iterating over the cachelines.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/kvm/sys_regs.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

Comments

Christoffer Dall Jan. 8, 2019, 11:02 a.m. UTC | #1
On Mon, Dec 17, 2018 at 04:02:05PM +0100, Ard Biesheuvel wrote:
> On SMP ARM systems, cache maintenance by set/way should only ever be
> done in the context of onlining or offlining CPUs, which is typically
> done by bare metal firmware and never in a virtual machine. For this
> reason, we trap set/way cache maintenance operations and replace them
> with conditional flushing of the entire guest address space.
> 
> Due to this trapping, the set/way arguments passed into the set/way
> ops are completely ignored, and thus irrelevant. This also means that
> the set/way geometry is equally irrelevant, and we can simply report
> it as 1 set and 1 way, so that legacy 32-bit ARM system software (i.e.,
> the kind that only receives odd fixes) doesn't take a performance hit
> due to the trapping when iterating over the cachelines.
> 
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  arch/arm64/kvm/sys_regs.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 464e794b5bc5..eb244ff98dca 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1180,6 +1180,21 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>  
>  	csselr = vcpu_read_sys_reg(vcpu, CSSELR_EL1);
>  	p->regval = get_ccsidr(csselr);
> +
> +	/*
> +	 * Guests should not be doing cache operations by set/way at all, and
> +	 * for this reason, we trap them and attempt to infer the intent, so
> +	 * that we can flush the entire guest's address space at the appropriate
> +	 * time.
> +	 * To prevent this trapping from causing performance problems, let's
> +	 * expose the geometry of all data and unified caches (which are
> +	 * guaranteed to be PIPT and thus non-aliasing) as 1 set and 1 way.
> +	 * [If guests should attempt to infer aliasing properties from the
> +	 * geometry (which is not permitted by the architecture), they would
> +	 * only do so for virtually indexed caches.]
> +	 */
> +	if (!(csselr & 1)) // data or unified cache
> +		p->regval &= ~GENMASK(27, 2);

Why are you clearing the upper bit the LineSize field?

Thanks,

    Christoffer
Ard Biesheuvel Jan. 8, 2019, 11:11 a.m. UTC | #2
On Tue, 8 Jan 2019 at 12:02, Christoffer Dall <christoffer.dall@arm.com> wrote:
>
> On Mon, Dec 17, 2018 at 04:02:05PM +0100, Ard Biesheuvel wrote:
> > On SMP ARM systems, cache maintenance by set/way should only ever be
> > done in the context of onlining or offlining CPUs, which is typically
> > done by bare metal firmware and never in a virtual machine. For this
> > reason, we trap set/way cache maintenance operations and replace them
> > with conditional flushing of the entire guest address space.
> >
> > Due to this trapping, the set/way arguments passed into the set/way
> > ops are completely ignored, and thus irrelevant. This also means that
> > the set/way geometry is equally irrelevant, and we can simply report
> > it as 1 set and 1 way, so that legacy 32-bit ARM system software (i.e.,
> > the kind that only receives odd fixes) doesn't take a performance hit
> > due to the trapping when iterating over the cachelines.
> >
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > ---
> >  arch/arm64/kvm/sys_regs.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > index 464e794b5bc5..eb244ff98dca 100644
> > --- a/arch/arm64/kvm/sys_regs.c
> > +++ b/arch/arm64/kvm/sys_regs.c
> > @@ -1180,6 +1180,21 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >
> >       csselr = vcpu_read_sys_reg(vcpu, CSSELR_EL1);
> >       p->regval = get_ccsidr(csselr);
> > +
> > +     /*
> > +      * Guests should not be doing cache operations by set/way at all, and
> > +      * for this reason, we trap them and attempt to infer the intent, so
> > +      * that we can flush the entire guest's address space at the appropriate
> > +      * time.
> > +      * To prevent this trapping from causing performance problems, let's
> > +      * expose the geometry of all data and unified caches (which are
> > +      * guaranteed to be PIPT and thus non-aliasing) as 1 set and 1 way.
> > +      * [If guests should attempt to infer aliasing properties from the
> > +      * geometry (which is not permitted by the architecture), they would
> > +      * only do so for virtually indexed caches.]
> > +      */
> > +     if (!(csselr & 1)) // data or unified cache
> > +             p->regval &= ~GENMASK(27, 2);
>
> Why are you clearing the upper bit the LineSize field?
>

Ah, that needs to be ~GENMASK(27,3), of course.
Christoffer Dall Jan. 8, 2019, 11:14 a.m. UTC | #3
On Tue, Jan 08, 2019 at 12:11:33PM +0100, Ard Biesheuvel wrote:
> On Tue, 8 Jan 2019 at 12:02, Christoffer Dall <christoffer.dall@arm.com> wrote:
> >
> > On Mon, Dec 17, 2018 at 04:02:05PM +0100, Ard Biesheuvel wrote:
> > > On SMP ARM systems, cache maintenance by set/way should only ever be
> > > done in the context of onlining or offlining CPUs, which is typically
> > > done by bare metal firmware and never in a virtual machine. For this
> > > reason, we trap set/way cache maintenance operations and replace them
> > > with conditional flushing of the entire guest address space.
> > >
> > > Due to this trapping, the set/way arguments passed into the set/way
> > > ops are completely ignored, and thus irrelevant. This also means that
> > > the set/way geometry is equally irrelevant, and we can simply report
> > > it as 1 set and 1 way, so that legacy 32-bit ARM system software (i.e.,
> > > the kind that only receives odd fixes) doesn't take a performance hit
> > > due to the trapping when iterating over the cachelines.
> > >
> > > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > ---
> > >  arch/arm64/kvm/sys_regs.c | 15 +++++++++++++++
> > >  1 file changed, 15 insertions(+)
> > >
> > > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > > index 464e794b5bc5..eb244ff98dca 100644
> > > --- a/arch/arm64/kvm/sys_regs.c
> > > +++ b/arch/arm64/kvm/sys_regs.c
> > > @@ -1180,6 +1180,21 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> > >
> > >       csselr = vcpu_read_sys_reg(vcpu, CSSELR_EL1);
> > >       p->regval = get_ccsidr(csselr);
> > > +
> > > +     /*
> > > +      * Guests should not be doing cache operations by set/way at all, and
> > > +      * for this reason, we trap them and attempt to infer the intent, so
> > > +      * that we can flush the entire guest's address space at the appropriate
> > > +      * time.
> > > +      * To prevent this trapping from causing performance problems, let's
> > > +      * expose the geometry of all data and unified caches (which are
> > > +      * guaranteed to be PIPT and thus non-aliasing) as 1 set and 1 way.
> > > +      * [If guests should attempt to infer aliasing properties from the
> > > +      * geometry (which is not permitted by the architecture), they would
> > > +      * only do so for virtually indexed caches.]
> > > +      */
> > > +     if (!(csselr & 1)) // data or unified cache
> > > +             p->regval &= ~GENMASK(27, 2);
> >
> > Why are you clearing the upper bit the LineSize field?
> >
> 
> Ah, that needs to be ~GENMASK(27,3), of course.

With that fixed, the patches look fine to me.

Acked-by: Christoffer Dall <christoffer.dall@arm.com>
diff mbox series

Patch

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 464e794b5bc5..eb244ff98dca 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1180,6 +1180,21 @@  static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 
 	csselr = vcpu_read_sys_reg(vcpu, CSSELR_EL1);
 	p->regval = get_ccsidr(csselr);
+
+	/*
+	 * Guests should not be doing cache operations by set/way at all, and
+	 * for this reason, we trap them and attempt to infer the intent, so
+	 * that we can flush the entire guest's address space at the appropriate
+	 * time.
+	 * To prevent this trapping from causing performance problems, let's
+	 * expose the geometry of all data and unified caches (which are
+	 * guaranteed to be PIPT and thus non-aliasing) as 1 set and 1 way.
+	 * [If guests should attempt to infer aliasing properties from the
+	 * geometry (which is not permitted by the architecture), they would
+	 * only do so for virtually indexed caches.]
+	 */
+	if (!(csselr & 1)) // data or unified cache
+		p->regval &= ~GENMASK(27, 2);
 	return true;
 }