Home | History | Annotate | Line # | Download | only in gvt
      1 /*	$NetBSD: mpt.h,v 1.2 2021/12/18 23:45:31 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Authors:
     26  *    Eddie Dong <eddie.dong (at) intel.com>
     27  *    Dexuan Cui
     28  *    Jike Song <jike.song (at) intel.com>
     29  *
     30  * Contributors:
     31  *    Zhi Wang <zhi.a.wang (at) intel.com>
     32  *
     33  */
     34 
     35 #ifndef _GVT_MPT_H_
     36 #define _GVT_MPT_H_
     37 
     38 /**
     39  * DOC: Hypervisor Service APIs for GVT-g Core Logic
     40  *
     41  * This is the glue layer between specific hypervisor MPT modules and GVT-g core
     42  * logic. Each kind of hypervisor MPT module provides a collection of function
     43  * callbacks and will be attached to GVT host when the driver is loading.
     44  * GVT-g core logic will call these APIs to request specific services from
     45  * hypervisor.
     46  */
     47 
     48 /**
     49  * intel_gvt_hypervisor_host_init - init GVT-g host side
     50  *
     51  * Returns:
     52  * Zero on success, negative error code if failed
     53  */
     54 static inline int intel_gvt_hypervisor_host_init(struct device *dev,
     55 						 void *gvt, const void *ops)
     56 {
     57 	if (!intel_gvt_host.mpt->host_init)
     58 		return -ENODEV;
     59 
     60 	return intel_gvt_host.mpt->host_init(dev, gvt, ops);
     61 }
     62 
     63 /**
     64  * intel_gvt_hypervisor_host_exit - exit GVT-g host side
     65  */
     66 static inline void intel_gvt_hypervisor_host_exit(struct device *dev)
     67 {
     68 	/* optional to provide */
     69 	if (!intel_gvt_host.mpt->host_exit)
     70 		return;
     71 
     72 	intel_gvt_host.mpt->host_exit(dev);
     73 }
     74 
     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 {
     84 	/* optional to provide */
     85 	if (!intel_gvt_host.mpt->attach_vgpu)
     86 		return 0;
     87 
     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 {
    100 	/* optional to provide */
    101 	if (!intel_gvt_host.mpt->detach_vgpu)
    102 		return;
    103 
    104 	intel_gvt_host.mpt->detach_vgpu(vgpu);
    105 }
    106 
    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 
    136 	trace_inject_msi(vgpu->id, addr, data);
    137 
    138 	ret = intel_gvt_host.mpt->inject_msi(vgpu->handle, addr, data);
    139 	if (ret)
    140 		return ret;
    141 	return 0;
    142 }
    143 
    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 /**
    157  * intel_gvt_hypervisor_enable_page_track - track a guest page
    158  * @vgpu: a vGPU
    159  * @gfn: the gfn of guest
    160  *
    161  * Returns:
    162  * Zero on success, negative error code if failed.
    163  */
    164 static inline int intel_gvt_hypervisor_enable_page_track(
    165 		struct intel_vgpu *vgpu, unsigned long gfn)
    166 {
    167 	return intel_gvt_host.mpt->enable_page_track(vgpu->handle, gfn);
    168 }
    169 
    170 /**
    171  * intel_gvt_hypervisor_disable_page_track - untrack a guest page
    172  * @vgpu: a vGPU
    173  * @gfn: the gfn of guest
    174  *
    175  * Returns:
    176  * Zero on success, negative error code if failed.
    177  */
    178 static inline int intel_gvt_hypervisor_disable_page_track(
    179 		struct intel_vgpu *vgpu, unsigned long gfn)
    180 {
    181 	return intel_gvt_host.mpt->disable_page_track(vgpu->handle, gfn);
    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 
    230 /**
    231  * intel_gvt_hypervisor_dma_map_guest_page - setup dma map for guest page
    232  * @vgpu: a vGPU
    233  * @gfn: guest pfn
    234  * @size: page size
    235  * @dma_addr: retrieve allocated dma addr
    236  *
    237  * Returns:
    238  * 0 on success, negative error code if failed.
    239  */
    240 static inline int intel_gvt_hypervisor_dma_map_guest_page(
    241 		struct intel_vgpu *vgpu, unsigned long gfn, unsigned long size,
    242 		dma_addr_t *dma_addr)
    243 {
    244 	return intel_gvt_host.mpt->dma_map_guest_page(vgpu->handle, gfn, size,
    245 						      dma_addr);
    246 }
    247 
    248 /**
    249  * intel_gvt_hypervisor_dma_unmap_guest_page - cancel dma map for guest page
    250  * @vgpu: a vGPU
    251  * @dma_addr: the mapped dma addr
    252  */
    253 static inline void intel_gvt_hypervisor_dma_unmap_guest_page(
    254 		struct intel_vgpu *vgpu, dma_addr_t dma_addr)
    255 {
    256 	intel_gvt_host.mpt->dma_unmap_guest_page(vgpu->handle, dma_addr);
    257 }
    258 
    259 /**
    260  * intel_gvt_hypervisor_dma_pin_guest_page - pin guest dma buf
    261  * @vgpu: a vGPU
    262  * @dma_addr: guest dma addr
    263  *
    264  * Returns:
    265  * 0 on success, negative error code if failed.
    266  */
    267 static inline int
    268 intel_gvt_hypervisor_dma_pin_guest_page(struct intel_vgpu *vgpu,
    269 					dma_addr_t dma_addr)
    270 {
    271 	return intel_gvt_host.mpt->dma_pin_guest_page(vgpu->handle, dma_addr);
    272 }
    273 
    274 /**
    275  * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN
    276  * @vgpu: a vGPU
    277  * @gfn: guest PFN
    278  * @mfn: host PFN
    279  * @nr: amount of PFNs
    280  * @map: map or unmap
    281  *
    282  * Returns:
    283  * Zero on success, negative error code if failed.
    284  */
    285 static inline int intel_gvt_hypervisor_map_gfn_to_mfn(
    286 		struct intel_vgpu *vgpu, unsigned long gfn,
    287 		unsigned long mfn, unsigned int nr,
    288 		bool map)
    289 {
    290 	/* a MPT implementation could have MMIO mapped elsewhere */
    291 	if (!intel_gvt_host.mpt->map_gfn_to_mfn)
    292 		return 0;
    293 
    294 	return intel_gvt_host.mpt->map_gfn_to_mfn(vgpu->handle, gfn, mfn, nr,
    295 						  map);
    296 }
    297 
    298 /**
    299  * intel_gvt_hypervisor_set_trap_area - Trap a guest PA region
    300  * @vgpu: a vGPU
    301  * @start: the beginning of the guest physical address region
    302  * @end: the end of the guest physical address region
    303  * @map: map or unmap
    304  *
    305  * Returns:
    306  * Zero on success, negative error code if failed.
    307  */
    308 static inline int intel_gvt_hypervisor_set_trap_area(
    309 		struct intel_vgpu *vgpu, u64 start, u64 end, bool map)
    310 {
    311 	/* a MPT implementation could have MMIO trapped elsewhere */
    312 	if (!intel_gvt_host.mpt->set_trap_area)
    313 		return 0;
    314 
    315 	return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map);
    316 }
    317 
    318 /**
    319  * intel_gvt_hypervisor_set_opregion - Set opregion for guest
    320  * @vgpu: a vGPU
    321  *
    322  * Returns:
    323  * Zero on success, negative error code if failed.
    324  */
    325 static inline int intel_gvt_hypervisor_set_opregion(struct intel_vgpu *vgpu)
    326 {
    327 	if (!intel_gvt_host.mpt->set_opregion)
    328 		return 0;
    329 
    330 	return intel_gvt_host.mpt->set_opregion(vgpu);
    331 }
    332 
    333 /**
    334  * intel_gvt_hypervisor_set_edid - Set EDID region for guest
    335  * @vgpu: a vGPU
    336  * @port_num: display port number
    337  *
    338  * Returns:
    339  * Zero on success, negative error code if failed.
    340  */
    341 static inline int intel_gvt_hypervisor_set_edid(struct intel_vgpu *vgpu,
    342 						int port_num)
    343 {
    344 	if (!intel_gvt_host.mpt->set_edid)
    345 		return 0;
    346 
    347 	return intel_gvt_host.mpt->set_edid(vgpu, port_num);
    348 }
    349 
    350 /**
    351  * intel_gvt_hypervisor_get_vfio_device - increase vfio device ref count
    352  * @vgpu: a vGPU
    353  *
    354  * Returns:
    355  * Zero on success, negative error code if failed.
    356  */
    357 static inline int intel_gvt_hypervisor_get_vfio_device(struct intel_vgpu *vgpu)
    358 {
    359 	if (!intel_gvt_host.mpt->get_vfio_device)
    360 		return 0;
    361 
    362 	return intel_gvt_host.mpt->get_vfio_device(vgpu);
    363 }
    364 
    365 /**
    366  * intel_gvt_hypervisor_put_vfio_device - decrease vfio device ref count
    367  * @vgpu: a vGPU
    368  *
    369  * Returns:
    370  * Zero on success, negative error code if failed.
    371  */
    372 static inline void intel_gvt_hypervisor_put_vfio_device(struct intel_vgpu *vgpu)
    373 {
    374 	if (!intel_gvt_host.mpt->put_vfio_device)
    375 		return;
    376 
    377 	intel_gvt_host.mpt->put_vfio_device(vgpu);
    378 }
    379 
    380 /**
    381  * intel_gvt_hypervisor_is_valid_gfn - check if a visible gfn
    382  * @vgpu: a vGPU
    383  * @gfn: guest PFN
    384  *
    385  * Returns:
    386  * true on valid gfn, false on not.
    387  */
    388 static inline bool intel_gvt_hypervisor_is_valid_gfn(
    389 		struct intel_vgpu *vgpu, unsigned long gfn)
    390 {
    391 	if (!intel_gvt_host.mpt->is_valid_gfn)
    392 		return true;
    393 
    394 	return intel_gvt_host.mpt->is_valid_gfn(vgpu->handle, gfn);
    395 }
    396 
    397 int intel_gvt_register_hypervisor(struct intel_gvt_mpt *);
    398 void intel_gvt_unregister_hypervisor(void);
    399 
    400 #endif /* _GVT_MPT_H_ */
    401