diff options
Diffstat (limited to 'virt/kvm/arm/psci.c')
-rw-r--r-- | virt/kvm/arm/psci.c | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index 9b73d3ad918a..34d08ee63747 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c | |||
@@ -104,12 +104,10 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) | |||
104 | 104 | ||
105 | static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) | 105 | static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) |
106 | { | 106 | { |
107 | struct vcpu_reset_state *reset_state; | ||
107 | struct kvm *kvm = source_vcpu->kvm; | 108 | struct kvm *kvm = source_vcpu->kvm; |
108 | struct kvm_vcpu *vcpu = NULL; | 109 | struct kvm_vcpu *vcpu = NULL; |
109 | struct swait_queue_head *wq; | ||
110 | unsigned long cpu_id; | 110 | unsigned long cpu_id; |
111 | unsigned long context_id; | ||
112 | phys_addr_t target_pc; | ||
113 | 111 | ||
114 | cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK; | 112 | cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK; |
115 | if (vcpu_mode_is_32bit(source_vcpu)) | 113 | if (vcpu_mode_is_32bit(source_vcpu)) |
@@ -130,32 +128,30 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) | |||
130 | return PSCI_RET_INVALID_PARAMS; | 128 | return PSCI_RET_INVALID_PARAMS; |
131 | } | 129 | } |
132 | 130 | ||
133 | target_pc = smccc_get_arg2(source_vcpu); | 131 | reset_state = &vcpu->arch.reset_state; |
134 | context_id = smccc_get_arg3(source_vcpu); | ||
135 | 132 | ||
136 | kvm_reset_vcpu(vcpu); | 133 | reset_state->pc = smccc_get_arg2(source_vcpu); |
137 | |||
138 | /* Gracefully handle Thumb2 entry point */ | ||
139 | if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) { | ||
140 | target_pc &= ~((phys_addr_t) 1); | ||
141 | vcpu_set_thumb(vcpu); | ||
142 | } | ||
143 | 134 | ||
144 | /* Propagate caller endianness */ | 135 | /* Propagate caller endianness */ |
145 | if (kvm_vcpu_is_be(source_vcpu)) | 136 | reset_state->be = kvm_vcpu_is_be(source_vcpu); |
146 | kvm_vcpu_set_be(vcpu); | ||
147 | 137 | ||
148 | *vcpu_pc(vcpu) = target_pc; | ||
149 | /* | 138 | /* |
150 | * NOTE: We always update r0 (or x0) because for PSCI v0.1 | 139 | * NOTE: We always update r0 (or x0) because for PSCI v0.1 |
151 | * the general puspose registers are undefined upon CPU_ON. | 140 | * the general puspose registers are undefined upon CPU_ON. |
152 | */ | 141 | */ |
153 | smccc_set_retval(vcpu, context_id, 0, 0, 0); | 142 | reset_state->r0 = smccc_get_arg3(source_vcpu); |
154 | vcpu->arch.power_off = false; | 143 | |
155 | smp_mb(); /* Make sure the above is visible */ | 144 | WRITE_ONCE(reset_state->reset, true); |
145 | kvm_make_request(KVM_REQ_VCPU_RESET, vcpu); | ||
156 | 146 | ||
157 | wq = kvm_arch_vcpu_wq(vcpu); | 147 | /* |
158 | swake_up_one(wq); | 148 | * Make sure the reset request is observed if the change to |
149 | * power_state is observed. | ||
150 | */ | ||
151 | smp_wmb(); | ||
152 | |||
153 | vcpu->arch.power_off = false; | ||
154 | kvm_vcpu_wake_up(vcpu); | ||
159 | 155 | ||
160 | return PSCI_RET_SUCCESS; | 156 | return PSCI_RET_SUCCESS; |
161 | } | 157 | } |