@@ -573,7 +573,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
/*
* Re-check atomic conditions
*/
- if (signal_pending(current)) {
+ if (!__this_cpu_read(kvm_arm_hardware_enabled)) {
+ /* cpu has been torn down */
+ ret = 0;
+ run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+ run->fail_entry.hardware_entry_failure_reason
+ = (u64)-ENOEXEC;
+ } else if (signal_pending(current)) {
ret = -EINTR;
run->exit_reason = KVM_EXIT_INTR;
}
@@ -950,7 +956,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
}
}
-int kvm_arch_hardware_enable(void)
+static void cpu_init_hyp_mode(void)
{
phys_addr_t boot_pgd_ptr;
phys_addr_t pgd_ptr;
@@ -958,9 +964,6 @@ int kvm_arch_hardware_enable(void)
unsigned long stack_page;
unsigned long vector_ptr;
- if (__hyp_get_vectors() != hyp_default_vectors)
- return 0;
-
/* Switch from the HYP stub to our own HYP init vector */
__hyp_set_vectors(kvm_get_idmap_vector());
@@ -973,24 +976,38 @@ int kvm_arch_hardware_enable(void)
__cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
kvm_arm_init_debug();
-
- return 0;
}
-void kvm_arch_hardware_disable(void)
+static void cpu_reset_hyp_mode(void)
{
phys_addr_t boot_pgd_ptr;
phys_addr_t phys_idmap_start;
- if (__hyp_get_vectors() == hyp_default_vectors)
- return;
-
boot_pgd_ptr = kvm_mmu_get_boot_httbr();
phys_idmap_start = kvm_get_idmap_start();
__cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
}
+int kvm_arch_hardware_enable(void)
+{
+ if (!__this_cpu_read(kvm_arm_hardware_enabled)) {
+ cpu_init_hyp_mode();
+ __this_cpu_write(kvm_arm_hardware_enabled, 1);
+ }
+
+ return 0;
+}
+
+void kvm_arch_hardware_disable(void)
+{
+ if (!__this_cpu_read(kvm_arm_hardware_enabled))
+ return;
+
+ cpu_reset_hyp_mode();
+ __this_cpu_write(kvm_arm_hardware_enabled, 0);
+}
+
#ifdef CONFIG_CPU_PM
static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
unsigned long cmd,
@@ -998,19 +1015,13 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
{
switch (cmd) {
case CPU_PM_ENTER:
- if (__hyp_get_vectors() != hyp_default_vectors)
- __this_cpu_write(kvm_arm_hardware_enabled, 1);
- else
- __this_cpu_write(kvm_arm_hardware_enabled, 0);
- /*
- * don't call kvm_arch_hardware_disable() in case of
- * CPU_PM_ENTER because it does't actually save any state.
- */
+ if (__this_cpu_read(kvm_arm_hardware_enabled))
+ cpu_reset_hyp_mode();
return NOTIFY_OK;
case CPU_PM_EXIT:
if (__this_cpu_read(kvm_arm_hardware_enabled))
- kvm_arch_hardware_enable();
+ cpu_init_hyp_mode();
return NOTIFY_OK;
@@ -1114,9 +1125,20 @@ static int init_hyp_mode(void)
}
/*
+ * Init this CPU temporarily to execute kvm_hyp_call()
+ * during kvm_vgic_hyp_init().
+ */
+ preempt_disable();
+ cpu_init_hyp_mode();
+
+ /*
* Init HYP view of VGIC
*/
err = kvm_vgic_hyp_init();
+
+ cpu_reset_hyp_mode();
+ preempt_enable();
+
if (err)
goto out_free_context;