1 /* $NetBSD: amdgpu_virt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $ */ 2 3 /* 4 * Copyright 2016 Advanced Micro Devices, Inc. 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 shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26 #include <sys/cdefs.h> 27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_virt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $"); 28 29 #include <linux/module.h> 30 31 #include <drm/drm_drv.h> 32 33 #include "amdgpu.h" 34 35 bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev) 36 { 37 /* By now all MMIO pages except mailbox are blocked */ 38 /* if blocking is enabled in hypervisor. Choose the */ 39 /* SCRATCH_REG0 to test. */ 40 return RREG32_NO_KIQ(0xc040) == 0xffffffff; 41 } 42 43 void amdgpu_virt_init_setting(struct amdgpu_device *adev) 44 { 45 /* enable virtual display */ 46 adev->mode_info.num_crtc = 1; 47 adev->enable_virtual_display = true; 48 adev->ddev->driver->driver_features &= ~DRIVER_ATOMIC; 49 adev->cg_flags = 0; 50 adev->pg_flags = 0; 51 } 52 53 void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, 54 uint32_t reg0, uint32_t reg1, 55 uint32_t ref, uint32_t mask) 56 { 57 struct amdgpu_kiq *kiq = &adev->gfx.kiq; 58 struct amdgpu_ring *ring = &kiq->ring; 59 signed long r, cnt = 0; 60 unsigned long flags; 61 uint32_t seq; 62 63 spin_lock_irqsave(&kiq->ring_lock, flags); 64 amdgpu_ring_alloc(ring, 32); 65 amdgpu_ring_emit_reg_write_reg_wait(ring, reg0, reg1, 66 ref, mask); 67 amdgpu_fence_emit_polling(ring, &seq); 68 amdgpu_ring_commit(ring); 69 spin_unlock_irqrestore(&kiq->ring_lock, flags); 70 71 r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); 72 73 /* don't wait anymore for IRQ context */ 74 if (r < 1 && in_interrupt()) 75 goto failed_kiq; 76 77 might_sleep(); 78 while (r < 1 && cnt++ < MAX_KIQ_REG_TRY) { 79 80 msleep(MAX_KIQ_REG_BAILOUT_INTERVAL); 81 r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); 82 } 83 84 if (cnt > MAX_KIQ_REG_TRY) 85 goto failed_kiq; 86 87 return; 88 89 failed_kiq: 90 pr_err("failed to write reg %x wait reg %x\n", reg0, reg1); 91 } 92 93 /** 94 * amdgpu_virt_request_full_gpu() - request full gpu access 95 * @amdgpu: amdgpu device. 96 * @init: is driver init time. 97 * When start to init/fini driver, first need to request full gpu access. 98 * Return: Zero if request success, otherwise will return error. 99 */ 100 int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init) 101 { 102 struct amdgpu_virt *virt = &adev->virt; 103 int r; 104 105 if (virt->ops && virt->ops->req_full_gpu) { 106 r = virt->ops->req_full_gpu(adev, init); 107 if (r) 108 return r; 109 110 adev->virt.caps &= ~AMDGPU_SRIOV_CAPS_RUNTIME; 111 } 112 113 return 0; 114 } 115 116 /** 117 * amdgpu_virt_release_full_gpu() - release full gpu access 118 * @amdgpu: amdgpu device. 119 * @init: is driver init time. 120 * When finishing driver init/fini, need to release full gpu access. 121 * Return: Zero if release success, otherwise will returen error. 122 */ 123 int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init) 124 { 125 struct amdgpu_virt *virt = &adev->virt; 126 int r; 127 128 if (virt->ops && virt->ops->rel_full_gpu) { 129 r = virt->ops->rel_full_gpu(adev, init); 130 if (r) 131 return r; 132 133 adev->virt.caps |= AMDGPU_SRIOV_CAPS_RUNTIME; 134 } 135 return 0; 136 } 137 138 /** 139 * amdgpu_virt_reset_gpu() - reset gpu 140 * @amdgpu: amdgpu device. 141 * Send reset command to GPU hypervisor to reset GPU that VM is using 142 * Return: Zero if reset success, otherwise will return error. 143 */ 144 int amdgpu_virt_reset_gpu(struct amdgpu_device *adev) 145 { 146 struct amdgpu_virt *virt = &adev->virt; 147 int r; 148 149 if (virt->ops && virt->ops->reset_gpu) { 150 r = virt->ops->reset_gpu(adev); 151 if (r) 152 return r; 153 154 adev->virt.caps &= ~AMDGPU_SRIOV_CAPS_RUNTIME; 155 } 156 157 return 0; 158 } 159 160 /** 161 * amdgpu_virt_wait_reset() - wait for reset gpu completed 162 * @amdgpu: amdgpu device. 163 * Wait for GPU reset completed. 164 * Return: Zero if reset success, otherwise will return error. 165 */ 166 int amdgpu_virt_wait_reset(struct amdgpu_device *adev) 167 { 168 struct amdgpu_virt *virt = &adev->virt; 169 170 if (!virt->ops || !virt->ops->wait_reset) 171 return -EINVAL; 172 173 return virt->ops->wait_reset(adev); 174 } 175 176 /** 177 * amdgpu_virt_alloc_mm_table() - alloc memory for mm table 178 * @amdgpu: amdgpu device. 179 * MM table is used by UVD and VCE for its initialization 180 * Return: Zero if allocate success. 181 */ 182 int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev) 183 { 184 int r; 185 186 if (!amdgpu_sriov_vf(adev) || adev->virt.mm_table.gpu_addr) 187 return 0; 188 189 r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, 190 AMDGPU_GEM_DOMAIN_VRAM, 191 &adev->virt.mm_table.bo, 192 &adev->virt.mm_table.gpu_addr, 193 (void *)&adev->virt.mm_table.cpu_addr); 194 if (r) { 195 DRM_ERROR("failed to alloc mm table and error = %d.\n", r); 196 return r; 197 } 198 199 memset((void *)adev->virt.mm_table.cpu_addr, 0, PAGE_SIZE); 200 DRM_INFO("MM table gpu addr = 0x%"PRIx64", cpu addr = %p.\n", 201 adev->virt.mm_table.gpu_addr, 202 adev->virt.mm_table.cpu_addr); 203 return 0; 204 } 205 206 /** 207 * amdgpu_virt_free_mm_table() - free mm table memory 208 * @amdgpu: amdgpu device. 209 * Free MM table memory 210 */ 211 void amdgpu_virt_free_mm_table(struct amdgpu_device *adev) 212 { 213 if (!amdgpu_sriov_vf(adev) || !adev->virt.mm_table.gpu_addr) 214 return; 215 216 amdgpu_bo_free_kernel(&adev->virt.mm_table.bo, 217 &adev->virt.mm_table.gpu_addr, 218 (void *)&adev->virt.mm_table.cpu_addr); 219 adev->virt.mm_table.gpu_addr = 0; 220 } 221 222 223 int amdgpu_virt_fw_reserve_get_checksum(void *obj, 224 unsigned long obj_size, 225 unsigned int key, 226 unsigned int chksum) 227 { 228 unsigned int ret = key; 229 unsigned long i = 0; 230 unsigned char *pos; 231 232 pos = (char *)obj; 233 /* calculate checksum */ 234 for (i = 0; i < obj_size; ++i) 235 ret += *(pos + i); 236 /* minus the chksum itself */ 237 pos = (char *)&chksum; 238 for (i = 0; i < sizeof(chksum); ++i) 239 ret -= *(pos + i); 240 return ret; 241 } 242 243 void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) 244 { 245 uint32_t pf2vf_size = 0; 246 uint32_t checksum = 0; 247 uint32_t checkval; 248 char *str; 249 250 adev->virt.fw_reserve.p_pf2vf = NULL; 251 adev->virt.fw_reserve.p_vf2pf = NULL; 252 253 if (adev->fw_vram_usage.va != NULL) { 254 adev->virt.fw_reserve.p_pf2vf = 255 (struct amd_sriov_msg_pf2vf_info_header *)( 256 adev->fw_vram_usage.va + AMDGIM_DATAEXCHANGE_OFFSET); 257 AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size); 258 AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum); 259 AMDGPU_FW_VRAM_PF2VF_READ(adev, feature_flags, &adev->virt.gim_feature); 260 261 /* pf2vf message must be in 4K */ 262 if (pf2vf_size > 0 && pf2vf_size < 4096) { 263 checkval = amdgpu_virt_fw_reserve_get_checksum( 264 adev->virt.fw_reserve.p_pf2vf, pf2vf_size, 265 adev->virt.fw_reserve.checksum_key, checksum); 266 if (checkval == checksum) { 267 adev->virt.fw_reserve.p_vf2pf = 268 ((void *)adev->virt.fw_reserve.p_pf2vf + 269 pf2vf_size); 270 memset((void *)adev->virt.fw_reserve.p_vf2pf, 0, 271 sizeof(amdgim_vf2pf_info)); 272 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.version, 273 AMDGPU_FW_VRAM_VF2PF_VER); 274 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.size, 275 sizeof(amdgim_vf2pf_info)); 276 AMDGPU_FW_VRAM_VF2PF_READ(adev, driver_version, 277 &str); 278 #ifndef __NetBSD__ /* XXX ??? */ 279 #ifdef MODULE 280 if (THIS_MODULE->version != NULL) 281 strcpy(str, THIS_MODULE->version); 282 else 283 #endif 284 #endif 285 strcpy(str, "N/A"); 286 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, driver_cert, 287 0); 288 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, checksum, 289 amdgpu_virt_fw_reserve_get_checksum( 290 adev->virt.fw_reserve.p_vf2pf, 291 pf2vf_size, 292 adev->virt.fw_reserve.checksum_key, 0)); 293 } 294 } 295 } 296 } 297