diff options
Diffstat (limited to 'arch/arm/kvm/arm.c')
-rw-r--r-- | arch/arm/kvm/arm.c | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 2a700e00528d..bd18bb8b2770 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/cpu.h> | 19 | #include <linux/cpu.h> |
20 | #include <linux/cpu_pm.h> | ||
20 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
21 | #include <linux/err.h> | 22 | #include <linux/err.h> |
22 | #include <linux/kvm_host.h> | 23 | #include <linux/kvm_host.h> |
@@ -137,6 +138,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
137 | if (ret) | 138 | if (ret) |
138 | goto out_free_stage2_pgd; | 139 | goto out_free_stage2_pgd; |
139 | 140 | ||
141 | kvm_timer_init(kvm); | ||
142 | |||
140 | /* Mark the initial VMID generation invalid */ | 143 | /* Mark the initial VMID generation invalid */ |
141 | kvm->arch.vmid_gen = 0; | 144 | kvm->arch.vmid_gen = 0; |
142 | 145 | ||
@@ -188,6 +191,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
188 | case KVM_CAP_IRQCHIP: | 191 | case KVM_CAP_IRQCHIP: |
189 | r = vgic_present; | 192 | r = vgic_present; |
190 | break; | 193 | break; |
194 | case KVM_CAP_DEVICE_CTRL: | ||
191 | case KVM_CAP_USER_MEMORY: | 195 | case KVM_CAP_USER_MEMORY: |
192 | case KVM_CAP_SYNC_MMU: | 196 | case KVM_CAP_SYNC_MMU: |
193 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: | 197 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: |
@@ -339,6 +343,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
339 | 343 | ||
340 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | 344 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) |
341 | { | 345 | { |
346 | /* | ||
347 | * The arch-generic KVM code expects the cpu field of a vcpu to be -1 | ||
348 | * if the vcpu is no longer assigned to a cpu. This is used for the | ||
349 | * optimized make_all_cpus_request path. | ||
350 | */ | ||
351 | vcpu->cpu = -1; | ||
352 | |||
342 | kvm_arm_set_running_vcpu(NULL); | 353 | kvm_arm_set_running_vcpu(NULL); |
343 | } | 354 | } |
344 | 355 | ||
@@ -462,6 +473,8 @@ static void update_vttbr(struct kvm *kvm) | |||
462 | 473 | ||
463 | static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | 474 | static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) |
464 | { | 475 | { |
476 | int ret; | ||
477 | |||
465 | if (likely(vcpu->arch.has_run_once)) | 478 | if (likely(vcpu->arch.has_run_once)) |
466 | return 0; | 479 | return 0; |
467 | 480 | ||
@@ -471,22 +484,12 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | |||
471 | * Initialize the VGIC before running a vcpu the first time on | 484 | * Initialize the VGIC before running a vcpu the first time on |
472 | * this VM. | 485 | * this VM. |
473 | */ | 486 | */ |
474 | if (irqchip_in_kernel(vcpu->kvm) && | 487 | if (unlikely(!vgic_initialized(vcpu->kvm))) { |
475 | unlikely(!vgic_initialized(vcpu->kvm))) { | 488 | ret = kvm_vgic_init(vcpu->kvm); |
476 | int ret = kvm_vgic_init(vcpu->kvm); | ||
477 | if (ret) | 489 | if (ret) |
478 | return ret; | 490 | return ret; |
479 | } | 491 | } |
480 | 492 | ||
481 | /* | ||
482 | * Handle the "start in power-off" case by calling into the | ||
483 | * PSCI code. | ||
484 | */ | ||
485 | if (test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) { | ||
486 | *vcpu_reg(vcpu, 0) = KVM_PSCI_FN_CPU_OFF; | ||
487 | kvm_psci_call(vcpu); | ||
488 | } | ||
489 | |||
490 | return 0; | 493 | return 0; |
491 | } | 494 | } |
492 | 495 | ||
@@ -700,6 +703,24 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, | |||
700 | return -EINVAL; | 703 | return -EINVAL; |
701 | } | 704 | } |
702 | 705 | ||
706 | static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, | ||
707 | struct kvm_vcpu_init *init) | ||
708 | { | ||
709 | int ret; | ||
710 | |||
711 | ret = kvm_vcpu_set_target(vcpu, init); | ||
712 | if (ret) | ||
713 | return ret; | ||
714 | |||
715 | /* | ||
716 | * Handle the "start in power-off" case by marking the VCPU as paused. | ||
717 | */ | ||
718 | if (__test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) | ||
719 | vcpu->arch.pause = true; | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
703 | long kvm_arch_vcpu_ioctl(struct file *filp, | 724 | long kvm_arch_vcpu_ioctl(struct file *filp, |
704 | unsigned int ioctl, unsigned long arg) | 725 | unsigned int ioctl, unsigned long arg) |
705 | { | 726 | { |
@@ -713,8 +734,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
713 | if (copy_from_user(&init, argp, sizeof(init))) | 734 | if (copy_from_user(&init, argp, sizeof(init))) |
714 | return -EFAULT; | 735 | return -EFAULT; |
715 | 736 | ||
716 | return kvm_vcpu_set_target(vcpu, &init); | 737 | return kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init); |
717 | |||
718 | } | 738 | } |
719 | case KVM_SET_ONE_REG: | 739 | case KVM_SET_ONE_REG: |
720 | case KVM_GET_ONE_REG: { | 740 | case KVM_GET_ONE_REG: { |
@@ -772,7 +792,7 @@ static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm, | |||
772 | case KVM_ARM_DEVICE_VGIC_V2: | 792 | case KVM_ARM_DEVICE_VGIC_V2: |
773 | if (!vgic_present) | 793 | if (!vgic_present) |
774 | return -ENXIO; | 794 | return -ENXIO; |
775 | return kvm_vgic_set_addr(kvm, type, dev_addr->addr); | 795 | return kvm_vgic_addr(kvm, type, &dev_addr->addr, true); |
776 | default: | 796 | default: |
777 | return -ENODEV; | 797 | return -ENODEV; |
778 | } | 798 | } |
@@ -853,6 +873,34 @@ static struct notifier_block hyp_init_cpu_nb = { | |||
853 | .notifier_call = hyp_init_cpu_notify, | 873 | .notifier_call = hyp_init_cpu_notify, |
854 | }; | 874 | }; |
855 | 875 | ||
876 | #ifdef CONFIG_CPU_PM | ||
877 | static int hyp_init_cpu_pm_notifier(struct notifier_block *self, | ||
878 | unsigned long cmd, | ||
879 | void *v) | ||
880 | { | ||
881 | if (cmd == CPU_PM_EXIT && | ||
882 | __hyp_get_vectors() == hyp_default_vectors) { | ||
883 | cpu_init_hyp_mode(NULL); | ||
884 | return NOTIFY_OK; | ||
885 | } | ||
886 | |||
887 | return NOTIFY_DONE; | ||
888 | } | ||
889 | |||
890 | static struct notifier_block hyp_init_cpu_pm_nb = { | ||
891 | .notifier_call = hyp_init_cpu_pm_notifier, | ||
892 | }; | ||
893 | |||
894 | static void __init hyp_cpu_pm_init(void) | ||
895 | { | ||
896 | cpu_pm_register_notifier(&hyp_init_cpu_pm_nb); | ||
897 | } | ||
898 | #else | ||
899 | static inline void hyp_cpu_pm_init(void) | ||
900 | { | ||
901 | } | ||
902 | #endif | ||
903 | |||
856 | /** | 904 | /** |
857 | * Inits Hyp-mode on all online CPUs | 905 | * Inits Hyp-mode on all online CPUs |
858 | */ | 906 | */ |
@@ -1013,6 +1061,8 @@ int kvm_arch_init(void *opaque) | |||
1013 | goto out_err; | 1061 | goto out_err; |
1014 | } | 1062 | } |
1015 | 1063 | ||
1064 | hyp_cpu_pm_init(); | ||
1065 | |||
1016 | kvm_coproc_table_init(); | 1066 | kvm_coproc_table_init(); |
1017 | return 0; | 1067 | return 0; |
1018 | out_err: | 1068 | out_err: |