diff options
Diffstat (limited to 'arch/arm/kvm/arm.c')
-rw-r--r-- | arch/arm/kvm/arm.c | 178 |
1 files changed, 166 insertions, 12 deletions
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 2d30e3afdaf9..9ada5549216d 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -54,11 +54,40 @@ static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); | |||
54 | static struct vfp_hard_struct __percpu *kvm_host_vfp_state; | 54 | static struct vfp_hard_struct __percpu *kvm_host_vfp_state; |
55 | static unsigned long hyp_default_vectors; | 55 | static unsigned long hyp_default_vectors; |
56 | 56 | ||
57 | /* Per-CPU variable containing the currently running vcpu. */ | ||
58 | static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); | ||
59 | |||
57 | /* The VMID used in the VTTBR */ | 60 | /* The VMID used in the VTTBR */ |
58 | static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); | 61 | static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); |
59 | static u8 kvm_next_vmid; | 62 | static u8 kvm_next_vmid; |
60 | static DEFINE_SPINLOCK(kvm_vmid_lock); | 63 | static DEFINE_SPINLOCK(kvm_vmid_lock); |
61 | 64 | ||
65 | static bool vgic_present; | ||
66 | |||
67 | static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) | ||
68 | { | ||
69 | BUG_ON(preemptible()); | ||
70 | __get_cpu_var(kvm_arm_running_vcpu) = vcpu; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * kvm_arm_get_running_vcpu - get the vcpu running on the current CPU. | ||
75 | * Must be called from non-preemptible context | ||
76 | */ | ||
77 | struct kvm_vcpu *kvm_arm_get_running_vcpu(void) | ||
78 | { | ||
79 | BUG_ON(preemptible()); | ||
80 | return __get_cpu_var(kvm_arm_running_vcpu); | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. | ||
85 | */ | ||
86 | struct kvm_vcpu __percpu **kvm_get_running_vcpus(void) | ||
87 | { | ||
88 | return &kvm_arm_running_vcpu; | ||
89 | } | ||
90 | |||
62 | int kvm_arch_hardware_enable(void *garbage) | 91 | int kvm_arch_hardware_enable(void *garbage) |
63 | { | 92 | { |
64 | return 0; | 93 | return 0; |
@@ -157,6 +186,9 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
157 | { | 186 | { |
158 | int r; | 187 | int r; |
159 | switch (ext) { | 188 | switch (ext) { |
189 | case KVM_CAP_IRQCHIP: | ||
190 | r = vgic_present; | ||
191 | break; | ||
160 | case KVM_CAP_USER_MEMORY: | 192 | case KVM_CAP_USER_MEMORY: |
161 | case KVM_CAP_SYNC_MMU: | 193 | case KVM_CAP_SYNC_MMU: |
162 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: | 194 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: |
@@ -167,6 +199,8 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
167 | case KVM_CAP_COALESCED_MMIO: | 199 | case KVM_CAP_COALESCED_MMIO: |
168 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; | 200 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; |
169 | break; | 201 | break; |
202 | case KVM_CAP_ARM_SET_DEVICE_ADDR: | ||
203 | r = 1; | ||
170 | case KVM_CAP_NR_VCPUS: | 204 | case KVM_CAP_NR_VCPUS: |
171 | r = num_online_cpus(); | 205 | r = num_online_cpus(); |
172 | break; | 206 | break; |
@@ -255,6 +289,7 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) | |||
255 | void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) | 289 | void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) |
256 | { | 290 | { |
257 | kvm_mmu_free_memory_caches(vcpu); | 291 | kvm_mmu_free_memory_caches(vcpu); |
292 | kvm_timer_vcpu_terminate(vcpu); | ||
258 | kmem_cache_free(kvm_vcpu_cache, vcpu); | 293 | kmem_cache_free(kvm_vcpu_cache, vcpu); |
259 | } | 294 | } |
260 | 295 | ||
@@ -286,8 +321,19 @@ int __attribute_const__ kvm_target_cpu(void) | |||
286 | 321 | ||
287 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | 322 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) |
288 | { | 323 | { |
324 | int ret; | ||
325 | |||
289 | /* Force users to call KVM_ARM_VCPU_INIT */ | 326 | /* Force users to call KVM_ARM_VCPU_INIT */ |
290 | vcpu->arch.target = -1; | 327 | vcpu->arch.target = -1; |
328 | |||
329 | /* Set up VGIC */ | ||
330 | ret = kvm_vgic_vcpu_init(vcpu); | ||
331 | if (ret) | ||
332 | return ret; | ||
333 | |||
334 | /* Set up the timer */ | ||
335 | kvm_timer_vcpu_init(vcpu); | ||
336 | |||
291 | return 0; | 337 | return 0; |
292 | } | 338 | } |
293 | 339 | ||
@@ -308,10 +354,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
308 | */ | 354 | */ |
309 | if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) | 355 | if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) |
310 | flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ | 356 | flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ |
357 | |||
358 | kvm_arm_set_running_vcpu(vcpu); | ||
311 | } | 359 | } |
312 | 360 | ||
313 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | 361 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) |
314 | { | 362 | { |
363 | kvm_arm_set_running_vcpu(NULL); | ||
315 | } | 364 | } |
316 | 365 | ||
317 | int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | 366 | int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, |
@@ -342,7 +391,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, | |||
342 | */ | 391 | */ |
343 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) | 392 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) |
344 | { | 393 | { |
345 | return !!v->arch.irq_lines; | 394 | return !!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v); |
346 | } | 395 | } |
347 | 396 | ||
348 | /* Just ensure a guest exit from a particular CPU */ | 397 | /* Just ensure a guest exit from a particular CPU */ |
@@ -597,6 +646,17 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | |||
597 | vcpu->arch.has_run_once = true; | 646 | vcpu->arch.has_run_once = true; |
598 | 647 | ||
599 | /* | 648 | /* |
649 | * Initialize the VGIC before running a vcpu the first time on | ||
650 | * this VM. | ||
651 | */ | ||
652 | if (irqchip_in_kernel(vcpu->kvm) && | ||
653 | unlikely(!vgic_initialized(vcpu->kvm))) { | ||
654 | int ret = kvm_vgic_init(vcpu->kvm); | ||
655 | if (ret) | ||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | /* | ||
600 | * Handle the "start in power-off" case by calling into the | 660 | * Handle the "start in power-off" case by calling into the |
601 | * PSCI code. | 661 | * PSCI code. |
602 | */ | 662 | */ |
@@ -661,6 +721,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
661 | if (vcpu->arch.pause) | 721 | if (vcpu->arch.pause) |
662 | vcpu_pause(vcpu); | 722 | vcpu_pause(vcpu); |
663 | 723 | ||
724 | kvm_vgic_flush_hwstate(vcpu); | ||
725 | kvm_timer_flush_hwstate(vcpu); | ||
726 | |||
664 | local_irq_disable(); | 727 | local_irq_disable(); |
665 | 728 | ||
666 | /* | 729 | /* |
@@ -673,6 +736,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
673 | 736 | ||
674 | if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) { | 737 | if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) { |
675 | local_irq_enable(); | 738 | local_irq_enable(); |
739 | kvm_timer_sync_hwstate(vcpu); | ||
740 | kvm_vgic_sync_hwstate(vcpu); | ||
676 | continue; | 741 | continue; |
677 | } | 742 | } |
678 | 743 | ||
@@ -705,6 +770,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
705 | * Back from guest | 770 | * Back from guest |
706 | *************************************************************/ | 771 | *************************************************************/ |
707 | 772 | ||
773 | kvm_timer_sync_hwstate(vcpu); | ||
774 | kvm_vgic_sync_hwstate(vcpu); | ||
775 | |||
708 | ret = handle_exit(vcpu, run, ret); | 776 | ret = handle_exit(vcpu, run, ret); |
709 | } | 777 | } |
710 | 778 | ||
@@ -760,20 +828,49 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level) | |||
760 | 828 | ||
761 | trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level); | 829 | trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level); |
762 | 830 | ||
763 | if (irq_type != KVM_ARM_IRQ_TYPE_CPU) | 831 | switch (irq_type) { |
764 | return -EINVAL; | 832 | case KVM_ARM_IRQ_TYPE_CPU: |
833 | if (irqchip_in_kernel(kvm)) | ||
834 | return -ENXIO; | ||
765 | 835 | ||
766 | if (vcpu_idx >= nrcpus) | 836 | if (vcpu_idx >= nrcpus) |
767 | return -EINVAL; | 837 | return -EINVAL; |
768 | 838 | ||
769 | vcpu = kvm_get_vcpu(kvm, vcpu_idx); | 839 | vcpu = kvm_get_vcpu(kvm, vcpu_idx); |
770 | if (!vcpu) | 840 | if (!vcpu) |
771 | return -EINVAL; | 841 | return -EINVAL; |
772 | 842 | ||
773 | if (irq_num > KVM_ARM_IRQ_CPU_FIQ) | 843 | if (irq_num > KVM_ARM_IRQ_CPU_FIQ) |
774 | return -EINVAL; | 844 | return -EINVAL; |
845 | |||
846 | return vcpu_interrupt_line(vcpu, irq_num, level); | ||
847 | case KVM_ARM_IRQ_TYPE_PPI: | ||
848 | if (!irqchip_in_kernel(kvm)) | ||
849 | return -ENXIO; | ||
775 | 850 | ||
776 | return vcpu_interrupt_line(vcpu, irq_num, level); | 851 | if (vcpu_idx >= nrcpus) |
852 | return -EINVAL; | ||
853 | |||
854 | vcpu = kvm_get_vcpu(kvm, vcpu_idx); | ||
855 | if (!vcpu) | ||
856 | return -EINVAL; | ||
857 | |||
858 | if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS) | ||
859 | return -EINVAL; | ||
860 | |||
861 | return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level); | ||
862 | case KVM_ARM_IRQ_TYPE_SPI: | ||
863 | if (!irqchip_in_kernel(kvm)) | ||
864 | return -ENXIO; | ||
865 | |||
866 | if (irq_num < VGIC_NR_PRIVATE_IRQS || | ||
867 | irq_num > KVM_ARM_IRQ_GIC_MAX) | ||
868 | return -EINVAL; | ||
869 | |||
870 | return kvm_vgic_inject_irq(kvm, 0, irq_num, level); | ||
871 | } | ||
872 | |||
873 | return -EINVAL; | ||
777 | } | 874 | } |
778 | 875 | ||
779 | long kvm_arch_vcpu_ioctl(struct file *filp, | 876 | long kvm_arch_vcpu_ioctl(struct file *filp, |
@@ -827,10 +924,49 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) | |||
827 | return -EINVAL; | 924 | return -EINVAL; |
828 | } | 925 | } |
829 | 926 | ||
927 | static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm, | ||
928 | struct kvm_arm_device_addr *dev_addr) | ||
929 | { | ||
930 | unsigned long dev_id, type; | ||
931 | |||
932 | dev_id = (dev_addr->id & KVM_ARM_DEVICE_ID_MASK) >> | ||
933 | KVM_ARM_DEVICE_ID_SHIFT; | ||
934 | type = (dev_addr->id & KVM_ARM_DEVICE_TYPE_MASK) >> | ||
935 | KVM_ARM_DEVICE_TYPE_SHIFT; | ||
936 | |||
937 | switch (dev_id) { | ||
938 | case KVM_ARM_DEVICE_VGIC_V2: | ||
939 | if (!vgic_present) | ||
940 | return -ENXIO; | ||
941 | return kvm_vgic_set_addr(kvm, type, dev_addr->addr); | ||
942 | default: | ||
943 | return -ENODEV; | ||
944 | } | ||
945 | } | ||
946 | |||
830 | long kvm_arch_vm_ioctl(struct file *filp, | 947 | long kvm_arch_vm_ioctl(struct file *filp, |
831 | unsigned int ioctl, unsigned long arg) | 948 | unsigned int ioctl, unsigned long arg) |
832 | { | 949 | { |
833 | return -EINVAL; | 950 | struct kvm *kvm = filp->private_data; |
951 | void __user *argp = (void __user *)arg; | ||
952 | |||
953 | switch (ioctl) { | ||
954 | case KVM_CREATE_IRQCHIP: { | ||
955 | if (vgic_present) | ||
956 | return kvm_vgic_create(kvm); | ||
957 | else | ||
958 | return -ENXIO; | ||
959 | } | ||
960 | case KVM_ARM_SET_DEVICE_ADDR: { | ||
961 | struct kvm_arm_device_addr dev_addr; | ||
962 | |||
963 | if (copy_from_user(&dev_addr, argp, sizeof(dev_addr))) | ||
964 | return -EFAULT; | ||
965 | return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); | ||
966 | } | ||
967 | default: | ||
968 | return -EINVAL; | ||
969 | } | ||
834 | } | 970 | } |
835 | 971 | ||
836 | static void cpu_init_hyp_mode(void *vector) | 972 | static void cpu_init_hyp_mode(void *vector) |
@@ -960,6 +1096,24 @@ static int init_hyp_mode(void) | |||
960 | } | 1096 | } |
961 | } | 1097 | } |
962 | 1098 | ||
1099 | /* | ||
1100 | * Init HYP view of VGIC | ||
1101 | */ | ||
1102 | err = kvm_vgic_hyp_init(); | ||
1103 | if (err) | ||
1104 | goto out_free_vfp; | ||
1105 | |||
1106 | #ifdef CONFIG_KVM_ARM_VGIC | ||
1107 | vgic_present = true; | ||
1108 | #endif | ||
1109 | |||
1110 | /* | ||
1111 | * Init HYP architected timer support | ||
1112 | */ | ||
1113 | err = kvm_timer_hyp_init(); | ||
1114 | if (err) | ||
1115 | goto out_free_mappings; | ||
1116 | |||
963 | kvm_info("Hyp mode initialized successfully\n"); | 1117 | kvm_info("Hyp mode initialized successfully\n"); |
964 | return 0; | 1118 | return 0; |
965 | out_free_vfp: | 1119 | out_free_vfp: |