From fc678d67fee1acccf21322318dd833b892a572e4 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 24 Aug 2010 15:48:50 +0200 Subject: KVM: S390: take a full byte as ext_param indicator Currenty the ext_param field only distinguishes between "config change" and "vring interrupt". We can do a lot more with it though, so let's enable a full byte of possible values and constants to #defines while at it. Signed-off-by: Alexander Graf Signed-off-by: Marcelo Tosatti --- drivers/s390/kvm/kvm_virtio.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 4e298bc8949d..68cef4da15e8 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -334,7 +334,7 @@ static void kvm_extint_handler(u16 code) { struct virtqueue *vq; u16 subcode; - int config_changed; + u32 param; subcode = S390_lowcore.cpu_addr; if ((subcode & 0xff00) != VIRTIO_SUBCODE_64) @@ -343,18 +343,25 @@ static void kvm_extint_handler(u16 code) /* The LSB might be overloaded, we have to mask it */ vq = (struct virtqueue *)(S390_lowcore.ext_params2 & ~1UL); - /* We use the LSB of extparam, to decide, if this interrupt is a config - * change or a "standard" interrupt */ - config_changed = S390_lowcore.ext_params & 1; + /* We use ext_params to decide what this interrupt means */ + param = S390_lowcore.ext_params & VIRTIO_PARAM_MASK; - if (config_changed) { + switch (param) { + case VIRTIO_PARAM_CONFIG_CHANGED: + { struct virtio_driver *drv; drv = container_of(vq->vdev->dev.driver, struct virtio_driver, driver); if (drv->config_changed) drv->config_changed(vq->vdev); - } else + + break; + } + case VIRTIO_PARAM_VRING_INTERRUPT: + default: vring_interrupt(0, vq); + break; + } } /* -- cgit v1.2.3 From cefa33e2f8f7852abb42f22ec25a6084a931c5ac Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 24 Aug 2010 15:48:51 +0200 Subject: KVM: S390: Add virtio hotplug add support The one big missing feature in s390-virtio was hotplugging. This is no more. This patch implements hotplug add support, so you can on the fly add new devices in the guest. Keep in mind that this needs a patch for qemu to actually leverage the functionality. Signed-off-by: Alexander Graf Signed-off-by: Marcelo Tosatti --- arch/s390/include/asm/kvm_virtio.h | 1 + drivers/s390/kvm/kvm_virtio.c | 47 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) (limited to 'drivers') diff --git a/arch/s390/include/asm/kvm_virtio.h b/arch/s390/include/asm/kvm_virtio.h index 3f5d100a42a2..72f614181eff 100644 --- a/arch/s390/include/asm/kvm_virtio.h +++ b/arch/s390/include/asm/kvm_virtio.h @@ -59,5 +59,6 @@ struct kvm_vqconfig { #define VIRTIO_PARAM_MASK 0xff #define VIRTIO_PARAM_VRING_INTERRUPT 0x0 #define VIRTIO_PARAM_CONFIG_CHANGED 0x1 +#define VIRTIO_PARAM_DEV_ADD 0x2 #endif diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 68cef4da15e8..5a46b8c5d68a 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -32,6 +32,7 @@ * The pointer to our (page) of device descriptions. */ static void *kvm_devices; +struct work_struct hotplug_work; struct kvm_device { struct virtio_device vdev; @@ -327,6 +328,47 @@ static void scan_devices(void) } } +/* + * match for a kvm device with a specific desc pointer + */ +static int match_desc(struct device *dev, void *data) +{ + if ((ulong)to_kvmdev(dev_to_virtio(dev))->desc == (ulong)data) + return 1; + + return 0; +} + +/* + * hotplug_device tries to find changes in the device page. + */ +static void hotplug_devices(struct work_struct *dummy) +{ + unsigned int i; + struct kvm_device_desc *d; + struct device *dev; + + for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { + d = kvm_devices + i; + + /* end of list */ + if (d->type == 0) + break; + + /* device already exists */ + dev = device_find_child(kvm_root, d, match_desc); + if (dev) { + /* XXX check for hotplug remove */ + put_device(dev); + continue; + } + + /* new device */ + printk(KERN_INFO "Adding new virtio device %p\n", d); + add_kvm_device(d, i); + } +} + /* * we emulate the request_irq behaviour on top of s390 extints */ @@ -357,6 +399,9 @@ static void kvm_extint_handler(u16 code) break; } + case VIRTIO_PARAM_DEV_ADD: + schedule_work(&hotplug_work); + break; case VIRTIO_PARAM_VRING_INTERRUPT: default: vring_interrupt(0, vq); @@ -390,6 +435,8 @@ static int __init kvm_devices_init(void) kvm_devices = (void *) real_memory_size; + INIT_WORK(&hotplug_work, hotplug_devices); + ctl_set_bit(0, 9); register_external_interrupt(0x2603, kvm_extint_handler); -- cgit v1.2.3