1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016-2018 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <errno.h> 25bf215546Sopenharmony_ci#include <string.h> 26bf215546Sopenharmony_ci#include <unistd.h> 27bf215546Sopenharmony_ci#include <sys/types.h> 28bf215546Sopenharmony_ci#include <sys/mman.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "aub_mem.h" 31bf215546Sopenharmony_ci#include "util/anon_file.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_cistruct bo_map { 34bf215546Sopenharmony_ci struct list_head link; 35bf215546Sopenharmony_ci struct intel_batch_decode_bo bo; 36bf215546Sopenharmony_ci bool unmap_after_use; 37bf215546Sopenharmony_ci bool ppgtt; 38bf215546Sopenharmony_ci}; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_cistruct ggtt_entry { 41bf215546Sopenharmony_ci struct rb_node node; 42bf215546Sopenharmony_ci uint64_t virt_addr; 43bf215546Sopenharmony_ci uint64_t phys_addr; 44bf215546Sopenharmony_ci}; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistruct phys_mem { 47bf215546Sopenharmony_ci struct rb_node node; 48bf215546Sopenharmony_ci uint64_t fd_offset; 49bf215546Sopenharmony_ci uint64_t phys_addr; 50bf215546Sopenharmony_ci uint8_t *data; 51bf215546Sopenharmony_ci const uint8_t *aub_data; 52bf215546Sopenharmony_ci}; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistatic void 55bf215546Sopenharmony_ciadd_gtt_bo_map(struct aub_mem *mem, struct intel_batch_decode_bo bo, bool ppgtt, bool unmap_after_use) 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci struct bo_map *m = calloc(1, sizeof(*m)); 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci m->ppgtt = ppgtt; 60bf215546Sopenharmony_ci m->bo = bo; 61bf215546Sopenharmony_ci m->unmap_after_use = unmap_after_use; 62bf215546Sopenharmony_ci list_add(&m->link, &mem->maps); 63bf215546Sopenharmony_ci} 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_civoid 66bf215546Sopenharmony_ciaub_mem_clear_bo_maps(struct aub_mem *mem) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci list_for_each_entry_safe(struct bo_map, i, &mem->maps, link) { 69bf215546Sopenharmony_ci if (i->unmap_after_use) 70bf215546Sopenharmony_ci munmap((void *)i->bo.map, i->bo.size); 71bf215546Sopenharmony_ci list_del(&i->link); 72bf215546Sopenharmony_ci free(i); 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistatic inline struct ggtt_entry * 77bf215546Sopenharmony_ciggtt_entry_next(struct ggtt_entry *entry) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci if (!entry) 80bf215546Sopenharmony_ci return NULL; 81bf215546Sopenharmony_ci struct rb_node *node = rb_node_next(&entry->node); 82bf215546Sopenharmony_ci if (!node) 83bf215546Sopenharmony_ci return NULL; 84bf215546Sopenharmony_ci return rb_node_data(struct ggtt_entry, node, node); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic inline int 88bf215546Sopenharmony_cicmp_uint64(uint64_t a, uint64_t b) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci if (a < b) 91bf215546Sopenharmony_ci return 1; 92bf215546Sopenharmony_ci if (a > b) 93bf215546Sopenharmony_ci return -1; 94bf215546Sopenharmony_ci return 0; 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_cistatic inline int 98bf215546Sopenharmony_cicmp_ggtt_entry(const struct rb_node *node, const void *addr) 99bf215546Sopenharmony_ci{ 100bf215546Sopenharmony_ci struct ggtt_entry *entry = rb_node_data(struct ggtt_entry, node, node); 101bf215546Sopenharmony_ci return cmp_uint64(entry->virt_addr, *(const uint64_t *)addr); 102bf215546Sopenharmony_ci} 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_cistatic struct ggtt_entry * 105bf215546Sopenharmony_ciensure_ggtt_entry(struct aub_mem *mem, uint64_t virt_addr) 106bf215546Sopenharmony_ci{ 107bf215546Sopenharmony_ci struct rb_node *node = rb_tree_search_sloppy(&mem->ggtt, &virt_addr, 108bf215546Sopenharmony_ci cmp_ggtt_entry); 109bf215546Sopenharmony_ci int cmp = 0; 110bf215546Sopenharmony_ci if (!node || (cmp = cmp_ggtt_entry(node, &virt_addr))) { 111bf215546Sopenharmony_ci struct ggtt_entry *new_entry = calloc(1, sizeof(*new_entry)); 112bf215546Sopenharmony_ci new_entry->virt_addr = virt_addr; 113bf215546Sopenharmony_ci rb_tree_insert_at(&mem->ggtt, node, &new_entry->node, cmp < 0); 114bf215546Sopenharmony_ci node = &new_entry->node; 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci return rb_node_data(struct ggtt_entry, node, node); 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_cistatic struct ggtt_entry * 121bf215546Sopenharmony_cisearch_ggtt_entry(struct aub_mem *mem, uint64_t virt_addr) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci virt_addr &= ~0xfff; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci struct rb_node *node = rb_tree_search(&mem->ggtt, &virt_addr, cmp_ggtt_entry); 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci if (!node) 128bf215546Sopenharmony_ci return NULL; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci return rb_node_data(struct ggtt_entry, node, node); 131bf215546Sopenharmony_ci} 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_cistatic inline int 134bf215546Sopenharmony_cicmp_phys_mem(const struct rb_node *node, const void *addr) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci struct phys_mem *mem = rb_node_data(struct phys_mem, node, node); 137bf215546Sopenharmony_ci return cmp_uint64(mem->phys_addr, *(uint64_t *)addr); 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_cistatic void 141bf215546Sopenharmony_cicheck_mmap_result(const void *res) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci if (res != MAP_FAILED) 144bf215546Sopenharmony_ci return; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci if (errno == ENOMEM) { 147bf215546Sopenharmony_ci fprintf(stderr, 148bf215546Sopenharmony_ci "Not enough memory available or maximum number of mappings reached. " 149bf215546Sopenharmony_ci "Consider increasing sysctl vm.max_map_count.\n"); 150bf215546Sopenharmony_ci } else { 151bf215546Sopenharmony_ci perror("mmap"); 152bf215546Sopenharmony_ci } 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci abort(); 155bf215546Sopenharmony_ci} 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_cistatic struct phys_mem * 158bf215546Sopenharmony_ciensure_phys_mem(struct aub_mem *mem, uint64_t phys_addr) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci struct rb_node *node = rb_tree_search_sloppy(&mem->mem, &phys_addr, cmp_phys_mem); 161bf215546Sopenharmony_ci int cmp = 0; 162bf215546Sopenharmony_ci if (!node || (cmp = cmp_phys_mem(node, &phys_addr))) { 163bf215546Sopenharmony_ci struct phys_mem *new_mem = calloc(1, sizeof(*new_mem)); 164bf215546Sopenharmony_ci new_mem->phys_addr = phys_addr; 165bf215546Sopenharmony_ci new_mem->fd_offset = mem->mem_fd_len; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci ASSERTED int ftruncate_res = ftruncate(mem->mem_fd, mem->mem_fd_len += 4096); 168bf215546Sopenharmony_ci assert(ftruncate_res == 0); 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci new_mem->data = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, 171bf215546Sopenharmony_ci mem->mem_fd, new_mem->fd_offset); 172bf215546Sopenharmony_ci check_mmap_result(new_mem->data); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci rb_tree_insert_at(&mem->mem, node, &new_mem->node, cmp < 0); 175bf215546Sopenharmony_ci node = &new_mem->node; 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci return rb_node_data(struct phys_mem, node, node); 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_cistatic struct phys_mem * 182bf215546Sopenharmony_cisearch_phys_mem(struct aub_mem *mem, uint64_t phys_addr) 183bf215546Sopenharmony_ci{ 184bf215546Sopenharmony_ci phys_addr &= ~0xfff; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci struct rb_node *node = rb_tree_search(&mem->mem, &phys_addr, cmp_phys_mem); 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci if (!node) 189bf215546Sopenharmony_ci return NULL; 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci return rb_node_data(struct phys_mem, node, node); 192bf215546Sopenharmony_ci} 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_civoid 195bf215546Sopenharmony_ciaub_mem_local_write(void *_mem, uint64_t address, 196bf215546Sopenharmony_ci const void *data, uint32_t size) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci struct aub_mem *mem = _mem; 199bf215546Sopenharmony_ci struct intel_batch_decode_bo bo = { 200bf215546Sopenharmony_ci .map = data, 201bf215546Sopenharmony_ci .addr = address, 202bf215546Sopenharmony_ci .size = size, 203bf215546Sopenharmony_ci }; 204bf215546Sopenharmony_ci add_gtt_bo_map(mem, bo, false, false); 205bf215546Sopenharmony_ci} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_civoid 208bf215546Sopenharmony_ciaub_mem_ggtt_entry_write(void *_mem, uint64_t address, 209bf215546Sopenharmony_ci const void *_data, uint32_t _size) 210bf215546Sopenharmony_ci{ 211bf215546Sopenharmony_ci struct aub_mem *mem = _mem; 212bf215546Sopenharmony_ci uint64_t virt_addr = (address / sizeof(uint64_t)) << 12; 213bf215546Sopenharmony_ci const uint64_t *data = _data; 214bf215546Sopenharmony_ci size_t size = _size / sizeof(*data); 215bf215546Sopenharmony_ci for (const uint64_t *entry = data; 216bf215546Sopenharmony_ci entry < data + size; 217bf215546Sopenharmony_ci entry++, virt_addr += 4096) { 218bf215546Sopenharmony_ci struct ggtt_entry *pt = ensure_ggtt_entry(mem, virt_addr); 219bf215546Sopenharmony_ci pt->phys_addr = *entry; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_civoid 224bf215546Sopenharmony_ciaub_mem_phys_write(void *_mem, uint64_t phys_address, 225bf215546Sopenharmony_ci const void *data, uint32_t size) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci struct aub_mem *mem = _mem; 228bf215546Sopenharmony_ci uint32_t to_write = size; 229bf215546Sopenharmony_ci for (uint64_t page = phys_address & ~0xfff; page < phys_address + size; page += 4096) { 230bf215546Sopenharmony_ci struct phys_mem *pmem = ensure_phys_mem(mem, page); 231bf215546Sopenharmony_ci uint64_t offset = MAX2(page, phys_address) - page; 232bf215546Sopenharmony_ci uint32_t size_this_page = MIN2(to_write, 4096 - offset); 233bf215546Sopenharmony_ci to_write -= size_this_page; 234bf215546Sopenharmony_ci memcpy(pmem->data + offset, data, size_this_page); 235bf215546Sopenharmony_ci pmem->aub_data = data - offset; 236bf215546Sopenharmony_ci data = (const uint8_t *)data + size_this_page; 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci} 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_civoid 241bf215546Sopenharmony_ciaub_mem_ggtt_write(void *_mem, uint64_t virt_address, 242bf215546Sopenharmony_ci const void *data, uint32_t size) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci struct aub_mem *mem = _mem; 245bf215546Sopenharmony_ci uint32_t to_write = size; 246bf215546Sopenharmony_ci for (uint64_t page = virt_address & ~0xfff; page < virt_address + size; page += 4096) { 247bf215546Sopenharmony_ci struct ggtt_entry *entry = search_ggtt_entry(mem, page); 248bf215546Sopenharmony_ci assert(entry && entry->phys_addr & 0x1); 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci uint64_t offset = MAX2(page, virt_address) - page; 251bf215546Sopenharmony_ci uint32_t size_this_page = MIN2(to_write, 4096 - offset); 252bf215546Sopenharmony_ci to_write -= size_this_page; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci uint64_t phys_page = entry->phys_addr & ~0xfff; /* Clear the validity bits. */ 255bf215546Sopenharmony_ci aub_mem_phys_write(mem, phys_page + offset, data, size_this_page); 256bf215546Sopenharmony_ci data = (const uint8_t *)data + size_this_page; 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci} 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_cistruct intel_batch_decode_bo 261bf215546Sopenharmony_ciaub_mem_get_ggtt_bo(void *_mem, uint64_t address) 262bf215546Sopenharmony_ci{ 263bf215546Sopenharmony_ci struct aub_mem *mem = _mem; 264bf215546Sopenharmony_ci struct intel_batch_decode_bo bo = {0}; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci list_for_each_entry(struct bo_map, i, &mem->maps, link) 267bf215546Sopenharmony_ci if (!i->ppgtt && i->bo.addr <= address && i->bo.addr + i->bo.size > address) 268bf215546Sopenharmony_ci return i->bo; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci address &= ~0xfff; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci struct ggtt_entry *start = 273bf215546Sopenharmony_ci (struct ggtt_entry *)rb_tree_search_sloppy(&mem->ggtt, &address, 274bf215546Sopenharmony_ci cmp_ggtt_entry); 275bf215546Sopenharmony_ci if (start && start->virt_addr < address) 276bf215546Sopenharmony_ci start = ggtt_entry_next(start); 277bf215546Sopenharmony_ci if (!start) 278bf215546Sopenharmony_ci return bo; 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci struct ggtt_entry *last = start; 281bf215546Sopenharmony_ci for (struct ggtt_entry *i = ggtt_entry_next(last); 282bf215546Sopenharmony_ci i && last->virt_addr + 4096 == i->virt_addr; 283bf215546Sopenharmony_ci last = i, i = ggtt_entry_next(last)) 284bf215546Sopenharmony_ci ; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci bo.addr = MIN2(address, start->virt_addr); 287bf215546Sopenharmony_ci bo.size = last->virt_addr - bo.addr + 4096; 288bf215546Sopenharmony_ci bo.map = mmap(NULL, bo.size, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 289bf215546Sopenharmony_ci check_mmap_result(bo.map); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci for (struct ggtt_entry *i = start; 292bf215546Sopenharmony_ci i; 293bf215546Sopenharmony_ci i = i == last ? NULL : ggtt_entry_next(i)) { 294bf215546Sopenharmony_ci uint64_t phys_addr = i->phys_addr & ~0xfff; 295bf215546Sopenharmony_ci struct phys_mem *phys_mem = search_phys_mem(mem, phys_addr); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (!phys_mem) 298bf215546Sopenharmony_ci continue; 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci uint32_t map_offset = i->virt_addr - address; 301bf215546Sopenharmony_ci void *res = mmap((uint8_t *)bo.map + map_offset, 4096, PROT_READ, 302bf215546Sopenharmony_ci MAP_SHARED | MAP_FIXED, mem->mem_fd, phys_mem->fd_offset); 303bf215546Sopenharmony_ci check_mmap_result(res); 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci add_gtt_bo_map(mem, bo, false, true); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci return bo; 309bf215546Sopenharmony_ci} 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_cistatic struct phys_mem * 312bf215546Sopenharmony_cippgtt_walk(struct aub_mem *mem, uint64_t pml4, uint64_t address) 313bf215546Sopenharmony_ci{ 314bf215546Sopenharmony_ci uint64_t shift = 39; 315bf215546Sopenharmony_ci uint64_t addr = pml4; 316bf215546Sopenharmony_ci for (int level = 4; level > 0; level--) { 317bf215546Sopenharmony_ci struct phys_mem *table = search_phys_mem(mem, addr); 318bf215546Sopenharmony_ci if (!table) 319bf215546Sopenharmony_ci return NULL; 320bf215546Sopenharmony_ci int index = (address >> shift) & 0x1ff; 321bf215546Sopenharmony_ci uint64_t entry = ((uint64_t *)table->data)[index]; 322bf215546Sopenharmony_ci if (!(entry & 1)) 323bf215546Sopenharmony_ci return NULL; 324bf215546Sopenharmony_ci addr = entry & ~0xfff; 325bf215546Sopenharmony_ci shift -= 9; 326bf215546Sopenharmony_ci } 327bf215546Sopenharmony_ci return search_phys_mem(mem, addr); 328bf215546Sopenharmony_ci} 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_cistatic bool 331bf215546Sopenharmony_cippgtt_mapped(struct aub_mem *mem, uint64_t pml4, uint64_t address) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci return ppgtt_walk(mem, pml4, address) != NULL; 334bf215546Sopenharmony_ci} 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_cistruct intel_batch_decode_bo 337bf215546Sopenharmony_ciaub_mem_get_ppgtt_bo(void *_mem, uint64_t address) 338bf215546Sopenharmony_ci{ 339bf215546Sopenharmony_ci struct aub_mem *mem = _mem; 340bf215546Sopenharmony_ci struct intel_batch_decode_bo bo = {0}; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci list_for_each_entry(struct bo_map, i, &mem->maps, link) 343bf215546Sopenharmony_ci if (i->ppgtt && i->bo.addr <= address && i->bo.addr + i->bo.size > address) 344bf215546Sopenharmony_ci return i->bo; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci address &= ~0xfff; 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci if (!ppgtt_mapped(mem, mem->pml4, address)) 349bf215546Sopenharmony_ci return bo; 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci /* Map everything until the first gap since we don't know how much the 352bf215546Sopenharmony_ci * decoder actually needs. 353bf215546Sopenharmony_ci */ 354bf215546Sopenharmony_ci uint64_t end = address; 355bf215546Sopenharmony_ci while (ppgtt_mapped(mem, mem->pml4, end)) 356bf215546Sopenharmony_ci end += 4096; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci bo.addr = address; 359bf215546Sopenharmony_ci bo.size = end - address; 360bf215546Sopenharmony_ci bo.map = mmap(NULL, bo.size, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 361bf215546Sopenharmony_ci assert(bo.map != MAP_FAILED); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci for (uint64_t page = address; page < end; page += 4096) { 364bf215546Sopenharmony_ci struct phys_mem *phys_mem = ppgtt_walk(mem, mem->pml4, page); 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci void *res = mmap((uint8_t *)bo.map + (page - bo.addr), 4096, PROT_READ, 367bf215546Sopenharmony_ci MAP_SHARED | MAP_FIXED, mem->mem_fd, phys_mem->fd_offset); 368bf215546Sopenharmony_ci check_mmap_result(res); 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci add_gtt_bo_map(mem, bo, true, true); 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci return bo; 374bf215546Sopenharmony_ci} 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_cibool 377bf215546Sopenharmony_ciaub_mem_init(struct aub_mem *mem) 378bf215546Sopenharmony_ci{ 379bf215546Sopenharmony_ci memset(mem, 0, sizeof(*mem)); 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci list_inithead(&mem->maps); 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci mem->mem_fd = os_create_anonymous_file(0, "phys memory"); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci return mem->mem_fd != -1; 386bf215546Sopenharmony_ci} 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_civoid 389bf215546Sopenharmony_ciaub_mem_fini(struct aub_mem *mem) 390bf215546Sopenharmony_ci{ 391bf215546Sopenharmony_ci if (mem->mem_fd == -1) 392bf215546Sopenharmony_ci return; 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci aub_mem_clear_bo_maps(mem); 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci rb_tree_foreach_safe(struct ggtt_entry, entry, &mem->ggtt, node) { 398bf215546Sopenharmony_ci rb_tree_remove(&mem->ggtt, &entry->node); 399bf215546Sopenharmony_ci free(entry); 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci rb_tree_foreach_safe(struct phys_mem, entry, &mem->mem, node) { 402bf215546Sopenharmony_ci rb_tree_remove(&mem->mem, &entry->node); 403bf215546Sopenharmony_ci free(entry); 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci close(mem->mem_fd); 407bf215546Sopenharmony_ci mem->mem_fd = -1; 408bf215546Sopenharmony_ci} 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_cistruct intel_batch_decode_bo 411bf215546Sopenharmony_ciaub_mem_get_phys_addr_data(struct aub_mem *mem, uint64_t phys_addr) 412bf215546Sopenharmony_ci{ 413bf215546Sopenharmony_ci struct phys_mem *page = search_phys_mem(mem, phys_addr); 414bf215546Sopenharmony_ci return page ? 415bf215546Sopenharmony_ci (struct intel_batch_decode_bo) { .map = page->data, .addr = page->phys_addr, .size = 4096 } : 416bf215546Sopenharmony_ci (struct intel_batch_decode_bo) {}; 417bf215546Sopenharmony_ci} 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_cistruct intel_batch_decode_bo 420bf215546Sopenharmony_ciaub_mem_get_ppgtt_addr_data(struct aub_mem *mem, uint64_t virt_addr) 421bf215546Sopenharmony_ci{ 422bf215546Sopenharmony_ci struct phys_mem *page = ppgtt_walk(mem, mem->pml4, virt_addr); 423bf215546Sopenharmony_ci return page ? 424bf215546Sopenharmony_ci (struct intel_batch_decode_bo) { .map = page->data, .addr = virt_addr & ~((1ULL << 12) - 1), .size = 4096 } : 425bf215546Sopenharmony_ci (struct intel_batch_decode_bo) {}; 426bf215546Sopenharmony_ci} 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_cistruct intel_batch_decode_bo 429bf215546Sopenharmony_ciaub_mem_get_ppgtt_addr_aub_data(struct aub_mem *mem, uint64_t virt_addr) 430bf215546Sopenharmony_ci{ 431bf215546Sopenharmony_ci struct phys_mem *page = ppgtt_walk(mem, mem->pml4, virt_addr); 432bf215546Sopenharmony_ci return page ? 433bf215546Sopenharmony_ci (struct intel_batch_decode_bo) { .map = page->aub_data, .addr = virt_addr & ~((1ULL << 12) - 1), .size = 4096 } : 434bf215546Sopenharmony_ci (struct intel_batch_decode_bo) {}; 435bf215546Sopenharmony_ci} 436