@@ -181,27 +181,51 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
181181 return 0 ;
182182}
183183
184- static bool vcpu_allowed_register_width (struct kvm_vcpu * vcpu )
184+ /**
185+ * kvm_set_vm_width() - set the register width for the guest
186+ * @vcpu: Pointer to the vcpu being configured
187+ *
188+ * Set both KVM_ARCH_FLAG_EL1_32BIT and KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED
189+ * in the VM flags based on the vcpu's requested register width, the HW
190+ * capabilities and other options (such as MTE).
191+ * When REG_WIDTH_CONFIGURED is already set, the vcpu settings must be
192+ * consistent with the value of the FLAG_EL1_32BIT bit in the flags.
193+ *
194+ * Return: 0 on success, negative error code on failure.
195+ */
196+ static int kvm_set_vm_width (struct kvm_vcpu * vcpu )
185197{
186- struct kvm_vcpu * tmp ;
198+ struct kvm * kvm = vcpu -> kvm ;
187199 bool is32bit ;
188- unsigned long i ;
189200
190201 is32bit = vcpu_has_feature (vcpu , KVM_ARM_VCPU_EL1_32BIT );
202+
203+ lockdep_assert_held (& kvm -> lock );
204+
205+ if (test_bit (KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED , & kvm -> arch .flags )) {
206+ /*
207+ * The guest's register width is already configured.
208+ * Make sure that the vcpu is consistent with it.
209+ */
210+ if (is32bit == test_bit (KVM_ARCH_FLAG_EL1_32BIT , & kvm -> arch .flags ))
211+ return 0 ;
212+
213+ return - EINVAL ;
214+ }
215+
191216 if (!cpus_have_const_cap (ARM64_HAS_32BIT_EL1 ) && is32bit )
192- return false ;
217+ return - EINVAL ;
193218
194219 /* MTE is incompatible with AArch32 */
195- if (kvm_has_mte (vcpu -> kvm ) && is32bit )
196- return false ;
220+ if (kvm_has_mte (kvm ) && is32bit )
221+ return - EINVAL ;
197222
198- /* Check that the vcpus are either all 32bit or all 64bit */
199- kvm_for_each_vcpu (i , tmp , vcpu -> kvm ) {
200- if (vcpu_has_feature (tmp , KVM_ARM_VCPU_EL1_32BIT ) != is32bit )
201- return false;
202- }
223+ if (is32bit )
224+ set_bit (KVM_ARCH_FLAG_EL1_32BIT , & kvm -> arch .flags );
203225
204- return true;
226+ set_bit (KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED , & kvm -> arch .flags );
227+
228+ return 0 ;
205229}
206230
207231/**
@@ -230,10 +254,16 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
230254 u32 pstate ;
231255
232256 mutex_lock (& vcpu -> kvm -> lock );
233- reset_state = vcpu -> arch .reset_state ;
234- WRITE_ONCE (vcpu -> arch .reset_state .reset , false);
257+ ret = kvm_set_vm_width (vcpu );
258+ if (!ret ) {
259+ reset_state = vcpu -> arch .reset_state ;
260+ WRITE_ONCE (vcpu -> arch .reset_state .reset , false);
261+ }
235262 mutex_unlock (& vcpu -> kvm -> lock );
236263
264+ if (ret )
265+ return ret ;
266+
237267 /* Reset PMU outside of the non-preemptible section */
238268 kvm_pmu_vcpu_reset (vcpu );
239269
@@ -260,14 +290,9 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
260290 }
261291 }
262292
263- if (!vcpu_allowed_register_width (vcpu )) {
264- ret = - EINVAL ;
265- goto out ;
266- }
267-
268293 switch (vcpu -> arch .target ) {
269294 default :
270- if (test_bit ( KVM_ARM_VCPU_EL1_32BIT , vcpu -> arch . features )) {
295+ if (vcpu_el1_is_32bit ( vcpu )) {
271296 pstate = VCPU_RESET_PSTATE_SVC ;
272297 } else {
273298 pstate = VCPU_RESET_PSTATE_EL1 ;
0 commit comments