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} |
|