arm/arm64: KVM: PSCI: propagate caller endianness to the incoming vcpu
authorMarc Zyngier <marc.zyngier@arm.com>
Tue, 5 Nov 2013 14:12:15 +0000 (14:12 +0000)
committerChristoffer Dall <christoffer.dall@linaro.org>
Thu, 2 Oct 2014 15:18:19 +0000 (17:18 +0200)
When booting a vcpu using PSCI, make sure we start it with the
endianness of the caller. Otherwise, secondaries can be pretty
unhappy to execute a BE kernel in LE mode...

This conforms to PSCI spec Rev B, 5.13.3.

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
(cherry picked from commit ce94fe93d566bf381c6ecbd45010d36c5f04d692)
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
arch/arm/include/asm/kvm_emulate.h
arch/arm/kvm/psci.c
arch/arm64/include/asm/kvm_emulate.h

index b79cd8d3d6eed1068ee5f2cc74b2d87eb8ce5842..0fa90c962ac831329df43a156c5b0583732099ac 100644 (file)
@@ -162,6 +162,11 @@ static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
        return vcpu->arch.cp15[c0_MPIDR];
 }
 
+static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
+{
+       *vcpu_cpsr(vcpu) |= PSR_E_BIT;
+}
+
 static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
 {
        return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT);
index 311263124acf303606b3081ae71fc0169e7f1dac..0881bf169fbce5cf09db6da3ff0996df6cf989cb 100644 (file)
@@ -71,6 +71,10 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
                vcpu_set_thumb(vcpu);
        }
 
+       /* Propagate caller endianness */
+       if (kvm_vcpu_is_be(source_vcpu))
+               kvm_vcpu_set_be(vcpu);
+
        *vcpu_pc(vcpu) = target_pc;
        vcpu->arch.pause = false;
        smp_mb();               /* Make sure the above is visible */
index 291f87cf457f04f76c478d2d855a2fb454a923ae..dd8ecfc3f9952fbf86e5d3dd69012ca9ab9a8385 100644 (file)
@@ -182,6 +182,14 @@ static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
        return vcpu_sys_reg(vcpu, MPIDR_EL1);
 }
 
+static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
+{
+       if (vcpu_mode_is_32bit(vcpu))
+               *vcpu_cpsr(vcpu) |= COMPAT_PSR_E_BIT;
+       else
+               vcpu_sys_reg(vcpu, SCTLR_EL1) |= (1 << 25);
+}
+
 static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
 {
        if (vcpu_mode_is_32bit(vcpu))