diff options
-rw-r--r-- | arch/s390/kvm/diag.c | 2 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 53 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 10 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 4 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 56 | ||||
-rw-r--r-- | arch/s390/kvm/trace.h | 1 |
6 files changed, 78 insertions, 48 deletions
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 78d967f180f4..5ff29be7d87a 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -137,7 +137,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu) | |||
137 | 137 | ||
138 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) | 138 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) |
139 | { | 139 | { |
140 | int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16; | 140 | int code = kvm_s390_get_base_disp_rs(vcpu) & 0xffff; |
141 | 141 | ||
142 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | 142 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) |
143 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | 143 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 569494e01ec6..1bb1ddaf93c0 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -732,14 +732,12 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) | |||
732 | 732 | ||
733 | if (exit_reason >= 0) { | 733 | if (exit_reason >= 0) { |
734 | rc = 0; | 734 | rc = 0; |
735 | } else { | 735 | } else if (kvm_is_ucontrol(vcpu->kvm)) { |
736 | if (kvm_is_ucontrol(vcpu->kvm)) { | 736 | vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL; |
737 | rc = SIE_INTERCEPT_UCONTROL; | 737 | vcpu->run->s390_ucontrol.trans_exc_code = |
738 | } else { | 738 | current->thread.gmap_addr; |
739 | VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); | 739 | vcpu->run->s390_ucontrol.pgm_code = 0x10; |
740 | trace_kvm_s390_sie_fault(vcpu); | 740 | rc = -EREMOTE; |
741 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
742 | } | ||
743 | } | 741 | } |
744 | 742 | ||
745 | memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16); | 743 | memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16); |
@@ -833,16 +831,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
833 | rc = -EINTR; | 831 | rc = -EINTR; |
834 | } | 832 | } |
835 | 833 | ||
836 | #ifdef CONFIG_KVM_S390_UCONTROL | ||
837 | if (rc == SIE_INTERCEPT_UCONTROL) { | ||
838 | kvm_run->exit_reason = KVM_EXIT_S390_UCONTROL; | ||
839 | kvm_run->s390_ucontrol.trans_exc_code = | ||
840 | current->thread.gmap_addr; | ||
841 | kvm_run->s390_ucontrol.pgm_code = 0x10; | ||
842 | rc = 0; | ||
843 | } | ||
844 | #endif | ||
845 | |||
846 | if (rc == -EOPNOTSUPP) { | 834 | if (rc == -EOPNOTSUPP) { |
847 | /* intercept cannot be handled in-kernel, prepare kvm-run */ | 835 | /* intercept cannot be handled in-kernel, prepare kvm-run */ |
848 | kvm_run->exit_reason = KVM_EXIT_S390_SIEIC; | 836 | kvm_run->exit_reason = KVM_EXIT_S390_SIEIC; |
@@ -885,10 +873,11 @@ static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from, | |||
885 | * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit | 873 | * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit |
886 | * KVM_S390_STORE_STATUS_PREFIXED: -> prefix | 874 | * KVM_S390_STORE_STATUS_PREFIXED: -> prefix |
887 | */ | 875 | */ |
888 | int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) | 876 | int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr) |
889 | { | 877 | { |
890 | unsigned char archmode = 1; | 878 | unsigned char archmode = 1; |
891 | int prefix; | 879 | int prefix; |
880 | u64 clkcomp; | ||
892 | 881 | ||
893 | if (addr == KVM_S390_STORE_STATUS_NOADDR) { | 882 | if (addr == KVM_S390_STORE_STATUS_NOADDR) { |
894 | if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1)) | 883 | if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1)) |
@@ -903,15 +892,6 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) | |||
903 | } else | 892 | } else |
904 | prefix = 0; | 893 | prefix = 0; |
905 | 894 | ||
906 | /* | ||
907 | * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy | ||
908 | * copying in vcpu load/put. Lets update our copies before we save | ||
909 | * it into the save area | ||
910 | */ | ||
911 | save_fp_ctl(&vcpu->arch.guest_fpregs.fpc); | ||
912 | save_fp_regs(vcpu->arch.guest_fpregs.fprs); | ||
913 | save_access_regs(vcpu->run->s.regs.acrs); | ||
914 | |||
915 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs), | 895 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs), |
916 | vcpu->arch.guest_fpregs.fprs, 128, prefix)) | 896 | vcpu->arch.guest_fpregs.fprs, 128, prefix)) |
917 | return -EFAULT; | 897 | return -EFAULT; |
@@ -941,8 +921,9 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) | |||
941 | &vcpu->arch.sie_block->cputm, 8, prefix)) | 921 | &vcpu->arch.sie_block->cputm, 8, prefix)) |
942 | return -EFAULT; | 922 | return -EFAULT; |
943 | 923 | ||
924 | clkcomp = vcpu->arch.sie_block->ckc >> 8; | ||
944 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, clk_cmp), | 925 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, clk_cmp), |
945 | &vcpu->arch.sie_block->ckc, 8, prefix)) | 926 | &clkcomp, 8, prefix)) |
946 | return -EFAULT; | 927 | return -EFAULT; |
947 | 928 | ||
948 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs), | 929 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs), |
@@ -956,6 +937,20 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) | |||
956 | return 0; | 937 | return 0; |
957 | } | 938 | } |
958 | 939 | ||
940 | int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) | ||
941 | { | ||
942 | /* | ||
943 | * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy | ||
944 | * copying in vcpu load/put. Lets update our copies before we save | ||
945 | * it into the save area | ||
946 | */ | ||
947 | save_fp_ctl(&vcpu->arch.guest_fpregs.fpc); | ||
948 | save_fp_regs(vcpu->arch.guest_fpregs.fprs); | ||
949 | save_access_regs(vcpu->run->s.regs.acrs); | ||
950 | |||
951 | return kvm_s390_store_status_unloaded(vcpu, addr); | ||
952 | } | ||
953 | |||
959 | static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, | 954 | static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, |
960 | struct kvm_enable_cap *cap) | 955 | struct kvm_enable_cap *cap) |
961 | { | 956 | { |
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index b44912a32949..095cf51b16ec 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -19,16 +19,11 @@ | |||
19 | #include <linux/kvm.h> | 19 | #include <linux/kvm.h> |
20 | #include <linux/kvm_host.h> | 20 | #include <linux/kvm_host.h> |
21 | 21 | ||
22 | /* The current code can have up to 256 pages for virtio */ | ||
23 | #define VIRTIODESCSPACE (256ul * 4096ul) | ||
24 | |||
25 | typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu); | 22 | typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu); |
26 | 23 | ||
27 | /* declare vfacilities extern */ | 24 | /* declare vfacilities extern */ |
28 | extern unsigned long *vfacilities; | 25 | extern unsigned long *vfacilities; |
29 | 26 | ||
30 | /* negativ values are error codes, positive values for internal conditions */ | ||
31 | #define SIE_INTERCEPT_UCONTROL (1<<0) | ||
32 | int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); | 27 | int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); |
33 | 28 | ||
34 | #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ | 29 | #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ |
@@ -133,7 +128,6 @@ int __must_check kvm_s390_inject_vm(struct kvm *kvm, | |||
133 | int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | 128 | int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, |
134 | struct kvm_s390_interrupt *s390int); | 129 | struct kvm_s390_interrupt *s390int); |
135 | int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); | 130 | int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); |
136 | int __must_check kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action); | ||
137 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | 131 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, |
138 | u64 cr6, u64 schid); | 132 | u64 cr6, u64 schid); |
139 | 133 | ||
@@ -150,8 +144,8 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); | |||
150 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); | 144 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); |
151 | 145 | ||
152 | /* implemented in kvm-s390.c */ | 146 | /* implemented in kvm-s390.c */ |
153 | int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, | 147 | int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr); |
154 | unsigned long addr); | 148 | int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr); |
155 | void s390_vcpu_block(struct kvm_vcpu *vcpu); | 149 | void s390_vcpu_block(struct kvm_vcpu *vcpu); |
156 | void s390_vcpu_unblock(struct kvm_vcpu *vcpu); | 150 | void s390_vcpu_unblock(struct kvm_vcpu *vcpu); |
157 | void exit_sie(struct kvm_vcpu *vcpu); | 151 | void exit_sie(struct kvm_vcpu *vcpu); |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 2440602e6df1..05537ab22382 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -197,7 +197,7 @@ static int handle_tpi(struct kvm_vcpu *vcpu) | |||
197 | if (addr & 3) | 197 | if (addr & 3) |
198 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 198 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
199 | cc = 0; | 199 | cc = 0; |
200 | inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->run->s.regs.crs[6], 0); | 200 | inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->arch.sie_block->gcr[6], 0); |
201 | if (!inti) | 201 | if (!inti) |
202 | goto no_interrupt; | 202 | goto no_interrupt; |
203 | cc = 1; | 203 | cc = 1; |
@@ -638,7 +638,6 @@ static int handle_pfmf(struct kvm_vcpu *vcpu) | |||
638 | 638 | ||
639 | static const intercept_handler_t b9_handlers[256] = { | 639 | static const intercept_handler_t b9_handlers[256] = { |
640 | [0x8d] = handle_epsw, | 640 | [0x8d] = handle_epsw, |
641 | [0x9c] = handle_io_inst, | ||
642 | [0xaf] = handle_pfmf, | 641 | [0xaf] = handle_pfmf, |
643 | }; | 642 | }; |
644 | 643 | ||
@@ -731,7 +730,6 @@ static int handle_lctlg(struct kvm_vcpu *vcpu) | |||
731 | 730 | ||
732 | static const intercept_handler_t eb_handlers[256] = { | 731 | static const intercept_handler_t eb_handlers[256] = { |
733 | [0x2f] = handle_lctlg, | 732 | [0x2f] = handle_lctlg, |
734 | [0x8a] = handle_io_inst, | ||
735 | }; | 733 | }; |
736 | 734 | ||
737 | int kvm_s390_handle_eb(struct kvm_vcpu *vcpu) | 735 | int kvm_s390_handle_eb(struct kvm_vcpu *vcpu) |
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index bec398c57acf..c3700585b4bb 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -130,6 +130,7 @@ unlock: | |||
130 | static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) | 130 | static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) |
131 | { | 131 | { |
132 | struct kvm_s390_interrupt_info *inti; | 132 | struct kvm_s390_interrupt_info *inti; |
133 | int rc = SIGP_CC_ORDER_CODE_ACCEPTED; | ||
133 | 134 | ||
134 | inti = kzalloc(sizeof(*inti), GFP_ATOMIC); | 135 | inti = kzalloc(sizeof(*inti), GFP_ATOMIC); |
135 | if (!inti) | 136 | if (!inti) |
@@ -139,6 +140,8 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) | |||
139 | spin_lock_bh(&li->lock); | 140 | spin_lock_bh(&li->lock); |
140 | if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { | 141 | if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { |
141 | kfree(inti); | 142 | kfree(inti); |
143 | if ((action & ACTION_STORE_ON_STOP) != 0) | ||
144 | rc = -ESHUTDOWN; | ||
142 | goto out; | 145 | goto out; |
143 | } | 146 | } |
144 | list_add_tail(&inti->list, &li->list); | 147 | list_add_tail(&inti->list, &li->list); |
@@ -150,7 +153,7 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) | |||
150 | out: | 153 | out: |
151 | spin_unlock_bh(&li->lock); | 154 | spin_unlock_bh(&li->lock); |
152 | 155 | ||
153 | return SIGP_CC_ORDER_CODE_ACCEPTED; | 156 | return rc; |
154 | } | 157 | } |
155 | 158 | ||
156 | static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action) | 159 | static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action) |
@@ -174,13 +177,17 @@ static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action) | |||
174 | unlock: | 177 | unlock: |
175 | spin_unlock(&fi->lock); | 178 | spin_unlock(&fi->lock); |
176 | VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr); | 179 | VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr); |
177 | return rc; | ||
178 | } | ||
179 | 180 | ||
180 | int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action) | 181 | if ((action & ACTION_STORE_ON_STOP) != 0 && rc == -ESHUTDOWN) { |
181 | { | 182 | /* If the CPU has already been stopped, we still have |
182 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 183 | * to save the status when doing stop-and-store. This |
183 | return __inject_sigp_stop(li, action); | 184 | * has to be done after unlocking all spinlocks. */ |
185 | struct kvm_vcpu *dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr); | ||
186 | rc = kvm_s390_store_status_unloaded(dst_vcpu, | ||
187 | KVM_S390_STORE_STATUS_NOADDR); | ||
188 | } | ||
189 | |||
190 | return rc; | ||
184 | } | 191 | } |
185 | 192 | ||
186 | static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) | 193 | static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) |
@@ -262,6 +269,37 @@ out_fi: | |||
262 | return rc; | 269 | return rc; |
263 | } | 270 | } |
264 | 271 | ||
272 | static int __sigp_store_status_at_addr(struct kvm_vcpu *vcpu, u16 cpu_id, | ||
273 | u32 addr, u64 *reg) | ||
274 | { | ||
275 | struct kvm_vcpu *dst_vcpu = NULL; | ||
276 | int flags; | ||
277 | int rc; | ||
278 | |||
279 | if (cpu_id < KVM_MAX_VCPUS) | ||
280 | dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_id); | ||
281 | if (!dst_vcpu) | ||
282 | return SIGP_CC_NOT_OPERATIONAL; | ||
283 | |||
284 | spin_lock_bh(&dst_vcpu->arch.local_int.lock); | ||
285 | flags = atomic_read(dst_vcpu->arch.local_int.cpuflags); | ||
286 | spin_unlock_bh(&dst_vcpu->arch.local_int.lock); | ||
287 | if (!(flags & CPUSTAT_STOPPED)) { | ||
288 | *reg &= 0xffffffff00000000UL; | ||
289 | *reg |= SIGP_STATUS_INCORRECT_STATE; | ||
290 | return SIGP_CC_STATUS_STORED; | ||
291 | } | ||
292 | |||
293 | addr &= 0x7ffffe00; | ||
294 | rc = kvm_s390_store_status_unloaded(dst_vcpu, addr); | ||
295 | if (rc == -EFAULT) { | ||
296 | *reg &= 0xffffffff00000000UL; | ||
297 | *reg |= SIGP_STATUS_INVALID_PARAMETER; | ||
298 | rc = SIGP_CC_STATUS_STORED; | ||
299 | } | ||
300 | return rc; | ||
301 | } | ||
302 | |||
265 | static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, | 303 | static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, |
266 | u64 *reg) | 304 | u64 *reg) |
267 | { | 305 | { |
@@ -366,6 +404,10 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | |||
366 | rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP | | 404 | rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP | |
367 | ACTION_STOP_ON_STOP); | 405 | ACTION_STOP_ON_STOP); |
368 | break; | 406 | break; |
407 | case SIGP_STORE_STATUS_AT_ADDRESS: | ||
408 | rc = __sigp_store_status_at_addr(vcpu, cpu_addr, parameter, | ||
409 | &vcpu->run->s.regs.gprs[r1]); | ||
410 | break; | ||
369 | case SIGP_SET_ARCHITECTURE: | 411 | case SIGP_SET_ARCHITECTURE: |
370 | vcpu->stat.instruction_sigp_arch++; | 412 | vcpu->stat.instruction_sigp_arch++; |
371 | rc = __sigp_set_arch(vcpu, parameter); | 413 | rc = __sigp_set_arch(vcpu, parameter); |
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h index 0c991c6748ab..3db76b2daed7 100644 --- a/arch/s390/kvm/trace.h +++ b/arch/s390/kvm/trace.h | |||
@@ -175,6 +175,7 @@ TRACE_EVENT(kvm_s390_intercept_validity, | |||
175 | {SIGP_STOP_AND_STORE_STATUS, "stop and store status"}, \ | 175 | {SIGP_STOP_AND_STORE_STATUS, "stop and store status"}, \ |
176 | {SIGP_SET_ARCHITECTURE, "set architecture"}, \ | 176 | {SIGP_SET_ARCHITECTURE, "set architecture"}, \ |
177 | {SIGP_SET_PREFIX, "set prefix"}, \ | 177 | {SIGP_SET_PREFIX, "set prefix"}, \ |
178 | {SIGP_STORE_STATUS_AT_ADDRESS, "store status at addr"}, \ | ||
178 | {SIGP_SENSE_RUNNING, "sense running"}, \ | 179 | {SIGP_SENSE_RUNNING, "sense running"}, \ |
179 | {SIGP_RESTART, "restart"} | 180 | {SIGP_RESTART, "restart"} |
180 | 181 | ||