1 1.3 riastrad /* $NetBSD: amdgpu_gmc.c,v 1.3 2021/12/19 12:02:39 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2018 Advanced Micro Devices, Inc. 5 1.1 riastrad * All Rights Reserved. 6 1.1 riastrad * 7 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 8 1.1 riastrad * copy of this software and associated documentation files (the 9 1.1 riastrad * "Software"), to deal in the Software without restriction, including 10 1.1 riastrad * without limitation the rights to use, copy, modify, merge, publish, 11 1.1 riastrad * distribute, sub license, and/or sell copies of the Software, and to 12 1.1 riastrad * permit persons to whom the Software is furnished to do so, subject to 13 1.1 riastrad * the following conditions: 14 1.1 riastrad * 15 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 1.1 riastrad * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 1.1 riastrad * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 1.1 riastrad * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 1.1 riastrad * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 1.1 riastrad * 23 1.1 riastrad * The above copyright notice and this permission notice (including the 24 1.1 riastrad * next paragraph) shall be included in all copies or substantial portions 25 1.1 riastrad * of the Software. 26 1.1 riastrad * 27 1.1 riastrad */ 28 1.1 riastrad 29 1.1 riastrad #include <sys/cdefs.h> 30 1.3 riastrad __KERNEL_RCSID(0, "$NetBSD: amdgpu_gmc.c,v 1.3 2021/12/19 12:02:39 riastradh Exp $"); 31 1.1 riastrad 32 1.1 riastrad #include <linux/io-64-nonatomic-lo-hi.h> 33 1.1 riastrad 34 1.1 riastrad #include "amdgpu.h" 35 1.1 riastrad #include "amdgpu_ras.h" 36 1.1 riastrad #include "amdgpu_xgmi.h" 37 1.1 riastrad 38 1.3 riastrad #include <linux/nbsd-namespace.h> 39 1.3 riastrad 40 1.1 riastrad /** 41 1.1 riastrad * amdgpu_gmc_get_pde_for_bo - get the PDE for a BO 42 1.1 riastrad * 43 1.1 riastrad * @bo: the BO to get the PDE for 44 1.1 riastrad * @level: the level in the PD hirarchy 45 1.1 riastrad * @addr: resulting addr 46 1.1 riastrad * @flags: resulting flags 47 1.1 riastrad * 48 1.1 riastrad * Get the address and flags to be used for a PDE (Page Directory Entry). 49 1.1 riastrad */ 50 1.1 riastrad void amdgpu_gmc_get_pde_for_bo(struct amdgpu_bo *bo, int level, 51 1.1 riastrad uint64_t *addr, uint64_t *flags) 52 1.1 riastrad { 53 1.1 riastrad struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); 54 1.1 riastrad struct ttm_dma_tt *ttm; 55 1.1 riastrad 56 1.1 riastrad switch (bo->tbo.mem.mem_type) { 57 1.1 riastrad case TTM_PL_TT: 58 1.1 riastrad ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm); 59 1.3 riastrad #ifdef __NetBSD__ 60 1.3 riastrad *addr = ttm->dma_address->dm_segs[0].ds_addr; 61 1.3 riastrad #else 62 1.1 riastrad *addr = ttm->dma_address[0]; 63 1.3 riastrad #endif 64 1.1 riastrad break; 65 1.1 riastrad case TTM_PL_VRAM: 66 1.1 riastrad *addr = amdgpu_bo_gpu_offset(bo); 67 1.1 riastrad break; 68 1.1 riastrad default: 69 1.1 riastrad *addr = 0; 70 1.1 riastrad break; 71 1.1 riastrad } 72 1.1 riastrad *flags = amdgpu_ttm_tt_pde_flags(bo->tbo.ttm, &bo->tbo.mem); 73 1.1 riastrad amdgpu_gmc_get_vm_pde(adev, level, addr, flags); 74 1.1 riastrad } 75 1.1 riastrad 76 1.1 riastrad /** 77 1.1 riastrad * amdgpu_gmc_pd_addr - return the address of the root directory 78 1.1 riastrad * 79 1.1 riastrad */ 80 1.1 riastrad uint64_t amdgpu_gmc_pd_addr(struct amdgpu_bo *bo) 81 1.1 riastrad { 82 1.1 riastrad struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); 83 1.1 riastrad uint64_t pd_addr; 84 1.1 riastrad 85 1.1 riastrad /* TODO: move that into ASIC specific code */ 86 1.1 riastrad if (adev->asic_type >= CHIP_VEGA10) { 87 1.1 riastrad uint64_t flags = AMDGPU_PTE_VALID; 88 1.1 riastrad 89 1.1 riastrad amdgpu_gmc_get_pde_for_bo(bo, -1, &pd_addr, &flags); 90 1.1 riastrad pd_addr |= flags; 91 1.1 riastrad } else { 92 1.1 riastrad pd_addr = amdgpu_bo_gpu_offset(bo); 93 1.1 riastrad } 94 1.1 riastrad return pd_addr; 95 1.1 riastrad } 96 1.1 riastrad 97 1.1 riastrad /** 98 1.1 riastrad * amdgpu_gmc_set_pte_pde - update the page tables using CPU 99 1.1 riastrad * 100 1.1 riastrad * @adev: amdgpu_device pointer 101 1.1 riastrad * @cpu_pt_addr: cpu address of the page table 102 1.1 riastrad * @gpu_page_idx: entry in the page table to update 103 1.1 riastrad * @addr: dst addr to write into pte/pde 104 1.1 riastrad * @flags: access flags 105 1.1 riastrad * 106 1.1 riastrad * Update the page tables using CPU. 107 1.1 riastrad */ 108 1.1 riastrad int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr, 109 1.1 riastrad uint32_t gpu_page_idx, uint64_t addr, 110 1.1 riastrad uint64_t flags) 111 1.1 riastrad { 112 1.3 riastrad #ifndef __NetBSD__ 113 1.1 riastrad void __iomem *ptr = (void *)cpu_pt_addr; 114 1.3 riastrad #endif 115 1.1 riastrad uint64_t value; 116 1.1 riastrad 117 1.1 riastrad /* 118 1.1 riastrad * The following is for PTE only. GART does not have PDEs. 119 1.1 riastrad */ 120 1.1 riastrad value = addr & 0x0000FFFFFFFFF000ULL; 121 1.1 riastrad value |= flags; 122 1.3 riastrad #ifdef __NetBSD__ 123 1.3 riastrad /* Caller must issue appropriate bus_dmamap_sync before use. */ 124 1.3 riastrad ((uint64_t *)cpu_pt_addr)[gpu_page_idx] = value; 125 1.3 riastrad #else 126 1.1 riastrad writeq(value, ptr + (gpu_page_idx * 8)); 127 1.3 riastrad #endif 128 1.1 riastrad return 0; 129 1.1 riastrad } 130 1.1 riastrad 131 1.1 riastrad /** 132 1.1 riastrad * amdgpu_gmc_agp_addr - return the address in the AGP address space 133 1.1 riastrad * 134 1.1 riastrad * @tbo: TTM BO which needs the address, must be in GTT domain 135 1.1 riastrad * 136 1.1 riastrad * Tries to figure out how to access the BO through the AGP aperture. Returns 137 1.1 riastrad * AMDGPU_BO_INVALID_OFFSET if that is not possible. 138 1.1 riastrad */ 139 1.1 riastrad uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo) 140 1.1 riastrad { 141 1.1 riastrad struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); 142 1.1 riastrad struct ttm_dma_tt *ttm; 143 1.3 riastrad resource_size_t addr; 144 1.1 riastrad 145 1.1 riastrad if (bo->num_pages != 1 || bo->ttm->caching_state == tt_cached) 146 1.1 riastrad return AMDGPU_BO_INVALID_OFFSET; 147 1.1 riastrad 148 1.1 riastrad ttm = container_of(bo->ttm, struct ttm_dma_tt, ttm); 149 1.3 riastrad #ifdef __NetBSD__ 150 1.3 riastrad addr = ttm->dma_address->dm_segs[0].ds_addr; 151 1.3 riastrad #else 152 1.3 riastrad addr = ttm->dma_address[0]; 153 1.3 riastrad #endif 154 1.3 riastrad if (addr + PAGE_SIZE >= adev->gmc.agp_size) 155 1.1 riastrad return AMDGPU_BO_INVALID_OFFSET; 156 1.1 riastrad 157 1.3 riastrad return adev->gmc.agp_start + addr; 158 1.1 riastrad } 159 1.1 riastrad 160 1.1 riastrad /** 161 1.1 riastrad * amdgpu_gmc_vram_location - try to find VRAM location 162 1.1 riastrad * 163 1.1 riastrad * @adev: amdgpu device structure holding all necessary informations 164 1.1 riastrad * @mc: memory controller structure holding memory informations 165 1.1 riastrad * @base: base address at which to put VRAM 166 1.1 riastrad * 167 1.1 riastrad * Function will try to place VRAM at base address provided 168 1.1 riastrad * as parameter. 169 1.1 riastrad */ 170 1.1 riastrad void amdgpu_gmc_vram_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc, 171 1.1 riastrad u64 base) 172 1.1 riastrad { 173 1.1 riastrad uint64_t limit = (uint64_t)amdgpu_vram_limit << 20; 174 1.1 riastrad 175 1.1 riastrad mc->vram_start = base; 176 1.1 riastrad mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; 177 1.1 riastrad if (limit && limit < mc->real_vram_size) 178 1.1 riastrad mc->real_vram_size = limit; 179 1.1 riastrad 180 1.1 riastrad if (mc->xgmi.num_physical_nodes == 0) { 181 1.1 riastrad mc->fb_start = mc->vram_start; 182 1.1 riastrad mc->fb_end = mc->vram_end; 183 1.1 riastrad } 184 1.3 riastrad dev_info(adev->dev, "VRAM: %"PRIu64"M 0x%016"PRIX64" - 0x%016"PRIX64" (%"PRIu64"M used)\n", 185 1.1 riastrad mc->mc_vram_size >> 20, mc->vram_start, 186 1.1 riastrad mc->vram_end, mc->real_vram_size >> 20); 187 1.1 riastrad } 188 1.1 riastrad 189 1.1 riastrad /** 190 1.1 riastrad * amdgpu_gmc_gart_location - try to find GART location 191 1.1 riastrad * 192 1.1 riastrad * @adev: amdgpu device structure holding all necessary informations 193 1.1 riastrad * @mc: memory controller structure holding memory informations 194 1.1 riastrad * 195 1.1 riastrad * Function will place try to place GART before or after VRAM. 196 1.1 riastrad * 197 1.1 riastrad * If GART size is bigger than space left then we ajust GART size. 198 1.1 riastrad * Thus function will never fails. 199 1.1 riastrad */ 200 1.1 riastrad void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc) 201 1.1 riastrad { 202 1.1 riastrad const uint64_t four_gb = 0x100000000ULL; 203 1.1 riastrad u64 size_af, size_bf; 204 1.1 riastrad /*To avoid the hole, limit the max mc address to AMDGPU_GMC_HOLE_START*/ 205 1.1 riastrad u64 max_mc_address = min(adev->gmc.mc_mask, AMDGPU_GMC_HOLE_START - 1); 206 1.1 riastrad 207 1.1 riastrad mc->gart_size += adev->pm.smu_prv_buffer_size; 208 1.1 riastrad 209 1.1 riastrad /* VCE doesn't like it when BOs cross a 4GB segment, so align 210 1.1 riastrad * the GART base on a 4GB boundary as well. 211 1.1 riastrad */ 212 1.1 riastrad size_bf = mc->fb_start; 213 1.1 riastrad size_af = max_mc_address + 1 - ALIGN(mc->fb_end + 1, four_gb); 214 1.1 riastrad 215 1.1 riastrad if (mc->gart_size > max(size_bf, size_af)) { 216 1.1 riastrad dev_warn(adev->dev, "limiting GART\n"); 217 1.1 riastrad mc->gart_size = max(size_bf, size_af); 218 1.1 riastrad } 219 1.1 riastrad 220 1.1 riastrad if ((size_bf >= mc->gart_size && size_bf < size_af) || 221 1.1 riastrad (size_af < mc->gart_size)) 222 1.1 riastrad mc->gart_start = 0; 223 1.1 riastrad else 224 1.1 riastrad mc->gart_start = max_mc_address - mc->gart_size + 1; 225 1.1 riastrad 226 1.1 riastrad mc->gart_start &= ~(four_gb - 1); 227 1.1 riastrad mc->gart_end = mc->gart_start + mc->gart_size - 1; 228 1.3 riastrad dev_info(adev->dev, "GART: %"PRIu64"M 0x%016"PRIX64" - 0x%016"PRIX64"\n", 229 1.1 riastrad mc->gart_size >> 20, mc->gart_start, mc->gart_end); 230 1.1 riastrad } 231 1.1 riastrad 232 1.1 riastrad /** 233 1.1 riastrad * amdgpu_gmc_agp_location - try to find AGP location 234 1.1 riastrad * @adev: amdgpu device structure holding all necessary informations 235 1.1 riastrad * @mc: memory controller structure holding memory informations 236 1.1 riastrad * 237 1.1 riastrad * Function will place try to find a place for the AGP BAR in the MC address 238 1.1 riastrad * space. 239 1.1 riastrad * 240 1.1 riastrad * AGP BAR will be assigned the largest available hole in the address space. 241 1.1 riastrad * Should be called after VRAM and GART locations are setup. 242 1.1 riastrad */ 243 1.1 riastrad void amdgpu_gmc_agp_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc) 244 1.1 riastrad { 245 1.1 riastrad const uint64_t sixteen_gb = 1ULL << 34; 246 1.1 riastrad const uint64_t sixteen_gb_mask = ~(sixteen_gb - 1); 247 1.1 riastrad u64 size_af, size_bf; 248 1.1 riastrad 249 1.1 riastrad if (amdgpu_sriov_vf(adev)) { 250 1.1 riastrad mc->agp_start = 0xffffffffffff; 251 1.1 riastrad mc->agp_end = 0x0; 252 1.1 riastrad mc->agp_size = 0; 253 1.1 riastrad 254 1.1 riastrad return; 255 1.1 riastrad } 256 1.1 riastrad 257 1.1 riastrad if (mc->fb_start > mc->gart_start) { 258 1.1 riastrad size_bf = (mc->fb_start & sixteen_gb_mask) - 259 1.1 riastrad ALIGN(mc->gart_end + 1, sixteen_gb); 260 1.1 riastrad size_af = mc->mc_mask + 1 - ALIGN(mc->fb_end + 1, sixteen_gb); 261 1.1 riastrad } else { 262 1.1 riastrad size_bf = mc->fb_start & sixteen_gb_mask; 263 1.1 riastrad size_af = (mc->gart_start & sixteen_gb_mask) - 264 1.1 riastrad ALIGN(mc->fb_end + 1, sixteen_gb); 265 1.1 riastrad } 266 1.1 riastrad 267 1.1 riastrad if (size_bf > size_af) { 268 1.1 riastrad mc->agp_start = (mc->fb_start - size_bf) & sixteen_gb_mask; 269 1.1 riastrad mc->agp_size = size_bf; 270 1.1 riastrad } else { 271 1.1 riastrad mc->agp_start = ALIGN(mc->fb_end + 1, sixteen_gb); 272 1.1 riastrad mc->agp_size = size_af; 273 1.1 riastrad } 274 1.1 riastrad 275 1.1 riastrad mc->agp_end = mc->agp_start + mc->agp_size - 1; 276 1.3 riastrad dev_info(adev->dev, "AGP: %"PRIu64"M 0x%016"PRIX64" - 0x%016"PRIX64"\n", 277 1.1 riastrad mc->agp_size >> 20, mc->agp_start, mc->agp_end); 278 1.1 riastrad } 279 1.1 riastrad 280 1.1 riastrad /** 281 1.1 riastrad * amdgpu_gmc_filter_faults - filter VM faults 282 1.1 riastrad * 283 1.1 riastrad * @adev: amdgpu device structure 284 1.1 riastrad * @addr: address of the VM fault 285 1.1 riastrad * @pasid: PASID of the process causing the fault 286 1.1 riastrad * @timestamp: timestamp of the fault 287 1.1 riastrad * 288 1.1 riastrad * Returns: 289 1.1 riastrad * True if the fault was filtered and should not be processed further. 290 1.1 riastrad * False if the fault is a new one and needs to be handled. 291 1.1 riastrad */ 292 1.1 riastrad bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr, 293 1.1 riastrad uint16_t pasid, uint64_t timestamp) 294 1.1 riastrad { 295 1.1 riastrad struct amdgpu_gmc *gmc = &adev->gmc; 296 1.1 riastrad 297 1.1 riastrad uint64_t stamp, key = addr << 4 | pasid; 298 1.1 riastrad struct amdgpu_gmc_fault *fault; 299 1.1 riastrad uint32_t hash; 300 1.1 riastrad 301 1.1 riastrad /* If we don't have space left in the ring buffer return immediately */ 302 1.1 riastrad stamp = max(timestamp, AMDGPU_GMC_FAULT_TIMEOUT + 1) - 303 1.1 riastrad AMDGPU_GMC_FAULT_TIMEOUT; 304 1.1 riastrad if (gmc->fault_ring[gmc->last_fault].timestamp >= stamp) 305 1.1 riastrad return true; 306 1.1 riastrad 307 1.1 riastrad /* Try to find the fault in the hash */ 308 1.1 riastrad hash = hash_64(key, AMDGPU_GMC_FAULT_HASH_ORDER); 309 1.1 riastrad fault = &gmc->fault_ring[gmc->fault_hash[hash].idx]; 310 1.1 riastrad while (fault->timestamp >= stamp) { 311 1.1 riastrad uint64_t tmp; 312 1.1 riastrad 313 1.1 riastrad if (fault->key == key) 314 1.1 riastrad return true; 315 1.1 riastrad 316 1.1 riastrad tmp = fault->timestamp; 317 1.1 riastrad fault = &gmc->fault_ring[fault->next]; 318 1.1 riastrad 319 1.1 riastrad /* Check if the entry was reused */ 320 1.1 riastrad if (fault->timestamp >= tmp) 321 1.1 riastrad break; 322 1.1 riastrad } 323 1.1 riastrad 324 1.1 riastrad /* Add the fault to the ring */ 325 1.1 riastrad fault = &gmc->fault_ring[gmc->last_fault]; 326 1.1 riastrad fault->key = key; 327 1.1 riastrad fault->timestamp = timestamp; 328 1.1 riastrad 329 1.1 riastrad /* And update the hash */ 330 1.1 riastrad fault->next = gmc->fault_hash[hash].idx; 331 1.1 riastrad gmc->fault_hash[hash].idx = gmc->last_fault++; 332 1.1 riastrad return false; 333 1.1 riastrad } 334 1.1 riastrad 335 1.1 riastrad int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) 336 1.1 riastrad { 337 1.1 riastrad int r; 338 1.1 riastrad 339 1.1 riastrad if (adev->umc.funcs && adev->umc.funcs->ras_late_init) { 340 1.1 riastrad r = adev->umc.funcs->ras_late_init(adev); 341 1.1 riastrad if (r) 342 1.1 riastrad return r; 343 1.1 riastrad } 344 1.1 riastrad 345 1.1 riastrad if (adev->mmhub.funcs && adev->mmhub.funcs->ras_late_init) { 346 1.1 riastrad r = adev->mmhub.funcs->ras_late_init(adev); 347 1.1 riastrad if (r) 348 1.1 riastrad return r; 349 1.1 riastrad } 350 1.1 riastrad 351 1.1 riastrad return amdgpu_xgmi_ras_late_init(adev); 352 1.1 riastrad } 353 1.1 riastrad 354 1.1 riastrad void amdgpu_gmc_ras_fini(struct amdgpu_device *adev) 355 1.1 riastrad { 356 1.1 riastrad amdgpu_umc_ras_fini(adev); 357 1.1 riastrad amdgpu_mmhub_ras_fini(adev); 358 1.1 riastrad amdgpu_xgmi_ras_fini(adev); 359 1.1 riastrad } 360 1.1 riastrad 361 1.1 riastrad /* 362 1.1 riastrad * The latest engine allocation on gfx9/10 is: 363 1.1 riastrad * Engine 2, 3: firmware 364 1.1 riastrad * Engine 0, 1, 4~16: amdgpu ring, 365 1.1 riastrad * subject to change when ring number changes 366 1.1 riastrad * Engine 17: Gart flushes 367 1.1 riastrad */ 368 1.1 riastrad #define GFXHUB_FREE_VM_INV_ENGS_BITMAP 0x1FFF3 369 1.1 riastrad #define MMHUB_FREE_VM_INV_ENGS_BITMAP 0x1FFF3 370 1.1 riastrad 371 1.1 riastrad int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev) 372 1.1 riastrad { 373 1.1 riastrad struct amdgpu_ring *ring; 374 1.1 riastrad unsigned vm_inv_engs[AMDGPU_MAX_VMHUBS] = 375 1.1 riastrad {GFXHUB_FREE_VM_INV_ENGS_BITMAP, MMHUB_FREE_VM_INV_ENGS_BITMAP, 376 1.1 riastrad GFXHUB_FREE_VM_INV_ENGS_BITMAP}; 377 1.1 riastrad unsigned i; 378 1.1 riastrad unsigned vmhub, inv_eng; 379 1.1 riastrad 380 1.1 riastrad for (i = 0; i < adev->num_rings; ++i) { 381 1.1 riastrad ring = adev->rings[i]; 382 1.1 riastrad vmhub = ring->funcs->vmhub; 383 1.1 riastrad 384 1.1 riastrad inv_eng = ffs(vm_inv_engs[vmhub]); 385 1.1 riastrad if (!inv_eng) { 386 1.1 riastrad dev_err(adev->dev, "no VM inv eng for ring %s\n", 387 1.1 riastrad ring->name); 388 1.1 riastrad return -EINVAL; 389 1.1 riastrad } 390 1.1 riastrad 391 1.1 riastrad ring->vm_inv_eng = inv_eng - 1; 392 1.1 riastrad vm_inv_engs[vmhub] &= ~(1 << ring->vm_inv_eng); 393 1.1 riastrad 394 1.1 riastrad dev_info(adev->dev, "ring %s uses VM inv eng %u on hub %u\n", 395 1.1 riastrad ring->name, ring->vm_inv_eng, ring->funcs->vmhub); 396 1.1 riastrad } 397 1.1 riastrad 398 1.1 riastrad return 0; 399 1.1 riastrad } 400