Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-22 Thread Christoffer Dall
On Thu, Feb 22, 2018 at 10:56:41AM +0100, Andrew Jones wrote:
> On Thu, Feb 22, 2018 at 10:10:34AM +0100, Christoffer Dall wrote:
> > On Wed, Feb 21, 2018 at 06:32:00PM +0100, Andrew Jones wrote:
> > > 
> > > Besides my confusion on motivation, it looks good to me
> > > 
> > 
> > In that case, unless there's an argument that the code has become too
> > hard to understand, ...
> >
> 
> On the contrary, I think it's easier to read now than before. I just
> wasn't clear how it all tied together with this series. If its
> combination with other patches enables a speedup, then it certainly
> fits here. I was just comparing mrs+loads vs. a load from stack and

The comparison should be mrs+load, vs. str+load (you save the store on
the stack).

> it seemed it would actually cause a micro-performance-decrease.
> 

Thanks,
-Christoffer
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-22 Thread Andrew Jones
On Thu, Feb 22, 2018 at 10:10:34AM +0100, Christoffer Dall wrote:
> On Wed, Feb 21, 2018 at 06:32:00PM +0100, Andrew Jones wrote:
> > 
> > Besides my confusion on motivation, it looks good to me
> > 
> 
> In that case, unless there's an argument that the code has become too
> hard to understand, ...
>

On the contrary, I think it's easier to read now than before. I just
wasn't clear how it all tied together with this series. If its
combination with other patches enables a speedup, then it certainly
fits here. I was just comparing mrs+loads vs. a load from stack and
it seemed it would actually cause a micro-performance-decrease.

