diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2009-06-29 15:24:32 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-09-10 01:33:05 -0400 |
commit | bda9020e2463ec94db9f97e8615f3bae22069838 (patch) | |
tree | 48125316d4c0f419a35aefdfbf665d30ad0c55ca | |
parent | 6c474694530f377507f9aca438c17206e051e6e7 (diff) |
KVM: remove in_range from io devices
This changes bus accesses to use high-level kvm_io_bus_read/kvm_io_bus_write
functions. in_range now becomes unused so it is removed from device ops in
favor of read/write callbacks performing range checks internally.
This allows aliasing (mostly for in-kernel virtio), as well as better error
handling by making it possible to pass errors up to userspace.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 28 | ||||
-rw-r--r-- | arch/x86/kvm/i8254.c | 49 | ||||
-rw-r--r-- | arch/x86/kvm/i8259.c | 20 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 44 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 110 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 6 | ||||
-rw-r--r-- | virt/kvm/coalesced_mmio.c | 16 | ||||
-rw-r--r-- | virt/kvm/ioapic.c | 22 | ||||
-rw-r--r-- | virt/kvm/iodev.h | 39 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 26 |
10 files changed, 152 insertions, 208 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 5c766bd82b05..d7aa6bb8f477 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -210,16 +210,6 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
210 | 210 | ||
211 | } | 211 | } |
212 | 212 | ||
213 | static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, | ||
214 | gpa_t addr, int len, int is_write) | ||
215 | { | ||
216 | struct kvm_io_device *dev; | ||
217 | |||
218 | dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr, len, is_write); | ||
219 | |||
220 | return dev; | ||
221 | } | ||
222 | |||
223 | static int handle_vm_error(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 213 | static int handle_vm_error(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
224 | { | 214 | { |
225 | kvm_run->exit_reason = KVM_EXIT_UNKNOWN; | 215 | kvm_run->exit_reason = KVM_EXIT_UNKNOWN; |
@@ -231,6 +221,7 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
231 | { | 221 | { |
232 | struct kvm_mmio_req *p; | 222 | struct kvm_mmio_req *p; |
233 | struct kvm_io_device *mmio_dev; | 223 | struct kvm_io_device *mmio_dev; |
224 | int r; | ||
234 | 225 | ||
235 | p = kvm_get_vcpu_ioreq(vcpu); | 226 | p = kvm_get_vcpu_ioreq(vcpu); |
236 | 227 | ||
@@ -247,16 +238,13 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
247 | kvm_run->exit_reason = KVM_EXIT_MMIO; | 238 | kvm_run->exit_reason = KVM_EXIT_MMIO; |
248 | return 0; | 239 | return 0; |
249 | mmio: | 240 | mmio: |
250 | mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr, p->size, !p->dir); | 241 | if (p->dir) |
251 | if (mmio_dev) { | 242 | r = kvm_io_bus_read(&vcpu->kvm->mmio_bus, p->addr, |
252 | if (!p->dir) | 243 | p->size, &p->data); |
253 | kvm_iodevice_write(mmio_dev, p->addr, p->size, | 244 | else |
254 | &p->data); | 245 | r = kvm_io_bus_write(&vcpu->kvm->mmio_bus, p->addr, |
255 | else | 246 | p->size, &p->data); |
256 | kvm_iodevice_read(mmio_dev, p->addr, p->size, | 247 | if (r) |
257 | &p->data); | ||
258 | |||
259 | } else | ||
260 | printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr); | 248 | printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr); |
261 | p->state = STATE_IORESP_READY; | 249 | p->state = STATE_IORESP_READY; |
262 | 250 | ||
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 4082cdd468ed..8c3ac30ef9bd 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -358,8 +358,14 @@ static inline struct kvm_pit *speaker_to_pit(struct kvm_io_device *dev) | |||
358 | return container_of(dev, struct kvm_pit, speaker_dev); | 358 | return container_of(dev, struct kvm_pit, speaker_dev); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void pit_ioport_write(struct kvm_io_device *this, | 361 | static inline int pit_in_range(gpa_t addr) |
362 | gpa_t addr, int len, const void *data) | 362 | { |
363 | return ((addr >= KVM_PIT_BASE_ADDRESS) && | ||
364 | (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH)); | ||
365 | } | ||
366 | |||
367 | static int pit_ioport_write(struct kvm_io_device *this, | ||
368 | gpa_t addr, int len, const void *data) | ||
363 | { | 369 | { |
364 | struct kvm_pit *pit = dev_to_pit(this); | 370 | struct kvm_pit *pit = dev_to_pit(this); |
365 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 371 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
@@ -367,6 +373,8 @@ static void pit_ioport_write(struct kvm_io_device *this, | |||
367 | int channel, access; | 373 | int channel, access; |
368 | struct kvm_kpit_channel_state *s; | 374 | struct kvm_kpit_channel_state *s; |
369 | u32 val = *(u32 *) data; | 375 | u32 val = *(u32 *) data; |
376 | if (!pit_in_range(addr)) | ||
377 | return -EOPNOTSUPP; | ||
370 | 378 | ||
371 | val &= 0xff; | 379 | val &= 0xff; |
372 | addr &= KVM_PIT_CHANNEL_MASK; | 380 | addr &= KVM_PIT_CHANNEL_MASK; |
@@ -429,16 +437,19 @@ static void pit_ioport_write(struct kvm_io_device *this, | |||
429 | } | 437 | } |
430 | 438 | ||
431 | mutex_unlock(&pit_state->lock); | 439 | mutex_unlock(&pit_state->lock); |
440 | return 0; | ||
432 | } | 441 | } |
433 | 442 | ||
434 | static void pit_ioport_read(struct kvm_io_device *this, | 443 | static int pit_ioport_read(struct kvm_io_device *this, |
435 | gpa_t addr, int len, void *data) | 444 | gpa_t addr, int len, void *data) |
436 | { | 445 | { |
437 | struct kvm_pit *pit = dev_to_pit(this); | 446 | struct kvm_pit *pit = dev_to_pit(this); |
438 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 447 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
439 | struct kvm *kvm = pit->kvm; | 448 | struct kvm *kvm = pit->kvm; |
440 | int ret, count; | 449 | int ret, count; |
441 | struct kvm_kpit_channel_state *s; | 450 | struct kvm_kpit_channel_state *s; |
451 | if (!pit_in_range(addr)) | ||
452 | return -EOPNOTSUPP; | ||
442 | 453 | ||
443 | addr &= KVM_PIT_CHANNEL_MASK; | 454 | addr &= KVM_PIT_CHANNEL_MASK; |
444 | s = &pit_state->channels[addr]; | 455 | s = &pit_state->channels[addr]; |
@@ -493,37 +504,36 @@ static void pit_ioport_read(struct kvm_io_device *this, | |||
493 | memcpy(data, (char *)&ret, len); | 504 | memcpy(data, (char *)&ret, len); |
494 | 505 | ||
495 | mutex_unlock(&pit_state->lock); | 506 | mutex_unlock(&pit_state->lock); |
507 | return 0; | ||
496 | } | 508 | } |
497 | 509 | ||
498 | static int pit_in_range(struct kvm_io_device *this, gpa_t addr, | 510 | static int speaker_ioport_write(struct kvm_io_device *this, |
499 | int len, int is_write) | 511 | gpa_t addr, int len, const void *data) |
500 | { | ||
501 | return ((addr >= KVM_PIT_BASE_ADDRESS) && | ||
502 | (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH)); | ||
503 | } | ||
504 | |||
505 | static void speaker_ioport_write(struct kvm_io_device *this, | ||
506 | gpa_t addr, int len, const void *data) | ||
507 | { | 512 | { |
508 | struct kvm_pit *pit = speaker_to_pit(this); | 513 | struct kvm_pit *pit = speaker_to_pit(this); |
509 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 514 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
510 | struct kvm *kvm = pit->kvm; | 515 | struct kvm *kvm = pit->kvm; |
511 | u32 val = *(u32 *) data; | 516 | u32 val = *(u32 *) data; |
517 | if (addr != KVM_SPEAKER_BASE_ADDRESS) | ||
518 | return -EOPNOTSUPP; | ||
512 | 519 | ||
513 | mutex_lock(&pit_state->lock); | 520 | mutex_lock(&pit_state->lock); |
514 | pit_state->speaker_data_on = (val >> 1) & 1; | 521 | pit_state->speaker_data_on = (val >> 1) & 1; |
515 | pit_set_gate(kvm, 2, val & 1); | 522 | pit_set_gate(kvm, 2, val & 1); |
516 | mutex_unlock(&pit_state->lock); | 523 | mutex_unlock(&pit_state->lock); |
524 | return 0; | ||
517 | } | 525 | } |
518 | 526 | ||
519 | static void speaker_ioport_read(struct kvm_io_device *this, | 527 | static int speaker_ioport_read(struct kvm_io_device *this, |
520 | gpa_t addr, int len, void *data) | 528 | gpa_t addr, int len, void *data) |
521 | { | 529 | { |
522 | struct kvm_pit *pit = speaker_to_pit(this); | 530 | struct kvm_pit *pit = speaker_to_pit(this); |
523 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 531 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
524 | struct kvm *kvm = pit->kvm; | 532 | struct kvm *kvm = pit->kvm; |
525 | unsigned int refresh_clock; | 533 | unsigned int refresh_clock; |
526 | int ret; | 534 | int ret; |
535 | if (addr != KVM_SPEAKER_BASE_ADDRESS) | ||
536 | return -EOPNOTSUPP; | ||
527 | 537 | ||
528 | /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ | 538 | /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ |
529 | refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1; | 539 | refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1; |
@@ -535,12 +545,7 @@ static void speaker_ioport_read(struct kvm_io_device *this, | |||
535 | len = sizeof(ret); | 545 | len = sizeof(ret); |
536 | memcpy(data, (char *)&ret, len); | 546 | memcpy(data, (char *)&ret, len); |
537 | mutex_unlock(&pit_state->lock); | 547 | mutex_unlock(&pit_state->lock); |
538 | } | 548 | return 0; |
539 | |||
540 | static int speaker_in_range(struct kvm_io_device *this, gpa_t addr, | ||
541 | int len, int is_write) | ||
542 | { | ||
543 | return (addr == KVM_SPEAKER_BASE_ADDRESS); | ||
544 | } | 549 | } |
545 | 550 | ||
546 | void kvm_pit_reset(struct kvm_pit *pit) | 551 | void kvm_pit_reset(struct kvm_pit *pit) |
@@ -574,13 +579,11 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) | |||
574 | static const struct kvm_io_device_ops pit_dev_ops = { | 579 | static const struct kvm_io_device_ops pit_dev_ops = { |
575 | .read = pit_ioport_read, | 580 | .read = pit_ioport_read, |
576 | .write = pit_ioport_write, | 581 | .write = pit_ioport_write, |
577 | .in_range = pit_in_range, | ||
578 | }; | 582 | }; |
579 | 583 | ||
580 | static const struct kvm_io_device_ops speaker_dev_ops = { | 584 | static const struct kvm_io_device_ops speaker_dev_ops = { |
581 | .read = speaker_ioport_read, | 585 | .read = speaker_ioport_read, |
582 | .write = speaker_ioport_write, | 586 | .write = speaker_ioport_write, |
583 | .in_range = speaker_in_range, | ||
584 | }; | 587 | }; |
585 | 588 | ||
586 | /* Caller must have writers lock on slots_lock */ | 589 | /* Caller must have writers lock on slots_lock */ |
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 1851aec8a7da..1d1bb75dc7bc 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
@@ -430,8 +430,7 @@ static u32 elcr_ioport_read(void *opaque, u32 addr1) | |||
430 | return s->elcr; | 430 | return s->elcr; |
431 | } | 431 | } |
432 | 432 | ||
433 | static int picdev_in_range(struct kvm_io_device *this, gpa_t addr, | 433 | static int picdev_in_range(gpa_t addr) |
434 | int len, int is_write) | ||
435 | { | 434 | { |
436 | switch (addr) { | 435 | switch (addr) { |
437 | case 0x20: | 436 | case 0x20: |
@@ -451,16 +450,18 @@ static inline struct kvm_pic *to_pic(struct kvm_io_device *dev) | |||
451 | return container_of(dev, struct kvm_pic, dev); | 450 | return container_of(dev, struct kvm_pic, dev); |
452 | } | 451 | } |
453 | 452 | ||
454 | static void picdev_write(struct kvm_io_device *this, | 453 | static int picdev_write(struct kvm_io_device *this, |
455 | gpa_t addr, int len, const void *val) | 454 | gpa_t addr, int len, const void *val) |
456 | { | 455 | { |
457 | struct kvm_pic *s = to_pic(this); | 456 | struct kvm_pic *s = to_pic(this); |
458 | unsigned char data = *(unsigned char *)val; | 457 | unsigned char data = *(unsigned char *)val; |
458 | if (!picdev_in_range(addr)) | ||
459 | return -EOPNOTSUPP; | ||
459 | 460 | ||
460 | if (len != 1) { | 461 | if (len != 1) { |
461 | if (printk_ratelimit()) | 462 | if (printk_ratelimit()) |
462 | printk(KERN_ERR "PIC: non byte write\n"); | 463 | printk(KERN_ERR "PIC: non byte write\n"); |
463 | return; | 464 | return 0; |
464 | } | 465 | } |
465 | pic_lock(s); | 466 | pic_lock(s); |
466 | switch (addr) { | 467 | switch (addr) { |
@@ -476,18 +477,21 @@ static void picdev_write(struct kvm_io_device *this, | |||
476 | break; | 477 | break; |
477 | } | 478 | } |
478 | pic_unlock(s); | 479 | pic_unlock(s); |
480 | return 0; | ||
479 | } | 481 | } |
480 | 482 | ||
481 | static void picdev_read(struct kvm_io_device *this, | 483 | static int picdev_read(struct kvm_io_device *this, |
482 | gpa_t addr, int len, void *val) | 484 | gpa_t addr, int len, void *val) |
483 | { | 485 | { |
484 | struct kvm_pic *s = to_pic(this); | 486 | struct kvm_pic *s = to_pic(this); |
485 | unsigned char data = 0; | 487 | unsigned char data = 0; |
488 | if (!picdev_in_range(addr)) | ||
489 | return -EOPNOTSUPP; | ||
486 | 490 | ||
487 | if (len != 1) { | 491 | if (len != 1) { |
488 | if (printk_ratelimit()) | 492 | if (printk_ratelimit()) |
489 | printk(KERN_ERR "PIC: non byte read\n"); | 493 | printk(KERN_ERR "PIC: non byte read\n"); |
490 | return; | 494 | return 0; |
491 | } | 495 | } |
492 | pic_lock(s); | 496 | pic_lock(s); |
493 | switch (addr) { | 497 | switch (addr) { |
@@ -504,6 +508,7 @@ static void picdev_read(struct kvm_io_device *this, | |||
504 | } | 508 | } |
505 | *(unsigned char *)val = data; | 509 | *(unsigned char *)val = data; |
506 | pic_unlock(s); | 510 | pic_unlock(s); |
511 | return 0; | ||
507 | } | 512 | } |
508 | 513 | ||
509 | /* | 514 | /* |
@@ -526,7 +531,6 @@ static void pic_irq_request(void *opaque, int level) | |||
526 | static const struct kvm_io_device_ops picdev_ops = { | 531 | static const struct kvm_io_device_ops picdev_ops = { |
527 | .read = picdev_read, | 532 | .read = picdev_read, |
528 | .write = picdev_write, | 533 | .write = picdev_write, |
529 | .in_range = picdev_in_range, | ||
530 | }; | 534 | }; |
531 | 535 | ||
532 | struct kvm_pic *kvm_create_pic(struct kvm *kvm) | 536 | struct kvm_pic *kvm_create_pic(struct kvm *kvm) |
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 2e0286596387..265a765f038f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -546,18 +546,27 @@ static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev) | |||
546 | return container_of(dev, struct kvm_lapic, dev); | 546 | return container_of(dev, struct kvm_lapic, dev); |
547 | } | 547 | } |
548 | 548 | ||
549 | static void apic_mmio_read(struct kvm_io_device *this, | 549 | static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr) |
550 | gpa_t address, int len, void *data) | 550 | { |
551 | return apic_hw_enabled(apic) && | ||
552 | addr >= apic->base_address && | ||
553 | addr < apic->base_address + LAPIC_MMIO_LENGTH; | ||
554 | } | ||
555 | |||
556 | static int apic_mmio_read(struct kvm_io_device *this, | ||
557 | gpa_t address, int len, void *data) | ||
551 | { | 558 | { |
552 | struct kvm_lapic *apic = to_lapic(this); | 559 | struct kvm_lapic *apic = to_lapic(this); |
553 | unsigned int offset = address - apic->base_address; | 560 | unsigned int offset = address - apic->base_address; |
554 | unsigned char alignment = offset & 0xf; | 561 | unsigned char alignment = offset & 0xf; |
555 | u32 result; | 562 | u32 result; |
563 | if (!apic_mmio_in_range(apic, address)) | ||
564 | return -EOPNOTSUPP; | ||
556 | 565 | ||
557 | if ((alignment + len) > 4) { | 566 | if ((alignment + len) > 4) { |
558 | printk(KERN_ERR "KVM_APIC_READ: alignment error %lx %d", | 567 | printk(KERN_ERR "KVM_APIC_READ: alignment error %lx %d", |
559 | (unsigned long)address, len); | 568 | (unsigned long)address, len); |
560 | return; | 569 | return 0; |
561 | } | 570 | } |
562 | result = __apic_read(apic, offset & ~0xf); | 571 | result = __apic_read(apic, offset & ~0xf); |
563 | 572 | ||
@@ -574,6 +583,7 @@ static void apic_mmio_read(struct kvm_io_device *this, | |||
574 | "should be 1,2, or 4 instead\n", len); | 583 | "should be 1,2, or 4 instead\n", len); |
575 | break; | 584 | break; |
576 | } | 585 | } |
586 | return 0; | ||
577 | } | 587 | } |
578 | 588 | ||
579 | static void update_divide_count(struct kvm_lapic *apic) | 589 | static void update_divide_count(struct kvm_lapic *apic) |
@@ -629,13 +639,15 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) | |||
629 | apic->vcpu->kvm->arch.vapics_in_nmi_mode--; | 639 | apic->vcpu->kvm->arch.vapics_in_nmi_mode--; |
630 | } | 640 | } |
631 | 641 | ||
632 | static void apic_mmio_write(struct kvm_io_device *this, | 642 | static int apic_mmio_write(struct kvm_io_device *this, |
633 | gpa_t address, int len, const void *data) | 643 | gpa_t address, int len, const void *data) |
634 | { | 644 | { |
635 | struct kvm_lapic *apic = to_lapic(this); | 645 | struct kvm_lapic *apic = to_lapic(this); |
636 | unsigned int offset = address - apic->base_address; | 646 | unsigned int offset = address - apic->base_address; |
637 | unsigned char alignment = offset & 0xf; | 647 | unsigned char alignment = offset & 0xf; |
638 | u32 val; | 648 | u32 val; |
649 | if (!apic_mmio_in_range(apic, address)) | ||
650 | return -EOPNOTSUPP; | ||
639 | 651 | ||
640 | /* | 652 | /* |
641 | * APIC register must be aligned on 128-bits boundary. | 653 | * APIC register must be aligned on 128-bits boundary. |
@@ -646,7 +658,7 @@ static void apic_mmio_write(struct kvm_io_device *this, | |||
646 | /* Don't shout loud, $infamous_os would cause only noise. */ | 658 | /* Don't shout loud, $infamous_os would cause only noise. */ |
647 | apic_debug("apic write: bad size=%d %lx\n", | 659 | apic_debug("apic write: bad size=%d %lx\n", |
648 | len, (long)address); | 660 | len, (long)address); |
649 | return; | 661 | return 0; |
650 | } | 662 | } |
651 | 663 | ||
652 | val = *(u32 *) data; | 664 | val = *(u32 *) data; |
@@ -729,7 +741,7 @@ static void apic_mmio_write(struct kvm_io_device *this, | |||
729 | hrtimer_cancel(&apic->lapic_timer.timer); | 741 | hrtimer_cancel(&apic->lapic_timer.timer); |
730 | apic_set_reg(apic, APIC_TMICT, val); | 742 | apic_set_reg(apic, APIC_TMICT, val); |
731 | start_apic_timer(apic); | 743 | start_apic_timer(apic); |
732 | return; | 744 | return 0; |
733 | 745 | ||
734 | case APIC_TDCR: | 746 | case APIC_TDCR: |
735 | if (val & 4) | 747 | if (val & 4) |
@@ -743,22 +755,7 @@ static void apic_mmio_write(struct kvm_io_device *this, | |||
743 | offset); | 755 | offset); |
744 | break; | 756 | break; |
745 | } | 757 | } |
746 | 758 | return 0; | |
747 | } | ||
748 | |||
749 | static int apic_mmio_range(struct kvm_io_device *this, gpa_t addr, | ||
750 | int len, int size) | ||
751 | { | ||
752 | struct kvm_lapic *apic = to_lapic(this); | ||
753 | int ret = 0; | ||
754 | |||
755 | |||
756 | if (apic_hw_enabled(apic) && | ||
757 | (addr >= apic->base_address) && | ||
758 | (addr < (apic->base_address + LAPIC_MMIO_LENGTH))) | ||
759 | ret = 1; | ||
760 | |||
761 | return ret; | ||
762 | } | 759 | } |
763 | 760 | ||
764 | void kvm_free_lapic(struct kvm_vcpu *vcpu) | 761 | void kvm_free_lapic(struct kvm_vcpu *vcpu) |
@@ -938,7 +935,6 @@ static struct kvm_timer_ops lapic_timer_ops = { | |||
938 | static const struct kvm_io_device_ops apic_mmio_ops = { | 935 | static const struct kvm_io_device_ops apic_mmio_ops = { |
939 | .read = apic_mmio_read, | 936 | .read = apic_mmio_read, |
940 | .write = apic_mmio_write, | 937 | .write = apic_mmio_write, |
941 | .in_range = apic_mmio_range, | ||
942 | }; | 938 | }; |
943 | 939 | ||
944 | int kvm_create_lapic(struct kvm_vcpu *vcpu) | 940 | int kvm_create_lapic(struct kvm_vcpu *vcpu) |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7ce6367c1976..96f0ae7d97b6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -2333,35 +2333,23 @@ static void kvm_init_msr_list(void) | |||
2333 | num_msrs_to_save = j; | 2333 | num_msrs_to_save = j; |
2334 | } | 2334 | } |
2335 | 2335 | ||
2336 | /* | 2336 | static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, |
2337 | * Only apic need an MMIO device hook, so shortcut now.. | 2337 | const void *v) |
2338 | */ | ||
2339 | static struct kvm_io_device *vcpu_find_pervcpu_dev(struct kvm_vcpu *vcpu, | ||
2340 | gpa_t addr, int len, | ||
2341 | int is_write) | ||
2342 | { | 2338 | { |
2343 | struct kvm_io_device *dev; | 2339 | if (vcpu->arch.apic && |
2340 | !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v)) | ||
2341 | return 0; | ||
2344 | 2342 | ||
2345 | if (vcpu->arch.apic) { | 2343 | return kvm_io_bus_write(&vcpu->kvm->mmio_bus, addr, len, v); |
2346 | dev = &vcpu->arch.apic->dev; | ||
2347 | if (kvm_iodevice_in_range(dev, addr, len, is_write)) | ||
2348 | return dev; | ||
2349 | } | ||
2350 | return NULL; | ||
2351 | } | 2344 | } |
2352 | 2345 | ||
2353 | 2346 | static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) | |
2354 | static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, | ||
2355 | gpa_t addr, int len, | ||
2356 | int is_write) | ||
2357 | { | 2347 | { |
2358 | struct kvm_io_device *dev; | 2348 | if (vcpu->arch.apic && |
2349 | !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v)) | ||
2350 | return 0; | ||
2359 | 2351 | ||
2360 | dev = vcpu_find_pervcpu_dev(vcpu, addr, len, is_write); | 2352 | return kvm_io_bus_read(&vcpu->kvm->mmio_bus, addr, len, v); |
2361 | if (dev == NULL) | ||
2362 | dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr, len, | ||
2363 | is_write); | ||
2364 | return dev; | ||
2365 | } | 2353 | } |
2366 | 2354 | ||
2367 | static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, | 2355 | static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, |
@@ -2430,7 +2418,6 @@ static int emulator_read_emulated(unsigned long addr, | |||
2430 | unsigned int bytes, | 2418 | unsigned int bytes, |
2431 | struct kvm_vcpu *vcpu) | 2419 | struct kvm_vcpu *vcpu) |
2432 | { | 2420 | { |
2433 | struct kvm_io_device *mmio_dev; | ||
2434 | gpa_t gpa; | 2421 | gpa_t gpa; |
2435 | 2422 | ||
2436 | if (vcpu->mmio_read_completed) { | 2423 | if (vcpu->mmio_read_completed) { |
@@ -2455,13 +2442,8 @@ mmio: | |||
2455 | /* | 2442 | /* |
2456 | * Is this MMIO handled locally? | 2443 | * Is this MMIO handled locally? |
2457 | */ | 2444 | */ |
2458 | mutex_lock(&vcpu->kvm->lock); | 2445 | if (!vcpu_mmio_read(vcpu, gpa, bytes, val)) |
2459 | mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 0); | ||
2460 | mutex_unlock(&vcpu->kvm->lock); | ||
2461 | if (mmio_dev) { | ||
2462 | kvm_iodevice_read(mmio_dev, gpa, bytes, val); | ||
2463 | return X86EMUL_CONTINUE; | 2446 | return X86EMUL_CONTINUE; |
2464 | } | ||
2465 | 2447 | ||
2466 | vcpu->mmio_needed = 1; | 2448 | vcpu->mmio_needed = 1; |
2467 | vcpu->mmio_phys_addr = gpa; | 2449 | vcpu->mmio_phys_addr = gpa; |
@@ -2488,7 +2470,6 @@ static int emulator_write_emulated_onepage(unsigned long addr, | |||
2488 | unsigned int bytes, | 2470 | unsigned int bytes, |
2489 | struct kvm_vcpu *vcpu) | 2471 | struct kvm_vcpu *vcpu) |
2490 | { | 2472 | { |
2491 | struct kvm_io_device *mmio_dev; | ||
2492 | gpa_t gpa; | 2473 | gpa_t gpa; |
2493 | 2474 | ||
2494 | gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); | 2475 | gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); |
@@ -2509,13 +2490,8 @@ mmio: | |||
2509 | /* | 2490 | /* |
2510 | * Is this MMIO handled locally? | 2491 | * Is this MMIO handled locally? |
2511 | */ | 2492 | */ |
2512 | mutex_lock(&vcpu->kvm->lock); | 2493 | if (!vcpu_mmio_write(vcpu, gpa, bytes, val)) |
2513 | mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 1); | ||
2514 | mutex_unlock(&vcpu->kvm->lock); | ||
2515 | if (mmio_dev) { | ||
2516 | kvm_iodevice_write(mmio_dev, gpa, bytes, val); | ||
2517 | return X86EMUL_CONTINUE; | 2494 | return X86EMUL_CONTINUE; |
2518 | } | ||
2519 | 2495 | ||
2520 | vcpu->mmio_needed = 1; | 2496 | vcpu->mmio_needed = 1; |
2521 | vcpu->mmio_phys_addr = gpa; | 2497 | vcpu->mmio_phys_addr = gpa; |
@@ -2850,48 +2826,40 @@ int complete_pio(struct kvm_vcpu *vcpu) | |||
2850 | return 0; | 2826 | return 0; |
2851 | } | 2827 | } |
2852 | 2828 | ||
2853 | static void kernel_pio(struct kvm_io_device *pio_dev, | 2829 | static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) |
2854 | struct kvm_vcpu *vcpu, | ||
2855 | void *pd) | ||
2856 | { | 2830 | { |
2857 | /* TODO: String I/O for in kernel device */ | 2831 | /* TODO: String I/O for in kernel device */ |
2832 | int r; | ||
2858 | 2833 | ||
2859 | if (vcpu->arch.pio.in) | 2834 | if (vcpu->arch.pio.in) |
2860 | kvm_iodevice_read(pio_dev, vcpu->arch.pio.port, | 2835 | r = kvm_io_bus_read(&vcpu->kvm->pio_bus, vcpu->arch.pio.port, |
2861 | vcpu->arch.pio.size, | 2836 | vcpu->arch.pio.size, pd); |
2862 | pd); | ||
2863 | else | 2837 | else |
2864 | kvm_iodevice_write(pio_dev, vcpu->arch.pio.port, | 2838 | r = kvm_io_bus_write(&vcpu->kvm->pio_bus, vcpu->arch.pio.port, |
2865 | vcpu->arch.pio.size, | 2839 | vcpu->arch.pio.size, pd); |
2866 | pd); | 2840 | return r; |
2867 | } | 2841 | } |
2868 | 2842 | ||
2869 | static void pio_string_write(struct kvm_io_device *pio_dev, | 2843 | static int pio_string_write(struct kvm_vcpu *vcpu) |
2870 | struct kvm_vcpu *vcpu) | ||
2871 | { | 2844 | { |
2872 | struct kvm_pio_request *io = &vcpu->arch.pio; | 2845 | struct kvm_pio_request *io = &vcpu->arch.pio; |
2873 | void *pd = vcpu->arch.pio_data; | 2846 | void *pd = vcpu->arch.pio_data; |
2874 | int i; | 2847 | int i, r = 0; |
2875 | 2848 | ||
2876 | for (i = 0; i < io->cur_count; i++) { | 2849 | for (i = 0; i < io->cur_count; i++) { |
2877 | kvm_iodevice_write(pio_dev, io->port, | 2850 | if (kvm_io_bus_write(&vcpu->kvm->pio_bus, |
2878 | io->size, | 2851 | io->port, io->size, pd)) { |
2879 | pd); | 2852 | r = -EOPNOTSUPP; |
2853 | break; | ||
2854 | } | ||
2880 | pd += io->size; | 2855 | pd += io->size; |
2881 | } | 2856 | } |
2882 | } | 2857 | return r; |
2883 | |||
2884 | static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu, | ||
2885 | gpa_t addr, int len, | ||
2886 | int is_write) | ||
2887 | { | ||
2888 | return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr, len, is_write); | ||
2889 | } | 2858 | } |
2890 | 2859 | ||
2891 | int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | 2860 | int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, |
2892 | int size, unsigned port) | 2861 | int size, unsigned port) |
2893 | { | 2862 | { |
2894 | struct kvm_io_device *pio_dev; | ||
2895 | unsigned long val; | 2863 | unsigned long val; |
2896 | 2864 | ||
2897 | vcpu->run->exit_reason = KVM_EXIT_IO; | 2865 | vcpu->run->exit_reason = KVM_EXIT_IO; |
@@ -2911,11 +2879,7 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
2911 | val = kvm_register_read(vcpu, VCPU_REGS_RAX); | 2879 | val = kvm_register_read(vcpu, VCPU_REGS_RAX); |
2912 | memcpy(vcpu->arch.pio_data, &val, 4); | 2880 | memcpy(vcpu->arch.pio_data, &val, 4); |
2913 | 2881 | ||
2914 | mutex_lock(&vcpu->kvm->lock); | 2882 | if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { |
2915 | pio_dev = vcpu_find_pio_dev(vcpu, port, size, !in); | ||
2916 | mutex_unlock(&vcpu->kvm->lock); | ||
2917 | if (pio_dev) { | ||
2918 | kernel_pio(pio_dev, vcpu, vcpu->arch.pio_data); | ||
2919 | complete_pio(vcpu); | 2883 | complete_pio(vcpu); |
2920 | return 1; | 2884 | return 1; |
2921 | } | 2885 | } |
@@ -2929,7 +2893,6 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
2929 | { | 2893 | { |
2930 | unsigned now, in_page; | 2894 | unsigned now, in_page; |
2931 | int ret = 0; | 2895 | int ret = 0; |
2932 | struct kvm_io_device *pio_dev; | ||
2933 | 2896 | ||
2934 | vcpu->run->exit_reason = KVM_EXIT_IO; | 2897 | vcpu->run->exit_reason = KVM_EXIT_IO; |
2935 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; | 2898 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; |
@@ -2973,12 +2936,6 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
2973 | 2936 | ||
2974 | vcpu->arch.pio.guest_gva = address; | 2937 | vcpu->arch.pio.guest_gva = address; |
2975 | 2938 | ||
2976 | mutex_lock(&vcpu->kvm->lock); | ||
2977 | pio_dev = vcpu_find_pio_dev(vcpu, port, | ||
2978 | vcpu->arch.pio.cur_count, | ||
2979 | !vcpu->arch.pio.in); | ||
2980 | mutex_unlock(&vcpu->kvm->lock); | ||
2981 | |||
2982 | if (!vcpu->arch.pio.in) { | 2939 | if (!vcpu->arch.pio.in) { |
2983 | /* string PIO write */ | 2940 | /* string PIO write */ |
2984 | ret = pio_copy_data(vcpu); | 2941 | ret = pio_copy_data(vcpu); |
@@ -2986,16 +2943,13 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
2986 | kvm_inject_gp(vcpu, 0); | 2943 | kvm_inject_gp(vcpu, 0); |
2987 | return 1; | 2944 | return 1; |
2988 | } | 2945 | } |
2989 | if (ret == 0 && pio_dev) { | 2946 | if (ret == 0 && !pio_string_write(vcpu)) { |
2990 | pio_string_write(pio_dev, vcpu); | ||
2991 | complete_pio(vcpu); | 2947 | complete_pio(vcpu); |
2992 | if (vcpu->arch.pio.count == 0) | 2948 | if (vcpu->arch.pio.count == 0) |
2993 | ret = 1; | 2949 | ret = 1; |
2994 | } | 2950 | } |
2995 | } else if (pio_dev) | 2951 | } |
2996 | pr_unimpl(vcpu, "no string pio read support yet, " | 2952 | /* no string PIO read support yet */ |
2997 | "port %x size %d count %ld\n", | ||
2998 | port, size, count); | ||
2999 | 2953 | ||
3000 | return ret; | 2954 | return ret; |
3001 | } | 2955 | } |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 96c8c0b01929..077e8bb875a9 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -60,8 +60,10 @@ struct kvm_io_bus { | |||
60 | 60 | ||
61 | void kvm_io_bus_init(struct kvm_io_bus *bus); | 61 | void kvm_io_bus_init(struct kvm_io_bus *bus); |
62 | void kvm_io_bus_destroy(struct kvm_io_bus *bus); | 62 | void kvm_io_bus_destroy(struct kvm_io_bus *bus); |
63 | struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, | 63 | int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len, |
64 | gpa_t addr, int len, int is_write); | 64 | const void *val); |
65 | int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, | ||
66 | void *val); | ||
65 | void __kvm_io_bus_register_dev(struct kvm_io_bus *bus, | 67 | void __kvm_io_bus_register_dev(struct kvm_io_bus *bus, |
66 | struct kvm_io_device *dev); | 68 | struct kvm_io_device *dev); |
67 | void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, | 69 | void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, |
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c index 7b7cc9fe5ee3..0352f81ecc0b 100644 --- a/virt/kvm/coalesced_mmio.c +++ b/virt/kvm/coalesced_mmio.c | |||
@@ -19,18 +19,14 @@ static inline struct kvm_coalesced_mmio_dev *to_mmio(struct kvm_io_device *dev) | |||
19 | return container_of(dev, struct kvm_coalesced_mmio_dev, dev); | 19 | return container_of(dev, struct kvm_coalesced_mmio_dev, dev); |
20 | } | 20 | } |
21 | 21 | ||
22 | static int coalesced_mmio_in_range(struct kvm_io_device *this, | 22 | static int coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev, |
23 | gpa_t addr, int len, int is_write) | 23 | gpa_t addr, int len) |
24 | { | 24 | { |
25 | struct kvm_coalesced_mmio_dev *dev = to_mmio(this); | ||
26 | struct kvm_coalesced_mmio_zone *zone; | 25 | struct kvm_coalesced_mmio_zone *zone; |
27 | struct kvm_coalesced_mmio_ring *ring; | 26 | struct kvm_coalesced_mmio_ring *ring; |
28 | unsigned avail; | 27 | unsigned avail; |
29 | int i; | 28 | int i; |
30 | 29 | ||
31 | if (!is_write) | ||
32 | return 0; | ||
33 | |||
34 | /* Are we able to batch it ? */ | 30 | /* Are we able to batch it ? */ |
35 | 31 | ||
36 | /* last is the first free entry | 32 | /* last is the first free entry |
@@ -60,11 +56,13 @@ static int coalesced_mmio_in_range(struct kvm_io_device *this, | |||
60 | return 0; | 56 | return 0; |
61 | } | 57 | } |
62 | 58 | ||
63 | static void coalesced_mmio_write(struct kvm_io_device *this, | 59 | static int coalesced_mmio_write(struct kvm_io_device *this, |
64 | gpa_t addr, int len, const void *val) | 60 | gpa_t addr, int len, const void *val) |
65 | { | 61 | { |
66 | struct kvm_coalesced_mmio_dev *dev = to_mmio(this); | 62 | struct kvm_coalesced_mmio_dev *dev = to_mmio(this); |
67 | struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring; | 63 | struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring; |
64 | if (!coalesced_mmio_in_range(dev, addr, len)) | ||
65 | return -EOPNOTSUPP; | ||
68 | 66 | ||
69 | spin_lock(&dev->lock); | 67 | spin_lock(&dev->lock); |
70 | 68 | ||
@@ -76,6 +74,7 @@ static void coalesced_mmio_write(struct kvm_io_device *this, | |||
76 | smp_wmb(); | 74 | smp_wmb(); |
77 | ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX; | 75 | ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX; |
78 | spin_unlock(&dev->lock); | 76 | spin_unlock(&dev->lock); |
77 | return 0; | ||
79 | } | 78 | } |
80 | 79 | ||
81 | static void coalesced_mmio_destructor(struct kvm_io_device *this) | 80 | static void coalesced_mmio_destructor(struct kvm_io_device *this) |
@@ -87,7 +86,6 @@ static void coalesced_mmio_destructor(struct kvm_io_device *this) | |||
87 | 86 | ||
88 | static const struct kvm_io_device_ops coalesced_mmio_ops = { | 87 | static const struct kvm_io_device_ops coalesced_mmio_ops = { |
89 | .write = coalesced_mmio_write, | 88 | .write = coalesced_mmio_write, |
90 | .in_range = coalesced_mmio_in_range, | ||
91 | .destructor = coalesced_mmio_destructor, | 89 | .destructor = coalesced_mmio_destructor, |
92 | }; | 90 | }; |
93 | 91 | ||
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 0eca54e06326..ddf6aa998b18 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -227,20 +227,19 @@ static inline struct kvm_ioapic *to_ioapic(struct kvm_io_device *dev) | |||
227 | return container_of(dev, struct kvm_ioapic, dev); | 227 | return container_of(dev, struct kvm_ioapic, dev); |
228 | } | 228 | } |
229 | 229 | ||
230 | static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr, | 230 | static inline int ioapic_in_range(struct kvm_ioapic *ioapic, gpa_t addr) |
231 | int len, int is_write) | ||
232 | { | 231 | { |
233 | struct kvm_ioapic *ioapic = to_ioapic(this); | ||
234 | |||
235 | return ((addr >= ioapic->base_address && | 232 | return ((addr >= ioapic->base_address && |
236 | (addr < ioapic->base_address + IOAPIC_MEM_LENGTH))); | 233 | (addr < ioapic->base_address + IOAPIC_MEM_LENGTH))); |
237 | } | 234 | } |
238 | 235 | ||
239 | static void ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, | 236 | static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, |
240 | void *val) | 237 | void *val) |
241 | { | 238 | { |
242 | struct kvm_ioapic *ioapic = to_ioapic(this); | 239 | struct kvm_ioapic *ioapic = to_ioapic(this); |
243 | u32 result; | 240 | u32 result; |
241 | if (!ioapic_in_range(ioapic, addr)) | ||
242 | return -EOPNOTSUPP; | ||
244 | 243 | ||
245 | ioapic_debug("addr %lx\n", (unsigned long)addr); | 244 | ioapic_debug("addr %lx\n", (unsigned long)addr); |
246 | ASSERT(!(addr & 0xf)); /* check alignment */ | 245 | ASSERT(!(addr & 0xf)); /* check alignment */ |
@@ -273,13 +272,16 @@ static void ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, | |||
273 | printk(KERN_WARNING "ioapic: wrong length %d\n", len); | 272 | printk(KERN_WARNING "ioapic: wrong length %d\n", len); |
274 | } | 273 | } |
275 | mutex_unlock(&ioapic->kvm->irq_lock); | 274 | mutex_unlock(&ioapic->kvm->irq_lock); |
275 | return 0; | ||
276 | } | 276 | } |
277 | 277 | ||
278 | static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, | 278 | static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, |
279 | const void *val) | 279 | const void *val) |
280 | { | 280 | { |
281 | struct kvm_ioapic *ioapic = to_ioapic(this); | 281 | struct kvm_ioapic *ioapic = to_ioapic(this); |
282 | u32 data; | 282 | u32 data; |
283 | if (!ioapic_in_range(ioapic, addr)) | ||
284 | return -EOPNOTSUPP; | ||
283 | 285 | ||
284 | ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p\n", | 286 | ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p\n", |
285 | (void*)addr, len, val); | 287 | (void*)addr, len, val); |
@@ -290,7 +292,7 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, | |||
290 | data = *(u32 *) val; | 292 | data = *(u32 *) val; |
291 | else { | 293 | else { |
292 | printk(KERN_WARNING "ioapic: Unsupported size %d\n", len); | 294 | printk(KERN_WARNING "ioapic: Unsupported size %d\n", len); |
293 | return; | 295 | return 0; |
294 | } | 296 | } |
295 | 297 | ||
296 | addr &= 0xff; | 298 | addr &= 0xff; |
@@ -312,6 +314,7 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, | |||
312 | break; | 314 | break; |
313 | } | 315 | } |
314 | mutex_unlock(&ioapic->kvm->irq_lock); | 316 | mutex_unlock(&ioapic->kvm->irq_lock); |
317 | return 0; | ||
315 | } | 318 | } |
316 | 319 | ||
317 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic) | 320 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic) |
@@ -329,7 +332,6 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic) | |||
329 | static const struct kvm_io_device_ops ioapic_mmio_ops = { | 332 | static const struct kvm_io_device_ops ioapic_mmio_ops = { |
330 | .read = ioapic_mmio_read, | 333 | .read = ioapic_mmio_read, |
331 | .write = ioapic_mmio_write, | 334 | .write = ioapic_mmio_write, |
332 | .in_range = ioapic_in_range, | ||
333 | }; | 335 | }; |
334 | 336 | ||
335 | int kvm_ioapic_init(struct kvm *kvm) | 337 | int kvm_ioapic_init(struct kvm *kvm) |
diff --git a/virt/kvm/iodev.h b/virt/kvm/iodev.h index 06e38b23fa61..12fd3caffd2b 100644 --- a/virt/kvm/iodev.h +++ b/virt/kvm/iodev.h | |||
@@ -17,23 +17,24 @@ | |||
17 | #define __KVM_IODEV_H__ | 17 | #define __KVM_IODEV_H__ |
18 | 18 | ||
19 | #include <linux/kvm_types.h> | 19 | #include <linux/kvm_types.h> |
20 | #include <asm/errno.h> | ||
20 | 21 | ||
21 | struct kvm_io_device; | 22 | struct kvm_io_device; |
22 | 23 | ||
23 | /** | 24 | /** |
24 | * kvm_io_device_ops are called under kvm slots_lock. | 25 | * kvm_io_device_ops are called under kvm slots_lock. |
26 | * read and write handlers return 0 if the transaction has been handled, | ||
27 | * or non-zero to have it passed to the next device. | ||
25 | **/ | 28 | **/ |
26 | struct kvm_io_device_ops { | 29 | struct kvm_io_device_ops { |
27 | void (*read)(struct kvm_io_device *this, | 30 | int (*read)(struct kvm_io_device *this, |
31 | gpa_t addr, | ||
32 | int len, | ||
33 | void *val); | ||
34 | int (*write)(struct kvm_io_device *this, | ||
28 | gpa_t addr, | 35 | gpa_t addr, |
29 | int len, | 36 | int len, |
30 | void *val); | 37 | const void *val); |
31 | void (*write)(struct kvm_io_device *this, | ||
32 | gpa_t addr, | ||
33 | int len, | ||
34 | const void *val); | ||
35 | int (*in_range)(struct kvm_io_device *this, gpa_t addr, int len, | ||
36 | int is_write); | ||
37 | void (*destructor)(struct kvm_io_device *this); | 38 | void (*destructor)(struct kvm_io_device *this); |
38 | }; | 39 | }; |
39 | 40 | ||
@@ -48,26 +49,16 @@ static inline void kvm_iodevice_init(struct kvm_io_device *dev, | |||
48 | dev->ops = ops; | 49 | dev->ops = ops; |
49 | } | 50 | } |
50 | 51 | ||
51 | static inline void kvm_iodevice_read(struct kvm_io_device *dev, | 52 | static inline int kvm_iodevice_read(struct kvm_io_device *dev, |
52 | gpa_t addr, | 53 | gpa_t addr, int l, void *v) |
53 | int len, | ||
54 | void *val) | ||
55 | { | 54 | { |
56 | dev->ops->read(dev, addr, len, val); | 55 | return dev->ops->read ? dev->ops->read(dev, addr, l, v) : -EOPNOTSUPP; |
57 | } | 56 | } |
58 | 57 | ||
59 | static inline void kvm_iodevice_write(struct kvm_io_device *dev, | 58 | static inline int kvm_iodevice_write(struct kvm_io_device *dev, |
60 | gpa_t addr, | 59 | gpa_t addr, int l, const void *v) |
61 | int len, | ||
62 | const void *val) | ||
63 | { | 60 | { |
64 | dev->ops->write(dev, addr, len, val); | 61 | return dev->ops->write ? dev->ops->write(dev, addr, l, v) : -EOPNOTSUPP; |
65 | } | ||
66 | |||
67 | static inline int kvm_iodevice_in_range(struct kvm_io_device *dev, | ||
68 | gpa_t addr, int len, int is_write) | ||
69 | { | ||
70 | return dev->ops->in_range(dev, addr, len, is_write); | ||
71 | } | 62 | } |
72 | 63 | ||
73 | static inline void kvm_iodevice_destructor(struct kvm_io_device *dev) | 64 | static inline void kvm_iodevice_destructor(struct kvm_io_device *dev) |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 0edc366ecf89..594606526620 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -2512,19 +2512,25 @@ void kvm_io_bus_destroy(struct kvm_io_bus *bus) | |||
2512 | } | 2512 | } |
2513 | } | 2513 | } |
2514 | 2514 | ||
2515 | struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, | 2515 | /* kvm_io_bus_write - called under kvm->slots_lock */ |
2516 | gpa_t addr, int len, int is_write) | 2516 | int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, |
2517 | int len, const void *val) | ||
2517 | { | 2518 | { |
2518 | int i; | 2519 | int i; |
2520 | for (i = 0; i < bus->dev_count; i++) | ||
2521 | if (!kvm_iodevice_write(bus->devs[i], addr, len, val)) | ||
2522 | return 0; | ||
2523 | return -EOPNOTSUPP; | ||
2524 | } | ||
2519 | 2525 | ||
2520 | for (i = 0; i < bus->dev_count; i++) { | 2526 | /* kvm_io_bus_read - called under kvm->slots_lock */ |
2521 | struct kvm_io_device *pos = bus->devs[i]; | 2527 | int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) |
2522 | 2528 | { | |
2523 | if (kvm_iodevice_in_range(pos, addr, len, is_write)) | 2529 | int i; |
2524 | return pos; | 2530 | for (i = 0; i < bus->dev_count; i++) |
2525 | } | 2531 | if (!kvm_iodevice_read(bus->devs[i], addr, len, val)) |
2526 | 2532 | return 0; | |
2527 | return NULL; | 2533 | return -EOPNOTSUPP; |
2528 | } | 2534 | } |
2529 | 2535 | ||
2530 | void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, | 2536 | void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, |