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 /arch/x86/kvm/lapic.c | |
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>
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 44 |
1 files changed, 20 insertions, 24 deletions
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) |