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