diff options
Diffstat (limited to 'arch/arm/kvm/reset.c')
-rw-r--r-- | arch/arm/kvm/reset.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c index 5ed0c3ee33d6..e53327912adc 100644 --- a/arch/arm/kvm/reset.c +++ b/arch/arm/kvm/reset.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/cputype.h> | 26 | #include <asm/cputype.h> |
27 | #include <asm/kvm_arm.h> | 27 | #include <asm/kvm_arm.h> |
28 | #include <asm/kvm_coproc.h> | 28 | #include <asm/kvm_coproc.h> |
29 | #include <asm/kvm_emulate.h> | ||
29 | 30 | ||
30 | #include <kvm/arm_arch_timer.h> | 31 | #include <kvm/arm_arch_timer.h> |
31 | 32 | ||
@@ -69,6 +70,29 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) | |||
69 | /* Reset CP15 registers */ | 70 | /* Reset CP15 registers */ |
70 | kvm_reset_coprocs(vcpu); | 71 | kvm_reset_coprocs(vcpu); |
71 | 72 | ||
73 | /* | ||
74 | * Additional reset state handling that PSCI may have imposed on us. | ||
75 | * Must be done after all the sys_reg reset. | ||
76 | */ | ||
77 | if (READ_ONCE(vcpu->arch.reset_state.reset)) { | ||
78 | unsigned long target_pc = vcpu->arch.reset_state.pc; | ||
79 | |||
80 | /* Gracefully handle Thumb2 entry point */ | ||
81 | if (target_pc & 1) { | ||
82 | target_pc &= ~1UL; | ||
83 | vcpu_set_thumb(vcpu); | ||
84 | } | ||
85 | |||
86 | /* Propagate caller endianness */ | ||
87 | if (vcpu->arch.reset_state.be) | ||
88 | kvm_vcpu_set_be(vcpu); | ||
89 | |||
90 | *vcpu_pc(vcpu) = target_pc; | ||
91 | vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0); | ||
92 | |||
93 | vcpu->arch.reset_state.reset = false; | ||
94 | } | ||
95 | |||
72 | /* Reset arch_timer context */ | 96 | /* Reset arch_timer context */ |
73 | return kvm_timer_vcpu_reset(vcpu); | 97 | return kvm_timer_vcpu_reset(vcpu); |
74 | } | 98 | } |