[PATCH v3 30/41] KVM: arm64: Prepare to handle deferred save/restore of 32-bit registers

Christoffer Dall christoffer.dall at linaro.org
Thu Jan 18 05:12:07 PST 2018


On Wed, Jan 17, 2018 at 06:22:29PM +0000, Julien Thierry wrote:
> Hi,
> 
> On 12/01/18 12:07, 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
> >the latest value depending on whether or not guest system registers are
> >loaded on the CPU or only reside in memory.
> >
> >Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Reviewed-by: Julien Thierry <julien.thierry at arm.com>
> 
> >---
> >  arch/arm64/include/asm/kvm_emulate.h | 32 +++++-------------
> >  arch/arm64/kvm/regmap.c              | 65 ++++++++++++++++++++++++++----------
> >  arch/arm64/kvm/sys_regs.c            |  6 ++--
> >  3 files changed, 60 insertions(+), 43 deletions(-)
> >
> 
> [...]
> 
> >diff --git a/arch/arm64/kvm/regmap.c b/arch/arm64/kvm/regmap.c
> >index bbc6ae32e4af..3f65098aff8d 100644
> >--- a/arch/arm64/kvm/regmap.c
> >+++ b/arch/arm64/kvm/regmap.c
> >@@ -141,28 +141,59 @@ 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();
> 
> Nit:
> 
> Since the BUG() is in vcpu_spsr32_mode now, you can probably remove it here
> (or add it to vcpu_write_sprsr32 for consistency).
> 
> >  	}

Yes, I'll remove it.

Thanks,
-Christoffer

> >+}
> >-	return (unsigned long *)&vcpu_gp_regs(vcpu)->spsr[mode];
> >+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;
> >+
> >+	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);
> >+	}
> >  }



More information about the linux-arm-kernel mailing list