1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include <linux/prandom.h> 7 8 #include "intel_memory_region.h" 9 #include "i915_drv.h" 10 #include "i915_ttm_buddy_manager.h" 11 12 static const struct { 13 u16 class; 14 u16 instance; 15 } intel_region_map[] = { 16 [INTEL_REGION_SMEM] = { 17 .class = INTEL_MEMORY_SYSTEM, 18 .instance = 0, 19 }, 20 [INTEL_REGION_LMEM] = { 21 .class = INTEL_MEMORY_LOCAL, 22 .instance = 0, 23 }, 24 [INTEL_REGION_STOLEN_SMEM] = { 25 .class = INTEL_MEMORY_STOLEN_SYSTEM, 26 .instance = 0, 27 }, 28 [INTEL_REGION_STOLEN_LMEM] = { 29 .class = INTEL_MEMORY_STOLEN_LOCAL, 30 .instance = 0, 31 }, 32 }; 33 34 static int __iopagetest(struct intel_memory_region *mem, 35 u8 __iomem *va, int pagesize, 36 u8 value, resource_size_t offset, 37 const void *caller) 38 { 39 int byte = prandom_u32_max(pagesize); 40 u8 result[3]; 41 42 memset_io(va, value, pagesize); /* or GPF! */ 43 wmb(); 44 45 result[0] = ioread8(va); 46 result[1] = ioread8(va + byte); 47 result[2] = ioread8(va + pagesize - 1); 48 if (memchr_inv(result, value, sizeof(result))) { 49 dev_err(mem->i915->drm.dev, 50 "Failed to read back from memory region:%pR at [%pa + %pa] for %ps; wrote %x, read (%x, %x, %x)\n", 51 &mem->region, &mem->io_start, &offset, caller, 52 value, result[0], result[1], result[2]); 53 return -EINVAL; 54 } 55 56 return 0; 57 } 58 59 static int iopagetest(struct intel_memory_region *mem, 60 resource_size_t offset, 61 const void *caller) 62 { 63 const u8 val[] = { 0x0, 0xa5, 0xc3, 0xf0 }; 64 void __iomem *va; 65 int err; 66 int i; 67 68 va = ioremap_wc(mem->io_start + offset, PAGE_SIZE); 69 if (!va) { 70 dev_err(mem->i915->drm.dev, 71 "Failed to ioremap memory region [%pa + %pa] for %ps\n", 72 &mem->io_start, &offset, caller); 73 return -EFAULT; 74 } 75 76 for (i = 0; i < ARRAY_SIZE(val); i++) { 77 err = __iopagetest(mem, va, PAGE_SIZE, val[i], offset, caller); 78 if (err) 79 break; 80 81 err = __iopagetest(mem, va, PAGE_SIZE, ~val[i], offset, caller); 82 if (err) 83 break; 84 } 85 86 iounmap(va); 87 return err; 88 } 89 90 static resource_size_t random_page(resource_size_t last) 91 { 92 /* Limited to low 44b (16TiB), but should suffice for a spot check */ 93 return prandom_u32_max(last >> PAGE_SHIFT) << PAGE_SHIFT; 94 } 95 96 static int iomemtest(struct intel_memory_region *mem, 97 bool test_all, 98 const void *caller) 99 { 100 resource_size_t last = resource_size(&mem->region) - PAGE_SIZE; 101 resource_size_t page; 102 int err; 103 104 /* 105 * Quick test to check read/write access to the iomap (backing store). 106 * 107 * Write a byte, read it back. If the iomapping fails, we expect 108 * a GPF preventing further execution. If the backing store does not 109 * exist, the read back will return garbage. We check a couple of pages, 110 * the first and last of the specified region to confirm the backing 111 * store + iomap does cover the entire memory region; and we check 112 * a random offset within as a quick spot check for bad memory. 113 */ 114 115 if (test_all) { 116 for (page = 0; page <= last; page += PAGE_SIZE) { 117 err = iopagetest(mem, page, caller); 118 if (err) 119 return err; 120 } 121 } else { 122 err = iopagetest(mem, 0, caller); 123 if (err) 124 return err; 125 126 err = iopagetest(mem, last, caller); 127 if (err) 128 return err; 129 130 err = iopagetest(mem, random_page(last), caller); 131 if (err) 132 return err; 133 } 134 135 return 0; 136 } 137 138 struct intel_memory_region * 139 intel_memory_region_lookup(struct drm_i915_private *i915, 140 u16 class, u16 instance) 141 { 142 struct intel_memory_region *mr; 143 int id; 144 145 /* XXX: consider maybe converting to an rb tree at some point */ 146 for_each_memory_region(mr, i915, id) { 147 if (mr->type == class && mr->instance == instance) 148 return mr; 149 } 150 151 return NULL; 152 } 153 154 struct intel_memory_region * 155 intel_memory_region_by_type(struct drm_i915_private *i915, 156 enum intel_memory_type mem_type) 157 { 158 struct intel_memory_region *mr; 159 int id; 160 161 for_each_memory_region(mr, i915, id) 162 if (mr->type == mem_type) 163 return mr; 164 165 return NULL; 166 } 167 168 /** 169 * intel_memory_region_reserve - Reserve a memory range 170 * @mem: The region for which we want to reserve a range. 171 * @offset: Start of the range to reserve. 172 * @size: The size of the range to reserve. 173 * 174 * Return: 0 on success, negative error code on failure. 175 */ 176 int intel_memory_region_reserve(struct intel_memory_region *mem, 177 resource_size_t offset, 178 resource_size_t size) 179 { 180 struct ttm_resource_manager *man = mem->region_private; 181 182 GEM_BUG_ON(mem->is_range_manager); 183 184 return i915_ttm_buddy_man_reserve(man, offset, size); 185 } 186 187 void intel_memory_region_debug(struct intel_memory_region *mr, 188 struct drm_printer *printer) 189 { 190 drm_printf(printer, "%s: ", mr->name); 191 192 if (mr->region_private) 193 ttm_resource_manager_debug(mr->region_private, printer); 194 else 195 drm_printf(printer, "total:%pa, available:%pa bytes\n", 196 &mr->total, &mr->avail); 197 } 198 199 static int intel_memory_region_memtest(struct intel_memory_region *mem, 200 void *caller) 201 { 202 struct drm_i915_private *i915 = mem->i915; 203 int err = 0; 204 205 if (!mem->io_start) 206 return 0; 207 208 if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) || i915->params.memtest) 209 err = iomemtest(mem, i915->params.memtest, caller); 210 211 return err; 212 } 213 214 struct intel_memory_region * 215 intel_memory_region_create(struct drm_i915_private *i915, 216 resource_size_t start, 217 resource_size_t size, 218 resource_size_t min_page_size, 219 resource_size_t io_start, 220 u16 type, 221 u16 instance, 222 const struct intel_memory_region_ops *ops) 223 { 224 struct intel_memory_region *mem; 225 int err; 226 227 mem = kzalloc(sizeof(*mem), GFP_KERNEL); 228 if (!mem) 229 return ERR_PTR(-ENOMEM); 230 231 mem->i915 = i915; 232 mem->region = (struct resource)DEFINE_RES_MEM(start, size); 233 mem->io_start = io_start; 234 mem->min_page_size = min_page_size; 235 mem->ops = ops; 236 mem->total = size; 237 mem->avail = mem->total; 238 mem->type = type; 239 mem->instance = instance; 240 241 mutex_init(&mem->objects.lock); 242 INIT_LIST_HEAD(&mem->objects.list); 243 244 if (ops->init) { 245 err = ops->init(mem); 246 if (err) 247 goto err_free; 248 } 249 250 err = intel_memory_region_memtest(mem, (void *)_RET_IP_); 251 if (err) 252 goto err_release; 253 254 return mem; 255 256 err_release: 257 if (mem->ops->release) 258 mem->ops->release(mem); 259 err_free: 260 kfree(mem); 261 return ERR_PTR(err); 262 } 263 264 void intel_memory_region_set_name(struct intel_memory_region *mem, 265 const char *fmt, ...) 266 { 267 va_list ap; 268 269 va_start(ap, fmt); 270 vsnprintf(mem->name, sizeof(mem->name), fmt, ap); 271 va_end(ap); 272 } 273 274 void intel_memory_region_destroy(struct intel_memory_region *mem) 275 { 276 int ret = 0; 277 278 if (mem->ops->release) 279 ret = mem->ops->release(mem); 280 281 GEM_WARN_ON(!list_empty_careful(&mem->objects.list)); 282 mutex_destroy(&mem->objects.lock); 283 if (!ret) 284 kfree(mem); 285 } 286 287 /* Global memory region registration -- only slight layer inversions! */ 288 289 int intel_memory_regions_hw_probe(struct drm_i915_private *i915) 290 { 291 int err, i; 292 293 for (i = 0; i < ARRAY_SIZE(i915->mm.regions); i++) { 294 struct intel_memory_region *mem = ERR_PTR(-ENODEV); 295 u16 type, instance; 296 297 if (!HAS_REGION(i915, BIT(i))) 298 continue; 299 300 type = intel_region_map[i].class; 301 instance = intel_region_map[i].instance; 302 switch (type) { 303 case INTEL_MEMORY_SYSTEM: 304 if (IS_DGFX(i915)) 305 mem = i915_gem_ttm_system_setup(i915, type, 306 instance); 307 else 308 mem = i915_gem_shmem_setup(i915, type, 309 instance); 310 break; 311 case INTEL_MEMORY_STOLEN_LOCAL: 312 mem = i915_gem_stolen_lmem_setup(i915, type, instance); 313 if (!IS_ERR(mem)) 314 i915->mm.stolen_region = mem; 315 break; 316 case INTEL_MEMORY_STOLEN_SYSTEM: 317 mem = i915_gem_stolen_smem_setup(i915, type, instance); 318 if (!IS_ERR(mem)) 319 i915->mm.stolen_region = mem; 320 break; 321 default: 322 continue; 323 } 324 325 if (IS_ERR(mem)) { 326 err = PTR_ERR(mem); 327 drm_err(&i915->drm, 328 "Failed to setup region(%d) type=%d\n", 329 err, type); 330 goto out_cleanup; 331 } 332 333 mem->id = i; 334 i915->mm.regions[i] = mem; 335 } 336 337 return 0; 338 339 out_cleanup: 340 intel_memory_regions_driver_release(i915); 341 return err; 342 } 343 344 void intel_memory_regions_driver_release(struct drm_i915_private *i915) 345 { 346 int i; 347 348 for (i = 0; i < ARRAY_SIZE(i915->mm.regions); i++) { 349 struct intel_memory_region *region = 350 fetch_and_zero(&i915->mm.regions[i]); 351 352 if (region) 353 intel_memory_region_destroy(region); 354 } 355 } 356 357 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 358 #include "selftests/intel_memory_region.c" 359 #include "selftests/mock_region.c" 360 #endif 361