diff options
-rw-r--r-- | drivers/s390/kvm/kvm_virtio.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 7dabef624da3..b846b6c4130a 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -422,6 +422,26 @@ static void kvm_extint_handler(struct ext_code ext_code, | |||
422 | } | 422 | } |
423 | 423 | ||
424 | /* | 424 | /* |
425 | * For s390-virtio, we expect a page above main storage containing | ||
426 | * the virtio configuration. Try to actually load from this area | ||
427 | * in order to figure out if the host provides this page. | ||
428 | */ | ||
429 | static int __init test_devices_support(unsigned long addr) | ||
430 | { | ||
431 | int ret = -EIO; | ||
432 | |||
433 | asm volatile( | ||
434 | "0: lura 0,%1\n" | ||
435 | "1: xgr %0,%0\n" | ||
436 | "2:\n" | ||
437 | EX_TABLE(0b,2b) | ||
438 | EX_TABLE(1b,2b) | ||
439 | : "+d" (ret) | ||
440 | : "a" (addr) | ||
441 | : "0", "cc"); | ||
442 | return ret; | ||
443 | } | ||
444 | /* | ||
425 | * Init function for virtio | 445 | * Init function for virtio |
426 | * devices are in a single page above top of "normal" mem | 446 | * devices are in a single page above top of "normal" mem |
427 | */ | 447 | */ |
@@ -432,21 +452,23 @@ static int __init kvm_devices_init(void) | |||
432 | if (!MACHINE_IS_KVM) | 452 | if (!MACHINE_IS_KVM) |
433 | return -ENODEV; | 453 | return -ENODEV; |
434 | 454 | ||
455 | if (test_devices_support(real_memory_size) < 0) | ||
456 | return -ENODEV; | ||
457 | |||
458 | rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); | ||
459 | if (rc) | ||
460 | return rc; | ||
461 | |||
462 | kvm_devices = (void *) real_memory_size; | ||
463 | |||
435 | kvm_root = root_device_register("kvm_s390"); | 464 | kvm_root = root_device_register("kvm_s390"); |
436 | if (IS_ERR(kvm_root)) { | 465 | if (IS_ERR(kvm_root)) { |
437 | rc = PTR_ERR(kvm_root); | 466 | rc = PTR_ERR(kvm_root); |
438 | printk(KERN_ERR "Could not register kvm_s390 root device"); | 467 | printk(KERN_ERR "Could not register kvm_s390 root device"); |
468 | vmem_remove_mapping(real_memory_size, PAGE_SIZE); | ||
439 | return rc; | 469 | return rc; |
440 | } | 470 | } |
441 | 471 | ||
442 | rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); | ||
443 | if (rc) { | ||
444 | root_device_unregister(kvm_root); | ||
445 | return rc; | ||
446 | } | ||
447 | |||
448 | kvm_devices = (void *) real_memory_size; | ||
449 | |||
450 | INIT_WORK(&hotplug_work, hotplug_devices); | 472 | INIT_WORK(&hotplug_work, hotplug_devices); |
451 | 473 | ||
452 | service_subclass_irq_register(); | 474 | service_subclass_irq_register(); |