diff options
-rw-r--r-- | Documentation/virtual/kvm/devices/s390_flic.txt | 46 | ||||
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 58 | ||||
-rw-r--r-- | arch/s390/include/asm/pgtable.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/s390/include/uapi/asm/kvm.h | 19 | ||||
-rw-r--r-- | arch/s390/kvm/Kconfig | 2 | ||||
-rw-r--r-- | arch/s390/kvm/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kvm/diag.c | 84 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 389 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 135 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 4 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 7 | ||||
-rw-r--r-- | arch/s390/kvm/trace.h | 46 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 26 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.c | 2 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/kvm.h | 66 | ||||
-rw-r--r-- | virt/kvm/Kconfig | 4 | ||||
-rw-r--r-- | virt/kvm/async_pf.c | 25 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 5 |
20 files changed, 822 insertions, 104 deletions
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt new file mode 100644 index 000000000000..410fa673e5b6 --- /dev/null +++ b/Documentation/virtual/kvm/devices/s390_flic.txt | |||
@@ -0,0 +1,46 @@ | |||
1 | FLIC (floating interrupt controller) | ||
2 | ==================================== | ||
3 | |||
4 | FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some | ||
5 | machine check interruptions. All interrupts are stored in a per-vm list of | ||
6 | pending interrupts. FLIC performs operations on this list. | ||
7 | |||
8 | Only one FLIC instance may be instantiated. | ||
9 | |||
10 | FLIC provides support to | ||
11 | - add interrupts (KVM_DEV_FLIC_ENQUEUE) | ||
12 | - inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS) | ||
13 | - purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS) | ||
14 | - enable/disable for the guest transparent async page faults | ||
15 | |||
16 | Groups: | ||
17 | KVM_DEV_FLIC_ENQUEUE | ||
18 | Passes a buffer and length into the kernel which are then injected into | ||
19 | the list of pending interrupts. | ||
20 | attr->addr contains the pointer to the buffer and attr->attr contains | ||
21 | the length of the buffer. | ||
22 | The format of the data structure kvm_s390_irq as it is copied from userspace | ||
23 | is defined in usr/include/linux/kvm.h. | ||
24 | |||
25 | KVM_DEV_FLIC_GET_ALL_IRQS | ||
26 | Copies all floating interrupts into a buffer provided by userspace. | ||
27 | When the buffer is too small it returns -ENOMEM, which is the indication | ||
28 | for userspace to try again with a bigger buffer. | ||
29 | All interrupts remain pending, i.e. are not deleted from the list of | ||
30 | currently pending interrupts. | ||
31 | attr->addr contains the userspace address of the buffer into which all | ||
32 | interrupt data will be copied. | ||
33 | attr->attr contains the size of the buffer in bytes. | ||
34 | |||
35 | KVM_DEV_FLIC_CLEAR_IRQS | ||
36 | Simply deletes all elements from the list of currently pending floating | ||
37 | interrupts. No interrupts are injected into the guest. | ||
38 | |||
39 | KVM_DEV_FLIC_APF_ENABLE | ||
40 | Enables async page faults for the guest. So in case of a major page fault | ||
41 | the host is allowed to handle this async and continues the guest. | ||
42 | |||
43 | KVM_DEV_FLIC_APF_DISABLE_WAIT | ||
44 | Disables async page faults for the guest and waits until already pending | ||
45 | async page faults are done. This is necessary to trigger a completion interrupt | ||
46 | for every init interrupt before migrating the interrupt list. | ||
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index eef3dd3fd9a9..2c69ba285e81 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/hrtimer.h> | 16 | #include <linux/hrtimer.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/kvm_host.h> | 18 | #include <linux/kvm_host.h> |
19 | #include <linux/kvm.h> | ||
19 | #include <asm/debug.h> | 20 | #include <asm/debug.h> |
20 | #include <asm/cpu.h> | 21 | #include <asm/cpu.h> |
21 | 22 | ||
@@ -168,18 +169,6 @@ struct kvm_vcpu_stat { | |||
168 | u32 diagnose_9c; | 169 | u32 diagnose_9c; |
169 | }; | 170 | }; |
170 | 171 | ||
171 | struct kvm_s390_io_info { | ||
172 | __u16 subchannel_id; /* 0x0b8 */ | ||
173 | __u16 subchannel_nr; /* 0x0ba */ | ||
174 | __u32 io_int_parm; /* 0x0bc */ | ||
175 | __u32 io_int_word; /* 0x0c0 */ | ||
176 | }; | ||
177 | |||
178 | struct kvm_s390_ext_info { | ||
179 | __u32 ext_params; | ||
180 | __u64 ext_params2; | ||
181 | }; | ||
182 | |||
183 | #define PGM_OPERATION 0x01 | 172 | #define PGM_OPERATION 0x01 |
184 | #define PGM_PRIVILEGED_OP 0x02 | 173 | #define PGM_PRIVILEGED_OP 0x02 |
185 | #define PGM_EXECUTE 0x03 | 174 | #define PGM_EXECUTE 0x03 |
@@ -188,27 +177,6 @@ struct kvm_s390_ext_info { | |||
188 | #define PGM_SPECIFICATION 0x06 | 177 | #define PGM_SPECIFICATION 0x06 |
189 | #define PGM_DATA 0x07 | 178 | #define PGM_DATA 0x07 |
190 | 179 | ||
191 | struct kvm_s390_pgm_info { | ||
192 | __u16 code; | ||
193 | }; | ||
194 | |||
195 | struct kvm_s390_prefix_info { | ||
196 | __u32 address; | ||
197 | }; | ||
198 | |||
199 | struct kvm_s390_extcall_info { | ||
200 | __u16 code; | ||
201 | }; | ||
202 | |||
203 | struct kvm_s390_emerg_info { | ||
204 | __u16 code; | ||
205 | }; | ||
206 | |||
207 | struct kvm_s390_mchk_info { | ||
208 | __u64 cr14; | ||
209 | __u64 mcic; | ||
210 | }; | ||
211 | |||
212 | struct kvm_s390_interrupt_info { | 180 | struct kvm_s390_interrupt_info { |
213 | struct list_head list; | 181 | struct list_head list; |
214 | u64 type; | 182 | u64 type; |
@@ -246,6 +214,7 @@ struct kvm_s390_float_interrupt { | |||
246 | unsigned long idle_mask[(KVM_MAX_VCPUS + sizeof(long) - 1) | 214 | unsigned long idle_mask[(KVM_MAX_VCPUS + sizeof(long) - 1) |
247 | / sizeof(long)]; | 215 | / sizeof(long)]; |
248 | struct kvm_s390_local_interrupt *local_int[KVM_MAX_VCPUS]; | 216 | struct kvm_s390_local_interrupt *local_int[KVM_MAX_VCPUS]; |
217 | unsigned int irq_count; | ||
249 | }; | 218 | }; |
250 | 219 | ||
251 | 220 | ||
@@ -262,6 +231,10 @@ struct kvm_vcpu_arch { | |||
262 | u64 stidp_data; | 231 | u64 stidp_data; |
263 | }; | 232 | }; |
264 | struct gmap *gmap; | 233 | struct gmap *gmap; |
234 | #define KVM_S390_PFAULT_TOKEN_INVALID (-1UL) | ||
235 | unsigned long pfault_token; | ||
236 | unsigned long pfault_select; | ||
237 | unsigned long pfault_compare; | ||
265 | }; | 238 | }; |
266 | 239 | ||
267 | struct kvm_vm_stat { | 240 | struct kvm_vm_stat { |
@@ -275,6 +248,7 @@ struct kvm_arch{ | |||
275 | struct sca_block *sca; | 248 | struct sca_block *sca; |
276 | debug_info_t *dbf; | 249 | debug_info_t *dbf; |
277 | struct kvm_s390_float_interrupt float_int; | 250 | struct kvm_s390_float_interrupt float_int; |
251 | struct kvm_device *flic; | ||
278 | struct gmap *gmap; | 252 | struct gmap *gmap; |
279 | int css_support; | 253 | int css_support; |
280 | }; | 254 | }; |
@@ -287,6 +261,24 @@ static inline bool kvm_is_error_hva(unsigned long addr) | |||
287 | return IS_ERR_VALUE(addr); | 261 | return IS_ERR_VALUE(addr); |
288 | } | 262 | } |
289 | 263 | ||
264 | #define ASYNC_PF_PER_VCPU 64 | ||
265 | struct kvm_vcpu; | ||
266 | struct kvm_async_pf; | ||
267 | struct kvm_arch_async_pf { | ||
268 | unsigned long pfault_token; | ||
269 | }; | ||
270 | |||
271 | bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu); | ||
272 | |||
273 | void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, | ||
274 | struct kvm_async_pf *work); | ||
275 | |||
276 | void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu, | ||
277 | struct kvm_async_pf *work); | ||
278 | |||
279 | void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, | ||
280 | struct kvm_async_pf *work); | ||
281 | |||
290 | extern int sie64a(struct kvm_s390_sie_block *, u64 *); | 282 | extern int sie64a(struct kvm_s390_sie_block *, u64 *); |
291 | extern char sie_exit; | 283 | extern char sie_exit; |
292 | #endif | 284 | #endif |
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 2204400d0bd5..66101f6c6d81 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -767,6 +767,7 @@ static inline void pgste_set_pte(pte_t *ptep, pte_t entry) | |||
767 | * @table: pointer to the page directory | 767 | * @table: pointer to the page directory |
768 | * @asce: address space control element for gmap page table | 768 | * @asce: address space control element for gmap page table |
769 | * @crst_list: list of all crst tables used in the guest address space | 769 | * @crst_list: list of all crst tables used in the guest address space |
770 | * @pfault_enabled: defines if pfaults are applicable for the guest | ||
770 | */ | 771 | */ |
771 | struct gmap { | 772 | struct gmap { |
772 | struct list_head list; | 773 | struct list_head list; |
@@ -775,6 +776,7 @@ struct gmap { | |||
775 | unsigned long asce; | 776 | unsigned long asce; |
776 | void *private; | 777 | void *private; |
777 | struct list_head crst_list; | 778 | struct list_head crst_list; |
779 | bool pfault_enabled; | ||
778 | }; | 780 | }; |
779 | 781 | ||
780 | /** | 782 | /** |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 0a876bc543d3..dc5fc4f90e52 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -79,6 +79,7 @@ struct thread_struct { | |||
79 | unsigned long ksp; /* kernel stack pointer */ | 79 | unsigned long ksp; /* kernel stack pointer */ |
80 | mm_segment_t mm_segment; | 80 | mm_segment_t mm_segment; |
81 | unsigned long gmap_addr; /* address of last gmap fault. */ | 81 | unsigned long gmap_addr; /* address of last gmap fault. */ |
82 | unsigned int gmap_pfault; /* signal of a pending guest pfault */ | ||
82 | struct per_regs per_user; /* User specified PER registers */ | 83 | struct per_regs per_user; /* User specified PER registers */ |
83 | struct per_event per_event; /* Cause of the last PER trap */ | 84 | struct per_event per_event; /* Cause of the last PER trap */ |
84 | unsigned long per_flags; /* Flags to control debug behavior */ | 85 | unsigned long per_flags; /* Flags to control debug behavior */ |
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h index d25da598ec62..cb4c1eb8a0a5 100644 --- a/arch/s390/include/uapi/asm/kvm.h +++ b/arch/s390/include/uapi/asm/kvm.h | |||
@@ -16,6 +16,22 @@ | |||
16 | 16 | ||
17 | #define __KVM_S390 | 17 | #define __KVM_S390 |
18 | 18 | ||
19 | /* Device control API: s390-specific devices */ | ||
20 | #define KVM_DEV_FLIC_GET_ALL_IRQS 1 | ||
21 | #define KVM_DEV_FLIC_ENQUEUE 2 | ||
22 | #define KVM_DEV_FLIC_CLEAR_IRQS 3 | ||
23 | #define KVM_DEV_FLIC_APF_ENABLE 4 | ||
24 | #define KVM_DEV_FLIC_APF_DISABLE_WAIT 5 | ||
25 | /* | ||
26 | * We can have up to 4*64k pending subchannels + 8 adapter interrupts, | ||
27 | * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. | ||
28 | * There are also sclp and machine checks. This gives us | ||
29 | * sizeof(kvm_s390_irq)*(4*65536+8+64*64+1+1) = 72 * 266250 = 19170000 | ||
30 | * Lets round up to 8192 pages. | ||
31 | */ | ||
32 | #define KVM_S390_MAX_FLOAT_IRQS 266250 | ||
33 | #define KVM_S390_FLIC_MAX_BUFFER 0x2000000 | ||
34 | |||
19 | /* for KVM_GET_REGS and KVM_SET_REGS */ | 35 | /* for KVM_GET_REGS and KVM_SET_REGS */ |
20 | struct kvm_regs { | 36 | struct kvm_regs { |
21 | /* general purpose regs for s390 */ | 37 | /* general purpose regs for s390 */ |
@@ -57,4 +73,7 @@ struct kvm_sync_regs { | |||
57 | #define KVM_REG_S390_EPOCHDIFF (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x2) | 73 | #define KVM_REG_S390_EPOCHDIFF (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x2) |
58 | #define KVM_REG_S390_CPU_TIMER (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x3) | 74 | #define KVM_REG_S390_CPU_TIMER (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x3) |
59 | #define KVM_REG_S390_CLOCK_COMP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x4) | 75 | #define KVM_REG_S390_CLOCK_COMP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x4) |
76 | #define KVM_REG_S390_PFTOKEN (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5) | ||
77 | #define KVM_REG_S390_PFCOMPARE (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6) | ||
78 | #define KVM_REG_S390_PFSELECT (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7) | ||
60 | #endif | 79 | #endif |
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index 70b46eacf8e1..c8bacbcd2e5b 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig | |||
@@ -23,6 +23,8 @@ config KVM | |||
23 | select ANON_INODES | 23 | select ANON_INODES |
24 | select HAVE_KVM_CPU_RELAX_INTERCEPT | 24 | select HAVE_KVM_CPU_RELAX_INTERCEPT |
25 | select HAVE_KVM_EVENTFD | 25 | select HAVE_KVM_EVENTFD |
26 | select KVM_ASYNC_PF | ||
27 | select KVM_ASYNC_PF_SYNC | ||
26 | ---help--- | 28 | ---help--- |
27 | Support hosting paravirtualized guest machines using the SIE | 29 | Support hosting paravirtualized guest machines using the SIE |
28 | virtualization capability on the mainframe. This should work | 30 | virtualization capability on the mainframe. This should work |
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile index 40b4c6470f88..a47d2c355f68 100644 --- a/arch/s390/kvm/Makefile +++ b/arch/s390/kvm/Makefile | |||
@@ -7,7 +7,7 @@ | |||
7 | # as published by the Free Software Foundation. | 7 | # as published by the Free Software Foundation. |
8 | 8 | ||
9 | KVM := ../../../virt/kvm | 9 | KVM := ../../../virt/kvm |
10 | common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o | 10 | common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o |
11 | 11 | ||
12 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm | 12 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm |
13 | 13 | ||
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 8216c0e0b2e2..bf9ed34c2bcd 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "kvm-s390.h" | 17 | #include "kvm-s390.h" |
18 | #include "trace.h" | 18 | #include "trace.h" |
19 | #include "trace-s390.h" | 19 | #include "trace-s390.h" |
20 | #include "gaccess.h" | ||
20 | 21 | ||
21 | static int diag_release_pages(struct kvm_vcpu *vcpu) | 22 | static int diag_release_pages(struct kvm_vcpu *vcpu) |
22 | { | 23 | { |
@@ -46,6 +47,87 @@ static int diag_release_pages(struct kvm_vcpu *vcpu) | |||
46 | return 0; | 47 | return 0; |
47 | } | 48 | } |
48 | 49 | ||
50 | static int __diag_page_ref_service(struct kvm_vcpu *vcpu) | ||
51 | { | ||
52 | struct prs_parm { | ||
53 | u16 code; | ||
54 | u16 subcode; | ||
55 | u16 parm_len; | ||
56 | u16 parm_version; | ||
57 | u64 token_addr; | ||
58 | u64 select_mask; | ||
59 | u64 compare_mask; | ||
60 | u64 zarch; | ||
61 | }; | ||
62 | struct prs_parm parm; | ||
63 | int rc; | ||
64 | u16 rx = (vcpu->arch.sie_block->ipa & 0xf0) >> 4; | ||
65 | u16 ry = (vcpu->arch.sie_block->ipa & 0x0f); | ||
66 | unsigned long hva_token = KVM_HVA_ERR_BAD; | ||
67 | |||
68 | if (vcpu->run->s.regs.gprs[rx] & 7) | ||
69 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
70 | if (copy_from_guest(vcpu, &parm, vcpu->run->s.regs.gprs[rx], sizeof(parm))) | ||
71 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
72 | if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258) | ||
73 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
74 | |||
75 | switch (parm.subcode) { | ||
76 | case 0: /* TOKEN */ | ||
77 | if (vcpu->arch.pfault_token != KVM_S390_PFAULT_TOKEN_INVALID) { | ||
78 | /* | ||
79 | * If the pagefault handshake is already activated, | ||
80 | * the token must not be changed. We have to return | ||
81 | * decimal 8 instead, as mandated in SC24-6084. | ||
82 | */ | ||
83 | vcpu->run->s.regs.gprs[ry] = 8; | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | if ((parm.compare_mask & parm.select_mask) != parm.compare_mask || | ||
88 | parm.token_addr & 7 || parm.zarch != 0x8000000000000000ULL) | ||
89 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
90 | |||
91 | hva_token = gfn_to_hva(vcpu->kvm, gpa_to_gfn(parm.token_addr)); | ||
92 | if (kvm_is_error_hva(hva_token)) | ||
93 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
94 | |||
95 | vcpu->arch.pfault_token = parm.token_addr; | ||
96 | vcpu->arch.pfault_select = parm.select_mask; | ||
97 | vcpu->arch.pfault_compare = parm.compare_mask; | ||
98 | vcpu->run->s.regs.gprs[ry] = 0; | ||
99 | rc = 0; | ||
100 | break; | ||
101 | case 1: /* | ||
102 | * CANCEL | ||
103 | * Specification allows to let already pending tokens survive | ||
104 | * the cancel, therefore to reduce code complexity, we assume | ||
105 | * all outstanding tokens are already pending. | ||
106 | */ | ||
107 | if (parm.token_addr || parm.select_mask || | ||
108 | parm.compare_mask || parm.zarch) | ||
109 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
110 | |||
111 | vcpu->run->s.regs.gprs[ry] = 0; | ||
112 | /* | ||
113 | * If the pfault handling was not established or is already | ||
114 | * canceled SC24-6084 requests to return decimal 4. | ||
115 | */ | ||
116 | if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) | ||
117 | vcpu->run->s.regs.gprs[ry] = 4; | ||
118 | else | ||
119 | vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; | ||
120 | |||
121 | rc = 0; | ||
122 | break; | ||
123 | default: | ||
124 | rc = -EOPNOTSUPP; | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | return rc; | ||
129 | } | ||
130 | |||
49 | static int __diag_time_slice_end(struct kvm_vcpu *vcpu) | 131 | static int __diag_time_slice_end(struct kvm_vcpu *vcpu) |
50 | { | 132 | { |
51 | VCPU_EVENT(vcpu, 5, "%s", "diag time slice end"); | 133 | VCPU_EVENT(vcpu, 5, "%s", "diag time slice end"); |
@@ -150,6 +232,8 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) | |||
150 | return __diag_time_slice_end(vcpu); | 232 | return __diag_time_slice_end(vcpu); |
151 | case 0x9c: | 233 | case 0x9c: |
152 | return __diag_time_slice_end_directed(vcpu); | 234 | return __diag_time_slice_end_directed(vcpu); |
235 | case 0x258: | ||
236 | return __diag_page_ref_service(vcpu); | ||
153 | case 0x308: | 237 | case 0x308: |
154 | return __diag_ipl_functions(vcpu); | 238 | return __diag_ipl_functions(vcpu); |
155 | case 0x500: | 239 | case 0x500: |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 5f79d2d79ca7..1848080c3f34 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -31,7 +31,7 @@ static int is_ioint(u64 type) | |||
31 | return ((type & 0xfffe0000u) != 0xfffe0000u); | 31 | return ((type & 0xfffe0000u) != 0xfffe0000u); |
32 | } | 32 | } |
33 | 33 | ||
34 | static int psw_extint_disabled(struct kvm_vcpu *vcpu) | 34 | int psw_extint_disabled(struct kvm_vcpu *vcpu) |
35 | { | 35 | { |
36 | return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT); | 36 | return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT); |
37 | } | 37 | } |
@@ -78,11 +78,8 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, | |||
78 | return 1; | 78 | return 1; |
79 | return 0; | 79 | return 0; |
80 | case KVM_S390_INT_SERVICE: | 80 | case KVM_S390_INT_SERVICE: |
81 | if (psw_extint_disabled(vcpu)) | 81 | case KVM_S390_INT_PFAULT_INIT: |
82 | return 0; | 82 | case KVM_S390_INT_PFAULT_DONE: |
83 | if (vcpu->arch.sie_block->gcr[0] & 0x200ul) | ||
84 | return 1; | ||
85 | return 0; | ||
86 | case KVM_S390_INT_VIRTIO: | 83 | case KVM_S390_INT_VIRTIO: |
87 | if (psw_extint_disabled(vcpu)) | 84 | if (psw_extint_disabled(vcpu)) |
88 | return 0; | 85 | return 0; |
@@ -150,6 +147,8 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu, | |||
150 | case KVM_S390_INT_EXTERNAL_CALL: | 147 | case KVM_S390_INT_EXTERNAL_CALL: |
151 | case KVM_S390_INT_EMERGENCY: | 148 | case KVM_S390_INT_EMERGENCY: |
152 | case KVM_S390_INT_SERVICE: | 149 | case KVM_S390_INT_SERVICE: |
150 | case KVM_S390_INT_PFAULT_INIT: | ||
151 | case KVM_S390_INT_PFAULT_DONE: | ||
153 | case KVM_S390_INT_VIRTIO: | 152 | case KVM_S390_INT_VIRTIO: |
154 | if (psw_extint_disabled(vcpu)) | 153 | if (psw_extint_disabled(vcpu)) |
155 | __set_cpuflag(vcpu, CPUSTAT_EXT_INT); | 154 | __set_cpuflag(vcpu, CPUSTAT_EXT_INT); |
@@ -223,6 +222,30 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, | |||
223 | rc |= put_guest(vcpu, inti->ext.ext_params, | 222 | rc |= put_guest(vcpu, inti->ext.ext_params, |
224 | (u32 __user *)__LC_EXT_PARAMS); | 223 | (u32 __user *)__LC_EXT_PARAMS); |
225 | break; | 224 | break; |
225 | case KVM_S390_INT_PFAULT_INIT: | ||
226 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, | ||
227 | inti->ext.ext_params2); | ||
228 | rc = put_guest(vcpu, 0x2603, (u16 __user *) __LC_EXT_INT_CODE); | ||
229 | rc |= put_guest(vcpu, 0x0600, (u16 __user *) __LC_EXT_CPU_ADDR); | ||
230 | rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW, | ||
231 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
232 | rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, | ||
233 | __LC_EXT_NEW_PSW, sizeof(psw_t)); | ||
234 | rc |= put_guest(vcpu, inti->ext.ext_params2, | ||
235 | (u64 __user *) __LC_EXT_PARAMS2); | ||
236 | break; | ||
237 | case KVM_S390_INT_PFAULT_DONE: | ||
238 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, | ||
239 | inti->ext.ext_params2); | ||
240 | rc = put_guest(vcpu, 0x2603, (u16 __user *) __LC_EXT_INT_CODE); | ||
241 | rc |= put_guest(vcpu, 0x0680, (u16 __user *) __LC_EXT_CPU_ADDR); | ||
242 | rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW, | ||
243 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
244 | rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, | ||
245 | __LC_EXT_NEW_PSW, sizeof(psw_t)); | ||
246 | rc |= put_guest(vcpu, inti->ext.ext_params2, | ||
247 | (u64 __user *) __LC_EXT_PARAMS2); | ||
248 | break; | ||
226 | case KVM_S390_INT_VIRTIO: | 249 | case KVM_S390_INT_VIRTIO: |
227 | VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", | 250 | VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", |
228 | inti->ext.ext_params, inti->ext.ext_params2); | 251 | inti->ext.ext_params, inti->ext.ext_params2); |
@@ -357,7 +380,7 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu) | |||
357 | return 1; | 380 | return 1; |
358 | } | 381 | } |
359 | 382 | ||
360 | static int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) | 383 | int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) |
361 | { | 384 | { |
362 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 385 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
363 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; | 386 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; |
@@ -528,6 +551,7 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) | |||
528 | list_for_each_entry_safe(inti, n, &fi->list, list) { | 551 | list_for_each_entry_safe(inti, n, &fi->list, list) { |
529 | if (__interrupt_is_deliverable(vcpu, inti)) { | 552 | if (__interrupt_is_deliverable(vcpu, inti)) { |
530 | list_del(&inti->list); | 553 | list_del(&inti->list); |
554 | fi->irq_count--; | ||
531 | deliver = 1; | 555 | deliver = 1; |
532 | break; | 556 | break; |
533 | } | 557 | } |
@@ -583,6 +607,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu) | |||
583 | if ((inti->type == KVM_S390_MCHK) && | 607 | if ((inti->type == KVM_S390_MCHK) && |
584 | __interrupt_is_deliverable(vcpu, inti)) { | 608 | __interrupt_is_deliverable(vcpu, inti)) { |
585 | list_del(&inti->list); | 609 | list_del(&inti->list); |
610 | fi->irq_count--; | ||
586 | deliver = 1; | 611 | deliver = 1; |
587 | break; | 612 | break; |
588 | } | 613 | } |
@@ -650,8 +675,10 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | |||
650 | inti = iter; | 675 | inti = iter; |
651 | break; | 676 | break; |
652 | } | 677 | } |
653 | if (inti) | 678 | if (inti) { |
654 | list_del_init(&inti->list); | 679 | list_del_init(&inti->list); |
680 | fi->irq_count--; | ||
681 | } | ||
655 | if (list_empty(&fi->list)) | 682 | if (list_empty(&fi->list)) |
656 | atomic_set(&fi->active, 0); | 683 | atomic_set(&fi->active, 0); |
657 | spin_unlock(&fi->lock); | 684 | spin_unlock(&fi->lock); |
@@ -659,53 +686,98 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | |||
659 | return inti; | 686 | return inti; |
660 | } | 687 | } |
661 | 688 | ||
662 | int kvm_s390_inject_vm(struct kvm *kvm, | 689 | static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) |
663 | struct kvm_s390_interrupt *s390int) | ||
664 | { | 690 | { |
665 | struct kvm_s390_local_interrupt *li; | 691 | struct kvm_s390_local_interrupt *li; |
666 | struct kvm_s390_float_interrupt *fi; | 692 | struct kvm_s390_float_interrupt *fi; |
667 | struct kvm_s390_interrupt_info *inti, *iter; | 693 | struct kvm_s390_interrupt_info *iter; |
668 | int sigcpu; | 694 | int sigcpu; |
695 | int rc = 0; | ||
696 | |||
697 | mutex_lock(&kvm->lock); | ||
698 | fi = &kvm->arch.float_int; | ||
699 | spin_lock(&fi->lock); | ||
700 | if (fi->irq_count >= KVM_S390_MAX_FLOAT_IRQS) { | ||
701 | rc = -EINVAL; | ||
702 | goto unlock_fi; | ||
703 | } | ||
704 | fi->irq_count++; | ||
705 | if (!is_ioint(inti->type)) { | ||
706 | list_add_tail(&inti->list, &fi->list); | ||
707 | } else { | ||
708 | u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word); | ||
709 | |||
710 | /* Keep I/O interrupts sorted in isc order. */ | ||
711 | list_for_each_entry(iter, &fi->list, list) { | ||
712 | if (!is_ioint(iter->type)) | ||
713 | continue; | ||
714 | if (int_word_to_isc_bits(iter->io.io_int_word) | ||
715 | <= isc_bits) | ||
716 | continue; | ||
717 | break; | ||
718 | } | ||
719 | list_add_tail(&inti->list, &iter->list); | ||
720 | } | ||
721 | atomic_set(&fi->active, 1); | ||
722 | sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS); | ||
723 | if (sigcpu == KVM_MAX_VCPUS) { | ||
724 | do { | ||
725 | sigcpu = fi->next_rr_cpu++; | ||
726 | if (sigcpu == KVM_MAX_VCPUS) | ||
727 | sigcpu = fi->next_rr_cpu = 0; | ||
728 | } while (fi->local_int[sigcpu] == NULL); | ||
729 | } | ||
730 | li = fi->local_int[sigcpu]; | ||
731 | spin_lock_bh(&li->lock); | ||
732 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
733 | if (waitqueue_active(li->wq)) | ||
734 | wake_up_interruptible(li->wq); | ||
735 | spin_unlock_bh(&li->lock); | ||
736 | unlock_fi: | ||
737 | spin_unlock(&fi->lock); | ||
738 | mutex_unlock(&kvm->lock); | ||
739 | return rc; | ||
740 | } | ||
741 | |||
742 | int kvm_s390_inject_vm(struct kvm *kvm, | ||
743 | struct kvm_s390_interrupt *s390int) | ||
744 | { | ||
745 | struct kvm_s390_interrupt_info *inti; | ||
669 | 746 | ||
670 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); | 747 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); |
671 | if (!inti) | 748 | if (!inti) |
672 | return -ENOMEM; | 749 | return -ENOMEM; |
673 | 750 | ||
674 | switch (s390int->type) { | 751 | inti->type = s390int->type; |
752 | switch (inti->type) { | ||
675 | case KVM_S390_INT_VIRTIO: | 753 | case KVM_S390_INT_VIRTIO: |
676 | VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx", | 754 | VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx", |
677 | s390int->parm, s390int->parm64); | 755 | s390int->parm, s390int->parm64); |
678 | inti->type = s390int->type; | ||
679 | inti->ext.ext_params = s390int->parm; | 756 | inti->ext.ext_params = s390int->parm; |
680 | inti->ext.ext_params2 = s390int->parm64; | 757 | inti->ext.ext_params2 = s390int->parm64; |
681 | break; | 758 | break; |
682 | case KVM_S390_INT_SERVICE: | 759 | case KVM_S390_INT_SERVICE: |
683 | VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm); | 760 | VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm); |
684 | inti->type = s390int->type; | ||
685 | inti->ext.ext_params = s390int->parm; | 761 | inti->ext.ext_params = s390int->parm; |
686 | break; | 762 | break; |
687 | case KVM_S390_PROGRAM_INT: | 763 | case KVM_S390_INT_PFAULT_DONE: |
688 | case KVM_S390_SIGP_STOP: | 764 | inti->type = s390int->type; |
689 | case KVM_S390_INT_EXTERNAL_CALL: | 765 | inti->ext.ext_params2 = s390int->parm64; |
690 | case KVM_S390_INT_EMERGENCY: | 766 | break; |
691 | kfree(inti); | ||
692 | return -EINVAL; | ||
693 | case KVM_S390_MCHK: | 767 | case KVM_S390_MCHK: |
694 | VM_EVENT(kvm, 5, "inject: machine check parm64:%llx", | 768 | VM_EVENT(kvm, 5, "inject: machine check parm64:%llx", |
695 | s390int->parm64); | 769 | s390int->parm64); |
696 | inti->type = s390int->type; | ||
697 | inti->mchk.cr14 = s390int->parm; /* upper bits are not used */ | 770 | inti->mchk.cr14 = s390int->parm; /* upper bits are not used */ |
698 | inti->mchk.mcic = s390int->parm64; | 771 | inti->mchk.mcic = s390int->parm64; |
699 | break; | 772 | break; |
700 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | 773 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: |
701 | if (s390int->type & IOINT_AI_MASK) | 774 | if (inti->type & IOINT_AI_MASK) |
702 | VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)"); | 775 | VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)"); |
703 | else | 776 | else |
704 | VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x", | 777 | VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x", |
705 | s390int->type & IOINT_CSSID_MASK, | 778 | s390int->type & IOINT_CSSID_MASK, |
706 | s390int->type & IOINT_SSID_MASK, | 779 | s390int->type & IOINT_SSID_MASK, |
707 | s390int->type & IOINT_SCHID_MASK); | 780 | s390int->type & IOINT_SCHID_MASK); |
708 | inti->type = s390int->type; | ||
709 | inti->io.subchannel_id = s390int->parm >> 16; | 781 | inti->io.subchannel_id = s390int->parm >> 16; |
710 | inti->io.subchannel_nr = s390int->parm & 0x0000ffffu; | 782 | inti->io.subchannel_nr = s390int->parm & 0x0000ffffu; |
711 | inti->io.io_int_parm = s390int->parm64 >> 32; | 783 | inti->io.io_int_parm = s390int->parm64 >> 32; |
@@ -718,43 +790,7 @@ int kvm_s390_inject_vm(struct kvm *kvm, | |||
718 | trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, | 790 | trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, |
719 | 2); | 791 | 2); |
720 | 792 | ||
721 | mutex_lock(&kvm->lock); | 793 | return __inject_vm(kvm, inti); |
722 | fi = &kvm->arch.float_int; | ||
723 | spin_lock(&fi->lock); | ||
724 | if (!is_ioint(inti->type)) | ||
725 | list_add_tail(&inti->list, &fi->list); | ||
726 | else { | ||
727 | u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word); | ||
728 | |||
729 | /* Keep I/O interrupts sorted in isc order. */ | ||
730 | list_for_each_entry(iter, &fi->list, list) { | ||
731 | if (!is_ioint(iter->type)) | ||
732 | continue; | ||
733 | if (int_word_to_isc_bits(iter->io.io_int_word) | ||
734 | <= isc_bits) | ||
735 | continue; | ||
736 | break; | ||
737 | } | ||
738 | list_add_tail(&inti->list, &iter->list); | ||
739 | } | ||
740 | atomic_set(&fi->active, 1); | ||
741 | sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS); | ||
742 | if (sigcpu == KVM_MAX_VCPUS) { | ||
743 | do { | ||
744 | sigcpu = fi->next_rr_cpu++; | ||
745 | if (sigcpu == KVM_MAX_VCPUS) | ||
746 | sigcpu = fi->next_rr_cpu = 0; | ||
747 | } while (fi->local_int[sigcpu] == NULL); | ||
748 | } | ||
749 | li = fi->local_int[sigcpu]; | ||
750 | spin_lock_bh(&li->lock); | ||
751 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
752 | if (waitqueue_active(li->wq)) | ||
753 | wake_up_interruptible(li->wq); | ||
754 | spin_unlock_bh(&li->lock); | ||
755 | spin_unlock(&fi->lock); | ||
756 | mutex_unlock(&kvm->lock); | ||
757 | return 0; | ||
758 | } | 794 | } |
759 | 795 | ||
760 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | 796 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, |
@@ -814,6 +850,10 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | |||
814 | inti->type = s390int->type; | 850 | inti->type = s390int->type; |
815 | inti->mchk.mcic = s390int->parm64; | 851 | inti->mchk.mcic = s390int->parm64; |
816 | break; | 852 | break; |
853 | case KVM_S390_INT_PFAULT_INIT: | ||
854 | inti->type = s390int->type; | ||
855 | inti->ext.ext_params2 = s390int->parm64; | ||
856 | break; | ||
817 | case KVM_S390_INT_VIRTIO: | 857 | case KVM_S390_INT_VIRTIO: |
818 | case KVM_S390_INT_SERVICE: | 858 | case KVM_S390_INT_SERVICE: |
819 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | 859 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: |
@@ -841,3 +881,232 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | |||
841 | mutex_unlock(&vcpu->kvm->lock); | 881 | mutex_unlock(&vcpu->kvm->lock); |
842 | return 0; | 882 | return 0; |
843 | } | 883 | } |
884 | |||
885 | static void clear_floating_interrupts(struct kvm *kvm) | ||
886 | { | ||
887 | struct kvm_s390_float_interrupt *fi; | ||
888 | struct kvm_s390_interrupt_info *n, *inti = NULL; | ||
889 | |||
890 | mutex_lock(&kvm->lock); | ||
891 | fi = &kvm->arch.float_int; | ||
892 | spin_lock(&fi->lock); | ||
893 | list_for_each_entry_safe(inti, n, &fi->list, list) { | ||
894 | list_del(&inti->list); | ||
895 | kfree(inti); | ||
896 | } | ||
897 | fi->irq_count = 0; | ||
898 | atomic_set(&fi->active, 0); | ||
899 | spin_unlock(&fi->lock); | ||
900 | mutex_unlock(&kvm->lock); | ||
901 | } | ||
902 | |||
903 | static inline int copy_irq_to_user(struct kvm_s390_interrupt_info *inti, | ||
904 | u8 *addr) | ||
905 | { | ||
906 | struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr; | ||
907 | struct kvm_s390_irq irq = {0}; | ||
908 | |||
909 | irq.type = inti->type; | ||
910 | switch (inti->type) { | ||
911 | case KVM_S390_INT_PFAULT_INIT: | ||
912 | case KVM_S390_INT_PFAULT_DONE: | ||
913 | case KVM_S390_INT_VIRTIO: | ||
914 | case KVM_S390_INT_SERVICE: | ||
915 | irq.u.ext = inti->ext; | ||
916 | break; | ||
917 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
918 | irq.u.io = inti->io; | ||
919 | break; | ||
920 | case KVM_S390_MCHK: | ||
921 | irq.u.mchk = inti->mchk; | ||
922 | break; | ||
923 | default: | ||
924 | return -EINVAL; | ||
925 | } | ||
926 | |||
927 | if (copy_to_user(uptr, &irq, sizeof(irq))) | ||
928 | return -EFAULT; | ||
929 | |||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | static int get_all_floating_irqs(struct kvm *kvm, __u8 *buf, __u64 len) | ||
934 | { | ||
935 | struct kvm_s390_interrupt_info *inti; | ||
936 | struct kvm_s390_float_interrupt *fi; | ||
937 | int ret = 0; | ||
938 | int n = 0; | ||
939 | |||
940 | mutex_lock(&kvm->lock); | ||
941 | fi = &kvm->arch.float_int; | ||
942 | spin_lock(&fi->lock); | ||
943 | |||
944 | list_for_each_entry(inti, &fi->list, list) { | ||
945 | if (len < sizeof(struct kvm_s390_irq)) { | ||
946 | /* signal userspace to try again */ | ||
947 | ret = -ENOMEM; | ||
948 | break; | ||
949 | } | ||
950 | ret = copy_irq_to_user(inti, buf); | ||
951 | if (ret) | ||
952 | break; | ||
953 | buf += sizeof(struct kvm_s390_irq); | ||
954 | len -= sizeof(struct kvm_s390_irq); | ||
955 | n++; | ||
956 | } | ||
957 | |||
958 | spin_unlock(&fi->lock); | ||
959 | mutex_unlock(&kvm->lock); | ||
960 | |||
961 | return ret < 0 ? ret : n; | ||
962 | } | ||
963 | |||
964 | static int flic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | ||
965 | { | ||
966 | int r; | ||
967 | |||
968 | switch (attr->group) { | ||
969 | case KVM_DEV_FLIC_GET_ALL_IRQS: | ||
970 | r = get_all_floating_irqs(dev->kvm, (u8 *) attr->addr, | ||
971 | attr->attr); | ||
972 | break; | ||
973 | default: | ||
974 | r = -EINVAL; | ||
975 | } | ||
976 | |||
977 | return r; | ||
978 | } | ||
979 | |||
980 | static inline int copy_irq_from_user(struct kvm_s390_interrupt_info *inti, | ||
981 | u64 addr) | ||
982 | { | ||
983 | struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr; | ||
984 | void *target = NULL; | ||
985 | void __user *source; | ||
986 | u64 size; | ||
987 | |||
988 | if (get_user(inti->type, (u64 __user *)addr)) | ||
989 | return -EFAULT; | ||
990 | |||
991 | switch (inti->type) { | ||
992 | case KVM_S390_INT_PFAULT_INIT: | ||
993 | case KVM_S390_INT_PFAULT_DONE: | ||
994 | case KVM_S390_INT_VIRTIO: | ||
995 | case KVM_S390_INT_SERVICE: | ||
996 | target = (void *) &inti->ext; | ||
997 | source = &uptr->u.ext; | ||
998 | size = sizeof(inti->ext); | ||
999 | break; | ||
1000 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
1001 | target = (void *) &inti->io; | ||
1002 | source = &uptr->u.io; | ||
1003 | size = sizeof(inti->io); | ||
1004 | break; | ||
1005 | case KVM_S390_MCHK: | ||
1006 | target = (void *) &inti->mchk; | ||
1007 | source = &uptr->u.mchk; | ||
1008 | size = sizeof(inti->mchk); | ||
1009 | break; | ||
1010 | default: | ||
1011 | return -EINVAL; | ||
1012 | } | ||
1013 | |||
1014 | if (copy_from_user(target, source, size)) | ||
1015 | return -EFAULT; | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static int enqueue_floating_irq(struct kvm_device *dev, | ||
1021 | struct kvm_device_attr *attr) | ||
1022 | { | ||
1023 | struct kvm_s390_interrupt_info *inti = NULL; | ||
1024 | int r = 0; | ||
1025 | int len = attr->attr; | ||
1026 | |||
1027 | if (len % sizeof(struct kvm_s390_irq) != 0) | ||
1028 | return -EINVAL; | ||
1029 | else if (len > KVM_S390_FLIC_MAX_BUFFER) | ||
1030 | return -EINVAL; | ||
1031 | |||
1032 | while (len >= sizeof(struct kvm_s390_irq)) { | ||
1033 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); | ||
1034 | if (!inti) | ||
1035 | return -ENOMEM; | ||
1036 | |||
1037 | r = copy_irq_from_user(inti, attr->addr); | ||
1038 | if (r) { | ||
1039 | kfree(inti); | ||
1040 | return r; | ||
1041 | } | ||
1042 | r = __inject_vm(dev->kvm, inti); | ||
1043 | if (r) { | ||
1044 | kfree(inti); | ||
1045 | return r; | ||
1046 | } | ||
1047 | len -= sizeof(struct kvm_s390_irq); | ||
1048 | attr->addr += sizeof(struct kvm_s390_irq); | ||
1049 | } | ||
1050 | |||
1051 | return r; | ||
1052 | } | ||
1053 | |||
1054 | static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | ||
1055 | { | ||
1056 | int r = 0; | ||
1057 | unsigned int i; | ||
1058 | struct kvm_vcpu *vcpu; | ||
1059 | |||
1060 | switch (attr->group) { | ||
1061 | case KVM_DEV_FLIC_ENQUEUE: | ||
1062 | r = enqueue_floating_irq(dev, attr); | ||
1063 | break; | ||
1064 | case KVM_DEV_FLIC_CLEAR_IRQS: | ||
1065 | r = 0; | ||
1066 | clear_floating_interrupts(dev->kvm); | ||
1067 | break; | ||
1068 | case KVM_DEV_FLIC_APF_ENABLE: | ||
1069 | dev->kvm->arch.gmap->pfault_enabled = 1; | ||
1070 | break; | ||
1071 | case KVM_DEV_FLIC_APF_DISABLE_WAIT: | ||
1072 | dev->kvm->arch.gmap->pfault_enabled = 0; | ||
1073 | /* | ||
1074 | * Make sure no async faults are in transition when | ||
1075 | * clearing the queues. So we don't need to worry | ||
1076 | * about late coming workers. | ||
1077 | */ | ||
1078 | synchronize_srcu(&dev->kvm->srcu); | ||
1079 | kvm_for_each_vcpu(i, vcpu, dev->kvm) | ||
1080 | kvm_clear_async_pf_completion_queue(vcpu); | ||
1081 | break; | ||
1082 | default: | ||
1083 | r = -EINVAL; | ||
1084 | } | ||
1085 | |||
1086 | return r; | ||
1087 | } | ||
1088 | |||
1089 | static int flic_create(struct kvm_device *dev, u32 type) | ||
1090 | { | ||
1091 | if (!dev) | ||
1092 | return -EINVAL; | ||
1093 | if (dev->kvm->arch.flic) | ||
1094 | return -EINVAL; | ||
1095 | dev->kvm->arch.flic = dev; | ||
1096 | return 0; | ||
1097 | } | ||
1098 | |||
1099 | static void flic_destroy(struct kvm_device *dev) | ||
1100 | { | ||
1101 | dev->kvm->arch.flic = NULL; | ||
1102 | kfree(dev); | ||
1103 | } | ||
1104 | |||
1105 | /* s390 floating irq controller (flic) */ | ||
1106 | struct kvm_device_ops kvm_flic_ops = { | ||
1107 | .name = "kvm-flic", | ||
1108 | .get_attr = flic_get_attr, | ||
1109 | .set_attr = flic_set_attr, | ||
1110 | .create = flic_create, | ||
1111 | .destroy = flic_destroy, | ||
1112 | }; | ||
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index e0676f390d57..a5da2cc798c8 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -152,11 +152,13 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
152 | #ifdef CONFIG_KVM_S390_UCONTROL | 152 | #ifdef CONFIG_KVM_S390_UCONTROL |
153 | case KVM_CAP_S390_UCONTROL: | 153 | case KVM_CAP_S390_UCONTROL: |
154 | #endif | 154 | #endif |
155 | case KVM_CAP_ASYNC_PF: | ||
155 | case KVM_CAP_SYNC_REGS: | 156 | case KVM_CAP_SYNC_REGS: |
156 | case KVM_CAP_ONE_REG: | 157 | case KVM_CAP_ONE_REG: |
157 | case KVM_CAP_ENABLE_CAP: | 158 | case KVM_CAP_ENABLE_CAP: |
158 | case KVM_CAP_S390_CSS_SUPPORT: | 159 | case KVM_CAP_S390_CSS_SUPPORT: |
159 | case KVM_CAP_IOEVENTFD: | 160 | case KVM_CAP_IOEVENTFD: |
161 | case KVM_CAP_DEVICE_CTRL: | ||
160 | r = 1; | 162 | r = 1; |
161 | break; | 163 | break; |
162 | case KVM_CAP_NR_VCPUS: | 164 | case KVM_CAP_NR_VCPUS: |
@@ -254,6 +256,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
254 | if (!kvm->arch.gmap) | 256 | if (!kvm->arch.gmap) |
255 | goto out_nogmap; | 257 | goto out_nogmap; |
256 | kvm->arch.gmap->private = kvm; | 258 | kvm->arch.gmap->private = kvm; |
259 | kvm->arch.gmap->pfault_enabled = 0; | ||
257 | } | 260 | } |
258 | 261 | ||
259 | kvm->arch.css_support = 0; | 262 | kvm->arch.css_support = 0; |
@@ -271,6 +274,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | |||
271 | { | 274 | { |
272 | VCPU_EVENT(vcpu, 3, "%s", "free cpu"); | 275 | VCPU_EVENT(vcpu, 3, "%s", "free cpu"); |
273 | trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id); | 276 | trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id); |
277 | kvm_clear_async_pf_completion_queue(vcpu); | ||
274 | if (!kvm_is_ucontrol(vcpu->kvm)) { | 278 | if (!kvm_is_ucontrol(vcpu->kvm)) { |
275 | clear_bit(63 - vcpu->vcpu_id, | 279 | clear_bit(63 - vcpu->vcpu_id, |
276 | (unsigned long *) &vcpu->kvm->arch.sca->mcn); | 280 | (unsigned long *) &vcpu->kvm->arch.sca->mcn); |
@@ -320,6 +324,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
320 | /* Section: vcpu related */ | 324 | /* Section: vcpu related */ |
321 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | 325 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) |
322 | { | 326 | { |
327 | vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; | ||
328 | kvm_clear_async_pf_completion_queue(vcpu); | ||
323 | if (kvm_is_ucontrol(vcpu->kvm)) { | 329 | if (kvm_is_ucontrol(vcpu->kvm)) { |
324 | vcpu->arch.gmap = gmap_alloc(current->mm); | 330 | vcpu->arch.gmap = gmap_alloc(current->mm); |
325 | if (!vcpu->arch.gmap) | 331 | if (!vcpu->arch.gmap) |
@@ -380,6 +386,8 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) | |||
380 | vcpu->arch.guest_fpregs.fpc = 0; | 386 | vcpu->arch.guest_fpregs.fpc = 0; |
381 | asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc)); | 387 | asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc)); |
382 | vcpu->arch.sie_block->gbea = 1; | 388 | vcpu->arch.sie_block->gbea = 1; |
389 | vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; | ||
390 | kvm_clear_async_pf_completion_queue(vcpu); | ||
383 | atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); | 391 | atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); |
384 | } | 392 | } |
385 | 393 | ||
@@ -553,6 +561,18 @@ static int kvm_arch_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, | |||
553 | r = put_user(vcpu->arch.sie_block->ckc, | 561 | r = put_user(vcpu->arch.sie_block->ckc, |
554 | (u64 __user *)reg->addr); | 562 | (u64 __user *)reg->addr); |
555 | break; | 563 | break; |
564 | case KVM_REG_S390_PFTOKEN: | ||
565 | r = put_user(vcpu->arch.pfault_token, | ||
566 | (u64 __user *)reg->addr); | ||
567 | break; | ||
568 | case KVM_REG_S390_PFCOMPARE: | ||
569 | r = put_user(vcpu->arch.pfault_compare, | ||
570 | (u64 __user *)reg->addr); | ||
571 | break; | ||
572 | case KVM_REG_S390_PFSELECT: | ||
573 | r = put_user(vcpu->arch.pfault_select, | ||
574 | (u64 __user *)reg->addr); | ||
575 | break; | ||
556 | default: | 576 | default: |
557 | break; | 577 | break; |
558 | } | 578 | } |
@@ -582,6 +602,18 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, | |||
582 | r = get_user(vcpu->arch.sie_block->ckc, | 602 | r = get_user(vcpu->arch.sie_block->ckc, |
583 | (u64 __user *)reg->addr); | 603 | (u64 __user *)reg->addr); |
584 | break; | 604 | break; |
605 | case KVM_REG_S390_PFTOKEN: | ||
606 | r = get_user(vcpu->arch.pfault_token, | ||
607 | (u64 __user *)reg->addr); | ||
608 | break; | ||
609 | case KVM_REG_S390_PFCOMPARE: | ||
610 | r = get_user(vcpu->arch.pfault_compare, | ||
611 | (u64 __user *)reg->addr); | ||
612 | break; | ||
613 | case KVM_REG_S390_PFSELECT: | ||
614 | r = get_user(vcpu->arch.pfault_select, | ||
615 | (u64 __user *)reg->addr); | ||
616 | break; | ||
585 | default: | 617 | default: |
586 | break; | 618 | break; |
587 | } | 619 | } |
@@ -700,10 +732,100 @@ static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) | |||
700 | return 0; | 732 | return 0; |
701 | } | 733 | } |
702 | 734 | ||
735 | static long kvm_arch_fault_in_sync(struct kvm_vcpu *vcpu) | ||
736 | { | ||
737 | long rc; | ||
738 | hva_t fault = gmap_fault(current->thread.gmap_addr, vcpu->arch.gmap); | ||
739 | struct mm_struct *mm = current->mm; | ||
740 | down_read(&mm->mmap_sem); | ||
741 | rc = get_user_pages(current, mm, fault, 1, 1, 0, NULL, NULL); | ||
742 | up_read(&mm->mmap_sem); | ||
743 | return rc; | ||
744 | } | ||
745 | |||
746 | static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token, | ||
747 | unsigned long token) | ||
748 | { | ||
749 | struct kvm_s390_interrupt inti; | ||
750 | inti.parm64 = token; | ||
751 | |||
752 | if (start_token) { | ||
753 | inti.type = KVM_S390_INT_PFAULT_INIT; | ||
754 | WARN_ON_ONCE(kvm_s390_inject_vcpu(vcpu, &inti)); | ||
755 | } else { | ||
756 | inti.type = KVM_S390_INT_PFAULT_DONE; | ||
757 | WARN_ON_ONCE(kvm_s390_inject_vm(vcpu->kvm, &inti)); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu, | ||
762 | struct kvm_async_pf *work) | ||
763 | { | ||
764 | trace_kvm_s390_pfault_init(vcpu, work->arch.pfault_token); | ||
765 | __kvm_inject_pfault_token(vcpu, true, work->arch.pfault_token); | ||
766 | } | ||
767 | |||
768 | void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, | ||
769 | struct kvm_async_pf *work) | ||
770 | { | ||
771 | trace_kvm_s390_pfault_done(vcpu, work->arch.pfault_token); | ||
772 | __kvm_inject_pfault_token(vcpu, false, work->arch.pfault_token); | ||
773 | } | ||
774 | |||
775 | void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, | ||
776 | struct kvm_async_pf *work) | ||
777 | { | ||
778 | /* s390 will always inject the page directly */ | ||
779 | } | ||
780 | |||
781 | bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) | ||
782 | { | ||
783 | /* | ||
784 | * s390 will always inject the page directly, | ||
785 | * but we still want check_async_completion to cleanup | ||
786 | */ | ||
787 | return true; | ||
788 | } | ||
789 | |||
790 | static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu) | ||
791 | { | ||
792 | hva_t hva; | ||
793 | struct kvm_arch_async_pf arch; | ||
794 | int rc; | ||
795 | |||
796 | if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) | ||
797 | return 0; | ||
798 | if ((vcpu->arch.sie_block->gpsw.mask & vcpu->arch.pfault_select) != | ||
799 | vcpu->arch.pfault_compare) | ||
800 | return 0; | ||
801 | if (psw_extint_disabled(vcpu)) | ||
802 | return 0; | ||
803 | if (kvm_cpu_has_interrupt(vcpu)) | ||
804 | return 0; | ||
805 | if (!(vcpu->arch.sie_block->gcr[0] & 0x200ul)) | ||
806 | return 0; | ||
807 | if (!vcpu->arch.gmap->pfault_enabled) | ||
808 | return 0; | ||
809 | |||
810 | hva = gmap_fault(current->thread.gmap_addr, vcpu->arch.gmap); | ||
811 | if (copy_from_guest(vcpu, &arch.pfault_token, vcpu->arch.pfault_token, 8)) | ||
812 | return 0; | ||
813 | |||
814 | rc = kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch); | ||
815 | return rc; | ||
816 | } | ||
817 | |||
703 | static int vcpu_pre_run(struct kvm_vcpu *vcpu) | 818 | static int vcpu_pre_run(struct kvm_vcpu *vcpu) |
704 | { | 819 | { |
705 | int rc, cpuflags; | 820 | int rc, cpuflags; |
706 | 821 | ||
822 | /* | ||
823 | * On s390 notifications for arriving pages will be delivered directly | ||
824 | * to the guest but the house keeping for completed pfaults is | ||
825 | * handled outside the worker. | ||
826 | */ | ||
827 | kvm_check_async_pf_completion(vcpu); | ||
828 | |||
707 | memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16); | 829 | memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16); |
708 | 830 | ||
709 | if (need_resched()) | 831 | if (need_resched()) |
@@ -729,7 +851,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu) | |||
729 | 851 | ||
730 | static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) | 852 | static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) |
731 | { | 853 | { |
732 | int rc; | 854 | int rc = -1; |
733 | 855 | ||
734 | VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", | 856 | VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", |
735 | vcpu->arch.sie_block->icptcode); | 857 | vcpu->arch.sie_block->icptcode); |
@@ -743,7 +865,16 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) | |||
743 | current->thread.gmap_addr; | 865 | current->thread.gmap_addr; |
744 | vcpu->run->s390_ucontrol.pgm_code = 0x10; | 866 | vcpu->run->s390_ucontrol.pgm_code = 0x10; |
745 | rc = -EREMOTE; | 867 | rc = -EREMOTE; |
746 | } else { | 868 | |
869 | } else if (current->thread.gmap_pfault) { | ||
870 | trace_kvm_s390_major_guest_pfault(vcpu); | ||
871 | current->thread.gmap_pfault = 0; | ||
872 | if (kvm_arch_setup_async_pf(vcpu) || | ||
873 | (kvm_arch_fault_in_sync(vcpu) >= 0)) | ||
874 | rc = 0; | ||
875 | } | ||
876 | |||
877 | if (rc == -1) { | ||
747 | VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); | 878 | VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); |
748 | trace_kvm_s390_sie_fault(vcpu); | 879 | trace_kvm_s390_sie_fault(vcpu); |
749 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 880 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index f9559b0bd620..ed4750a5bc3c 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -159,4 +159,8 @@ void exit_sie_sync(struct kvm_vcpu *vcpu); | |||
159 | /* implemented in diag.c */ | 159 | /* implemented in diag.c */ |
160 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); | 160 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); |
161 | 161 | ||
162 | /* implemented in interrupt.c */ | ||
163 | int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu); | ||
164 | int psw_extint_disabled(struct kvm_vcpu *vcpu); | ||
165 | |||
162 | #endif | 166 | #endif |
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 87c2b3a3bd3e..fe9442d39f0e 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -224,6 +224,8 @@ unlock: | |||
224 | static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) | 224 | static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) |
225 | { | 225 | { |
226 | int rc; | 226 | int rc; |
227 | unsigned int i; | ||
228 | struct kvm_vcpu *v; | ||
227 | 229 | ||
228 | switch (parameter & 0xff) { | 230 | switch (parameter & 0xff) { |
229 | case 0: | 231 | case 0: |
@@ -231,6 +233,11 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) | |||
231 | break; | 233 | break; |
232 | case 1: | 234 | case 1: |
233 | case 2: | 235 | case 2: |
236 | kvm_for_each_vcpu(i, v, vcpu->kvm) { | ||
237 | v->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; | ||
238 | kvm_clear_async_pf_completion_queue(v); | ||
239 | } | ||
240 | |||
234 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; | 241 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; |
235 | break; | 242 | break; |
236 | default: | 243 | default: |
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h index 3db76b2daed7..e8e7213d4cc5 100644 --- a/arch/s390/kvm/trace.h +++ b/arch/s390/kvm/trace.h | |||
@@ -30,6 +30,52 @@ | |||
30 | TP_printk("%02d[%016lx-%016lx]: " p_str, __entry->id, \ | 30 | TP_printk("%02d[%016lx-%016lx]: " p_str, __entry->id, \ |
31 | __entry->pswmask, __entry->pswaddr, p_args) | 31 | __entry->pswmask, __entry->pswaddr, p_args) |
32 | 32 | ||
33 | TRACE_EVENT(kvm_s390_major_guest_pfault, | ||
34 | TP_PROTO(VCPU_PROTO_COMMON), | ||
35 | TP_ARGS(VCPU_ARGS_COMMON), | ||
36 | |||
37 | TP_STRUCT__entry( | ||
38 | VCPU_FIELD_COMMON | ||
39 | ), | ||
40 | |||
41 | TP_fast_assign( | ||
42 | VCPU_ASSIGN_COMMON | ||
43 | ), | ||
44 | VCPU_TP_PRINTK("%s", "major fault, maybe applicable for pfault") | ||
45 | ); | ||
46 | |||
47 | TRACE_EVENT(kvm_s390_pfault_init, | ||
48 | TP_PROTO(VCPU_PROTO_COMMON, long pfault_token), | ||
49 | TP_ARGS(VCPU_ARGS_COMMON, pfault_token), | ||
50 | |||
51 | TP_STRUCT__entry( | ||
52 | VCPU_FIELD_COMMON | ||
53 | __field(long, pfault_token) | ||
54 | ), | ||
55 | |||
56 | TP_fast_assign( | ||
57 | VCPU_ASSIGN_COMMON | ||
58 | __entry->pfault_token = pfault_token; | ||
59 | ), | ||
60 | VCPU_TP_PRINTK("init pfault token %ld", __entry->pfault_token) | ||
61 | ); | ||
62 | |||
63 | TRACE_EVENT(kvm_s390_pfault_done, | ||
64 | TP_PROTO(VCPU_PROTO_COMMON, long pfault_token), | ||
65 | TP_ARGS(VCPU_ARGS_COMMON, pfault_token), | ||
66 | |||
67 | TP_STRUCT__entry( | ||
68 | VCPU_FIELD_COMMON | ||
69 | __field(long, pfault_token) | ||
70 | ), | ||
71 | |||
72 | TP_fast_assign( | ||
73 | VCPU_ASSIGN_COMMON | ||
74 | __entry->pfault_token = pfault_token; | ||
75 | ), | ||
76 | VCPU_TP_PRINTK("done pfault token %ld", __entry->pfault_token) | ||
77 | ); | ||
78 | |||
33 | /* | 79 | /* |
34 | * Tracepoints for SIE entry and exit. | 80 | * Tracepoints for SIE entry and exit. |
35 | */ | 81 | */ |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index d95265b2719f..88cef505453b 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #define VM_FAULT_BADMAP 0x020000 | 50 | #define VM_FAULT_BADMAP 0x020000 |
51 | #define VM_FAULT_BADACCESS 0x040000 | 51 | #define VM_FAULT_BADACCESS 0x040000 |
52 | #define VM_FAULT_SIGNAL 0x080000 | 52 | #define VM_FAULT_SIGNAL 0x080000 |
53 | #define VM_FAULT_PFAULT 0x100000 | ||
53 | 54 | ||
54 | static unsigned long store_indication __read_mostly; | 55 | static unsigned long store_indication __read_mostly; |
55 | 56 | ||
@@ -227,6 +228,7 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault) | |||
227 | return; | 228 | return; |
228 | } | 229 | } |
229 | case VM_FAULT_BADCONTEXT: | 230 | case VM_FAULT_BADCONTEXT: |
231 | case VM_FAULT_PFAULT: | ||
230 | do_no_context(regs); | 232 | do_no_context(regs); |
231 | break; | 233 | break; |
232 | case VM_FAULT_SIGNAL: | 234 | case VM_FAULT_SIGNAL: |
@@ -264,6 +266,9 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault) | |||
264 | */ | 266 | */ |
265 | static inline int do_exception(struct pt_regs *regs, int access) | 267 | static inline int do_exception(struct pt_regs *regs, int access) |
266 | { | 268 | { |
269 | #ifdef CONFIG_PGSTE | ||
270 | struct gmap *gmap; | ||
271 | #endif | ||
267 | struct task_struct *tsk; | 272 | struct task_struct *tsk; |
268 | struct mm_struct *mm; | 273 | struct mm_struct *mm; |
269 | struct vm_area_struct *vma; | 274 | struct vm_area_struct *vma; |
@@ -304,9 +309,10 @@ static inline int do_exception(struct pt_regs *regs, int access) | |||
304 | down_read(&mm->mmap_sem); | 309 | down_read(&mm->mmap_sem); |
305 | 310 | ||
306 | #ifdef CONFIG_PGSTE | 311 | #ifdef CONFIG_PGSTE |
307 | if ((current->flags & PF_VCPU) && S390_lowcore.gmap) { | 312 | gmap = (struct gmap *) |
308 | address = __gmap_fault(address, | 313 | ((current->flags & PF_VCPU) ? S390_lowcore.gmap : 0); |
309 | (struct gmap *) S390_lowcore.gmap); | 314 | if (gmap) { |
315 | address = __gmap_fault(address, gmap); | ||
310 | if (address == -EFAULT) { | 316 | if (address == -EFAULT) { |
311 | fault = VM_FAULT_BADMAP; | 317 | fault = VM_FAULT_BADMAP; |
312 | goto out_up; | 318 | goto out_up; |
@@ -315,6 +321,8 @@ static inline int do_exception(struct pt_regs *regs, int access) | |||
315 | fault = VM_FAULT_OOM; | 321 | fault = VM_FAULT_OOM; |
316 | goto out_up; | 322 | goto out_up; |
317 | } | 323 | } |
324 | if (gmap->pfault_enabled) | ||
325 | flags |= FAULT_FLAG_RETRY_NOWAIT; | ||
318 | } | 326 | } |
319 | #endif | 327 | #endif |
320 | 328 | ||
@@ -371,9 +379,19 @@ retry: | |||
371 | regs, address); | 379 | regs, address); |
372 | } | 380 | } |
373 | if (fault & VM_FAULT_RETRY) { | 381 | if (fault & VM_FAULT_RETRY) { |
382 | #ifdef CONFIG_PGSTE | ||
383 | if (gmap && (flags & FAULT_FLAG_RETRY_NOWAIT)) { | ||
384 | /* FAULT_FLAG_RETRY_NOWAIT has been set, | ||
385 | * mmap_sem has not been released */ | ||
386 | current->thread.gmap_pfault = 1; | ||
387 | fault = VM_FAULT_PFAULT; | ||
388 | goto out_up; | ||
389 | } | ||
390 | #endif | ||
374 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | 391 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk |
375 | * of starvation. */ | 392 | * of starvation. */ |
376 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 393 | flags &= ~(FAULT_FLAG_ALLOW_RETRY | |
394 | FAULT_FLAG_RETRY_NOWAIT); | ||
377 | flags |= FAULT_FLAG_TRIED; | 395 | flags |= FAULT_FLAG_TRIED; |
378 | down_read(&mm->mmap_sem); | 396 | down_read(&mm->mmap_sem); |
379 | goto retry; | 397 | goto retry; |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index e50425d0f5f7..aaa60f347b73 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -3328,7 +3328,7 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn) | |||
3328 | arch.direct_map = vcpu->arch.mmu.direct_map; | 3328 | arch.direct_map = vcpu->arch.mmu.direct_map; |
3329 | arch.cr3 = vcpu->arch.mmu.get_cr3(vcpu); | 3329 | arch.cr3 = vcpu->arch.mmu.get_cr3(vcpu); |
3330 | 3330 | ||
3331 | return kvm_setup_async_pf(vcpu, gva, gfn, &arch); | 3331 | return kvm_setup_async_pf(vcpu, gva, gfn_to_hva(vcpu->kvm, gfn), &arch); |
3332 | } | 3332 | } |
3333 | 3333 | ||
3334 | static bool can_do_async_pf(struct kvm_vcpu *vcpu) | 3334 | static bool can_do_async_pf(struct kvm_vcpu *vcpu) |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index b8e9a43e501a..f5937b8188b4 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -192,7 +192,7 @@ struct kvm_async_pf { | |||
192 | 192 | ||
193 | void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu); | 193 | void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu); |
194 | void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu); | 194 | void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu); |
195 | int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn, | 195 | int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva, |
196 | struct kvm_arch_async_pf *arch); | 196 | struct kvm_arch_async_pf *arch); |
197 | int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu); | 197 | int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu); |
198 | #endif | 198 | #endif |
@@ -1064,6 +1064,7 @@ extern struct kvm_device_ops kvm_mpic_ops; | |||
1064 | extern struct kvm_device_ops kvm_xics_ops; | 1064 | extern struct kvm_device_ops kvm_xics_ops; |
1065 | extern struct kvm_device_ops kvm_vfio_ops; | 1065 | extern struct kvm_device_ops kvm_vfio_ops; |
1066 | extern struct kvm_device_ops kvm_arm_vgic_v2_ops; | 1066 | extern struct kvm_device_ops kvm_arm_vgic_v2_ops; |
1067 | extern struct kvm_device_ops kvm_flic_ops; | ||
1067 | 1068 | ||
1068 | #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT | 1069 | #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT |
1069 | 1070 | ||
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 932d7f2637d6..7d76401d2bb5 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h | |||
@@ -413,6 +413,8 @@ struct kvm_s390_psw { | |||
413 | #define KVM_S390_PROGRAM_INT 0xfffe0001u | 413 | #define KVM_S390_PROGRAM_INT 0xfffe0001u |
414 | #define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u | 414 | #define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u |
415 | #define KVM_S390_RESTART 0xfffe0003u | 415 | #define KVM_S390_RESTART 0xfffe0003u |
416 | #define KVM_S390_INT_PFAULT_INIT 0xfffe0004u | ||
417 | #define KVM_S390_INT_PFAULT_DONE 0xfffe0005u | ||
416 | #define KVM_S390_MCHK 0xfffe1000u | 418 | #define KVM_S390_MCHK 0xfffe1000u |
417 | #define KVM_S390_INT_VIRTIO 0xffff2603u | 419 | #define KVM_S390_INT_VIRTIO 0xffff2603u |
418 | #define KVM_S390_INT_SERVICE 0xffff2401u | 420 | #define KVM_S390_INT_SERVICE 0xffff2401u |
@@ -434,6 +436,69 @@ struct kvm_s390_interrupt { | |||
434 | __u64 parm64; | 436 | __u64 parm64; |
435 | }; | 437 | }; |
436 | 438 | ||
439 | struct kvm_s390_io_info { | ||
440 | __u16 subchannel_id; | ||
441 | __u16 subchannel_nr; | ||
442 | __u32 io_int_parm; | ||
443 | __u32 io_int_word; | ||
444 | }; | ||
445 | |||
446 | struct kvm_s390_ext_info { | ||
447 | __u32 ext_params; | ||
448 | __u32 pad; | ||
449 | __u64 ext_params2; | ||
450 | }; | ||
451 | |||
452 | struct kvm_s390_pgm_info { | ||
453 | __u64 trans_exc_code; | ||
454 | __u64 mon_code; | ||
455 | __u64 per_address; | ||
456 | __u32 data_exc_code; | ||
457 | __u16 code; | ||
458 | __u16 mon_class_nr; | ||
459 | __u8 per_code; | ||
460 | __u8 per_atmid; | ||
461 | __u8 exc_access_id; | ||
462 | __u8 per_access_id; | ||
463 | __u8 op_access_id; | ||
464 | __u8 pad[3]; | ||
465 | }; | ||
466 | |||
467 | struct kvm_s390_prefix_info { | ||
468 | __u32 address; | ||
469 | }; | ||
470 | |||
471 | struct kvm_s390_extcall_info { | ||
472 | __u16 code; | ||
473 | }; | ||
474 | |||
475 | struct kvm_s390_emerg_info { | ||
476 | __u16 code; | ||
477 | }; | ||
478 | |||
479 | struct kvm_s390_mchk_info { | ||
480 | __u64 cr14; | ||
481 | __u64 mcic; | ||
482 | __u64 failing_storage_address; | ||
483 | __u32 ext_damage_code; | ||
484 | __u32 pad; | ||
485 | __u8 fixed_logout[16]; | ||
486 | }; | ||
487 | |||
488 | struct kvm_s390_irq { | ||
489 | __u64 type; | ||
490 | union { | ||
491 | struct kvm_s390_io_info io; | ||
492 | struct kvm_s390_ext_info ext; | ||
493 | struct kvm_s390_pgm_info pgm; | ||
494 | struct kvm_s390_emerg_info emerg; | ||
495 | struct kvm_s390_extcall_info extcall; | ||
496 | struct kvm_s390_prefix_info prefix; | ||
497 | struct kvm_s390_mchk_info mchk; | ||
498 | char reserved[64]; | ||
499 | } u; | ||
500 | }; | ||
501 | |||
437 | /* for KVM_SET_GUEST_DEBUG */ | 502 | /* for KVM_SET_GUEST_DEBUG */ |
438 | 503 | ||
439 | #define KVM_GUESTDBG_ENABLE 0x00000001 | 504 | #define KVM_GUESTDBG_ENABLE 0x00000001 |
@@ -855,6 +920,7 @@ struct kvm_device_attr { | |||
855 | #define KVM_DEV_VFIO_GROUP_ADD 1 | 920 | #define KVM_DEV_VFIO_GROUP_ADD 1 |
856 | #define KVM_DEV_VFIO_GROUP_DEL 2 | 921 | #define KVM_DEV_VFIO_GROUP_DEL 2 |
857 | #define KVM_DEV_TYPE_ARM_VGIC_V2 5 | 922 | #define KVM_DEV_TYPE_ARM_VGIC_V2 5 |
923 | #define KVM_DEV_TYPE_FLIC 6 | ||
858 | 924 | ||
859 | /* | 925 | /* |
860 | * ioctls for VM fds | 926 | * ioctls for VM fds |
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig index fbe1a48bd629..13f2d19793e3 100644 --- a/virt/kvm/Kconfig +++ b/virt/kvm/Kconfig | |||
@@ -22,6 +22,10 @@ config KVM_MMIO | |||
22 | config KVM_ASYNC_PF | 22 | config KVM_ASYNC_PF |
23 | bool | 23 | bool |
24 | 24 | ||
25 | # Toggle to switch between direct notification and batch job | ||
26 | config KVM_ASYNC_PF_SYNC | ||
27 | bool | ||
28 | |||
25 | config HAVE_KVM_MSI | 29 | config HAVE_KVM_MSI |
26 | bool | 30 | bool |
27 | 31 | ||
diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c index 8631d9c14320..889aad022014 100644 --- a/virt/kvm/async_pf.c +++ b/virt/kvm/async_pf.c | |||
@@ -28,6 +28,21 @@ | |||
28 | #include "async_pf.h" | 28 | #include "async_pf.h" |
29 | #include <trace/events/kvm.h> | 29 | #include <trace/events/kvm.h> |
30 | 30 | ||
31 | static inline void kvm_async_page_present_sync(struct kvm_vcpu *vcpu, | ||
32 | struct kvm_async_pf *work) | ||
33 | { | ||
34 | #ifdef CONFIG_KVM_ASYNC_PF_SYNC | ||
35 | kvm_arch_async_page_present(vcpu, work); | ||
36 | #endif | ||
37 | } | ||
38 | static inline void kvm_async_page_present_async(struct kvm_vcpu *vcpu, | ||
39 | struct kvm_async_pf *work) | ||
40 | { | ||
41 | #ifndef CONFIG_KVM_ASYNC_PF_SYNC | ||
42 | kvm_arch_async_page_present(vcpu, work); | ||
43 | #endif | ||
44 | } | ||
45 | |||
31 | static struct kmem_cache *async_pf_cache; | 46 | static struct kmem_cache *async_pf_cache; |
32 | 47 | ||
33 | int kvm_async_pf_init(void) | 48 | int kvm_async_pf_init(void) |
@@ -69,6 +84,7 @@ static void async_pf_execute(struct work_struct *work) | |||
69 | down_read(&mm->mmap_sem); | 84 | down_read(&mm->mmap_sem); |
70 | get_user_pages(current, mm, addr, 1, 1, 0, NULL, NULL); | 85 | get_user_pages(current, mm, addr, 1, 1, 0, NULL, NULL); |
71 | up_read(&mm->mmap_sem); | 86 | up_read(&mm->mmap_sem); |
87 | kvm_async_page_present_sync(vcpu, apf); | ||
72 | unuse_mm(mm); | 88 | unuse_mm(mm); |
73 | 89 | ||
74 | spin_lock(&vcpu->async_pf.lock); | 90 | spin_lock(&vcpu->async_pf.lock); |
@@ -97,11 +113,16 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu) | |||
97 | list_entry(vcpu->async_pf.queue.next, | 113 | list_entry(vcpu->async_pf.queue.next, |
98 | typeof(*work), queue); | 114 | typeof(*work), queue); |
99 | list_del(&work->queue); | 115 | list_del(&work->queue); |
116 | |||
117 | #ifdef CONFIG_KVM_ASYNC_PF_SYNC | ||
118 | flush_work(&work->work); | ||
119 | #else | ||
100 | if (cancel_work_sync(&work->work)) { | 120 | if (cancel_work_sync(&work->work)) { |
101 | mmdrop(work->mm); | 121 | mmdrop(work->mm); |
102 | kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */ | 122 | kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */ |
103 | kmem_cache_free(async_pf_cache, work); | 123 | kmem_cache_free(async_pf_cache, work); |
104 | } | 124 | } |
125 | #endif | ||
105 | } | 126 | } |
106 | 127 | ||
107 | spin_lock(&vcpu->async_pf.lock); | 128 | spin_lock(&vcpu->async_pf.lock); |
@@ -138,7 +159,7 @@ void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu) | |||
138 | } | 159 | } |
139 | } | 160 | } |
140 | 161 | ||
141 | int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn, | 162 | int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva, |
142 | struct kvm_arch_async_pf *arch) | 163 | struct kvm_arch_async_pf *arch) |
143 | { | 164 | { |
144 | struct kvm_async_pf *work; | 165 | struct kvm_async_pf *work; |
@@ -159,7 +180,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn, | |||
159 | work->wakeup_all = false; | 180 | work->wakeup_all = false; |
160 | work->vcpu = vcpu; | 181 | work->vcpu = vcpu; |
161 | work->gva = gva; | 182 | work->gva = gva; |
162 | work->addr = gfn_to_hva(vcpu->kvm, gfn); | 183 | work->addr = hva; |
163 | work->arch = *arch; | 184 | work->arch = *arch; |
164 | work->mm = current->mm; | 185 | work->mm = current->mm; |
165 | atomic_inc(&work->mm->mm_count); | 186 | atomic_inc(&work->mm->mm_count); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 03a0381b1cb7..a9e999a48e43 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -2284,6 +2284,11 @@ static int kvm_ioctl_create_device(struct kvm *kvm, | |||
2284 | ops = &kvm_arm_vgic_v2_ops; | 2284 | ops = &kvm_arm_vgic_v2_ops; |
2285 | break; | 2285 | break; |
2286 | #endif | 2286 | #endif |
2287 | #ifdef CONFIG_S390 | ||
2288 | case KVM_DEV_TYPE_FLIC: | ||
2289 | ops = &kvm_flic_ops; | ||
2290 | break; | ||
2291 | #endif | ||
2287 | default: | 2292 | default: |
2288 | return -ENODEV; | 2293 | return -ENODEV; |
2289 | } | 2294 | } |