aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/virtual/kvm/api.txt21
-rw-r--r--arch/s390/include/asm/kvm_host.h9
-rw-r--r--arch/s390/kvm/Kconfig2
-rw-r--r--arch/s390/kvm/Makefile2
-rw-r--r--arch/s390/kvm/interrupt.c121
-rw-r--r--arch/s390/kvm/irq.h22
-rw-r--r--arch/s390/kvm/kvm-s390.c17
-rw-r--r--include/linux/kvm_host.h9
-rw-r--r--include/uapi/linux/kvm.h11
9 files changed, 209 insertions, 5 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index faf6fe9772c7..2cb1640a90ad 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -586,8 +586,8 @@ struct kvm_fpu {
586 586
5874.24 KVM_CREATE_IRQCHIP 5874.24 KVM_CREATE_IRQCHIP
588 588
589Capability: KVM_CAP_IRQCHIP 589Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
590Architectures: x86, ia64, ARM, arm64 590Architectures: x86, ia64, ARM, arm64, s390
591Type: vm ioctl 591Type: vm ioctl
592Parameters: none 592Parameters: none
593Returns: 0 on success, -1 on error 593Returns: 0 on success, -1 on error
@@ -596,7 +596,10 @@ Creates an interrupt controller model in the kernel. On x86, creates a virtual
596ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a 596ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a
597local APIC. IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23 597local APIC. IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23
598only go to the IOAPIC. On ia64, a IOSAPIC is created. On ARM/arm64, a GIC is 598only go to the IOAPIC. On ia64, a IOSAPIC is created. On ARM/arm64, a GIC is
599created. 599created. On s390, a dummy irq routing table is created.
600
601Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
602before KVM_CREATE_IRQCHIP can be used.
600 603
601 604
6024.25 KVM_IRQ_LINE 6054.25 KVM_IRQ_LINE
@@ -1336,7 +1339,7 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
13364.52 KVM_SET_GSI_ROUTING 13394.52 KVM_SET_GSI_ROUTING
1337 1340
1338Capability: KVM_CAP_IRQ_ROUTING 1341Capability: KVM_CAP_IRQ_ROUTING
1339Architectures: x86 ia64 1342Architectures: x86 ia64 s390
1340Type: vm ioctl 1343Type: vm ioctl
1341Parameters: struct kvm_irq_routing (in) 1344Parameters: struct kvm_irq_routing (in)
1342Returns: 0 on success, -1 on error 1345Returns: 0 on success, -1 on error
@@ -1359,6 +1362,7 @@ struct kvm_irq_routing_entry {
1359 union { 1362 union {
1360 struct kvm_irq_routing_irqchip irqchip; 1363 struct kvm_irq_routing_irqchip irqchip;
1361 struct kvm_irq_routing_msi msi; 1364 struct kvm_irq_routing_msi msi;
1365 struct kvm_irq_routing_s390_adapter adapter;
1362 __u32 pad[8]; 1366 __u32 pad[8];
1363 } u; 1367 } u;
1364}; 1368};
@@ -1366,6 +1370,7 @@ struct kvm_irq_routing_entry {
1366/* gsi routing entry types */ 1370/* gsi routing entry types */
1367#define KVM_IRQ_ROUTING_IRQCHIP 1 1371#define KVM_IRQ_ROUTING_IRQCHIP 1
1368#define KVM_IRQ_ROUTING_MSI 2 1372#define KVM_IRQ_ROUTING_MSI 2
1373#define KVM_IRQ_ROUTING_S390_ADAPTER 3
1369 1374
1370No flags are specified so far, the corresponding field must be set to zero. 1375No flags are specified so far, the corresponding field must be set to zero.
1371 1376
@@ -1381,6 +1386,14 @@ struct kvm_irq_routing_msi {
1381 __u32 pad; 1386 __u32 pad;
1382}; 1387};
1383 1388
1389struct kvm_irq_routing_s390_adapter {
1390 __u64 ind_addr;
1391 __u64 summary_addr;
1392 __u64 ind_offset;
1393 __u32 summary_offset;
1394 __u32 adapter_id;
1395};
1396
1384 1397
13854.53 KVM_ASSIGN_SET_MSIX_NR 13984.53 KVM_ASSIGN_SET_MSIX_NR
1386 1399
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 0d5235262707..dd3933754d23 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -24,6 +24,14 @@
24#define KVM_MAX_VCPUS 64 24#define KVM_MAX_VCPUS 64
25#define KVM_USER_MEM_SLOTS 32 25#define KVM_USER_MEM_SLOTS 32
26 26
27/*
28 * These seem to be used for allocating ->chip in the routing table,
29 * which we don't use. 4096 is an out-of-thin-air value. If we need
30 * to look at ->chip later on, we'll need to revisit this.
31 */
32#define KVM_NR_IRQCHIPS 1
33#define KVM_IRQCHIP_NUM_PINS 4096
34
27struct sca_entry { 35struct sca_entry {
28 atomic_t scn; 36 atomic_t scn;
29 __u32 reserved; 37 __u32 reserved;
@@ -274,6 +282,7 @@ struct kvm_arch{
274 struct kvm_device *flic; 282 struct kvm_device *flic;
275 struct gmap *gmap; 283 struct gmap *gmap;
276 int css_support; 284 int css_support;
285 int use_irqchip;
277 struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS]; 286 struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
278}; 287};
279 288
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index c8bacbcd2e5b..10d529ac9821 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -25,6 +25,8 @@ config KVM
25 select HAVE_KVM_EVENTFD 25 select HAVE_KVM_EVENTFD
26 select KVM_ASYNC_PF 26 select KVM_ASYNC_PF
27 select KVM_ASYNC_PF_SYNC 27 select KVM_ASYNC_PF_SYNC
28 select HAVE_KVM_IRQCHIP
29 select HAVE_KVM_IRQ_ROUTING
28 ---help--- 30 ---help---
29 Support hosting paravirtualized guest machines using the SIE 31 Support hosting paravirtualized guest machines using the SIE
30 virtualization capability on the mainframe. This should work 32 virtualization capability on the mainframe. This should work
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index a47d2c355f68..d3adb37e93a4 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
9KVM := ../../../virt/kvm 9KVM := ../../../virt/kvm
10common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o 10common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqchip.o
11 11
12ccflags-y := -Ivirt/kvm -Iarch/s390/kvm 12ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
13 13
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 7ecef5a18e25..2e2814eceb85 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -13,6 +13,7 @@
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/kvm_host.h> 14#include <linux/kvm_host.h>
15#include <linux/hrtimer.h> 15#include <linux/hrtimer.h>
16#include <linux/mmu_context.h>
16#include <linux/signal.h> 17#include <linux/signal.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
18#include <asm/asm-offsets.h> 19#include <asm/asm-offsets.h>
@@ -1284,3 +1285,123 @@ struct kvm_device_ops kvm_flic_ops = {
1284 .create = flic_create, 1285 .create = flic_create,
1285 .destroy = flic_destroy, 1286 .destroy = flic_destroy,
1286}; 1287};
1288
1289static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap)
1290{
1291 unsigned long bit;
1292
1293 bit = bit_nr + (addr % PAGE_SIZE) * 8;
1294
1295 return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit;
1296}
1297
1298static struct s390_map_info *get_map_info(struct s390_io_adapter *adapter,
1299 u64 addr)
1300{
1301 struct s390_map_info *map;
1302
1303 if (!adapter)
1304 return NULL;
1305
1306 list_for_each_entry(map, &adapter->maps, list) {
1307 if (map->guest_addr == addr)
1308 return map;
1309 }
1310 return NULL;
1311}
1312
1313static int adapter_indicators_set(struct kvm *kvm,
1314 struct s390_io_adapter *adapter,
1315 struct kvm_s390_adapter_int *adapter_int)
1316{
1317 unsigned long bit;
1318 int summary_set, idx;
1319 struct s390_map_info *info;
1320 void *map;
1321
1322 info = get_map_info(adapter, adapter_int->ind_addr);
1323 if (!info)
1324 return -1;
1325 map = page_address(info->page);
1326 bit = get_ind_bit(info->addr, adapter_int->ind_offset, adapter->swap);
1327 set_bit(bit, map);
1328 idx = srcu_read_lock(&kvm->srcu);
1329 mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
1330 set_page_dirty_lock(info->page);
1331 info = get_map_info(adapter, adapter_int->summary_addr);
1332 if (!info) {
1333 srcu_read_unlock(&kvm->srcu, idx);
1334 return -1;
1335 }
1336 map = page_address(info->page);
1337 bit = get_ind_bit(info->addr, adapter_int->summary_offset,
1338 adapter->swap);
1339 summary_set = test_and_set_bit(bit, map);
1340 mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
1341 set_page_dirty_lock(info->page);
1342 srcu_read_unlock(&kvm->srcu, idx);
1343 return summary_set ? 0 : 1;
1344}
1345
1346/*
1347 * < 0 - not injected due to error
1348 * = 0 - coalesced, summary indicator already active
1349 * > 0 - injected interrupt
1350 */
1351static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
1352 struct kvm *kvm, int irq_source_id, int level,
1353 bool line_status)
1354{
1355 int ret;
1356 struct s390_io_adapter *adapter;
1357
1358 /* We're only interested in the 0->1 transition. */
1359 if (!level)
1360 return 0;
1361 adapter = get_io_adapter(kvm, e->adapter.adapter_id);
1362 if (!adapter)
1363 return -1;
1364 down_read(&adapter->maps_lock);
1365 ret = adapter_indicators_set(kvm, adapter, &e->adapter);
1366 up_read(&adapter->maps_lock);
1367 if ((ret > 0) && !adapter->masked) {
1368 struct kvm_s390_interrupt s390int = {
1369 .type = KVM_S390_INT_IO(1, 0, 0, 0),
1370 .parm = 0,
1371 .parm64 = (adapter->isc << 27) | 0x80000000,
1372 };
1373 ret = kvm_s390_inject_vm(kvm, &s390int);
1374 if (ret == 0)
1375 ret = 1;
1376 }
1377 return ret;
1378}
1379
1380int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
1381 struct kvm_kernel_irq_routing_entry *e,
1382 const struct kvm_irq_routing_entry *ue)
1383{
1384 int ret;
1385
1386 switch (ue->type) {
1387 case KVM_IRQ_ROUTING_S390_ADAPTER:
1388 e->set = set_adapter_int;
1389 e->adapter.summary_addr = ue->u.adapter.summary_addr;
1390 e->adapter.ind_addr = ue->u.adapter.ind_addr;
1391 e->adapter.summary_offset = ue->u.adapter.summary_offset;
1392 e->adapter.ind_offset = ue->u.adapter.ind_offset;
1393 e->adapter.adapter_id = ue->u.adapter.adapter_id;
1394 ret = 0;
1395 break;
1396 default:
1397 ret = -EINVAL;
1398 }
1399
1400 return ret;
1401}
1402
1403int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
1404 int irq_source_id, int level, bool line_status)
1405{
1406 return -EINVAL;
1407}
diff --git a/arch/s390/kvm/irq.h b/arch/s390/kvm/irq.h
new file mode 100644
index 000000000000..d98e4159643d
--- /dev/null
+++ b/arch/s390/kvm/irq.h
@@ -0,0 +1,22 @@
1/*
2 * s390 irqchip routines
3 *
4 * Copyright IBM Corp. 2014
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License (version 2 only)
8 * as published by the Free Software Foundation.
9 *
10 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
11 */
12#ifndef __KVM_IRQ_H
13#define __KVM_IRQ_H
14
15#include <linux/kvm_host.h>
16
17static inline int irqchip_in_kernel(struct kvm *kvm)
18{
19 return 1;
20}
21
22#endif
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 2e6fbb0b4f68..ce5b659ec531 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -196,6 +196,10 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
196 return -EINVAL; 196 return -EINVAL;
197 197
198 switch (cap->cap) { 198 switch (cap->cap) {
199 case KVM_CAP_S390_IRQCHIP:
200 kvm->arch.use_irqchip = 1;
201 r = 0;
202 break;
199 default: 203 default:
200 r = -EINVAL; 204 r = -EINVAL;
201 break; 205 break;
@@ -228,6 +232,18 @@ long kvm_arch_vm_ioctl(struct file *filp,
228 r = kvm_vm_ioctl_enable_cap(kvm, &cap); 232 r = kvm_vm_ioctl_enable_cap(kvm, &cap);
229 break; 233 break;
230 } 234 }
235 case KVM_CREATE_IRQCHIP: {
236 struct kvm_irq_routing_entry routing;
237
238 r = -EINVAL;
239 if (kvm->arch.use_irqchip) {
240 /* Set up dummy routing. */
241 memset(&routing, 0, sizeof(routing));
242 kvm_set_irq_routing(kvm, &routing, 0, 0);
243 r = 0;
244 }
245 break;
246 }
231 default: 247 default:
232 r = -ENOTTY; 248 r = -ENOTTY;
233 } 249 }
@@ -284,6 +300,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
284 } 300 }
285 301
286 kvm->arch.css_support = 0; 302 kvm->arch.css_support = 0;
303 kvm->arch.use_irqchip = 0;
287 304
288 return 0; 305 return 0;
289out_nogmap: 306out_nogmap:
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 9816b68b085f..da7510b4c6ad 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -297,6 +297,14 @@ static inline unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memsl
297 return ALIGN(memslot->npages, BITS_PER_LONG) / 8; 297 return ALIGN(memslot->npages, BITS_PER_LONG) / 8;
298} 298}
299 299
300struct kvm_s390_adapter_int {
301 u64 ind_addr;
302 u64 summary_addr;
303 u64 ind_offset;
304 u32 summary_offset;
305 u32 adapter_id;
306};
307
300struct kvm_kernel_irq_routing_entry { 308struct kvm_kernel_irq_routing_entry {
301 u32 gsi; 309 u32 gsi;
302 u32 type; 310 u32 type;
@@ -309,6 +317,7 @@ struct kvm_kernel_irq_routing_entry {
309 unsigned pin; 317 unsigned pin;
310 } irqchip; 318 } irqchip;
311 struct msi_msg msi; 319 struct msi_msg msi;
320 struct kvm_s390_adapter_int adapter;
312 }; 321 };
313 struct hlist_node link; 322 struct hlist_node link;
314}; 323};
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 46ea1b470c76..a8f4ee5d2e82 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -742,6 +742,7 @@ struct kvm_ppc_smmu_info {
742#define KVM_CAP_HYPERV_TIME 96 742#define KVM_CAP_HYPERV_TIME 96
743#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97 743#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
744#define KVM_CAP_ENABLE_CAP_VM 98 744#define KVM_CAP_ENABLE_CAP_VM 98
745#define KVM_CAP_S390_IRQCHIP 99
745 746
746#ifdef KVM_CAP_IRQ_ROUTING 747#ifdef KVM_CAP_IRQ_ROUTING
747 748
@@ -757,9 +758,18 @@ struct kvm_irq_routing_msi {
757 __u32 pad; 758 __u32 pad;
758}; 759};
759 760
761struct kvm_irq_routing_s390_adapter {
762 __u64 ind_addr;
763 __u64 summary_addr;
764 __u64 ind_offset;
765 __u32 summary_offset;
766 __u32 adapter_id;
767};
768
760/* gsi routing entry types */ 769/* gsi routing entry types */
761#define KVM_IRQ_ROUTING_IRQCHIP 1 770#define KVM_IRQ_ROUTING_IRQCHIP 1
762#define KVM_IRQ_ROUTING_MSI 2 771#define KVM_IRQ_ROUTING_MSI 2
772#define KVM_IRQ_ROUTING_S390_ADAPTER 3
763 773
764struct kvm_irq_routing_entry { 774struct kvm_irq_routing_entry {
765 __u32 gsi; 775 __u32 gsi;
@@ -769,6 +779,7 @@ struct kvm_irq_routing_entry {
769 union { 779 union {
770 struct kvm_irq_routing_irqchip irqchip; 780 struct kvm_irq_routing_irqchip irqchip;
771 struct kvm_irq_routing_msi msi; 781 struct kvm_irq_routing_msi msi;
782 struct kvm_irq_routing_s390_adapter adapter;
772 __u32 pad[8]; 783 __u32 pad[8];
773 } u; 784 } u;
774}; 785};