Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1-rc2 476 lines 11 kB view raw
1/* 2 * kvm_virtio.c - virtio for kvm on s390 3 * 4 * Copyright IBM Corp. 2008 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): Christian Borntraeger <borntraeger@de.ibm.com> 11 */ 12 13#include <linux/kernel_stat.h> 14#include <linux/init.h> 15#include <linux/bootmem.h> 16#include <linux/err.h> 17#include <linux/virtio.h> 18#include <linux/virtio_config.h> 19#include <linux/slab.h> 20#include <linux/virtio_console.h> 21#include <linux/interrupt.h> 22#include <linux/virtio_ring.h> 23#include <linux/pfn.h> 24#include <asm/io.h> 25#include <asm/kvm_para.h> 26#include <asm/kvm_virtio.h> 27#include <asm/setup.h> 28#include <asm/irq.h> 29 30#define VIRTIO_SUBCODE_64 0x0D00 31 32/* 33 * The pointer to our (page) of device descriptions. 34 */ 35static void *kvm_devices; 36struct work_struct hotplug_work; 37 38struct kvm_device { 39 struct virtio_device vdev; 40 struct kvm_device_desc *desc; 41}; 42 43#define to_kvmdev(vd) container_of(vd, struct kvm_device, vdev) 44 45/* 46 * memory layout: 47 * - kvm_device_descriptor 48 * struct kvm_device_desc 49 * - configuration 50 * struct kvm_vqconfig 51 * - feature bits 52 * - config space 53 */ 54static struct kvm_vqconfig *kvm_vq_config(const struct kvm_device_desc *desc) 55{ 56 return (struct kvm_vqconfig *)(desc + 1); 57} 58 59static u8 *kvm_vq_features(const struct kvm_device_desc *desc) 60{ 61 return (u8 *)(kvm_vq_config(desc) + desc->num_vq); 62} 63 64static u8 *kvm_vq_configspace(const struct kvm_device_desc *desc) 65{ 66 return kvm_vq_features(desc) + desc->feature_len * 2; 67} 68 69/* 70 * The total size of the config page used by this device (incl. desc) 71 */ 72static unsigned desc_size(const struct kvm_device_desc *desc) 73{ 74 return sizeof(*desc) 75 + desc->num_vq * sizeof(struct kvm_vqconfig) 76 + desc->feature_len * 2 77 + desc->config_len; 78} 79 80/* This gets the device's feature bits. */ 81static u32 kvm_get_features(struct virtio_device *vdev) 82{ 83 unsigned int i; 84 u32 features = 0; 85 struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; 86 u8 *in_features = kvm_vq_features(desc); 87 88 for (i = 0; i < min(desc->feature_len * 8, 32); i++) 89 if (in_features[i / 8] & (1 << (i % 8))) 90 features |= (1 << i); 91 return features; 92} 93 94static void kvm_finalize_features(struct virtio_device *vdev) 95{ 96 unsigned int i, bits; 97 struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; 98 /* Second half of bitmap is features we accept. */ 99 u8 *out_features = kvm_vq_features(desc) + desc->feature_len; 100 101 /* Give virtio_ring a chance to accept features. */ 102 vring_transport_features(vdev); 103 104 memset(out_features, 0, desc->feature_len); 105 bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; 106 for (i = 0; i < bits; i++) { 107 if (test_bit(i, vdev->features)) 108 out_features[i / 8] |= (1 << (i % 8)); 109 } 110} 111 112/* 113 * Reading and writing elements in config space 114 */ 115static void kvm_get(struct virtio_device *vdev, unsigned int offset, 116 void *buf, unsigned len) 117{ 118 struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; 119 120 BUG_ON(offset + len > desc->config_len); 121 memcpy(buf, kvm_vq_configspace(desc) + offset, len); 122} 123 124static void kvm_set(struct virtio_device *vdev, unsigned int offset, 125 const void *buf, unsigned len) 126{ 127 struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; 128 129 BUG_ON(offset + len > desc->config_len); 130 memcpy(kvm_vq_configspace(desc) + offset, buf, len); 131} 132 133/* 134 * The operations to get and set the status word just access 135 * the status field of the device descriptor. set_status will also 136 * make a hypercall to the host, to tell about status changes 137 */ 138static u8 kvm_get_status(struct virtio_device *vdev) 139{ 140 return to_kvmdev(vdev)->desc->status; 141} 142 143static void kvm_set_status(struct virtio_device *vdev, u8 status) 144{ 145 BUG_ON(!status); 146 to_kvmdev(vdev)->desc->status = status; 147 kvm_hypercall1(KVM_S390_VIRTIO_SET_STATUS, 148 (unsigned long) to_kvmdev(vdev)->desc); 149} 150 151/* 152 * To reset the device, we use the KVM_VIRTIO_RESET hypercall, using the 153 * descriptor address. The Host will zero the status and all the 154 * features. 155 */ 156static void kvm_reset(struct virtio_device *vdev) 157{ 158 kvm_hypercall1(KVM_S390_VIRTIO_RESET, 159 (unsigned long) to_kvmdev(vdev)->desc); 160} 161 162/* 163 * When the virtio_ring code wants to notify the Host, it calls us here and we 164 * make a hypercall. We hand the address of the virtqueue so the Host 165 * knows which virtqueue we're talking about. 166 */ 167static void kvm_notify(struct virtqueue *vq) 168{ 169 struct kvm_vqconfig *config = vq->priv; 170 171 kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address); 172} 173 174/* 175 * This routine finds the first virtqueue described in the configuration of 176 * this device and sets it up. 177 */ 178static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, 179 unsigned index, 180 void (*callback)(struct virtqueue *vq), 181 const char *name) 182{ 183 struct kvm_device *kdev = to_kvmdev(vdev); 184 struct kvm_vqconfig *config; 185 struct virtqueue *vq; 186 int err; 187 188 if (index >= kdev->desc->num_vq) 189 return ERR_PTR(-ENOENT); 190 191 config = kvm_vq_config(kdev->desc)+index; 192 193 err = vmem_add_mapping(config->address, 194 vring_size(config->num, 195 KVM_S390_VIRTIO_RING_ALIGN)); 196 if (err) 197 goto out; 198 199 vq = vring_new_virtqueue(config->num, KVM_S390_VIRTIO_RING_ALIGN, 200 vdev, (void *) config->address, 201 kvm_notify, callback, name); 202 if (!vq) { 203 err = -ENOMEM; 204 goto unmap; 205 } 206 207 /* 208 * register a callback token 209 * The host will sent this via the external interrupt parameter 210 */ 211 config->token = (u64) vq; 212 213 vq->priv = config; 214 return vq; 215unmap: 216 vmem_remove_mapping(config->address, 217 vring_size(config->num, 218 KVM_S390_VIRTIO_RING_ALIGN)); 219out: 220 return ERR_PTR(err); 221} 222 223static void kvm_del_vq(struct virtqueue *vq) 224{ 225 struct kvm_vqconfig *config = vq->priv; 226 227 vring_del_virtqueue(vq); 228 vmem_remove_mapping(config->address, 229 vring_size(config->num, 230 KVM_S390_VIRTIO_RING_ALIGN)); 231} 232 233static void kvm_del_vqs(struct virtio_device *vdev) 234{ 235 struct virtqueue *vq, *n; 236 237 list_for_each_entry_safe(vq, n, &vdev->vqs, list) 238 kvm_del_vq(vq); 239} 240 241static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs, 242 struct virtqueue *vqs[], 243 vq_callback_t *callbacks[], 244 const char *names[]) 245{ 246 struct kvm_device *kdev = to_kvmdev(vdev); 247 int i; 248 249 /* We must have this many virtqueues. */ 250 if (nvqs > kdev->desc->num_vq) 251 return -ENOENT; 252 253 for (i = 0; i < nvqs; ++i) { 254 vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i]); 255 if (IS_ERR(vqs[i])) 256 goto error; 257 } 258 return 0; 259 260error: 261 kvm_del_vqs(vdev); 262 return PTR_ERR(vqs[i]); 263} 264 265/* 266 * The config ops structure as defined by virtio config 267 */ 268static struct virtio_config_ops kvm_vq_configspace_ops = { 269 .get_features = kvm_get_features, 270 .finalize_features = kvm_finalize_features, 271 .get = kvm_get, 272 .set = kvm_set, 273 .get_status = kvm_get_status, 274 .set_status = kvm_set_status, 275 .reset = kvm_reset, 276 .find_vqs = kvm_find_vqs, 277 .del_vqs = kvm_del_vqs, 278}; 279 280/* 281 * The root device for the kvm virtio devices. 282 * This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2. 283 */ 284static struct device *kvm_root; 285 286/* 287 * adds a new device and register it with virtio 288 * appropriate drivers are loaded by the device model 289 */ 290static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset) 291{ 292 struct kvm_device *kdev; 293 294 kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); 295 if (!kdev) { 296 printk(KERN_EMERG "Cannot allocate kvm dev %u type %u\n", 297 offset, d->type); 298 return; 299 } 300 301 kdev->vdev.dev.parent = kvm_root; 302 kdev->vdev.id.device = d->type; 303 kdev->vdev.config = &kvm_vq_configspace_ops; 304 kdev->desc = d; 305 306 if (register_virtio_device(&kdev->vdev) != 0) { 307 printk(KERN_ERR "Failed to register kvm device %u type %u\n", 308 offset, d->type); 309 kfree(kdev); 310 } 311} 312 313/* 314 * scan_devices() simply iterates through the device page. 315 * The type 0 is reserved to mean "end of devices". 316 */ 317static void scan_devices(void) 318{ 319 unsigned int i; 320 struct kvm_device_desc *d; 321 322 for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { 323 d = kvm_devices + i; 324 325 if (d->type == 0) 326 break; 327 328 add_kvm_device(d, i); 329 } 330} 331 332/* 333 * match for a kvm device with a specific desc pointer 334 */ 335static int match_desc(struct device *dev, void *data) 336{ 337 if ((ulong)to_kvmdev(dev_to_virtio(dev))->desc == (ulong)data) 338 return 1; 339 340 return 0; 341} 342 343/* 344 * hotplug_device tries to find changes in the device page. 345 */ 346static void hotplug_devices(struct work_struct *dummy) 347{ 348 unsigned int i; 349 struct kvm_device_desc *d; 350 struct device *dev; 351 352 for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { 353 d = kvm_devices + i; 354 355 /* end of list */ 356 if (d->type == 0) 357 break; 358 359 /* device already exists */ 360 dev = device_find_child(kvm_root, d, match_desc); 361 if (dev) { 362 /* XXX check for hotplug remove */ 363 put_device(dev); 364 continue; 365 } 366 367 /* new device */ 368 printk(KERN_INFO "Adding new virtio device %p\n", d); 369 add_kvm_device(d, i); 370 } 371} 372 373/* 374 * we emulate the request_irq behaviour on top of s390 extints 375 */ 376static void kvm_extint_handler(unsigned int ext_int_code, 377 unsigned int param32, unsigned long param64) 378{ 379 struct virtqueue *vq; 380 u16 subcode; 381 u32 param; 382 383 subcode = ext_int_code >> 16; 384 if ((subcode & 0xff00) != VIRTIO_SUBCODE_64) 385 return; 386 kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++; 387 388 /* The LSB might be overloaded, we have to mask it */ 389 vq = (struct virtqueue *)(param64 & ~1UL); 390 391 /* We use ext_params to decide what this interrupt means */ 392 param = param32 & VIRTIO_PARAM_MASK; 393 394 switch (param) { 395 case VIRTIO_PARAM_CONFIG_CHANGED: 396 { 397 struct virtio_driver *drv; 398 drv = container_of(vq->vdev->dev.driver, 399 struct virtio_driver, driver); 400 if (drv->config_changed) 401 drv->config_changed(vq->vdev); 402 403 break; 404 } 405 case VIRTIO_PARAM_DEV_ADD: 406 schedule_work(&hotplug_work); 407 break; 408 case VIRTIO_PARAM_VRING_INTERRUPT: 409 default: 410 vring_interrupt(0, vq); 411 break; 412 } 413} 414 415/* 416 * Init function for virtio 417 * devices are in a single page above top of "normal" mem 418 */ 419static int __init kvm_devices_init(void) 420{ 421 int rc; 422 423 if (!MACHINE_IS_KVM) 424 return -ENODEV; 425 426 kvm_root = root_device_register("kvm_s390"); 427 if (IS_ERR(kvm_root)) { 428 rc = PTR_ERR(kvm_root); 429 printk(KERN_ERR "Could not register kvm_s390 root device"); 430 return rc; 431 } 432 433 rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); 434 if (rc) { 435 root_device_unregister(kvm_root); 436 return rc; 437 } 438 439 kvm_devices = (void *) real_memory_size; 440 441 INIT_WORK(&hotplug_work, hotplug_devices); 442 443 service_subclass_irq_register(); 444 register_external_interrupt(0x2603, kvm_extint_handler); 445 446 scan_devices(); 447 return 0; 448} 449 450/* code for early console output with virtio_console */ 451static __init int early_put_chars(u32 vtermno, const char *buf, int count) 452{ 453 char scratch[17]; 454 unsigned int len = count; 455 456 if (len > sizeof(scratch) - 1) 457 len = sizeof(scratch) - 1; 458 scratch[len] = '\0'; 459 memcpy(scratch, buf, len); 460 kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, __pa(scratch)); 461 return len; 462} 463 464static int __init s390_virtio_console_init(void) 465{ 466 if (!MACHINE_IS_KVM) 467 return -ENODEV; 468 return virtio_cons_early_init(early_put_chars); 469} 470console_initcall(s390_virtio_console_init); 471 472 473/* 474 * We do this after core stuff, but before the drivers. 475 */ 476postcore_initcall(kvm_devices_init);