interrupt.c (841b91c584b6d1e2a2cb508bd2d0236cd37e1750) interrupt.c (84223598778ba08041f4297fda485df83414d57e)
1/*
2 * handling kvm guest interrupts
3 *
4 * Copyright IBM Corp. 2008,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): Carsten Otte <cotte@de.ibm.com>
11 */
12
13#include <linux/interrupt.h>
14#include <linux/kvm_host.h>
15#include <linux/hrtimer.h>
1/*
2 * handling kvm guest interrupts
3 *
4 * Copyright IBM Corp. 2008,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): Carsten Otte <cotte@de.ibm.com>
11 */
12
13#include <linux/interrupt.h>
14#include <linux/kvm_host.h>
15#include <linux/hrtimer.h>
16#include <linux/mmu_context.h>
16#include <linux/signal.h>
17#include <linux/slab.h>
18#include <asm/asm-offsets.h>
19#include <asm/uaccess.h>
20#include "kvm-s390.h"
21#include "gaccess.h"
22#include "trace-s390.h"
23

--- 1255 unchanged lines hidden (view full) ---

1279/* s390 floating irq controller (flic) */
1280struct kvm_device_ops kvm_flic_ops = {
1281 .name = "kvm-flic",
1282 .get_attr = flic_get_attr,
1283 .set_attr = flic_set_attr,
1284 .create = flic_create,
1285 .destroy = flic_destroy,
1286};
17#include <linux/signal.h>
18#include <linux/slab.h>
19#include <asm/asm-offsets.h>
20#include <asm/uaccess.h>
21#include "kvm-s390.h"
22#include "gaccess.h"
23#include "trace-s390.h"
24

--- 1255 unchanged lines hidden (view full) ---

1280/* s390 floating irq controller (flic) */
1281struct kvm_device_ops kvm_flic_ops = {
1282 .name = "kvm-flic",
1283 .get_attr = flic_get_attr,
1284 .set_attr = flic_set_attr,
1285 .create = flic_create,
1286 .destroy = flic_destroy,
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}