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/x86.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/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 110 |
1 files changed, 32 insertions, 78 deletions
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 | } |