diff options
| -rw-r--r-- | Documentation/virtual/kvm/api.txt | 9 | ||||
| -rw-r--r-- | Documentation/virtual/kvm/devices/s390_flic.txt | 5 | ||||
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 26 | ||||
| -rw-r--r-- | arch/s390/include/asm/sysinfo.h | 1 | ||||
| -rw-r--r-- | arch/s390/include/uapi/asm/sthyi.h | 6 | ||||
| -rw-r--r-- | arch/s390/include/uapi/asm/unistd.h | 3 | ||||
| -rw-r--r-- | arch/s390/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/compat_wrapper.c | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.h | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/sthyi.c (renamed from arch/s390/kvm/sthyi.c) | 172 | ||||
| -rw-r--r-- | arch/s390/kernel/syscalls.S | 1 | ||||
| -rw-r--r-- | arch/s390/kvm/Makefile | 2 | ||||
| -rw-r--r-- | arch/s390/kvm/intercept.c | 56 | ||||
| -rw-r--r-- | arch/s390/kvm/interrupt.c | 26 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 3 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.h | 5 | ||||
| -rw-r--r-- | arch/s390/kvm/vsie.c | 50 | ||||
| -rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
| -rw-r--r-- | include/uapi/linux/kvm.h | 1 | ||||
| -rw-r--r-- | virt/kvm/kvm_main.c | 4 |
20 files changed, 262 insertions, 113 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index dd2dd96927b8..f670e4b9e7f3 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
| @@ -4351,3 +4351,12 @@ This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr. Its | |||
| 4351 | value is used to denote the target vcpu for a SynIC interrupt. For | 4351 | value is used to denote the target vcpu for a SynIC interrupt. For |
| 4352 | compatibilty, KVM initializes this msr to KVM's internal vcpu index. When this | 4352 | compatibilty, KVM initializes this msr to KVM's internal vcpu index. When this |
| 4353 | capability is absent, userspace can still query this msr's value. | 4353 | capability is absent, userspace can still query this msr's value. |
| 4354 | |||
| 4355 | 8.13 KVM_CAP_S390_AIS_MIGRATION | ||
| 4356 | |||
| 4357 | Architectures: s390 | ||
| 4358 | Parameters: none | ||
| 4359 | |||
| 4360 | This capability indicates if the flic device will be able to get/set the | ||
| 4361 | AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows | ||
| 4362 | to discover this without having to create a flic device. | ||
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt index 2f1cbf1301d2..a4e20a090174 100644 --- a/Documentation/virtual/kvm/devices/s390_flic.txt +++ b/Documentation/virtual/kvm/devices/s390_flic.txt | |||
| @@ -151,8 +151,13 @@ struct kvm_s390_ais_all { | |||
| 151 | to an ISC (MSB0 bit 0 to ISC 0 and so on). The combination of simm bit and | 151 | to an ISC (MSB0 bit 0 to ISC 0 and so on). The combination of simm bit and |
| 152 | nimm bit presents AIS mode for a ISC. | 152 | nimm bit presents AIS mode for a ISC. |
| 153 | 153 | ||
| 154 | KVM_DEV_FLIC_AISM_ALL is indicated by KVM_CAP_S390_AIS_MIGRATION. | ||
| 155 | |||
| 154 | Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on | 156 | Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on |
| 155 | FLIC with an unknown group or attribute gives the error code EINVAL (instead of | 157 | FLIC with an unknown group or attribute gives the error code EINVAL (instead of |
| 156 | ENXIO, as specified in the API documentation). It is not possible to conclude | 158 | ENXIO, as specified in the API documentation). It is not possible to conclude |
| 157 | that a FLIC operation is unavailable based on the error code resulting from a | 159 | that a FLIC operation is unavailable based on the error code resulting from a |
| 158 | usage attempt. | 160 | usage attempt. |
| 161 | |||
| 162 | Note: The KVM_DEV_FLIC_CLEAR_IO_IRQ ioctl will return EINVAL in case a zero | ||
| 163 | schid is specified. | ||
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 51375e766e90..f3a9b5a445b6 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
| @@ -685,11 +685,28 @@ struct kvm_s390_crypto { | |||
| 685 | __u8 dea_kw; | 685 | __u8 dea_kw; |
| 686 | }; | 686 | }; |
| 687 | 687 | ||
| 688 | #define APCB0_MASK_SIZE 1 | ||
| 689 | struct kvm_s390_apcb0 { | ||
| 690 | __u64 apm[APCB0_MASK_SIZE]; /* 0x0000 */ | ||
| 691 | __u64 aqm[APCB0_MASK_SIZE]; /* 0x0008 */ | ||
| 692 | __u64 adm[APCB0_MASK_SIZE]; /* 0x0010 */ | ||
| 693 | __u64 reserved18; /* 0x0018 */ | ||
| 694 | }; | ||
| 695 | |||
| 696 | #define APCB1_MASK_SIZE 4 | ||
| 697 | struct kvm_s390_apcb1 { | ||
| 698 | __u64 apm[APCB1_MASK_SIZE]; /* 0x0000 */ | ||
| 699 | __u64 aqm[APCB1_MASK_SIZE]; /* 0x0020 */ | ||
| 700 | __u64 adm[APCB1_MASK_SIZE]; /* 0x0040 */ | ||
| 701 | __u64 reserved60[4]; /* 0x0060 */ | ||
| 702 | }; | ||
| 703 | |||
| 688 | struct kvm_s390_crypto_cb { | 704 | struct kvm_s390_crypto_cb { |
| 689 | __u8 reserved00[72]; /* 0x0000 */ | 705 | struct kvm_s390_apcb0 apcb0; /* 0x0000 */ |
| 690 | __u8 dea_wrapping_key_mask[24]; /* 0x0048 */ | 706 | __u8 reserved20[0x0048 - 0x0020]; /* 0x0020 */ |
| 691 | __u8 aes_wrapping_key_mask[32]; /* 0x0060 */ | 707 | __u8 dea_wrapping_key_mask[24]; /* 0x0048 */ |
| 692 | __u8 reserved80[128]; /* 0x0080 */ | 708 | __u8 aes_wrapping_key_mask[32]; /* 0x0060 */ |
| 709 | struct kvm_s390_apcb1 apcb1; /* 0x0080 */ | ||
| 693 | }; | 710 | }; |
| 694 | 711 | ||
| 695 | /* | 712 | /* |
| @@ -736,7 +753,6 @@ struct kvm_arch{ | |||
| 736 | wait_queue_head_t ipte_wq; | 753 | wait_queue_head_t ipte_wq; |
| 737 | int ipte_lock_count; | 754 | int ipte_lock_count; |
| 738 | struct mutex ipte_mutex; | 755 | struct mutex ipte_mutex; |
| 739 | struct ratelimit_state sthyi_limit; | ||
| 740 | spinlock_t start_stop_lock; | 756 | spinlock_t start_stop_lock; |
| 741 | struct sie_page2 *sie_page2; | 757 | struct sie_page2 *sie_page2; |
| 742 | struct kvm_s390_cpu_model model; | 758 | struct kvm_s390_cpu_model model; |
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index 2b498e58b914..e4a28307bc5d 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h | |||
| @@ -198,4 +198,5 @@ struct service_level { | |||
| 198 | int register_service_level(struct service_level *); | 198 | int register_service_level(struct service_level *); |
| 199 | int unregister_service_level(struct service_level *); | 199 | int unregister_service_level(struct service_level *); |
| 200 | 200 | ||
| 201 | int sthyi_fill(void *dst, u64 *rc); | ||
| 201 | #endif /* __ASM_S390_SYSINFO_H */ | 202 | #endif /* __ASM_S390_SYSINFO_H */ |
diff --git a/arch/s390/include/uapi/asm/sthyi.h b/arch/s390/include/uapi/asm/sthyi.h new file mode 100644 index 000000000000..ec113db4eb7e --- /dev/null +++ b/arch/s390/include/uapi/asm/sthyi.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #ifndef _UAPI_ASM_STHYI_H | ||
| 2 | #define _UAPI_ASM_STHYI_H | ||
| 3 | |||
| 4 | #define STHYI_FC_CP_IFL_CAP 0 | ||
| 5 | |||
| 6 | #endif /* _UAPI_ASM_STHYI_H */ | ||
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h index ea42290e7d51..61c64f543769 100644 --- a/arch/s390/include/uapi/asm/unistd.h +++ b/arch/s390/include/uapi/asm/unistd.h | |||
| @@ -315,7 +315,8 @@ | |||
| 315 | #define __NR_pwritev2 377 | 315 | #define __NR_pwritev2 377 |
| 316 | #define __NR_s390_guarded_storage 378 | 316 | #define __NR_s390_guarded_storage 378 |
| 317 | #define __NR_statx 379 | 317 | #define __NR_statx 379 |
| 318 | #define NR_syscalls 380 | 318 | #define __NR_s390_sthyi 380 |
| 319 | #define NR_syscalls 381 | ||
| 319 | 320 | ||
| 320 | /* | 321 | /* |
| 321 | * There are some system calls that are not present on 64 bit, some | 322 | * There are some system calls that are not present on 64 bit, some |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index adb3fe2e3d42..1fefb7f9216f 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
| @@ -55,7 +55,7 @@ obj-y := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o | |||
| 55 | obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o | 55 | obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o |
| 56 | obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o als.o | 56 | obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o als.o |
| 57 | obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o | 57 | obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o |
| 58 | obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o | 58 | obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o |
| 59 | obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o | 59 | obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o |
| 60 | 60 | ||
| 61 | extra-y += head.o head64.o vmlinux.lds | 61 | extra-y += head.o head64.o vmlinux.lds |
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c index 986642a3543b..eb0b17ed95b6 100644 --- a/arch/s390/kernel/compat_wrapper.c +++ b/arch/s390/kernel/compat_wrapper.c | |||
| @@ -180,3 +180,4 @@ COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags); | |||
| 180 | COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags); | 180 | COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags); |
| 181 | COMPAT_SYSCALL_WRAP2(s390_guarded_storage, int, command, struct gs_cb *, gs_cb); | 181 | COMPAT_SYSCALL_WRAP2(s390_guarded_storage, int, command, struct gs_cb *, gs_cb); |
| 182 | COMPAT_SYSCALL_WRAP5(statx, int, dfd, const char __user *, path, unsigned, flags, unsigned, mask, struct statx __user *, buffer); | 182 | COMPAT_SYSCALL_WRAP5(statx, int, dfd, const char __user *, path, unsigned, flags, unsigned, mask, struct statx __user *, buffer); |
| 183 | COMPAT_SYSCALL_WRAP4(s390_sthyi, unsigned long, code, void __user *, info, u64 __user *, rc, unsigned long, flags); | ||
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index dbf5f7e18246..bb5301eeb4f4 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
| @@ -77,6 +77,7 @@ long sys_s390_runtime_instr(int command, int signum); | |||
| 77 | long sys_s390_guarded_storage(int command, struct gs_cb __user *); | 77 | long sys_s390_guarded_storage(int command, struct gs_cb __user *); |
| 78 | long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t); | 78 | long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t); |
| 79 | long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t); | 79 | long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t); |
| 80 | long sys_s390_sthyi(unsigned long function_code, void __user *buffer, u64 __user *return_code, unsigned long flags); | ||
| 80 | 81 | ||
| 81 | DECLARE_PER_CPU(u64, mt_cycles[8]); | 82 | DECLARE_PER_CPU(u64, mt_cycles[8]); |
| 82 | 83 | ||
diff --git a/arch/s390/kvm/sthyi.c b/arch/s390/kernel/sthyi.c index 395926b8c1ed..12981e197f01 100644 --- a/arch/s390/kvm/sthyi.c +++ b/arch/s390/kernel/sthyi.c | |||
| @@ -8,22 +8,19 @@ | |||
| 8 | * Copyright IBM Corp. 2016 | 8 | * Copyright IBM Corp. 2016 |
| 9 | * Author(s): Janosch Frank <frankja@linux.vnet.ibm.com> | 9 | * Author(s): Janosch Frank <frankja@linux.vnet.ibm.com> |
| 10 | */ | 10 | */ |
| 11 | #include <linux/kvm_host.h> | ||
| 12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| 13 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
| 14 | #include <linux/vmalloc.h> | 13 | #include <linux/vmalloc.h> |
| 15 | #include <linux/ratelimit.h> | 14 | #include <linux/syscalls.h> |
| 16 | 15 | #include <linux/mutex.h> | |
| 17 | #include <asm/kvm_host.h> | ||
| 18 | #include <asm/asm-offsets.h> | 16 | #include <asm/asm-offsets.h> |
| 19 | #include <asm/sclp.h> | 17 | #include <asm/sclp.h> |
| 20 | #include <asm/diag.h> | 18 | #include <asm/diag.h> |
| 21 | #include <asm/sysinfo.h> | 19 | #include <asm/sysinfo.h> |
| 22 | #include <asm/ebcdic.h> | 20 | #include <asm/ebcdic.h> |
| 23 | 21 | #include <asm/facility.h> | |
| 24 | #include "kvm-s390.h" | 22 | #include <asm/sthyi.h> |
| 25 | #include "gaccess.h" | 23 | #include "entry.h" |
| 26 | #include "trace.h" | ||
| 27 | 24 | ||
| 28 | #define DED_WEIGHT 0xffff | 25 | #define DED_WEIGHT 0xffff |
| 29 | /* | 26 | /* |
| @@ -144,6 +141,21 @@ struct lpar_cpu_inf { | |||
| 144 | struct cpu_inf ifl; | 141 | struct cpu_inf ifl; |
| 145 | }; | 142 | }; |
| 146 | 143 | ||
| 144 | /* | ||
| 145 | * STHYI requires extensive locking in the higher hypervisors | ||
| 146 | * and is very computational/memory expensive. Therefore we | ||
| 147 | * cache the retrieved data whose valid period is 1s. | ||
| 148 | */ | ||
| 149 | #define CACHE_VALID_JIFFIES HZ | ||
| 150 | |||
| 151 | struct sthyi_info { | ||
| 152 | void *info; | ||
| 153 | unsigned long end; | ||
| 154 | }; | ||
| 155 | |||
| 156 | static DEFINE_MUTEX(sthyi_mutex); | ||
| 157 | static struct sthyi_info sthyi_cache; | ||
| 158 | |||
| 147 | static inline u64 cpu_id(u8 ctidx, void *diag224_buf) | 159 | static inline u64 cpu_id(u8 ctidx, void *diag224_buf) |
| 148 | { | 160 | { |
| 149 | return *((u64 *)(diag224_buf + (ctidx + 1) * DIAG204_CPU_NAME_LEN)); | 161 | return *((u64 *)(diag224_buf + (ctidx + 1) * DIAG204_CPU_NAME_LEN)); |
| @@ -382,88 +394,124 @@ out: | |||
| 382 | vfree(diag204_buf); | 394 | vfree(diag204_buf); |
| 383 | } | 395 | } |
| 384 | 396 | ||
| 385 | static int sthyi(u64 vaddr) | 397 | static int sthyi(u64 vaddr, u64 *rc) |
| 386 | { | 398 | { |
| 387 | register u64 code asm("0") = 0; | 399 | register u64 code asm("0") = 0; |
| 388 | register u64 addr asm("2") = vaddr; | 400 | register u64 addr asm("2") = vaddr; |
| 401 | register u64 rcode asm("3"); | ||
| 389 | int cc; | 402 | int cc; |
| 390 | 403 | ||
| 391 | asm volatile( | 404 | asm volatile( |
| 392 | ".insn rre,0xB2560000,%[code],%[addr]\n" | 405 | ".insn rre,0xB2560000,%[code],%[addr]\n" |
| 393 | "ipm %[cc]\n" | 406 | "ipm %[cc]\n" |
| 394 | "srl %[cc],28\n" | 407 | "srl %[cc],28\n" |
| 395 | : [cc] "=d" (cc) | 408 | : [cc] "=d" (cc), "=d" (rcode) |
| 396 | : [code] "d" (code), [addr] "a" (addr) | 409 | : [code] "d" (code), [addr] "a" (addr) |
| 397 | : "3", "memory", "cc"); | 410 | : "memory", "cc"); |
| 411 | *rc = rcode; | ||
| 398 | return cc; | 412 | return cc; |
| 399 | } | 413 | } |
| 400 | 414 | ||
| 401 | int handle_sthyi(struct kvm_vcpu *vcpu) | 415 | static int fill_dst(void *dst, u64 *rc) |
| 402 | { | 416 | { |
| 403 | int reg1, reg2, r = 0; | 417 | struct sthyi_sctns *sctns = (struct sthyi_sctns *)dst; |
| 404 | u64 code, addr, cc = 0; | ||
| 405 | struct sthyi_sctns *sctns = NULL; | ||
| 406 | |||
| 407 | if (!test_kvm_facility(vcpu->kvm, 74)) | ||
| 408 | return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); | ||
| 409 | 418 | ||
| 410 | /* | 419 | /* |
| 411 | * STHYI requires extensive locking in the higher hypervisors | 420 | * If the facility is on, we don't want to emulate the instruction. |
| 412 | * and is very computational/memory expensive. Therefore we | 421 | * We ask the hypervisor to provide the data. |
| 413 | * ratelimit the executions per VM. | ||
| 414 | */ | 422 | */ |
| 415 | if (!__ratelimit(&vcpu->kvm->arch.sthyi_limit)) { | 423 | if (test_facility(74)) |
| 416 | kvm_s390_retry_instr(vcpu); | 424 | return sthyi((u64)dst, rc); |
| 425 | |||
| 426 | fill_hdr(sctns); | ||
| 427 | fill_stsi(sctns); | ||
| 428 | fill_diag(sctns); | ||
| 429 | *rc = 0; | ||
| 430 | return 0; | ||
| 431 | } | ||
| 432 | |||
| 433 | static int sthyi_init_cache(void) | ||
| 434 | { | ||
| 435 | if (sthyi_cache.info) | ||
| 417 | return 0; | 436 | return 0; |
| 418 | } | 437 | sthyi_cache.info = (void *)get_zeroed_page(GFP_KERNEL); |
| 438 | if (!sthyi_cache.info) | ||
| 439 | return -ENOMEM; | ||
| 440 | sthyi_cache.end = jiffies - 1; /* expired */ | ||
| 441 | return 0; | ||
| 442 | } | ||
| 419 | 443 | ||
| 420 | kvm_s390_get_regs_rre(vcpu, ®1, ®2); | 444 | static int sthyi_update_cache(u64 *rc) |
| 421 | code = vcpu->run->s.regs.gprs[reg1]; | 445 | { |
| 422 | addr = vcpu->run->s.regs.gprs[reg2]; | 446 | int r; |
| 423 | 447 | ||
| 424 | vcpu->stat.instruction_sthyi++; | 448 | memset(sthyi_cache.info, 0, PAGE_SIZE); |
| 425 | VCPU_EVENT(vcpu, 3, "STHYI: fc: %llu addr: 0x%016llx", code, addr); | 449 | r = fill_dst(sthyi_cache.info, rc); |
| 426 | trace_kvm_s390_handle_sthyi(vcpu, code, addr); | 450 | if (r) |
| 451 | return r; | ||
| 452 | sthyi_cache.end = jiffies + CACHE_VALID_JIFFIES; | ||
| 453 | return r; | ||
| 454 | } | ||
| 427 | 455 | ||
| 428 | if (reg1 == reg2 || reg1 & 1 || reg2 & 1) | 456 | /* |
| 429 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 457 | * sthyi_fill - Fill page with data returned by the STHYI instruction |
| 458 | * | ||
| 459 | * @dst: Pointer to zeroed page | ||
| 460 | * @rc: Pointer for storing the return code of the instruction | ||
| 461 | * | ||
| 462 | * Fills the destination with system information returned by the STHYI | ||
| 463 | * instruction. The data is generated by emulation or execution of STHYI, | ||
| 464 | * if available. The return value is the condition code that would be | ||
| 465 | * returned, the rc parameter is the return code which is passed in | ||
| 466 | * register R2 + 1. | ||
| 467 | */ | ||
| 468 | int sthyi_fill(void *dst, u64 *rc) | ||
| 469 | { | ||
| 470 | int r; | ||
| 430 | 471 | ||
| 431 | if (code & 0xffff) { | 472 | mutex_lock(&sthyi_mutex); |
| 432 | cc = 3; | 473 | r = sthyi_init_cache(); |
| 474 | if (r) | ||
| 433 | goto out; | 475 | goto out; |
| 434 | } | ||
| 435 | 476 | ||
| 436 | if (addr & ~PAGE_MASK) | 477 | if (time_is_before_jiffies(sthyi_cache.end)) { |
| 437 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 478 | /* cache expired */ |
| 479 | r = sthyi_update_cache(rc); | ||
| 480 | if (r) | ||
| 481 | goto out; | ||
| 482 | } | ||
| 483 | *rc = 0; | ||
| 484 | memcpy(dst, sthyi_cache.info, PAGE_SIZE); | ||
| 485 | out: | ||
| 486 | mutex_unlock(&sthyi_mutex); | ||
| 487 | return r; | ||
| 488 | } | ||
| 489 | EXPORT_SYMBOL_GPL(sthyi_fill); | ||
| 438 | 490 | ||
| 439 | sctns = (void *)get_zeroed_page(GFP_KERNEL); | 491 | SYSCALL_DEFINE4(s390_sthyi, unsigned long, function_code, void __user *, buffer, |
| 440 | if (!sctns) | 492 | u64 __user *, return_code, unsigned long, flags) |
| 493 | { | ||
| 494 | u64 sthyi_rc; | ||
| 495 | void *info; | ||
| 496 | int r; | ||
| 497 | |||
| 498 | if (flags) | ||
| 499 | return -EINVAL; | ||
| 500 | if (function_code != STHYI_FC_CP_IFL_CAP) | ||
| 501 | return -EOPNOTSUPP; | ||
| 502 | info = (void *)get_zeroed_page(GFP_KERNEL); | ||
| 503 | if (!info) | ||
| 441 | return -ENOMEM; | 504 | return -ENOMEM; |
| 442 | 505 | r = sthyi_fill(info, &sthyi_rc); | |
| 443 | /* | 506 | if (r < 0) |
| 444 | * If we are a guest, we don't want to emulate an emulated | 507 | goto out; |
| 445 | * instruction. We ask the hypervisor to provide the data. | 508 | if (return_code && put_user(sthyi_rc, return_code)) { |
| 446 | */ | 509 | r = -EFAULT; |
| 447 | if (test_facility(74)) { | ||
| 448 | cc = sthyi((u64)sctns); | ||
| 449 | goto out; | 510 | goto out; |
| 450 | } | 511 | } |
| 451 | 512 | if (copy_to_user(buffer, info, PAGE_SIZE)) | |
| 452 | fill_hdr(sctns); | 513 | r = -EFAULT; |
| 453 | fill_stsi(sctns); | ||
| 454 | fill_diag(sctns); | ||
| 455 | |||
| 456 | out: | 514 | out: |
| 457 | if (!cc) { | 515 | free_page((unsigned long)info); |
| 458 | r = write_guest(vcpu, addr, reg2, sctns, PAGE_SIZE); | ||
| 459 | if (r) { | ||
| 460 | free_page((unsigned long)sctns); | ||
| 461 | return kvm_s390_inject_prog_cond(vcpu, r); | ||
| 462 | } | ||
| 463 | } | ||
| 464 | |||
| 465 | free_page((unsigned long)sctns); | ||
| 466 | vcpu->run->s.regs.gprs[reg2 + 1] = cc ? 4 : 0; | ||
| 467 | kvm_s390_set_psw_cc(vcpu, cc); | ||
| 468 | return r; | 516 | return r; |
| 469 | } | 517 | } |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 54fce7b065de..0fb407ebbf46 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
| @@ -388,3 +388,4 @@ SYSCALL(sys_preadv2,compat_sys_preadv2) | |||
| 388 | SYSCALL(sys_pwritev2,compat_sys_pwritev2) | 388 | SYSCALL(sys_pwritev2,compat_sys_pwritev2) |
| 389 | SYSCALL(sys_s390_guarded_storage,compat_sys_s390_guarded_storage) /* 378 */ | 389 | SYSCALL(sys_s390_guarded_storage,compat_sys_s390_guarded_storage) /* 378 */ |
| 390 | SYSCALL(sys_statx,compat_sys_statx) | 390 | SYSCALL(sys_statx,compat_sys_statx) |
| 391 | SYSCALL(sys_s390_sthyi,compat_sys_s390_sthyi) | ||
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile index 09a9e6dfc09f..6048b1c6e580 100644 --- a/arch/s390/kvm/Makefile +++ b/arch/s390/kvm/Makefile | |||
| @@ -12,6 +12,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqch | |||
| 12 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm | 12 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm |
| 13 | 13 | ||
| 14 | kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o | 14 | kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o |
| 15 | kvm-objs += diag.o gaccess.o guestdbg.o sthyi.o vsie.o | 15 | kvm-objs += diag.o gaccess.o guestdbg.o vsie.o |
| 16 | 16 | ||
| 17 | obj-$(CONFIG_KVM) += kvm.o | 17 | obj-$(CONFIG_KVM) += kvm.o |
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index a4752bf6b526..8fe034beb623 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <asm/kvm_host.h> | 18 | #include <asm/kvm_host.h> |
| 19 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> |
| 20 | #include <asm/irq.h> | 20 | #include <asm/irq.h> |
| 21 | #include <asm/sysinfo.h> | ||
| 21 | 22 | ||
| 22 | #include "kvm-s390.h" | 23 | #include "kvm-s390.h" |
| 23 | #include "gaccess.h" | 24 | #include "gaccess.h" |
| @@ -360,6 +361,61 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu) | |||
| 360 | return -EOPNOTSUPP; | 361 | return -EOPNOTSUPP; |
| 361 | } | 362 | } |
| 362 | 363 | ||
| 364 | /* | ||
| 365 | * Handle the sthyi instruction that provides the guest with system | ||
| 366 | * information, like current CPU resources available at each level of | ||
| 367 | * the machine. | ||
| 368 | */ | ||
| 369 | int handle_sthyi(struct kvm_vcpu *vcpu) | ||
| 370 | { | ||
| 371 | int reg1, reg2, r = 0; | ||
| 372 | u64 code, addr, cc = 0, rc = 0; | ||
| 373 | struct sthyi_sctns *sctns = NULL; | ||
| 374 | |||
| 375 | if (!test_kvm_facility(vcpu->kvm, 74)) | ||
| 376 | return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); | ||
| 377 | |||
| 378 | kvm_s390_get_regs_rre(vcpu, ®1, ®2); | ||
| 379 | code = vcpu->run->s.regs.gprs[reg1]; | ||
| 380 | addr = vcpu->run->s.regs.gprs[reg2]; | ||
| 381 | |||
| 382 | vcpu->stat.instruction_sthyi++; | ||
| 383 | VCPU_EVENT(vcpu, 3, "STHYI: fc: %llu addr: 0x%016llx", code, addr); | ||
| 384 | trace_kvm_s390_handle_sthyi(vcpu, code, addr); | ||
| 385 | |||
| 386 | if (reg1 == reg2 || reg1 & 1 || reg2 & 1) | ||
| 387 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
| 388 | |||
| 389 | if (code & 0xffff) { | ||
| 390 | cc = 3; | ||
| 391 | rc = 4; | ||
| 392 | goto out; | ||
| 393 | } | ||
| 394 | |||
| 395 | if (addr & ~PAGE_MASK) | ||
| 396 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
| 397 | |||
| 398 | sctns = (void *)get_zeroed_page(GFP_KERNEL); | ||
| 399 | if (!sctns) | ||
| 400 | return -ENOMEM; | ||
| 401 | |||
| 402 | cc = sthyi_fill(sctns, &rc); | ||
| 403 | |||
| 404 | out: | ||
| 405 | if (!cc) { | ||
| 406 | r = write_guest(vcpu, addr, reg2, sctns, PAGE_SIZE); | ||
| 407 | if (r) { | ||
| 408 | free_page((unsigned long)sctns); | ||
| 409 | return kvm_s390_inject_prog_cond(vcpu, r); | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | free_page((unsigned long)sctns); | ||
| 414 | vcpu->run->s.regs.gprs[reg2 + 1] = rc; | ||
| 415 | kvm_s390_set_psw_cc(vcpu, cc); | ||
| 416 | return r; | ||
| 417 | } | ||
| 418 | |||
| 363 | static int handle_operexc(struct kvm_vcpu *vcpu) | 419 | static int handle_operexc(struct kvm_vcpu *vcpu) |
| 364 | { | 420 | { |
| 365 | psw_t oldpsw, newpsw; | 421 | psw_t oldpsw, newpsw; |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index a832ad031cee..c8aacced23fb 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
| @@ -213,6 +213,16 @@ static inline unsigned long pending_irqs(struct kvm_vcpu *vcpu) | |||
| 213 | vcpu->arch.local_int.pending_irqs; | 213 | vcpu->arch.local_int.pending_irqs; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | static inline int isc_to_irq_type(unsigned long isc) | ||
| 217 | { | ||
| 218 | return IRQ_PEND_IO_ISC_0 + isc; | ||
| 219 | } | ||
| 220 | |||
| 221 | static inline int irq_type_to_isc(unsigned long irq_type) | ||
| 222 | { | ||
| 223 | return irq_type - IRQ_PEND_IO_ISC_0; | ||
| 224 | } | ||
| 225 | |||
| 216 | static unsigned long disable_iscs(struct kvm_vcpu *vcpu, | 226 | static unsigned long disable_iscs(struct kvm_vcpu *vcpu, |
| 217 | unsigned long active_mask) | 227 | unsigned long active_mask) |
| 218 | { | 228 | { |
| @@ -220,7 +230,7 @@ static unsigned long disable_iscs(struct kvm_vcpu *vcpu, | |||
| 220 | 230 | ||
| 221 | for (i = 0; i <= MAX_ISC; i++) | 231 | for (i = 0; i <= MAX_ISC; i++) |
| 222 | if (!(vcpu->arch.sie_block->gcr[6] & isc_to_isc_bits(i))) | 232 | if (!(vcpu->arch.sie_block->gcr[6] & isc_to_isc_bits(i))) |
| 223 | active_mask &= ~(1UL << (IRQ_PEND_IO_ISC_0 + i)); | 233 | active_mask &= ~(1UL << (isc_to_irq_type(i))); |
| 224 | 234 | ||
| 225 | return active_mask; | 235 | return active_mask; |
| 226 | } | 236 | } |
| @@ -901,7 +911,7 @@ static int __must_check __deliver_io(struct kvm_vcpu *vcpu, | |||
| 901 | fi = &vcpu->kvm->arch.float_int; | 911 | fi = &vcpu->kvm->arch.float_int; |
| 902 | 912 | ||
| 903 | spin_lock(&fi->lock); | 913 | spin_lock(&fi->lock); |
| 904 | isc_list = &fi->lists[irq_type - IRQ_PEND_IO_ISC_0]; | 914 | isc_list = &fi->lists[irq_type_to_isc(irq_type)]; |
| 905 | inti = list_first_entry_or_null(isc_list, | 915 | inti = list_first_entry_or_null(isc_list, |
| 906 | struct kvm_s390_interrupt_info, | 916 | struct kvm_s390_interrupt_info, |
| 907 | list); | 917 | list); |
| @@ -1074,6 +1084,12 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) | |||
| 1074 | * in kvm_vcpu_block without having the waitqueue set (polling) | 1084 | * in kvm_vcpu_block without having the waitqueue set (polling) |
| 1075 | */ | 1085 | */ |
| 1076 | vcpu->valid_wakeup = true; | 1086 | vcpu->valid_wakeup = true; |
| 1087 | /* | ||
| 1088 | * This is mostly to document, that the read in swait_active could | ||
| 1089 | * be moved before other stores, leading to subtle races. | ||
| 1090 | * All current users do not store or use an atomic like update | ||
| 1091 | */ | ||
| 1092 | smp_mb__after_atomic(); | ||
| 1077 | if (swait_active(&vcpu->wq)) { | 1093 | if (swait_active(&vcpu->wq)) { |
| 1078 | /* | 1094 | /* |
| 1079 | * The vcpu gave up the cpu voluntarily, mark it as a good | 1095 | * The vcpu gave up the cpu voluntarily, mark it as a good |
| @@ -1395,7 +1411,7 @@ static struct kvm_s390_interrupt_info *get_io_int(struct kvm *kvm, | |||
| 1395 | list_del_init(&iter->list); | 1411 | list_del_init(&iter->list); |
| 1396 | fi->counters[FIRQ_CNTR_IO] -= 1; | 1412 | fi->counters[FIRQ_CNTR_IO] -= 1; |
| 1397 | if (list_empty(isc_list)) | 1413 | if (list_empty(isc_list)) |
| 1398 | clear_bit(IRQ_PEND_IO_ISC_0 + isc, &fi->pending_irqs); | 1414 | clear_bit(isc_to_irq_type(isc), &fi->pending_irqs); |
| 1399 | spin_unlock(&fi->lock); | 1415 | spin_unlock(&fi->lock); |
| 1400 | return iter; | 1416 | return iter; |
| 1401 | } | 1417 | } |
| @@ -1522,7 +1538,7 @@ static int __inject_io(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) | |||
| 1522 | isc = int_word_to_isc(inti->io.io_int_word); | 1538 | isc = int_word_to_isc(inti->io.io_int_word); |
| 1523 | list = &fi->lists[FIRQ_LIST_IO_ISC_0 + isc]; | 1539 | list = &fi->lists[FIRQ_LIST_IO_ISC_0 + isc]; |
| 1524 | list_add_tail(&inti->list, list); | 1540 | list_add_tail(&inti->list, list); |
| 1525 | set_bit(IRQ_PEND_IO_ISC_0 + isc, &fi->pending_irqs); | 1541 | set_bit(isc_to_irq_type(isc), &fi->pending_irqs); |
| 1526 | spin_unlock(&fi->lock); | 1542 | spin_unlock(&fi->lock); |
| 1527 | return 0; | 1543 | return 0; |
| 1528 | } | 1544 | } |
| @@ -2175,6 +2191,8 @@ static int clear_io_irq(struct kvm *kvm, struct kvm_device_attr *attr) | |||
| 2175 | return -EINVAL; | 2191 | return -EINVAL; |
| 2176 | if (copy_from_user(&schid, (void __user *) attr->addr, sizeof(schid))) | 2192 | if (copy_from_user(&schid, (void __user *) attr->addr, sizeof(schid))) |
| 2177 | return -EFAULT; | 2193 | return -EFAULT; |
| 2194 | if (!schid) | ||
| 2195 | return -EINVAL; | ||
| 2178 | kfree(kvm_s390_get_io_int(kvm, isc_mask, schid)); | 2196 | kfree(kvm_s390_get_io_int(kvm, isc_mask, schid)); |
| 2179 | /* | 2197 | /* |
| 2180 | * If userspace is conforming to the architecture, we can have at most | 2198 | * If userspace is conforming to the architecture, we can have at most |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 40d0a1a97889..8f4b655f65d7 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
| @@ -395,6 +395,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) | |||
| 395 | case KVM_CAP_S390_USER_INSTR0: | 395 | case KVM_CAP_S390_USER_INSTR0: |
| 396 | case KVM_CAP_S390_CMMA_MIGRATION: | 396 | case KVM_CAP_S390_CMMA_MIGRATION: |
| 397 | case KVM_CAP_S390_AIS: | 397 | case KVM_CAP_S390_AIS: |
| 398 | case KVM_CAP_S390_AIS_MIGRATION: | ||
| 398 | r = 1; | 399 | r = 1; |
| 399 | break; | 400 | break; |
| 400 | case KVM_CAP_S390_MEM_OP: | 401 | case KVM_CAP_S390_MEM_OP: |
| @@ -1884,8 +1885,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
| 1884 | 1885 | ||
| 1885 | rc = -ENOMEM; | 1886 | rc = -ENOMEM; |
| 1886 | 1887 | ||
| 1887 | ratelimit_state_init(&kvm->arch.sthyi_limit, 5 * HZ, 500); | ||
| 1888 | |||
| 1889 | kvm->arch.use_esca = 0; /* start with basic SCA */ | 1888 | kvm->arch.use_esca = 0; /* start with basic SCA */ |
| 1890 | if (!sclp.has_64bscao) | 1889 | if (!sclp.has_64bscao) |
| 1891 | alloc_flags |= GFP_DMA; | 1890 | alloc_flags |= GFP_DMA; |
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 9f8fdd7b2311..10d65dfbc306 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
| @@ -242,6 +242,8 @@ static inline void kvm_s390_retry_instr(struct kvm_vcpu *vcpu) | |||
| 242 | kvm_s390_rewind_psw(vcpu, kvm_s390_get_ilen(vcpu)); | 242 | kvm_s390_rewind_psw(vcpu, kvm_s390_get_ilen(vcpu)); |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | int handle_sthyi(struct kvm_vcpu *vcpu); | ||
| 246 | |||
| 245 | /* implemented in priv.c */ | 247 | /* implemented in priv.c */ |
| 246 | int is_valid_psw(psw_t *psw); | 248 | int is_valid_psw(psw_t *psw); |
| 247 | int kvm_s390_handle_aa(struct kvm_vcpu *vcpu); | 249 | int kvm_s390_handle_aa(struct kvm_vcpu *vcpu); |
| @@ -268,9 +270,6 @@ void kvm_s390_vsie_destroy(struct kvm *kvm); | |||
| 268 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); | 270 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); |
| 269 | int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu); | 271 | int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu); |
| 270 | 272 | ||
| 271 | /* implemented in sthyi.c */ | ||
| 272 | int handle_sthyi(struct kvm_vcpu *vcpu); | ||
| 273 | |||
| 274 | /* implemented in kvm-s390.c */ | 273 | /* implemented in kvm-s390.c */ |
| 275 | void kvm_s390_set_tod_clock_ext(struct kvm *kvm, | 274 | void kvm_s390_set_tod_clock_ext(struct kvm *kvm, |
| 276 | const struct kvm_s390_vm_tod_clock *gtod); | 275 | const struct kvm_s390_vm_tod_clock *gtod); |
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index b18b5652e5c5..a311938b63b3 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c | |||
| @@ -443,22 +443,14 @@ static int map_prefix(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) | |||
| 443 | * | 443 | * |
| 444 | * Returns: - 0 on success | 444 | * Returns: - 0 on success |
| 445 | * - -EINVAL if the gpa is not valid guest storage | 445 | * - -EINVAL if the gpa is not valid guest storage |
| 446 | * - -ENOMEM if out of memory | ||
| 447 | */ | 446 | */ |
| 448 | static int pin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t *hpa) | 447 | static int pin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t *hpa) |
| 449 | { | 448 | { |
| 450 | struct page *page; | 449 | struct page *page; |
| 451 | hva_t hva; | ||
| 452 | int rc; | ||
| 453 | 450 | ||
| 454 | hva = gfn_to_hva(kvm, gpa_to_gfn(gpa)); | 451 | page = gfn_to_page(kvm, gpa_to_gfn(gpa)); |
| 455 | if (kvm_is_error_hva(hva)) | 452 | if (is_error_page(page)) |
| 456 | return -EINVAL; | 453 | return -EINVAL; |
| 457 | rc = get_user_pages_fast(hva, 1, 1, &page); | ||
| 458 | if (rc < 0) | ||
| 459 | return rc; | ||
| 460 | else if (rc != 1) | ||
| 461 | return -ENOMEM; | ||
| 462 | *hpa = (hpa_t) page_to_virt(page) + (gpa & ~PAGE_MASK); | 454 | *hpa = (hpa_t) page_to_virt(page) + (gpa & ~PAGE_MASK); |
| 463 | return 0; | 455 | return 0; |
| 464 | } | 456 | } |
| @@ -466,11 +458,7 @@ static int pin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t *hpa) | |||
| 466 | /* Unpins a page previously pinned via pin_guest_page, marking it as dirty. */ | 458 | /* Unpins a page previously pinned via pin_guest_page, marking it as dirty. */ |
| 467 | static void unpin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t hpa) | 459 | static void unpin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t hpa) |
| 468 | { | 460 | { |
| 469 | struct page *page; | 461 | kvm_release_pfn_dirty(hpa >> PAGE_SHIFT); |
| 470 | |||
| 471 | page = virt_to_page(hpa); | ||
| 472 | set_page_dirty_lock(page); | ||
| 473 | put_page(page); | ||
| 474 | /* mark the page always as dirty for migration */ | 462 | /* mark the page always as dirty for migration */ |
| 475 | mark_page_dirty(kvm, gpa_to_gfn(gpa)); | 463 | mark_page_dirty(kvm, gpa_to_gfn(gpa)); |
| 476 | } | 464 | } |
| @@ -557,7 +545,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) | |||
| 557 | rc = set_validity_icpt(scb_s, 0x003bU); | 545 | rc = set_validity_icpt(scb_s, 0x003bU); |
| 558 | if (!rc) { | 546 | if (!rc) { |
| 559 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); | 547 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); |
| 560 | if (rc == -EINVAL) | 548 | if (rc) |
| 561 | rc = set_validity_icpt(scb_s, 0x0034U); | 549 | rc = set_validity_icpt(scb_s, 0x0034U); |
| 562 | } | 550 | } |
| 563 | if (rc) | 551 | if (rc) |
| @@ -574,10 +562,10 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) | |||
| 574 | } | 562 | } |
| 575 | /* 256 bytes cannot cross page boundaries */ | 563 | /* 256 bytes cannot cross page boundaries */ |
| 576 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); | 564 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); |
| 577 | if (rc == -EINVAL) | 565 | if (rc) { |
| 578 | rc = set_validity_icpt(scb_s, 0x0080U); | 566 | rc = set_validity_icpt(scb_s, 0x0080U); |
| 579 | if (rc) | ||
| 580 | goto unpin; | 567 | goto unpin; |
| 568 | } | ||
| 581 | scb_s->itdba = hpa; | 569 | scb_s->itdba = hpa; |
| 582 | } | 570 | } |
| 583 | 571 | ||
| @@ -592,10 +580,10 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) | |||
| 592 | * if this block gets bigger, we have to shadow it. | 580 | * if this block gets bigger, we have to shadow it. |
| 593 | */ | 581 | */ |
| 594 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); | 582 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); |
| 595 | if (rc == -EINVAL) | 583 | if (rc) { |
| 596 | rc = set_validity_icpt(scb_s, 0x1310U); | 584 | rc = set_validity_icpt(scb_s, 0x1310U); |
| 597 | if (rc) | ||
| 598 | goto unpin; | 585 | goto unpin; |
| 586 | } | ||
| 599 | scb_s->gvrd = hpa; | 587 | scb_s->gvrd = hpa; |
| 600 | } | 588 | } |
| 601 | 589 | ||
| @@ -607,11 +595,11 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) | |||
| 607 | } | 595 | } |
| 608 | /* 64 bytes cannot cross page boundaries */ | 596 | /* 64 bytes cannot cross page boundaries */ |
| 609 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); | 597 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); |
| 610 | if (rc == -EINVAL) | 598 | if (rc) { |
| 611 | rc = set_validity_icpt(scb_s, 0x0043U); | 599 | rc = set_validity_icpt(scb_s, 0x0043U); |
| 612 | /* Validity 0x0044 will be checked by SIE */ | ||
| 613 | if (rc) | ||
| 614 | goto unpin; | 600 | goto unpin; |
| 601 | } | ||
| 602 | /* Validity 0x0044 will be checked by SIE */ | ||
| 615 | scb_s->riccbd = hpa; | 603 | scb_s->riccbd = hpa; |
| 616 | } | 604 | } |
| 617 | if ((scb_s->ecb & ECB_GS) && !(scb_s->ecd & ECD_HOSTREGMGMT)) { | 605 | if ((scb_s->ecb & ECB_GS) && !(scb_s->ecd & ECD_HOSTREGMGMT)) { |
| @@ -635,10 +623,10 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) | |||
| 635 | * cross page boundaries | 623 | * cross page boundaries |
| 636 | */ | 624 | */ |
| 637 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); | 625 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); |
| 638 | if (rc == -EINVAL) | 626 | if (rc) { |
| 639 | rc = set_validity_icpt(scb_s, 0x10b0U); | 627 | rc = set_validity_icpt(scb_s, 0x10b0U); |
| 640 | if (rc) | ||
| 641 | goto unpin; | 628 | goto unpin; |
| 629 | } | ||
| 642 | scb_s->sdnxo = hpa | sdnxc; | 630 | scb_s->sdnxo = hpa | sdnxc; |
| 643 | } | 631 | } |
| 644 | return 0; | 632 | return 0; |
| @@ -663,7 +651,6 @@ static void unpin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, | |||
| 663 | * | 651 | * |
| 664 | * Returns: - 0 if the scb was pinned. | 652 | * Returns: - 0 if the scb was pinned. |
| 665 | * - > 0 if control has to be given to guest 2 | 653 | * - > 0 if control has to be given to guest 2 |
| 666 | * - -ENOMEM if out of memory | ||
| 667 | */ | 654 | */ |
| 668 | static int pin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, | 655 | static int pin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, |
| 669 | gpa_t gpa) | 656 | gpa_t gpa) |
| @@ -672,14 +659,13 @@ static int pin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, | |||
| 672 | int rc; | 659 | int rc; |
| 673 | 660 | ||
| 674 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); | 661 | rc = pin_guest_page(vcpu->kvm, gpa, &hpa); |
| 675 | if (rc == -EINVAL) { | 662 | if (rc) { |
| 676 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 663 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
| 677 | if (!rc) | 664 | WARN_ON_ONCE(rc); |
| 678 | rc = 1; | 665 | return 1; |
| 679 | } | 666 | } |
| 680 | if (!rc) | 667 | vsie_page->scb_o = (struct kvm_s390_sie_block *) hpa; |
| 681 | vsie_page->scb_o = (struct kvm_s390_sie_block *) hpa; | 668 | return 0; |
| 682 | return rc; | ||
| 683 | } | 669 | } |
| 684 | 670 | ||
| 685 | /* | 671 | /* |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 6882538eda32..2e754b7c282c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
| @@ -667,6 +667,7 @@ kvm_pfn_t __gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn, | |||
| 667 | bool *writable); | 667 | bool *writable); |
| 668 | 668 | ||
| 669 | void kvm_release_pfn_clean(kvm_pfn_t pfn); | 669 | void kvm_release_pfn_clean(kvm_pfn_t pfn); |
| 670 | void kvm_release_pfn_dirty(kvm_pfn_t pfn); | ||
| 670 | void kvm_set_pfn_dirty(kvm_pfn_t pfn); | 671 | void kvm_set_pfn_dirty(kvm_pfn_t pfn); |
| 671 | void kvm_set_pfn_accessed(kvm_pfn_t pfn); | 672 | void kvm_set_pfn_accessed(kvm_pfn_t pfn); |
| 672 | void kvm_get_pfn(kvm_pfn_t pfn); | 673 | void kvm_get_pfn(kvm_pfn_t pfn); |
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 838887587411..b60595696836 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h | |||
| @@ -930,6 +930,7 @@ struct kvm_ppc_resize_hpt { | |||
| 930 | #define KVM_CAP_PPC_SMT_POSSIBLE 147 | 930 | #define KVM_CAP_PPC_SMT_POSSIBLE 147 |
| 931 | #define KVM_CAP_HYPERV_SYNIC2 148 | 931 | #define KVM_CAP_HYPERV_SYNIC2 148 |
| 932 | #define KVM_CAP_HYPERV_VP_INDEX 149 | 932 | #define KVM_CAP_HYPERV_VP_INDEX 149 |
| 933 | #define KVM_CAP_S390_AIS_MIGRATION 150 | ||
| 933 | 934 | ||
| 934 | #ifdef KVM_CAP_IRQ_ROUTING | 935 | #ifdef KVM_CAP_IRQ_ROUTING |
| 935 | 936 | ||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 3d73299e05f2..c114d7948743 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -122,7 +122,6 @@ static void hardware_disable_all(void); | |||
| 122 | 122 | ||
| 123 | static void kvm_io_bus_destroy(struct kvm_io_bus *bus); | 123 | static void kvm_io_bus_destroy(struct kvm_io_bus *bus); |
| 124 | 124 | ||
| 125 | static void kvm_release_pfn_dirty(kvm_pfn_t pfn); | ||
| 126 | static void mark_page_dirty_in_slot(struct kvm_memory_slot *memslot, gfn_t gfn); | 125 | static void mark_page_dirty_in_slot(struct kvm_memory_slot *memslot, gfn_t gfn); |
| 127 | 126 | ||
| 128 | __visible bool kvm_rebooting; | 127 | __visible bool kvm_rebooting; |
| @@ -1679,11 +1678,12 @@ void kvm_release_page_dirty(struct page *page) | |||
| 1679 | } | 1678 | } |
| 1680 | EXPORT_SYMBOL_GPL(kvm_release_page_dirty); | 1679 | EXPORT_SYMBOL_GPL(kvm_release_page_dirty); |
| 1681 | 1680 | ||
| 1682 | static void kvm_release_pfn_dirty(kvm_pfn_t pfn) | 1681 | void kvm_release_pfn_dirty(kvm_pfn_t pfn) |
| 1683 | { | 1682 | { |
| 1684 | kvm_set_pfn_dirty(pfn); | 1683 | kvm_set_pfn_dirty(pfn); |
| 1685 | kvm_release_pfn_clean(pfn); | 1684 | kvm_release_pfn_clean(pfn); |
| 1686 | } | 1685 | } |
| 1686 | EXPORT_SYMBOL_GPL(kvm_release_pfn_dirty); | ||
| 1687 | 1687 | ||
| 1688 | void kvm_set_pfn_dirty(kvm_pfn_t pfn) | 1688 | void kvm_set_pfn_dirty(kvm_pfn_t pfn) |
| 1689 | { | 1689 | { |
