aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-08-24 09:48:51 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:29 -0400
commitcefa33e2f8f7852abb42f22ec25a6084a931c5ac (patch)
tree6944f5afe499955b69316cf7b3f62e7464028dd3 /drivers/s390
parentfc678d67fee1acccf21322318dd833b892a572e4 (diff)
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 <agraf@suse.de> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/kvm/kvm_virtio.c47
1 files changed, 47 insertions, 0 deletions
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 @@
32 * The pointer to our (page) of device descriptions. 32 * The pointer to our (page) of device descriptions.
33 */ 33 */
34static void *kvm_devices; 34static void *kvm_devices;
35struct work_struct hotplug_work;
35 36
36struct kvm_device { 37struct kvm_device {
37 struct virtio_device vdev; 38 struct virtio_device vdev;
@@ -328,6 +329,47 @@ static void scan_devices(void)
328} 329}
329 330
330/* 331/*
332 * match for a kvm device with a specific desc pointer
333 */
334static int match_desc(struct device *dev, void *data)
335{
336 if ((ulong)to_kvmdev(dev_to_virtio(dev))->desc == (ulong)data)
337 return 1;
338
339 return 0;
340}
341
342/*
343 * hotplug_device tries to find changes in the device page.
344 */
345static void hotplug_devices(struct work_struct *dummy)
346{
347 unsigned int i;
348 struct kvm_device_desc *d;
349 struct device *dev;
350
351 for (i = 0; i < PAGE_SIZE; i += desc_size(d)) {
352 d = kvm_devices + i;
353
354 /* end of list */
355 if (d->type == 0)
356 break;
357
358 /* device already exists */
359 dev = device_find_child(kvm_root, d, match_desc);
360 if (dev) {
361 /* XXX check for hotplug remove */
362 put_device(dev);
363 continue;
364 }
365
366 /* new device */
367 printk(KERN_INFO "Adding new virtio device %p\n", d);
368 add_kvm_device(d, i);
369 }
370}
371
372/*
331 * we emulate the request_irq behaviour on top of s390 extints 373 * we emulate the request_irq behaviour on top of s390 extints
332 */ 374 */
333static void kvm_extint_handler(u16 code) 375static void kvm_extint_handler(u16 code)
@@ -357,6 +399,9 @@ static void kvm_extint_handler(u16 code)
357 399
358 break; 400 break;
359 } 401 }
402 case VIRTIO_PARAM_DEV_ADD:
403 schedule_work(&hotplug_work);
404 break;
360 case VIRTIO_PARAM_VRING_INTERRUPT: 405 case VIRTIO_PARAM_VRING_INTERRUPT:
361 default: 406 default:
362 vring_interrupt(0, vq); 407 vring_interrupt(0, vq);
@@ -390,6 +435,8 @@ static int __init kvm_devices_init(void)
390 435
391 kvm_devices = (void *) real_memory_size; 436 kvm_devices = (void *) real_memory_size;
392 437
438 INIT_WORK(&hotplug_work, hotplug_devices);
439
393 ctl_set_bit(0, 9); 440 ctl_set_bit(0, 9);
394 register_external_interrupt(0x2603, kvm_extint_handler); 441 register_external_interrupt(0x2603, kvm_extint_handler);
395 442