aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/kvm-s390.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kvm/kvm-s390.c')
-rw-r--r--arch/s390/kvm/kvm-s390.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index a906499214bb..5e3473c9a639 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -20,6 +20,7 @@
20#include <linux/kvm_host.h> 20#include <linux/kvm_host.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/timer.h>
23#include <asm/lowcore.h> 24#include <asm/lowcore.h>
24#include <asm/pgtable.h> 25#include <asm/pgtable.h>
25 26
@@ -34,6 +35,19 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
34 { "exit_stop_request", VCPU_STAT(exit_stop_request) }, 35 { "exit_stop_request", VCPU_STAT(exit_stop_request) },
35 { "exit_external_request", VCPU_STAT(exit_external_request) }, 36 { "exit_external_request", VCPU_STAT(exit_external_request) },
36 { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) }, 37 { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
38 { "exit_instruction", VCPU_STAT(exit_instruction) },
39 { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
40 { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
41 { "instruction_lctg", VCPU_STAT(instruction_lctg) },
42 { "instruction_lctl", VCPU_STAT(instruction_lctl) },
43 { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
44 { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
45 { "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
46 { "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
47 { "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
48 { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
49 { "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
50 { "exit_wait_state", VCPU_STAT(exit_wait_state) },
37 { NULL } 51 { NULL }
38}; 52};
39 53
@@ -106,6 +120,15 @@ long kvm_arch_vm_ioctl(struct file *filp,
106 int r; 120 int r;
107 121
108 switch (ioctl) { 122 switch (ioctl) {
123 case KVM_S390_INTERRUPT: {
124 struct kvm_s390_interrupt s390int;
125
126 r = -EFAULT;
127 if (copy_from_user(&s390int, argp, sizeof(s390int)))
128 break;
129 r = kvm_s390_inject_vm(kvm, &s390int);
130 break;
131 }
109 default: 132 default:
110 r = -EINVAL; 133 r = -EINVAL;
111 } 134 }
@@ -138,6 +161,9 @@ struct kvm *kvm_arch_create_vm(void)
138 if (!kvm->arch.dbf) 161 if (!kvm->arch.dbf)
139 goto out_nodbf; 162 goto out_nodbf;
140 163
164 spin_lock_init(&kvm->arch.float_int.lock);
165 INIT_LIST_HEAD(&kvm->arch.float_int.list);
166
141 debug_register_view(kvm->arch.dbf, &debug_sprintf_view); 167 debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
142 VM_EVENT(kvm, 3, "%s", "vm created"); 168 VM_EVENT(kvm, 3, "%s", "vm created");
143 169
@@ -218,7 +244,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
218 vcpu->arch.sie_block->gmsor = 0x000000000000; 244 vcpu->arch.sie_block->gmsor = 0x000000000000;
219 vcpu->arch.sie_block->ecb = 2; 245 vcpu->arch.sie_block->ecb = 2;
220 vcpu->arch.sie_block->eca = 0xC1002001U; 246 vcpu->arch.sie_block->eca = 0xC1002001U;
221 247 setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
248 (unsigned long) vcpu);
222 return 0; 249 return 0;
223} 250}
224 251
@@ -243,6 +270,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
243 vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32); 270 vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
244 vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca; 271 vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
245 272
273 spin_lock_init(&vcpu->arch.local_int.lock);
274 INIT_LIST_HEAD(&vcpu->arch.local_int.list);
275 vcpu->arch.local_int.float_int = &kvm->arch.float_int;
276 spin_lock_bh(&kvm->arch.float_int.lock);
277 kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
278 init_waitqueue_head(&vcpu->arch.local_int.wq);
279 spin_unlock_bh(&kvm->arch.float_int.lock);
280
246 rc = kvm_vcpu_init(vcpu, kvm, id); 281 rc = kvm_vcpu_init(vcpu, kvm, id);
247 if (rc) 282 if (rc)
248 goto out_free_cpu; 283 goto out_free_cpu;
@@ -395,6 +430,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
395 430
396 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); 431 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
397 432
433 BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
434
398 switch (kvm_run->exit_reason) { 435 switch (kvm_run->exit_reason) {
399 case KVM_EXIT_S390_SIEIC: 436 case KVM_EXIT_S390_SIEIC:
400 vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask; 437 vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask;
@@ -410,8 +447,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
410 might_sleep(); 447 might_sleep();
411 448
412 do { 449 do {
450 kvm_s390_deliver_pending_interrupts(vcpu);
413 __vcpu_run(vcpu); 451 __vcpu_run(vcpu);
414
415 rc = kvm_handle_sie_intercept(vcpu); 452 rc = kvm_handle_sie_intercept(vcpu);
416 } while (!signal_pending(current) && !rc); 453 } while (!signal_pending(current) && !rc);
417 454
@@ -538,6 +575,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
538 void __user *argp = (void __user *)arg; 575 void __user *argp = (void __user *)arg;
539 576
540 switch (ioctl) { 577 switch (ioctl) {
578 case KVM_S390_INTERRUPT: {
579 struct kvm_s390_interrupt s390int;
580
581 if (copy_from_user(&s390int, argp, sizeof(s390int)))
582 return -EFAULT;
583 return kvm_s390_inject_vcpu(vcpu, &s390int);
584 }
541 case KVM_S390_STORE_STATUS: 585 case KVM_S390_STORE_STATUS:
542 return kvm_s390_vcpu_store_status(vcpu, arg); 586 return kvm_s390_vcpu_store_status(vcpu, arg);
543 case KVM_S390_SET_INITIAL_PSW: { 587 case KVM_S390_SET_INITIAL_PSW: {