Commit | Line | Data |
---|---|---|
0ad35fed ZW |
1 | /* |
2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice (including the next | |
12 | * paragraph) shall be included in all copies or substantial portions of the | |
13 | * Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
21 | * SOFTWARE. | |
82d375d1 ZW |
22 | * |
23 | * Authors: | |
24 | * Eddie Dong <eddie.dong@intel.com> | |
25 | * Dexuan Cui | |
26 | * Jike Song <jike.song@intel.com> | |
27 | * | |
28 | * Contributors: | |
29 | * Zhi Wang <zhi.a.wang@intel.com> | |
30 | * | |
0ad35fed ZW |
31 | */ |
32 | ||
33 | #ifndef _GVT_MPT_H_ | |
34 | #define _GVT_MPT_H_ | |
35 | ||
36 | /** | |
37 | * DOC: Hypervisor Service APIs for GVT-g Core Logic | |
38 | * | |
39 | * This is the glue layer between specific hypervisor MPT modules and GVT-g core | |
40 | * logic. Each kind of hypervisor MPT module provides a collection of function | |
41 | * callbacks and will be attached to GVT host when the driver is loading. | |
42 | * GVT-g core logic will call these APIs to request specific services from | |
43 | * hypervisor. | |
44 | */ | |
45 | ||
40df6ea0 JS |
46 | /** |
47 | * intel_gvt_hypervisor_host_init - init GVT-g host side | |
48 | * | |
49 | * Returns: | |
50 | * Zero on success, negative error code if failed | |
51 | */ | |
52 | static inline int intel_gvt_hypervisor_host_init(struct device *dev, | |
53 | void *gvt, const void *ops) | |
54 | { | |
7b3343b7 JS |
55 | /* optional to provide */ |
56 | if (!intel_gvt_host.mpt->host_init) | |
57 | return 0; | |
58 | ||
40df6ea0 JS |
59 | return intel_gvt_host.mpt->host_init(dev, gvt, ops); |
60 | } | |
61 | ||
62 | /** | |
63 | * intel_gvt_hypervisor_host_exit - exit GVT-g host side | |
64 | */ | |
65 | static inline void intel_gvt_hypervisor_host_exit(struct device *dev, | |
66 | void *gvt) | |
67 | { | |
7b3343b7 JS |
68 | /* optional to provide */ |
69 | if (!intel_gvt_host.mpt->host_exit) | |
70 | return; | |
71 | ||
40df6ea0 JS |
72 | intel_gvt_host.mpt->host_exit(dev, gvt); |
73 | } | |
74 | ||
82d375d1 ZW |
75 | /** |
76 | * intel_gvt_hypervisor_attach_vgpu - call hypervisor to initialize vGPU | |
77 | * related stuffs inside hypervisor. | |
78 | * | |
79 | * Returns: | |
80 | * Zero on success, negative error code if failed. | |
81 | */ | |
82 | static inline int intel_gvt_hypervisor_attach_vgpu(struct intel_vgpu *vgpu) | |
83 | { | |
7b3343b7 JS |
84 | /* optional to provide */ |
85 | if (!intel_gvt_host.mpt->attach_vgpu) | |
86 | return 0; | |
87 | ||
82d375d1 ZW |
88 | return intel_gvt_host.mpt->attach_vgpu(vgpu, &vgpu->handle); |
89 | } | |
90 | ||
91 | /** | |
92 | * intel_gvt_hypervisor_detach_vgpu - call hypervisor to release vGPU | |
93 | * related stuffs inside hypervisor. | |
94 | * | |
95 | * Returns: | |
96 | * Zero on success, negative error code if failed. | |
97 | */ | |
98 | static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu) | |
99 | { | |
7b3343b7 JS |
100 | /* optional to provide */ |
101 | if (!intel_gvt_host.mpt->detach_vgpu) | |
102 | return; | |
103 | ||
82d375d1 ZW |
104 | intel_gvt_host.mpt->detach_vgpu(vgpu->handle); |
105 | } | |
106 | ||
c8fe6a68 ZW |
107 | #define MSI_CAP_CONTROL(offset) (offset + 2) |
108 | #define MSI_CAP_ADDRESS(offset) (offset + 4) | |
109 | #define MSI_CAP_DATA(offset) (offset + 8) | |
110 | #define MSI_CAP_EN 0x1 | |
111 | ||
112 | /** | |
113 | * intel_gvt_hypervisor_inject_msi - inject a MSI interrupt into vGPU | |
114 | * | |
115 | * Returns: | |
116 | * Zero on success, negative error code if failed. | |
117 | */ | |
118 | static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu) | |
119 | { | |
120 | unsigned long offset = vgpu->gvt->device_info.msi_cap_offset; | |
121 | u16 control, data; | |
122 | u32 addr; | |
123 | int ret; | |
124 | ||
125 | control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset)); | |
126 | addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset)); | |
127 | data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset)); | |
128 | ||
129 | /* Do not generate MSI if MSIEN is disable */ | |
130 | if (!(control & MSI_CAP_EN)) | |
131 | return 0; | |
132 | ||
133 | if (WARN(control & GENMASK(15, 1), "only support one MSI format\n")) | |
134 | return -EINVAL; | |
135 | ||
7fb6a7d6 | 136 | trace_inject_msi(vgpu->id, addr, data); |
c8fe6a68 ZW |
137 | |
138 | ret = intel_gvt_host.mpt->inject_msi(vgpu->handle, addr, data); | |
139 | if (ret) | |
140 | return ret; | |
141 | return 0; | |
142 | } | |
143 | ||
2707e444 ZW |
144 | /** |
145 | * intel_gvt_hypervisor_set_wp_page - translate a host VA into MFN | |
146 | * @p: host kernel virtual address | |
147 | * | |
148 | * Returns: | |
149 | * MFN on success, INTEL_GVT_INVALID_ADDR if failed. | |
150 | */ | |
151 | static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p) | |
152 | { | |
153 | return intel_gvt_host.mpt->from_virt_to_mfn(p); | |
154 | } | |
155 | ||
156 | /** | |
f66e5ff7 | 157 | * intel_gvt_hypervisor_enable_page_track - track a guest page |
2707e444 | 158 | * @vgpu: a vGPU |
09475728 | 159 | * @gfn: the gfn of guest |
2707e444 ZW |
160 | * |
161 | * Returns: | |
162 | * Zero on success, negative error code if failed. | |
163 | */ | |
7d1e5cdf | 164 | static inline int intel_gvt_hypervisor_enable_page_track( |
09475728 | 165 | struct intel_vgpu *vgpu, unsigned long gfn) |
2707e444 | 166 | { |
09475728 | 167 | return intel_gvt_host.mpt->enable_page_track(vgpu->handle, gfn); |
2707e444 ZW |
168 | } |
169 | ||
170 | /** | |
f66e5ff7 | 171 | * intel_gvt_hypervisor_disable_page_track - untrack a guest page |
2707e444 | 172 | * @vgpu: a vGPU |
09475728 | 173 | * @gfn: the gfn of guest |
2707e444 ZW |
174 | * |
175 | * Returns: | |
176 | * Zero on success, negative error code if failed. | |
177 | */ | |
7d1e5cdf | 178 | static inline int intel_gvt_hypervisor_disable_page_track( |
09475728 | 179 | struct intel_vgpu *vgpu, unsigned long gfn) |
2707e444 | 180 | { |
09475728 | 181 | return intel_gvt_host.mpt->disable_page_track(vgpu->handle, gfn); |
2707e444 ZW |
182 | } |
183 | ||
184 | /** | |
185 | * intel_gvt_hypervisor_read_gpa - copy data from GPA to host data buffer | |
186 | * @vgpu: a vGPU | |
187 | * @gpa: guest physical address | |
188 | * @buf: host data buffer | |
189 | * @len: data length | |
190 | * | |
191 | * Returns: | |
192 | * Zero on success, negative error code if failed. | |
193 | */ | |
194 | static inline int intel_gvt_hypervisor_read_gpa(struct intel_vgpu *vgpu, | |
195 | unsigned long gpa, void *buf, unsigned long len) | |
196 | { | |
197 | return intel_gvt_host.mpt->read_gpa(vgpu->handle, gpa, buf, len); | |
198 | } | |
199 | ||
200 | /** | |
201 | * intel_gvt_hypervisor_write_gpa - copy data from host data buffer to GPA | |
202 | * @vgpu: a vGPU | |
203 | * @gpa: guest physical address | |
204 | * @buf: host data buffer | |
205 | * @len: data length | |
206 | * | |
207 | * Returns: | |
208 | * Zero on success, negative error code if failed. | |
209 | */ | |
210 | static inline int intel_gvt_hypervisor_write_gpa(struct intel_vgpu *vgpu, | |
211 | unsigned long gpa, void *buf, unsigned long len) | |
212 | { | |
213 | return intel_gvt_host.mpt->write_gpa(vgpu->handle, gpa, buf, len); | |
214 | } | |
215 | ||
216 | /** | |
217 | * intel_gvt_hypervisor_gfn_to_mfn - translate a GFN to MFN | |
218 | * @vgpu: a vGPU | |
219 | * @gpfn: guest pfn | |
220 | * | |
221 | * Returns: | |
222 | * MFN on success, INTEL_GVT_INVALID_ADDR if failed. | |
223 | */ | |
224 | static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn( | |
225 | struct intel_vgpu *vgpu, unsigned long gfn) | |
226 | { | |
227 | return intel_gvt_host.mpt->gfn_to_mfn(vgpu->handle, gfn); | |
228 | } | |
229 | ||
cf4ee73f CD |
230 | /** |
231 | * intel_gvt_hypervisor_dma_map_guest_page - setup dma map for guest page | |
232 | * @vgpu: a vGPU | |
233 | * @gpfn: guest pfn | |
234 | * @dma_addr: retrieve allocated dma addr | |
235 | * | |
236 | * Returns: | |
237 | * 0 on success, negative error code if failed. | |
238 | */ | |
239 | static inline int intel_gvt_hypervisor_dma_map_guest_page( | |
240 | struct intel_vgpu *vgpu, unsigned long gfn, | |
241 | dma_addr_t *dma_addr) | |
242 | { | |
243 | return intel_gvt_host.mpt->dma_map_guest_page(vgpu->handle, gfn, | |
244 | dma_addr); | |
245 | } | |
246 | ||
247 | /** | |
248 | * intel_gvt_hypervisor_dma_unmap_guest_page - cancel dma map for guest page | |
249 | * @vgpu: a vGPU | |
250 | * @dma_addr: the mapped dma addr | |
251 | */ | |
252 | static inline void intel_gvt_hypervisor_dma_unmap_guest_page( | |
253 | struct intel_vgpu *vgpu, dma_addr_t dma_addr) | |
254 | { | |
255 | intel_gvt_host.mpt->dma_unmap_guest_page(vgpu->handle, dma_addr); | |
256 | } | |
257 | ||
4d60c5fd ZW |
258 | /** |
259 | * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN | |
260 | * @vgpu: a vGPU | |
261 | * @gfn: guest PFN | |
262 | * @mfn: host PFN | |
263 | * @nr: amount of PFNs | |
264 | * @map: map or unmap | |
4d60c5fd ZW |
265 | * |
266 | * Returns: | |
267 | * Zero on success, negative error code if failed. | |
268 | */ | |
269 | static inline int intel_gvt_hypervisor_map_gfn_to_mfn( | |
270 | struct intel_vgpu *vgpu, unsigned long gfn, | |
271 | unsigned long mfn, unsigned int nr, | |
8f89743b | 272 | bool map) |
4d60c5fd | 273 | { |
7b3343b7 JS |
274 | /* a MPT implementation could have MMIO mapped elsewhere */ |
275 | if (!intel_gvt_host.mpt->map_gfn_to_mfn) | |
276 | return 0; | |
277 | ||
4d60c5fd | 278 | return intel_gvt_host.mpt->map_gfn_to_mfn(vgpu->handle, gfn, mfn, nr, |
8f89743b | 279 | map); |
4d60c5fd ZW |
280 | } |
281 | ||
282 | /** | |
283 | * intel_gvt_hypervisor_set_trap_area - Trap a guest PA region | |
284 | * @vgpu: a vGPU | |
285 | * @start: the beginning of the guest physical address region | |
286 | * @end: the end of the guest physical address region | |
287 | * @map: map or unmap | |
288 | * | |
289 | * Returns: | |
290 | * Zero on success, negative error code if failed. | |
291 | */ | |
292 | static inline int intel_gvt_hypervisor_set_trap_area( | |
293 | struct intel_vgpu *vgpu, u64 start, u64 end, bool map) | |
294 | { | |
7b3343b7 JS |
295 | /* a MPT implementation could have MMIO trapped elsewhere */ |
296 | if (!intel_gvt_host.mpt->set_trap_area) | |
297 | return 0; | |
298 | ||
4d60c5fd ZW |
299 | return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map); |
300 | } | |
301 | ||
b851adea TZ |
302 | /** |
303 | * intel_gvt_hypervisor_set_opregion - Set opregion for guest | |
304 | * @vgpu: a vGPU | |
305 | * | |
306 | * Returns: | |
307 | * Zero on success, negative error code if failed. | |
308 | */ | |
309 | static inline int intel_gvt_hypervisor_set_opregion(struct intel_vgpu *vgpu) | |
310 | { | |
311 | if (!intel_gvt_host.mpt->set_opregion) | |
312 | return 0; | |
313 | ||
314 | return intel_gvt_host.mpt->set_opregion(vgpu); | |
315 | } | |
316 | ||
e546e281 TZ |
317 | /** |
318 | * intel_gvt_hypervisor_get_vfio_device - increase vfio device ref count | |
319 | * @vgpu: a vGPU | |
320 | * | |
321 | * Returns: | |
322 | * Zero on success, negative error code if failed. | |
323 | */ | |
324 | static inline int intel_gvt_hypervisor_get_vfio_device(struct intel_vgpu *vgpu) | |
325 | { | |
326 | if (!intel_gvt_host.mpt->get_vfio_device) | |
327 | return 0; | |
328 | ||
329 | return intel_gvt_host.mpt->get_vfio_device(vgpu); | |
330 | } | |
331 | ||
332 | /** | |
333 | * intel_gvt_hypervisor_put_vfio_device - decrease vfio device ref count | |
334 | * @vgpu: a vGPU | |
335 | * | |
336 | * Returns: | |
337 | * Zero on success, negative error code if failed. | |
338 | */ | |
339 | static inline void intel_gvt_hypervisor_put_vfio_device(struct intel_vgpu *vgpu) | |
340 | { | |
341 | if (!intel_gvt_host.mpt->put_vfio_device) | |
342 | return; | |
343 | ||
344 | intel_gvt_host.mpt->put_vfio_device(vgpu); | |
345 | } | |
346 | ||
cc753fbe HY |
347 | /** |
348 | * intel_gvt_hypervisor_is_valid_gfn - check if a visible gfn | |
349 | * @vgpu: a vGPU | |
350 | * @gfn: guest PFN | |
351 | * | |
352 | * Returns: | |
353 | * true on valid gfn, false on not. | |
354 | */ | |
355 | static inline bool intel_gvt_hypervisor_is_valid_gfn( | |
356 | struct intel_vgpu *vgpu, unsigned long gfn) | |
357 | { | |
358 | if (!intel_gvt_host.mpt->is_valid_gfn) | |
359 | return true; | |
360 | ||
361 | return intel_gvt_host.mpt->is_valid_gfn(vgpu->handle, gfn); | |
362 | } | |
363 | ||
0ad35fed | 364 | #endif /* _GVT_MPT_H_ */ |