diff options
-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 | ||||
-rw-r--r-- | include/asm-s390/kvm_host.h | 5 | ||||
-rw-r--r-- | include/linux/kvm.h | 8 |
7 files changed, 85 insertions, 2 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 |
diff --git a/include/asm-s390/kvm_host.h b/include/asm-s390/kvm_host.h index 1c829bdf5889..f8204a4f2e02 100644 --- a/include/asm-s390/kvm_host.h +++ b/include/asm-s390/kvm_host.h | |||
@@ -94,7 +94,9 @@ struct sie_block { | |||
94 | psw_t gpsw; /* 0x0090 */ | 94 | psw_t gpsw; /* 0x0090 */ |
95 | __u64 gg14; /* 0x00a0 */ | 95 | __u64 gg14; /* 0x00a0 */ |
96 | __u64 gg15; /* 0x00a8 */ | 96 | __u64 gg15; /* 0x00a8 */ |
97 | __u8 reservedb0[80]; /* 0x00b0 */ | 97 | __u8 reservedb0[30]; /* 0x00b0 */ |
98 | __u16 iprcc; /* 0x00ce */ | ||
99 | __u8 reservedd0[48]; /* 0x00d0 */ | ||
98 | __u64 gcr[16]; /* 0x0100 */ | 100 | __u64 gcr[16]; /* 0x0100 */ |
99 | __u64 gbea; /* 0x0180 */ | 101 | __u64 gbea; /* 0x0180 */ |
100 | __u8 reserved188[120]; /* 0x0188 */ | 102 | __u8 reserved188[120]; /* 0x0188 */ |
@@ -134,6 +136,7 @@ struct kvm_vcpu_stat { | |||
134 | u32 instruction_sigp_arch; | 136 | u32 instruction_sigp_arch; |
135 | u32 instruction_sigp_prefix; | 137 | u32 instruction_sigp_prefix; |
136 | u32 instruction_sigp_restart; | 138 | u32 instruction_sigp_restart; |
139 | u32 diagnose_44; | ||
137 | }; | 140 | }; |
138 | 141 | ||
139 | struct io_info { | 142 | struct io_info { |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 029f0284a2fd..f04bb426618f 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -75,6 +75,7 @@ struct kvm_irqchip { | |||
75 | #define KVM_EXIT_SET_TPR 11 | 75 | #define KVM_EXIT_SET_TPR 11 |
76 | #define KVM_EXIT_TPR_ACCESS 12 | 76 | #define KVM_EXIT_TPR_ACCESS 12 |
77 | #define KVM_EXIT_S390_SIEIC 13 | 77 | #define KVM_EXIT_S390_SIEIC 13 |
78 | #define KVM_EXIT_S390_RESET 14 | ||
78 | 79 | ||
79 | /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ | 80 | /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ |
80 | struct kvm_run { | 81 | struct kvm_run { |
@@ -147,6 +148,13 @@ struct kvm_run { | |||
147 | __u16 ipa; | 148 | __u16 ipa; |
148 | __u32 ipb; | 149 | __u32 ipb; |
149 | } s390_sieic; | 150 | } s390_sieic; |
151 | /* KVM_EXIT_S390_RESET */ | ||
152 | #define KVM_S390_RESET_POR 1 | ||
153 | #define KVM_S390_RESET_CLEAR 2 | ||
154 | #define KVM_S390_RESET_SUBSYSTEM 4 | ||
155 | #define KVM_S390_RESET_CPU_INIT 8 | ||
156 | #define KVM_S390_RESET_IPL 16 | ||
157 | __u64 s390_reset_flags; | ||
150 | /* Fix the size of the union. */ | 158 | /* Fix the size of the union. */ |
151 | char padding[256]; | 159 | char padding[256]; |
152 | }; | 160 | }; |