0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include "i915_drv.h"
0024 #include "gvt.h"
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 struct intel_vgpu_page_track *intel_vgpu_find_page_track(
0035 struct intel_vgpu *vgpu, unsigned long gfn)
0036 {
0037 return radix_tree_lookup(&vgpu->page_track_tree, gfn);
0038 }
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 int intel_vgpu_register_page_track(struct intel_vgpu *vgpu, unsigned long gfn,
0051 gvt_page_track_handler_t handler, void *priv)
0052 {
0053 struct intel_vgpu_page_track *track;
0054 int ret;
0055
0056 track = intel_vgpu_find_page_track(vgpu, gfn);
0057 if (track)
0058 return -EEXIST;
0059
0060 track = kzalloc(sizeof(*track), GFP_KERNEL);
0061 if (!track)
0062 return -ENOMEM;
0063
0064 track->handler = handler;
0065 track->priv_data = priv;
0066
0067 ret = radix_tree_insert(&vgpu->page_track_tree, gfn, track);
0068 if (ret) {
0069 kfree(track);
0070 return ret;
0071 }
0072
0073 return 0;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082 void intel_vgpu_unregister_page_track(struct intel_vgpu *vgpu,
0083 unsigned long gfn)
0084 {
0085 struct intel_vgpu_page_track *track;
0086
0087 track = radix_tree_delete(&vgpu->page_track_tree, gfn);
0088 if (track) {
0089 if (track->tracked)
0090 intel_gvt_page_track_remove(vgpu, gfn);
0091 kfree(track);
0092 }
0093 }
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 int intel_vgpu_enable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
0104 {
0105 struct intel_vgpu_page_track *track;
0106 int ret;
0107
0108 track = intel_vgpu_find_page_track(vgpu, gfn);
0109 if (!track)
0110 return -ENXIO;
0111
0112 if (track->tracked)
0113 return 0;
0114
0115 ret = intel_gvt_page_track_add(vgpu, gfn);
0116 if (ret)
0117 return ret;
0118 track->tracked = true;
0119 return 0;
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 int intel_vgpu_disable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
0131 {
0132 struct intel_vgpu_page_track *track;
0133 int ret;
0134
0135 track = intel_vgpu_find_page_track(vgpu, gfn);
0136 if (!track)
0137 return -ENXIO;
0138
0139 if (!track->tracked)
0140 return 0;
0141
0142 ret = intel_gvt_page_track_remove(vgpu, gfn);
0143 if (ret)
0144 return ret;
0145 track->tracked = false;
0146 return 0;
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 int intel_vgpu_page_track_handler(struct intel_vgpu *vgpu, u64 gpa,
0160 void *data, unsigned int bytes)
0161 {
0162 struct intel_vgpu_page_track *page_track;
0163 int ret = 0;
0164
0165 mutex_lock(&vgpu->vgpu_lock);
0166
0167 page_track = intel_vgpu_find_page_track(vgpu, gpa >> PAGE_SHIFT);
0168 if (!page_track) {
0169 ret = -ENXIO;
0170 goto out;
0171 }
0172
0173 if (unlikely(vgpu->failsafe)) {
0174
0175 intel_gvt_page_track_remove(vgpu, gpa >> PAGE_SHIFT);
0176 } else {
0177 ret = page_track->handler(page_track, gpa, data, bytes);
0178 if (ret)
0179 gvt_err("guest page write error, gpa %llx\n", gpa);
0180 }
0181
0182 out:
0183 mutex_unlock(&vgpu->vgpu_lock);
0184 return ret;
0185 }