diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kvm/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kvm/diag.c | 67 | ||||
-rw-r--r-- | arch/s390/kvm/intercept.c | 1 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 1 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 3 |
5 files changed, 73 insertions, 1 deletions
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile index f3bf11a88bc7..e5221ec0b8e3 100644 --- a/arch/s390/kvm/Makefile +++ b/arch/s390/kvm/Makefile | |||
@@ -10,5 +10,5 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o) | |||
10 | 10 | ||
11 | EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm | 11 | EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm |
12 | 12 | ||
13 | kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o | 13 | kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o |
14 | obj-$(CONFIG_KVM) += kvm.o | 14 | obj-$(CONFIG_KVM) += kvm.o |
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c new file mode 100644 index 000000000000..f639a152869f --- /dev/null +++ b/arch/s390/kvm/diag.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * diag.c - handling diagnose instructions | ||
3 | * | ||
4 | * Copyright IBM Corp. 2008 | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License (version 2 only) | ||
8 | * as published by the Free Software Foundation. | ||
9 | * | ||
10 | * Author(s): Carsten Otte <cotte@de.ibm.com> | ||
11 | * Christian Borntraeger <borntraeger@de.ibm.com> | ||
12 | */ | ||
13 | |||
14 | #include <linux/kvm.h> | ||
15 | #include <linux/kvm_host.h> | ||
16 | #include "kvm-s390.h" | ||
17 | |||
18 | static int __diag_time_slice_end(struct kvm_vcpu *vcpu) | ||
19 | { | ||
20 | VCPU_EVENT(vcpu, 5, "%s", "diag time slice end"); | ||
21 | vcpu->stat.diagnose_44++; | ||
22 | vcpu_put(vcpu); | ||
23 | schedule(); | ||
24 | vcpu_load(vcpu); | ||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | static int __diag_ipl_functions(struct kvm_vcpu *vcpu) | ||
29 | { | ||
30 | unsigned int reg = vcpu->arch.sie_block->ipa & 0xf; | ||
31 | unsigned long subcode = vcpu->arch.guest_gprs[reg] & 0xffff; | ||
32 | |||
33 | VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode); | ||
34 | switch (subcode) { | ||
35 | case 3: | ||
36 | vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR; | ||
37 | break; | ||
38 | case 4: | ||
39 | vcpu->run->s390_reset_flags = 0; | ||
40 | break; | ||
41 | default: | ||
42 | return -ENOTSUPP; | ||
43 | } | ||
44 | |||
45 | atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); | ||
46 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM; | ||
47 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL; | ||
48 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT; | ||
49 | vcpu->run->exit_reason = KVM_EXIT_S390_RESET; | ||
50 | VCPU_EVENT(vcpu, 3, "requesting userspace resets %lx", | ||
51 | vcpu->run->s390_reset_flags); | ||
52 | return -EREMOTE; | ||
53 | } | ||
54 | |||
55 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) | ||
56 | { | ||
57 | int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16; | ||
58 | |||
59 | switch (code) { | ||
60 | case 0x44: | ||
61 | return __diag_time_slice_end(vcpu); | ||
62 | case 0x308: | ||
63 | return __diag_ipl_functions(vcpu); | ||
64 | default: | ||
65 | return -ENOTSUPP; | ||
66 | } | ||
67 | } | ||
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 9f0d8b239436..349581a26103 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c | |||
@@ -95,6 +95,7 @@ static int handle_lctl(struct kvm_vcpu *vcpu) | |||
95 | } | 95 | } |
96 | 96 | ||
97 | static intercept_handler_t instruction_handlers[256] = { | 97 | static intercept_handler_t instruction_handlers[256] = { |
98 | [0x83] = kvm_s390_handle_diag, | ||
98 | [0xae] = kvm_s390_handle_sigp, | 99 | [0xae] = kvm_s390_handle_sigp, |
99 | [0xb2] = kvm_s390_handle_priv, | 100 | [0xb2] = kvm_s390_handle_priv, |
100 | [0xb7] = handle_lctl, | 101 | [0xb7] = handle_lctl, |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c632180739ee..d3b1de83678b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -63,6 +63,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
63 | { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) }, | 63 | { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) }, |
64 | { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) }, | 64 | { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) }, |
65 | { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) }, | 65 | { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) }, |
66 | { "diagnose_44", VCPU_STAT(diagnose_44) }, | ||
66 | { NULL } | 67 | { NULL } |
67 | }; | 68 | }; |
68 | 69 | ||
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index e6e5756a0e07..3893cf12eacf 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -58,4 +58,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); | |||
58 | /* implemented in kvm-s390.c */ | 58 | /* implemented in kvm-s390.c */ |
59 | int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, | 59 | int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, |
60 | unsigned long addr); | 60 | unsigned long addr); |
61 | /* implemented in diag.c */ | ||
62 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); | ||
63 | |||
61 | #endif | 64 | #endif |