On Thu, Feb 15, 2018 at 10:03:21PM +0100, Christoffer Dall wrote:
> 32-bit registers are not used by a 64-bit host kernel and can be
> deferred, but we need to rework the accesses to this register to access

these registers

> the latest value depending on whether or not guest system registers are

values

> loaded on the CPU or only reside in memory.
> 
> Signed-off-by: Christoffer Dall <christoffer.d...@linaro.org>
> ---
> 
> Notes:
>     Changes since v3:
>      - Don't also try to write hardware spsr when sysregs are not loaded
>      - Adapted patch to use switch-based sysreg save/restore approach
>      - (Kept additional BUG_ON() in vcpu_read_spsr32() to keep the compiler 
> happy)
>     
>     Changes since v2:
>      - New patch (deferred register handling has been reworked)
> 
>  arch/arm64/include/asm/kvm_emulate.h | 32 +++++------------
>  arch/arm64/kvm/regmap.c              | 67 
> +++++++++++++++++++++++++++---------
>  arch/arm64/kvm/sys_regs.c            |  6 ++++
>  3 files changed, 65 insertions(+), 40 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_emulate.h 
> b/arch/arm64/include/asm/kvm_emulate.h
> index 9cb13b23c7a1..23b33e8ea03a 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -33,7 +33,8 @@
>  #include <asm/virt.h>
>  
>  unsigned long *vcpu_reg32(const struct kvm_vcpu *vcpu, u8 reg_num);
> -unsigned long *vcpu_spsr32(const struct kvm_vcpu *vcpu);
> +unsigned long vcpu_read_spsr32(const struct kvm_vcpu *vcpu);
> +void vcpu_write_spsr32(struct kvm_vcpu *vcpu, unsigned long v);
>  
>  bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
>  void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
> @@ -162,41 +163,26 @@ static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, 
> u8 reg_num,
>  
>  static inline unsigned long vcpu_read_spsr(const struct kvm_vcpu *vcpu)
>  {
> -     unsigned long *p = (unsigned long 
> *)&vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1];
> -
> -     if (vcpu_mode_is_32bit(vcpu)) {
> -             unsigned long *p_32bit = vcpu_spsr32(vcpu);
> -
> -             /* KVM_SPSR_SVC aliases KVM_SPSR_EL1 */
> -             if (p_32bit != (unsigned long *)p)
> -                     return *p_32bit;
> -     }
> +     if (vcpu_mode_is_32bit(vcpu))
> +             return vcpu_read_spsr32(vcpu);
>  
>       if (vcpu->arch.sysregs_loaded_on_cpu)
>               return read_sysreg_el1(spsr);
>       else
> -             return *p;
> +             return vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1];
>  }
>  
> -static inline void vcpu_write_spsr(const struct kvm_vcpu *vcpu, unsigned 
> long v)
> +static inline void vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long v)
>  {
> -     unsigned long *p = (unsigned long 
> *)&vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1];
> -
> -     /* KVM_SPSR_SVC aliases KVM_SPSR_EL1 */
>       if (vcpu_mode_is_32bit(vcpu)) {
> -             unsigned long *p_32bit = vcpu_spsr32(vcpu);
> -
> -             /* KVM_SPSR_SVC aliases KVM_SPSR_EL1 */
> -             if (p_32bit != (unsigned long *)p) {
> -                     *p_32bit = v;
> -                     return;
> -             }
> +             vcpu_write_spsr32(vcpu, v);
> +             return;
>       }
>  
>       if (vcpu->arch.sysregs_loaded_on_cpu)
>               write_sysreg_el1(v, spsr);
>       else
> -             *p = v;
> +             vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1] = v;
>  }
>  
>  static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
> diff --git a/arch/arm64/kvm/regmap.c b/arch/arm64/kvm/regmap.c
> index bbc6ae32e4af..eefe403a2e63 100644
> --- a/arch/arm64/kvm/regmap.c
> +++ b/arch/arm64/kvm/regmap.c
> @@ -141,28 +141,61 @@ unsigned long *vcpu_reg32(const struct kvm_vcpu *vcpu, 
> u8 reg_num)
>  /*
>   * Return the SPSR for the current mode of the virtual CPU.
>   */
> -unsigned long *vcpu_spsr32(const struct kvm_vcpu *vcpu)
> +static int vcpu_spsr32_mode(const struct kvm_vcpu *vcpu)
>  {
>       unsigned long mode = *vcpu_cpsr(vcpu) & COMPAT_PSR_MODE_MASK;
>       switch (mode) {
> -     case COMPAT_PSR_MODE_SVC:
> -             mode = KVM_SPSR_SVC;
> -             break;
> -     case COMPAT_PSR_MODE_ABT:
> -             mode = KVM_SPSR_ABT;
> -             break;
> -     case COMPAT_PSR_MODE_UND:
> -             mode = KVM_SPSR_UND;
> -             break;
> -     case COMPAT_PSR_MODE_IRQ:
> -             mode = KVM_SPSR_IRQ;
> -             break;
> -     case COMPAT_PSR_MODE_FIQ:
> -             mode = KVM_SPSR_FIQ;
> -             break;
> +     case COMPAT_PSR_MODE_SVC: return KVM_SPSR_SVC;
> +     case COMPAT_PSR_MODE_ABT: return KVM_SPSR_ABT;
> +     case COMPAT_PSR_MODE_UND: return KVM_SPSR_UND;
> +     case COMPAT_PSR_MODE_IRQ: return KVM_SPSR_IRQ;
> +     case COMPAT_PSR_MODE_FIQ: return KVM_SPSR_FIQ;
> +     default: BUG();
> +     }
> +}
> +
> +unsigned long vcpu_read_spsr32(const struct kvm_vcpu *vcpu)
> +{
> +     int spsr_idx = vcpu_spsr32_mode(vcpu);
> +
> +     if (!vcpu->arch.sysregs_loaded_on_cpu)
> +             return vcpu_gp_regs(vcpu)->spsr[spsr_idx];
> +
> +     switch (spsr_idx) {
> +     case KVM_SPSR_SVC:
> +             return read_sysreg_el1(spsr);
> +     case KVM_SPSR_ABT:
> +             return read_sysreg(spsr_abt);
> +     case KVM_SPSR_UND:
> +             return read_sysreg(spsr_und);
> +     case KVM_SPSR_IRQ:
> +             return read_sysreg(spsr_irq);
> +     case KVM_SPSR_FIQ:
> +             return read_sysreg(spsr_fiq);
>       default:
>               BUG();
>       }
> +}
> +
> +void vcpu_write_spsr32(struct kvm_vcpu *vcpu, unsigned long v)
> +{
> +     int spsr_idx = vcpu_spsr32_mode(vcpu);
> +
> +     if (!vcpu->arch.sysregs_loaded_on_cpu) {
> +             vcpu_gp_regs(vcpu)->spsr[spsr_idx] = v;
> +             return;
> +     }
>  
> -     return (unsigned long *)&vcpu_gp_regs(vcpu)->spsr[mode];
> +     switch (spsr_idx) {
> +     case KVM_SPSR_SVC:
> +             write_sysreg_el1(v, spsr);
> +     case KVM_SPSR_ABT:
> +             write_sysreg(v, spsr_abt);
> +     case KVM_SPSR_UND:
> +             write_sysreg(v, spsr_und);
> +     case KVM_SPSR_IRQ:
> +             write_sysreg(v, spsr_irq);
> +     case KVM_SPSR_FIQ:
> +             write_sysreg(v, spsr_fiq);
> +     }
>  }
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index f060309337aa..d2324560c9f5 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -107,6 +107,9 @@ u64 vcpu_read_sys_reg(struct kvm_vcpu *vcpu, int reg)
>       case AMAIR_EL1:         return read_sysreg_s(amair_EL12);
>       case CNTKCTL_EL1:       return read_sysreg_s(cntkctl_EL12);
>       case PAR_EL1:           return read_sysreg_s(SYS_PAR_EL1);
> +     case DACR32_EL2:        return read_sysreg_s(SYS_DACR32_EL2);
> +     case IFSR32_EL2:        return read_sysreg_s(SYS_IFSR32_EL2);
> +     case DBGVCR32_EL2:      return read_sysreg_s(SYS_DBGVCR32_EL2);
>       }
>  
>  immediate_read:
> @@ -143,6 +146,9 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, int reg, 
> u64 val)
>       case AMAIR_EL1:         write_sysreg_s(val, amair_EL12);        return;
>       case CNTKCTL_EL1:       write_sysreg_s(val, cntkctl_EL12);      return;
>       case PAR_EL1:           write_sysreg_s(val, SYS_PAR_EL1);       return;
> +     case DACR32_EL2:        write_sysreg_s(val, SYS_DACR32_EL2);    return;
> +     case IFSR32_EL2:        write_sysreg_s(val, SYS_IFSR32_EL2);    return;
> +     case DBGVCR32_EL2:      write_sysreg_s(val, SYS_DBGVCR32_EL2);  return;
>       }
>  
>  immediate_write:
> -- 
> 2.14.2
>

I think the last two hunks would fit better in the next patch. It's not a
huge deal, though. If they do get moved, then I guess the patch summary
and commit message should only focus on sprs32 - returning its grammar to
the singular case.

Reviewed-by: Andrew Jones <drjo...@redhat.com>

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

Reply via email to