diff options
| author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2013-07-15 07:36:01 -0400 |
|---|---|---|
| committer | Cornelia Huck <cornelia.huck@de.ibm.com> | 2014-03-21 08:43:00 -0400 |
| commit | 84223598778ba08041f4297fda485df83414d57e (patch) | |
| tree | bd93b83a13cc5cd1f6781bf681161fb3982548c5 | |
| parent | 841b91c584b6d1e2a2cb508bd2d0236cd37e1750 (diff) | |
KVM: s390: irq routing for adapter interrupts.
Introduce a new interrupt class for s390 adapter interrupts and enable
irqfds for s390.
This is depending on a new s390 specific vm capability, KVM_CAP_S390_IRQCHIP,
that needs to be enabled by userspace.
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
| -rw-r--r-- | Documentation/virtual/kvm/api.txt | 21 | ||||
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 9 | ||||
| -rw-r--r-- | arch/s390/kvm/Kconfig | 2 | ||||
| -rw-r--r-- | arch/s390/kvm/Makefile | 2 | ||||
| -rw-r--r-- | arch/s390/kvm/interrupt.c | 121 | ||||
| -rw-r--r-- | arch/s390/kvm/irq.h | 22 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 17 | ||||
| -rw-r--r-- | include/linux/kvm_host.h | 9 | ||||
| -rw-r--r-- | include/uapi/linux/kvm.h | 11 |
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 | ||
| 587 | 4.24 KVM_CREATE_IRQCHIP | 587 | 4.24 KVM_CREATE_IRQCHIP |
| 588 | 588 | ||
| 589 | Capability: KVM_CAP_IRQCHIP | 589 | Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390) |
| 590 | Architectures: x86, ia64, ARM, arm64 | 590 | Architectures: x86, ia64, ARM, arm64, s390 |
| 591 | Type: vm ioctl | 591 | Type: vm ioctl |
| 592 | Parameters: none | 592 | Parameters: none |
| 593 | Returns: 0 on success, -1 on error | 593 | Returns: 0 on success, -1 on error |
| @@ -596,7 +596,10 @@ Creates an interrupt controller model in the kernel. On x86, creates a virtual | |||
| 596 | ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a | 596 | ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a |
| 597 | local APIC. IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23 | 597 | local APIC. IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23 |
| 598 | only go to the IOAPIC. On ia64, a IOSAPIC is created. On ARM/arm64, a GIC is | 598 | only go to the IOAPIC. On ia64, a IOSAPIC is created. On ARM/arm64, a GIC is |
| 599 | created. | 599 | created. On s390, a dummy irq routing table is created. |
| 600 | |||
| 601 | Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled | ||
| 602 | before KVM_CREATE_IRQCHIP can be used. | ||
| 600 | 603 | ||
| 601 | 604 | ||
| 602 | 4.25 KVM_IRQ_LINE | 605 | 4.25 KVM_IRQ_LINE |
| @@ -1336,7 +1339,7 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed. | |||
| 1336 | 4.52 KVM_SET_GSI_ROUTING | 1339 | 4.52 KVM_SET_GSI_ROUTING |
| 1337 | 1340 | ||
| 1338 | Capability: KVM_CAP_IRQ_ROUTING | 1341 | Capability: KVM_CAP_IRQ_ROUTING |
| 1339 | Architectures: x86 ia64 | 1342 | Architectures: x86 ia64 s390 |
| 1340 | Type: vm ioctl | 1343 | Type: vm ioctl |
| 1341 | Parameters: struct kvm_irq_routing (in) | 1344 | Parameters: struct kvm_irq_routing (in) |
| 1342 | Returns: 0 on success, -1 on error | 1345 | Returns: 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 | ||
| 1370 | No flags are specified so far, the corresponding field must be set to zero. | 1375 | No 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 | ||
| 1389 | struct 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 | ||
| 1385 | 4.53 KVM_ASSIGN_SET_MSIX_NR | 1398 | 4.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 | |||
| 27 | struct sca_entry { | 35 | struct 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 | ||
| 9 | KVM := ../../../virt/kvm | 9 | KVM := ../../../virt/kvm |
| 10 | common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o | 10 | common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqchip.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/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 | |||
| 1289 | static 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 | |||
| 1298 | static 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 | |||
| 1313 | static 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; | ||
