aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2013-07-03 10:30:53 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2013-07-18 06:29:23 -0400
commit126a5af520eff9b99a0bb1ca4bb4a0b7973f7d5a (patch)
tree74084d4e3bb3526c132f58b0ca8b9c98065452b9 /virt/kvm
parent1c118b8226922d225a7df4127926ed2a2d73baaf (diff)
KVM: kvm-io: support cookies
Add new functions kvm_io_bus_{read,write}_cookie() that allows users of the kvm io infrastructure to use a cookie value to speed up lookup of a device on an io bus. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/kvm_main.c108
1 files changed, 92 insertions, 16 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 1580dd4ace4e..71960fb03c2a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2863,13 +2863,33 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
2863 return off; 2863 return off;
2864} 2864}
2865 2865
2866static int __kvm_io_bus_write(struct kvm_io_bus *bus,
2867 struct kvm_io_range *range, const void *val)
2868{
2869 int idx;
2870
2871 idx = kvm_io_bus_get_first_dev(bus, range->addr, range->len);
2872 if (idx < 0)
2873 return -EOPNOTSUPP;
2874
2875 while (idx < bus->dev_count &&
2876 kvm_io_bus_sort_cmp(range, &bus->range[idx]) == 0) {
2877 if (!kvm_iodevice_write(bus->range[idx].dev, range->addr,
2878 range->len, val))
2879 return idx;
2880 idx++;
2881 }
2882
2883 return -EOPNOTSUPP;
2884}
2885
2866/* kvm_io_bus_write - called under kvm->slots_lock */ 2886/* kvm_io_bus_write - called under kvm->slots_lock */
2867int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, 2887int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2868 int len, const void *val) 2888 int len, const void *val)
2869{ 2889{
2870 int idx;
2871 struct kvm_io_bus *bus; 2890 struct kvm_io_bus *bus;
2872 struct kvm_io_range range; 2891 struct kvm_io_range range;
2892 int r;
2873 2893
2874 range = (struct kvm_io_range) { 2894 range = (struct kvm_io_range) {
2875 .addr = addr, 2895 .addr = addr,
@@ -2877,14 +2897,52 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2877 }; 2897 };
2878 2898
2879 bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu); 2899 bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
2880 idx = kvm_io_bus_get_first_dev(bus, addr, len); 2900 r = __kvm_io_bus_write(bus, &range, val);
2901 return r < 0 ? r : 0;
2902}
2903
2904/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
2905int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2906 int len, const void *val, long cookie)
2907{
2908 struct kvm_io_bus *bus;
2909 struct kvm_io_range range;
2910
2911 range = (struct kvm_io_range) {
2912 .addr = addr,
2913 .len = len,
2914 };
2915
2916 bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
2917
2918 /* First try the device referenced by cookie. */
2919 if ((cookie >= 0) && (cookie < bus->dev_count) &&
2920 (kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
2921 if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
2922 val))
2923 return cookie;
2924
2925 /*
2926 * cookie contained garbage; fall back to search and return the
2927 * correct cookie value.
2928 */
2929 return __kvm_io_bus_write(bus, &range, val);
2930}
2931
2932static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
2933 void *val)
2934{
2935 int idx;
2936
2937 idx = kvm_io_bus_get_first_dev(bus, range->addr, range->len);
2881 if (idx < 0) 2938 if (idx < 0)
2882 return -EOPNOTSUPP; 2939 return -EOPNOTSUPP;
2883 2940
2884 while (idx < bus->dev_count && 2941 while (idx < bus->dev_count &&
2885 kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) { 2942 kvm_io_bus_sort_cmp(range, &bus->range[idx]) == 0) {
2886 if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val)) 2943 if (!kvm_iodevice_read(bus->range[idx].dev, range->addr,
2887 return 0; 2944 range->len, val))
2945 return idx;
2888 idx++; 2946 idx++;
2889 } 2947 }
2890 2948
@@ -2895,9 +2953,9 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2895int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, 2953int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2896 int len, void *val) 2954 int len, void *val)
2897{ 2955{
2898 int idx;
2899 struct kvm_io_bus *bus; 2956 struct kvm_io_bus *bus;
2900 struct kvm_io_range range; 2957 struct kvm_io_range range;
2958 int r;
2901 2959
2902 range = (struct kvm_io_range) { 2960 range = (struct kvm_io_range) {
2903 .addr = addr, 2961 .addr = addr,
@@ -2905,18 +2963,36 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2905 }; 2963 };
2906 2964
2907 bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu); 2965 bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
2908 idx = kvm_io_bus_get_first_dev(bus, addr, len); 2966 r = __kvm_io_bus_read(bus, &range, val);
2909 if (idx < 0) 2967 return r < 0 ? r : 0;
2910 return -EOPNOTSUPP; 2968}
2911 2969
2912 while (idx < bus->dev_count && 2970/* kvm_io_bus_read_cookie - called under kvm->slots_lock */
2913 kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) { 2971int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2914 if (!kvm_iodevice_read(bus->range[idx].dev, addr, len, val)) 2972 int len, void *val, long cookie)
2915 return 0; 2973{
2916 idx++; 2974 struct kvm_io_bus *bus;
2917 } 2975 struct kvm_io_range range;
2918 2976
2919 return -EOPNOTSUPP; 2977 range = (struct kvm_io_range) {
2978 .addr = addr,
2979 .len = len,
2980 };
2981
2982 bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
2983
2984 /* First try the device referenced by cookie. */
2985 if ((cookie >= 0) && (cookie < bus->dev_count) &&
2986 (kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
2987 if (!kvm_iodevice_read(bus->range[cookie].dev, addr, len,
2988 val))
2989 return cookie;
2990
2991 /*
2992 * cookie contained garbage; fall back to search and return the
2993 * correct cookie value.
2994 */
2995 return __kvm_io_bus_read(bus, &range, val);
2920} 2996}
2921 2997
2922/* Caller must hold slots_lock. */ 2998/* Caller must hold slots_lock. */