Thanks,
drew
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-22 Thread Andrew Jones
On Thu, Feb 22, 2018 at 10:02:48AM +0100, Christoffer Dall wrote:
> On Wed, Feb 21, 2018 at 11:34:07AM +, Marc Zyngier wrote:
> > On Thu, 15 Feb 2018 21:02:55 +,
> > Christoffer Dall wrote:
> > > @@ -138,13 +138,15 @@ alternative_else_nop_endif
> > >  
> > >  el1_irq:
> > >   stp x0, x1, [sp, #-16]!
> > > - ldr x1, [sp, #16 + 8]
> > > + get_host_ctxt   x0, x1
> > > + get_vcpux1, x0
> > >   mov x0, #ARM_EXCEPTION_IRQ
> > >   b   __guest_exit
> > >  
> > >  el1_error:
> > >   stp x0, x1, [sp, #-16]!
> > > - ldr x1, [sp, #16 + 8]
> > > + get_host_ctxt   x0, x1
> > > + get_vcpux1, x0
> > 
> > Given how frequent this construct is, would there be a benefit in
> > having something like "get_vcpu_ptr" that conflates the two macros? We
> > don't seem to have a single case of using get_vcpu on its own.
> > 
> 
> I think my intention was to make it obvious how we get to the vcpu
> pointer, but looking at it now I don't think this adds anything, so I'm
> happy to adjust.  How about adding a get_vcpu_ptr macro which calls the
> other two macros?
>

Do we really need three macros, if get_vcpu is never used independently?
In the first round of reviews I suggested redefining get_vcpu like this

"""
 .macro get_vcpu vcpu, tmp
 get_host_ctxt \tmp, \vcpu
 ldr \vcpu, [\tmp, #HOST_CONTEXT_VCPU]
 kern_hyp_va \vcpu
 .endm

 which also has the side-effect of tmp being ctxt after the call.
"""

Thanks,
drew
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-22 Thread Marc Zyngier
On Thu, 22 Feb 2018 09:02:48 +,
Christoffer Dall wrote:
> 
> On Wed, Feb 21, 2018 at 11:34:07AM +, Marc Zyngier wrote:
> > On Thu, 15 Feb 2018 21:02:55 +,
> > Christoffer Dall wrote:
> > > 
> > > We already have the percpu area for the host cpu state, which points to
> > > the VCPU, so there's no need to store the VCPU pointer on the stack on
> > > every context switch.  We can be a little more clever and just use
> > > tpidr_el2 for the percpu offset and load the VCPU pointer from the host
> > > context.
> > > 
> > > This does require us to calculate the percpu offset without including
> > > the offset from the kernel mapping of the percpu array to the linear
> > > mapping of the array (which is what we store in tpidr_el1), because a
> > > PC-relative generated address in EL2 is already giving us the hyp alias
> > > of the linear mapping of a kernel address.  We do this in
> > > __cpu_init_hyp_mode() by using kvm_ksym_ref().
> > > 
> > > This change also requires us to have a scratch register, so we take the
> > > chance to rearrange some of the el1_sync code to only look at the
> > > vttbr_el2 to determine if this is a trap from the guest or an HVC from
> > > the host.  We do add an extra check to call the panic code if the kernel
> > > is configured with debugging enabled and we saw a trap from the host
> > > which wasn't an HVC, indicating that we left some EL2 trap configured by
> > > mistake.
> > > 
> > > The code that accesses ESR_EL2 was previously using an alternative to
> > > use the _EL1 accessor on VHE systems, but this was actually unnecessary
> > > as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
> > > accessor does the same thing on both systems.
> > > 
> > > Cc: Ard Biesheuvel 
> > > Signed-off-by: Christoffer Dall 
> > > ---
> > > 
> > > Notes:
> > > Changes since v3:
> > >  - Reworked the assembly part of the patch after rebasing on v4.16-rc1
> > >which created a conflict with the variant 2 mitigations.
> > >  - Removed Marc's reviewed-by due to the rework.
> > >  - Removed unneeded extern keyword in declaration in header file
> > > 
> > > Changes since v1:
> > >  - Use PC-relative addressing to access per-cpu variables instead of
> > >using a load from the literal pool.
> > >  - Remove stale comments as pointed out by Marc
> > >  - Reworded the commit message as suggested by Drew
> > > 
> > >  arch/arm64/include/asm/kvm_asm.h  | 14 ++
> > >  arch/arm64/include/asm/kvm_host.h | 15 +++
> > >  arch/arm64/kernel/asm-offsets.c   |  1 +
> > >  arch/arm64/kvm/hyp/entry.S|  6 +-
> > >  arch/arm64/kvm/hyp/hyp-entry.S| 31 +--
> > >  arch/arm64/kvm/hyp/switch.c   |  5 +
> > >  arch/arm64/kvm/hyp/sysreg-sr.c|  5 +
> > >  7 files changed, 50 insertions(+), 27 deletions(-)
> > > 
> > > diff --git a/arch/arm64/include/asm/kvm_asm.h 
> > > b/arch/arm64/include/asm/kvm_asm.h
> > > index 24961b732e65..6b626750b0a1 100644
> > > --- a/arch/arm64/include/asm/kvm_asm.h
> > > +++ b/arch/arm64/include/asm/kvm_asm.h
> > > @@ -33,6 +33,7 @@
> > >  #define KVM_ARM64_DEBUG_DIRTY_SHIFT  0
> > >  #define KVM_ARM64_DEBUG_DIRTY(1 << 
> > > KVM_ARM64_DEBUG_DIRTY_SHIFT)
> > >  
> > > +/* Translate a kernel address of @sym into its equivalent linear mapping 
> > > */
> > >  #define kvm_ksym_ref(sym)
> > > \
> > >   ({  \
> > >   void *val =\
> > > @@ -70,6 +71,19 @@ extern u32 __init_stage2_translation(void);
> > >  
> > >  extern void __qcom_hyp_sanitize_btac_predictors(void);
> > >  
> > > +#else /* __ASSEMBLY__ */
> > > +
> > > +.macro get_host_ctxt reg, tmp
> > > + adr_l   \reg, kvm_host_cpu_state
> > > + mrs \tmp, tpidr_el2
> > > + add \reg, \reg, \tmp
> > > +.endm
> > > +
> > > +.macro get_vcpu vcpu, ctxt
> > > + ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
> > > + kern_hyp_va \vcpu
> > > +.endm
> > > +
> > >  #endif
> > >  
> > >  #endif /* __ARM_KVM_ASM_H__ */
> > > diff --git a/arch/arm64/include/asm/kvm_host.h 
> > > b/arch/arm64/include/asm/kvm_host.h
> > > index 596f8e414a4c..618cfee7206a 100644
> > > --- a/arch/arm64/include/asm/kvm_host.h
> > > +++ b/arch/arm64/include/asm/kvm_host.h
> > > @@ -358,10 +358,15 @@ int kvm_perf_teardown(void);
> > >  
> > >  struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
> > >  
> > > +void __kvm_set_tpidr_el2(u64 tpidr_el2);
> > > +DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
> > > +
> > >  static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
> > >  unsigned long hyp_stack_ptr,
> > >  unsigned long vector_ptr)
> > >  {
> > > + u64 tpidr_el2;
> > > +
> > >   /*
> > >

Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-22 Thread Christoffer Dall
On Wed, Feb 21, 2018 at 06:32:00PM +0100, Andrew Jones wrote:
> On Thu, Feb 15, 2018 at 10:02:55PM +0100, Christoffer Dall wrote:
> > We already have the percpu area for the host cpu state, which points to
> > the VCPU, so there's no need to store the VCPU pointer on the stack on
> > every context switch.  We can be a little more clever and just use
> > tpidr_el2 for the percpu offset and load the VCPU pointer from the host
> > context.
> > 
> > This does require us to calculate the percpu offset without including
> > the offset from the kernel mapping of the percpu array to the linear
> > mapping of the array (which is what we store in tpidr_el1), because a
> > PC-relative generated address in EL2 is already giving us the hyp alias
> > of the linear mapping of a kernel address.  We do this in
> > __cpu_init_hyp_mode() by using kvm_ksym_ref().
> > 
> > This change also requires us to have a scratch register, so we take the
> > chance to rearrange some of the el1_sync code to only look at the
> > vttbr_el2 to determine if this is a trap from the guest or an HVC from
> > the host.  We do add an extra check to call the panic code if the kernel
> > is configured with debugging enabled and we saw a trap from the host
> > which wasn't an HVC, indicating that we left some EL2 trap configured by
> > mistake.
> > 
> > The code that accesses ESR_EL2 was previously using an alternative to
> > use the _EL1 accessor on VHE systems, but this was actually unnecessary
> > as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
> > accessor does the same thing on both systems.
> > 
> > Cc: Ard Biesheuvel 
> > Signed-off-by: Christoffer Dall 
> > ---
> > 
> > Notes:
> > Changes since v3:
> >  - Reworked the assembly part of the patch after rebasing on v4.16-rc1
> >which created a conflict with the variant 2 mitigations.
> >  - Removed Marc's reviewed-by due to the rework.
> >  - Removed unneeded extern keyword in declaration in header file
> > 
> > Changes since v1:
> >  - Use PC-relative addressing to access per-cpu variables instead of
> >using a load from the literal pool.
> >  - Remove stale comments as pointed out by Marc
> >  - Reworded the commit message as suggested by Drew
> > 
> >  arch/arm64/include/asm/kvm_asm.h  | 14 ++
> >  arch/arm64/include/asm/kvm_host.h | 15 +++
> >  arch/arm64/kernel/asm-offsets.c   |  1 +
> >  arch/arm64/kvm/hyp/entry.S|  6 +-
> >  arch/arm64/kvm/hyp/hyp-entry.S| 31 +--
> >  arch/arm64/kvm/hyp/switch.c   |  5 +
> >  arch/arm64/kvm/hyp/sysreg-sr.c|  5 +
> >  7 files changed, 50 insertions(+), 27 deletions(-)
> > 
> 
> I'm not clear on the motivation for this patch. I assumed it enabled
> simpler patches later in the series, but I did a bit of reading ahead
> and didn't see anything obvious. I doubt it gives a speedup, so is it
> just to avoid stack use? Making it easier to maintain these assembly
> functions that span a couple files? If so, should it be posted separately
> from this series? If not, could you please add some more text to the
> commit message helping me better understand the full motivation?

In the past we've had difficulties debugging things where we messed up
the stack because we couldn't get back to the normal world with no
reliable way to get the vcpu pointer.  That was the rationale for
storing the vcpu in a register as opposed to on the stack before.

We only recently changed that so that we could use tpidr_el2 to access
per-CPU variables.  Given that the vcpu pointer can already be found via
per-CPU variables, it makes sense to do that.

In terms of performance, your argument can be applied in isolation to
most patches in this series, and that was the initial approach I took in
the optimization work, only optimizing things that appeared significant
and would likely result in significant changes.  The results were
disappointing.  It was only when I included every micro-optimization for
the critical path that I could think of, that we were able to observe
order of magnitude improvements for some workloads.  Subsequent
measurements confirmed this, it was hard to measure individual benefits
from each patch, but overall the changes matter.

> 
> Besides my confusion on motivation, it looks good to me
> 

In that case, unless there's an argument that the code has become too
hard to understand, ...

> Reviewed-by: Andrew Jones 
> 
...then thanks!
-Christoffer
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-22 Thread Christoffer Dall
On Wed, Feb 21, 2018 at 11:34:07AM +, Marc Zyngier wrote:
> On Thu, 15 Feb 2018 21:02:55 +,
> Christoffer Dall wrote:
> > 
> > We already have the percpu area for the host cpu state, which points to
> > the VCPU, so there's no need to store the VCPU pointer on the stack on
> > every context switch.  We can be a little more clever and just use
> > tpidr_el2 for the percpu offset and load the VCPU pointer from the host
> > context.
> > 
> > This does require us to calculate the percpu offset without including
> > the offset from the kernel mapping of the percpu array to the linear
> > mapping of the array (which is what we store in tpidr_el1), because a
> > PC-relative generated address in EL2 is already giving us the hyp alias
> > of the linear mapping of a kernel address.  We do this in
> > __cpu_init_hyp_mode() by using kvm_ksym_ref().
> > 
> > This change also requires us to have a scratch register, so we take the
> > chance to rearrange some of the el1_sync code to only look at the
> > vttbr_el2 to determine if this is a trap from the guest or an HVC from
> > the host.  We do add an extra check to call the panic code if the kernel
> > is configured with debugging enabled and we saw a trap from the host
> > which wasn't an HVC, indicating that we left some EL2 trap configured by
> > mistake.
> > 
> > The code that accesses ESR_EL2 was previously using an alternative to
> > use the _EL1 accessor on VHE systems, but this was actually unnecessary
> > as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
> > accessor does the same thing on both systems.
> > 
> > Cc: Ard Biesheuvel 
> > Signed-off-by: Christoffer Dall 
> > ---
> > 
> > Notes:
> > Changes since v3:
> >  - Reworked the assembly part of the patch after rebasing on v4.16-rc1
> >which created a conflict with the variant 2 mitigations.
> >  - Removed Marc's reviewed-by due to the rework.
> >  - Removed unneeded extern keyword in declaration in header file
> > 
> > Changes since v1:
> >  - Use PC-relative addressing to access per-cpu variables instead of
> >using a load from the literal pool.
> >  - Remove stale comments as pointed out by Marc
> >  - Reworded the commit message as suggested by Drew
> > 
> >  arch/arm64/include/asm/kvm_asm.h  | 14 ++
> >  arch/arm64/include/asm/kvm_host.h | 15 +++
> >  arch/arm64/kernel/asm-offsets.c   |  1 +
> >  arch/arm64/kvm/hyp/entry.S|  6 +-
> >  arch/arm64/kvm/hyp/hyp-entry.S| 31 +--
> >  arch/arm64/kvm/hyp/switch.c   |  5 +
> >  arch/arm64/kvm/hyp/sysreg-sr.c|  5 +
> >  7 files changed, 50 insertions(+), 27 deletions(-)
> > 
> > diff --git a/arch/arm64/include/asm/kvm_asm.h 
> > b/arch/arm64/include/asm/kvm_asm.h
> > index 24961b732e65..6b626750b0a1 100644
> > --- a/arch/arm64/include/asm/kvm_asm.h
> > +++ b/arch/arm64/include/asm/kvm_asm.h
> > @@ -33,6 +33,7 @@
> >  #define KVM_ARM64_DEBUG_DIRTY_SHIFT0
> >  #define KVM_ARM64_DEBUG_DIRTY  (1 << 
> > KVM_ARM64_DEBUG_DIRTY_SHIFT)
> >  
> > +/* Translate a kernel address of @sym into its equivalent linear mapping */
> >  #define kvm_ksym_ref(sym)  \
> > ({  \
> > void *val =\
> > @@ -70,6 +71,19 @@ extern u32 __init_stage2_translation(void);
> >  
> >  extern void __qcom_hyp_sanitize_btac_predictors(void);
> >  
> > +#else /* __ASSEMBLY__ */
> > +
> > +.macro get_host_ctxt reg, tmp
> > +   adr_l   \reg, kvm_host_cpu_state
> > +   mrs \tmp, tpidr_el2
> > +   add \reg, \reg, \tmp
> > +.endm
> > +
> > +.macro get_vcpu vcpu, ctxt
> > +   ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
> > +   kern_hyp_va \vcpu
> > +.endm
> > +
> >  #endif
> >  
> >  #endif /* __ARM_KVM_ASM_H__ */
> > diff --git a/arch/arm64/include/asm/kvm_host.h 
> > b/arch/arm64/include/asm/kvm_host.h
> > index 596f8e414a4c..618cfee7206a 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -358,10 +358,15 @@ int kvm_perf_teardown(void);
> >  
> >  struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
> >  
> > +void __kvm_set_tpidr_el2(u64 tpidr_el2);
> > +DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
> > +
> >  static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
> >unsigned long hyp_stack_ptr,
> >unsigned long vector_ptr)
> >  {
> > +   u64 tpidr_el2;
> > +
> > /*
> >  * Call initialization code, and switch to the full blown HYP code.
> >  * If the cpucaps haven't been finalized yet, something has gone very
> > @@ -370,6 +375,16 @@ static inline void __cpu_init_hyp_mode(phys_addr_t 
> > pgd_ptr,
> >  */
> > 

Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-22 Thread Christoffer Dall
On Mon, Feb 19, 2018 at 03:50:20PM +, Julien Grall wrote:
> Hi Christoffer,
> 
> On 15/02/18 21:02, Christoffer Dall wrote:
> >We already have the percpu area for the host cpu state, which points to
> >the VCPU, so there's no need to store the VCPU pointer on the stack on
> >every context switch.  We can be a little more clever and just use
> >tpidr_el2 for the percpu offset and load the VCPU pointer from the host
> >context.
> >
> >This does require us to calculate the percpu offset without including
> >the offset from the kernel mapping of the percpu array to the linear
> >mapping of the array (which is what we store in tpidr_el1), because a
> >PC-relative generated address in EL2 is already giving us the hyp alias
> >of the linear mapping of a kernel address.  We do this in
> >__cpu_init_hyp_mode() by using kvm_ksym_ref().
> >
> >This change also requires us to have a scratch register, so we take the
> >chance to rearrange some of the el1_sync code to only look at the
> >vttbr_el2 to determine if this is a trap from the guest or an HVC from
> >the host.  We do add an extra check to call the panic code if the kernel
> >is configured with debugging enabled and we saw a trap from the host
> >which wasn't an HVC, indicating that we left some EL2 trap configured by
> >mistake.
> 
> You might want to remove this paragraph as you don't seem to have rework
> that part of the code in this version.
> 
Yes, will do.

Thanks,
-Christoffer
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-21 Thread Andrew Jones
On Thu, Feb 15, 2018 at 10:02:55PM +0100, Christoffer Dall wrote:
> We already have the percpu area for the host cpu state, which points to
> the VCPU, so there's no need to store the VCPU pointer on the stack on
> every context switch.  We can be a little more clever and just use
> tpidr_el2 for the percpu offset and load the VCPU pointer from the host
> context.
> 
> This does require us to calculate the percpu offset without including
> the offset from the kernel mapping of the percpu array to the linear
> mapping of the array (which is what we store in tpidr_el1), because a
> PC-relative generated address in EL2 is already giving us the hyp alias
> of the linear mapping of a kernel address.  We do this in
> __cpu_init_hyp_mode() by using kvm_ksym_ref().
> 
> This change also requires us to have a scratch register, so we take the
> chance to rearrange some of the el1_sync code to only look at the
> vttbr_el2 to determine if this is a trap from the guest or an HVC from
> the host.  We do add an extra check to call the panic code if the kernel
> is configured with debugging enabled and we saw a trap from the host
> which wasn't an HVC, indicating that we left some EL2 trap configured by
> mistake.
> 
> The code that accesses ESR_EL2 was previously using an alternative to
> use the _EL1 accessor on VHE systems, but this was actually unnecessary
> as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
> accessor does the same thing on both systems.
> 
> Cc: Ard Biesheuvel 
> Signed-off-by: Christoffer Dall 
> ---
> 
> Notes:
> Changes since v3:
>  - Reworked the assembly part of the patch after rebasing on v4.16-rc1
>which created a conflict with the variant 2 mitigations.
>  - Removed Marc's reviewed-by due to the rework.
>  - Removed unneeded extern keyword in declaration in header file
> 
> Changes since v1:
>  - Use PC-relative addressing to access per-cpu variables instead of
>using a load from the literal pool.
>  - Remove stale comments as pointed out by Marc
>  - Reworded the commit message as suggested by Drew
> 
>  arch/arm64/include/asm/kvm_asm.h  | 14 ++
>  arch/arm64/include/asm/kvm_host.h | 15 +++
>  arch/arm64/kernel/asm-offsets.c   |  1 +
>  arch/arm64/kvm/hyp/entry.S|  6 +-
>  arch/arm64/kvm/hyp/hyp-entry.S| 31 +--
>  arch/arm64/kvm/hyp/switch.c   |  5 +
>  arch/arm64/kvm/hyp/sysreg-sr.c|  5 +
>  7 files changed, 50 insertions(+), 27 deletions(-)
> 

I'm not clear on the motivation for this patch. I assumed it enabled
simpler patches later in the series, but I did a bit of reading ahead
and didn't see anything obvious. I doubt it gives a speedup, so is it
just to avoid stack use? Making it easier to maintain these assembly
functions that span a couple files? If so, should it be posted separately
from this series? If not, could you please add some more text to the
commit message helping me better understand the full motivation?

Besides my confusion on motivation, it looks good to me

Reviewed-by: Andrew Jones 

Thanks,
drew
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-21 Thread Marc Zyngier
On Thu, 15 Feb 2018 21:02:55 +,
Christoffer Dall wrote:
> 
> We already have the percpu area for the host cpu state, which points to
> the VCPU, so there's no need to store the VCPU pointer on the stack on
> every context switch.  We can be a little more clever and just use
> tpidr_el2 for the percpu offset and load the VCPU pointer from the host
> context.
> 
> This does require us to calculate the percpu offset without including
> the offset from the kernel mapping of the percpu array to the linear
> mapping of the array (which is what we store in tpidr_el1), because a
> PC-relative generated address in EL2 is already giving us the hyp alias
> of the linear mapping of a kernel address.  We do this in
> __cpu_init_hyp_mode() by using kvm_ksym_ref().
> 
> This change also requires us to have a scratch register, so we take the
> chance to rearrange some of the el1_sync code to only look at the
> vttbr_el2 to determine if this is a trap from the guest or an HVC from
> the host.  We do add an extra check to call the panic code if the kernel
> is configured with debugging enabled and we saw a trap from the host
> which wasn't an HVC, indicating that we left some EL2 trap configured by
> mistake.
> 
> The code that accesses ESR_EL2 was previously using an alternative to
> use the _EL1 accessor on VHE systems, but this was actually unnecessary
> as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
> accessor does the same thing on both systems.
> 
> Cc: Ard Biesheuvel 
> Signed-off-by: Christoffer Dall 
> ---
> 
> Notes:
> Changes since v3:
>  - Reworked the assembly part of the patch after rebasing on v4.16-rc1
>which created a conflict with the variant 2 mitigations.
>  - Removed Marc's reviewed-by due to the rework.
>  - Removed unneeded extern keyword in declaration in header file
> 
> Changes since v1:
>  - Use PC-relative addressing to access per-cpu variables instead of
>using a load from the literal pool.
>  - Remove stale comments as pointed out by Marc
>  - Reworded the commit message as suggested by Drew
> 
>  arch/arm64/include/asm/kvm_asm.h  | 14 ++
>  arch/arm64/include/asm/kvm_host.h | 15 +++
>  arch/arm64/kernel/asm-offsets.c   |  1 +
>  arch/arm64/kvm/hyp/entry.S|  6 +-
>  arch/arm64/kvm/hyp/hyp-entry.S| 31 +--
>  arch/arm64/kvm/hyp/switch.c   |  5 +
>  arch/arm64/kvm/hyp/sysreg-sr.c|  5 +
>  7 files changed, 50 insertions(+), 27 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_asm.h 
> b/arch/arm64/include/asm/kvm_asm.h
> index 24961b732e65..6b626750b0a1 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -33,6 +33,7 @@
>  #define KVM_ARM64_DEBUG_DIRTY_SHIFT  0
>  #define KVM_ARM64_DEBUG_DIRTY(1 << 
> KVM_ARM64_DEBUG_DIRTY_SHIFT)
>  
> +/* Translate a kernel address of @sym into its equivalent linear mapping */
>  #define kvm_ksym_ref(sym)\
>   ({  \
>   void *val =\
> @@ -70,6 +71,19 @@ extern u32 __init_stage2_translation(void);
>  
>  extern void __qcom_hyp_sanitize_btac_predictors(void);
>  
> +#else /* __ASSEMBLY__ */
> +
> +.macro get_host_ctxt reg, tmp
> + adr_l   \reg, kvm_host_cpu_state
> + mrs \tmp, tpidr_el2
> + add \reg, \reg, \tmp
> +.endm
> +
> +.macro get_vcpu vcpu, ctxt
> + ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
> + kern_hyp_va \vcpu
> +.endm
> +
>  #endif
>  
>  #endif /* __ARM_KVM_ASM_H__ */
> diff --git a/arch/arm64/include/asm/kvm_host.h 
> b/arch/arm64/include/asm/kvm_host.h
> index 596f8e414a4c..618cfee7206a 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -358,10 +358,15 @@ int kvm_perf_teardown(void);
>  
>  struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
>  
> +void __kvm_set_tpidr_el2(u64 tpidr_el2);
> +DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
> +
>  static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
>  unsigned long hyp_stack_ptr,
>  unsigned long vector_ptr)
>  {
> + u64 tpidr_el2;
> +
>   /*
>* Call initialization code, and switch to the full blown HYP code.
>* If the cpucaps haven't been finalized yet, something has gone very
> @@ -370,6 +375,16 @@ static inline void __cpu_init_hyp_mode(phys_addr_t 
> pgd_ptr,
>*/
>   BUG_ON(!static_branch_likely(_const_caps_ready));
>   __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
> +
> + /*
> +  * Calculate the raw per-cpu offset without a translation from the
> +  * kernel's mapping to the linear mapping, and store it in 

Re: [PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-19 Thread Julien Grall

Hi Christoffer,

On 15/02/18 21:02, Christoffer Dall wrote:

We already have the percpu area for the host cpu state, which points to
the VCPU, so there's no need to store the VCPU pointer on the stack on
every context switch.  We can be a little more clever and just use
tpidr_el2 for the percpu offset and load the VCPU pointer from the host
context.

This does require us to calculate the percpu offset without including
the offset from the kernel mapping of the percpu array to the linear
mapping of the array (which is what we store in tpidr_el1), because a
PC-relative generated address in EL2 is already giving us the hyp alias
of the linear mapping of a kernel address.  We do this in
__cpu_init_hyp_mode() by using kvm_ksym_ref().

This change also requires us to have a scratch register, so we take the
chance to rearrange some of the el1_sync code to only look at the
vttbr_el2 to determine if this is a trap from the guest or an HVC from
the host.  We do add an extra check to call the panic code if the kernel
is configured with debugging enabled and we saw a trap from the host
which wasn't an HVC, indicating that we left some EL2 trap configured by
mistake.


You might want to remove this paragraph as you don't seem to have rework 
that part of the code in this version.


Cheers,

--
Julien Grall
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v4 03/40] KVM: arm64: Avoid storing the vcpu pointer on the stack

2018-02-15 Thread Christoffer Dall
We already have the percpu area for the host cpu state, which points to
the VCPU, so there's no need to store the VCPU pointer on the stack on
every context switch.  We can be a little more clever and just use
tpidr_el2 for the percpu offset and load the VCPU pointer from the host
context.

This does require us to calculate the percpu offset without including
the offset from the kernel mapping of the percpu array to the linear
mapping of the array (which is what we store in tpidr_el1), because a
PC-relative generated address in EL2 is already giving us the hyp alias
of the linear mapping of a kernel address.  We do this in
__cpu_init_hyp_mode() by using kvm_ksym_ref().

This change also requires us to have a scratch register, so we take the
chance to rearrange some of the el1_sync code to only look at the
vttbr_el2 to determine if this is a trap from the guest or an HVC from
the host.  We do add an extra check to call the panic code if the kernel
is configured with debugging enabled and we saw a trap from the host
which wasn't an HVC, indicating that we left some EL2 trap configured by
mistake.

The code that accesses ESR_EL2 was previously using an alternative to
use the _EL1 accessor on VHE systems, but this was actually unnecessary
as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
accessor does the same thing on both systems.

Cc: Ard Biesheuvel 
Signed-off-by: Christoffer Dall 
---

Notes:
Changes since v3:
 - Reworked the assembly part of the patch after rebasing on v4.16-rc1
   which created a conflict with the variant 2 mitigations.
 - Removed Marc's reviewed-by due to the rework.
 - Removed unneeded extern keyword in declaration in header file

Changes since v1:
 - Use PC-relative addressing to access per-cpu variables instead of
   using a load from the literal pool.
 - Remove stale comments as pointed out by Marc
 - Reworded the commit message as suggested by Drew

 arch/arm64/include/asm/kvm_asm.h  | 14 ++
 arch/arm64/include/asm/kvm_host.h | 15 +++
 arch/arm64/kernel/asm-offsets.c   |  1 +
 arch/arm64/kvm/hyp/entry.S|  6 +-
 arch/arm64/kvm/hyp/hyp-entry.S| 31 +--
 arch/arm64/kvm/hyp/switch.c   |  5 +
 arch/arm64/kvm/hyp/sysreg-sr.c|  5 +
 7 files changed, 50 insertions(+), 27 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 24961b732e65..6b626750b0a1 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -33,6 +33,7 @@
 #define KVM_ARM64_DEBUG_DIRTY_SHIFT0
 #define KVM_ARM64_DEBUG_DIRTY  (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
 
+/* Translate a kernel address of @sym into its equivalent linear mapping */
 #define kvm_ksym_ref(sym)  \
({  \
void *val =\
@@ -70,6 +71,19 @@ extern u32 __init_stage2_translation(void);
 
 extern void __qcom_hyp_sanitize_btac_predictors(void);
 
+#else /* __ASSEMBLY__ */
+
+.macro get_host_ctxt reg, tmp
+   adr_l   \reg, kvm_host_cpu_state
+   mrs \tmp, tpidr_el2
+   add \reg, \reg, \tmp
+.endm
+
+.macro get_vcpu vcpu, ctxt
+   ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
+   kern_hyp_va \vcpu
+.endm
+
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 596f8e414a4c..618cfee7206a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -358,10 +358,15 @@ int kvm_perf_teardown(void);
 
 struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 
+void __kvm_set_tpidr_el2(u64 tpidr_el2);
+DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
+
 static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
   unsigned long hyp_stack_ptr,
   unsigned long vector_ptr)
 {
+   u64 tpidr_el2;
+
/*
 * Call initialization code, and switch to the full blown HYP code.
 * If the cpucaps haven't been finalized yet, something has gone very
@@ -370,6 +375,16 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
 */
BUG_ON(!static_branch_likely(_const_caps_ready));
__kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
+
+   /*
+* Calculate the raw per-cpu offset without a translation from the
+* kernel's mapping to the linear mapping, and store it in tpidr_el2
+* so that we can use adr_l to access per-cpu variables in EL2.
+*/
+   tpidr_el2 = (u64)this_cpu_ptr(_host_cpu_state)
+   - (u64)kvm_ksym_ref(kvm_host_cpu_state);
+
+   kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2);
 }