Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55c171a6 authored by Cornelia Huck's avatar Cornelia Huck Committed by Gleb Natapov
Browse files

KVM: s390: Handle hosts not supporting s390-virtio.



Running under a kvm host does not necessarily imply the presence of
a page mapped above the main memory with the virtio information;
however, the code includes a hard coded access to that page.

Instead, check for the presence of the page and exit gracefully
before we hit an addressing exception if it does not exist.

Reviewed-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Reviewed-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
cc: stable@vger.kernel.org
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
parent d4b06c2d
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -421,6 +421,26 @@ static void kvm_extint_handler(struct ext_code ext_code,
	}
}

/*
 * For s390-virtio, we expect a page above main storage containing
 * the virtio configuration. Try to actually load from this area
 * in order to figure out if the host provides this page.
 */
static int __init test_devices_support(unsigned long addr)
{
	int ret = -EIO;

	asm volatile(
		"0:	lura	0,%1\n"
		"1:	xgr	%0,%0\n"
		"2:\n"
		EX_TABLE(0b,2b)
		EX_TABLE(1b,2b)
		: "+d" (ret)
		: "a" (addr)
		: "0", "cc");
	return ret;
}
/*
 * Init function for virtio
 * devices are in a single page above top of "normal" mem
@@ -432,21 +452,23 @@ static int __init kvm_devices_init(void)
	if (!MACHINE_IS_KVM)
		return -ENODEV;

	if (test_devices_support(real_memory_size) < 0)
		return -ENODEV;

	rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
	if (rc)
		return rc;

	kvm_devices = (void *) real_memory_size;

	kvm_root = root_device_register("kvm_s390");
	if (IS_ERR(kvm_root)) {
		rc = PTR_ERR(kvm_root);
		printk(KERN_ERR "Could not register kvm_s390 root device");
		vmem_remove_mapping(real_memory_size, PAGE_SIZE);
		return rc;
	}

	rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
	if (rc) {
		root_device_unregister(kvm_root);
		return rc;
	}

	kvm_devices = (void *) real_memory_size;

	INIT_WORK(&hotplug_work, hotplug_devices);

	service_subclass_irq_register();