/* * Copyright © 2014 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include "main.h" /* i915_gem_gtt.h */ /* GEN8 legacy style address is defined as a 3 level page table: * 31:30 | 29:21 | 20:12 | 11:0 * PDPE | PDE | PTE | offset * The difference as compared to normal x86 3 level page table is the PDPEs are * programmed via register. */ #define FOUR_PAGE_SIZE (4096 * 4) #define PDE_COUNT_PER_PAGE 512 #define PTE_COUNT_PER_PDE 512 #define PDE_COUNT (4*PDE_COUNT_PER_PAGE) #define PDE_MAPPABLE_SIZE (512*4096) static uint64_t pd_page[PDE_COUNT]; static uint64_t pt_page[PTE_COUNT_PER_PDE]; int print_ppgtt_mapping(uint32_t pd_phyaddr) { uint32_t pde, pte; uint64_t *pd; /* first map page directory */ pd_phyaddr &= 0xfffff000; lseek(devmem_fd, pd_phyaddr, SEEK_SET); if (read(devmem_fd, pd_page, FOUR_PAGE_SIZE) != FOUR_PAGE_SIZE) { perror("Read page directory content from /dev/mem failed\n"); exit(-1); } pd = &pd_page[0]; for (pde = 0; pde>20, addr_end>>20); lseek(devmem_fd, pde_addr, SEEK_SET); if (read(devmem_fd, &pt_page[0], 4096) != 4096) { perror("Read page table content from /dev/mem failed\n"); exit(-1); } pt = &pt_page[0]; for (pte=0; pte 0) { if (pt[pte] == pt[pte-1]) continue; } pte_value = (uint32_t) pt[pte]; pte_addr = pte_value & 0xfffff000; addr = addr_start + pte * 4096; printf("\t pte[%03d] = 0x%08x(page no.=%06d, ppgtt addr 0x%x(%04dM+%04dK))\n", pte, pte_value, pte_addr>>12, addr, addr>>20, (addr>>10)&0x3ff); } } return 0; } int get_ppgtt_page(uint32_t pd_phyaddr, uint32_t addr, unsigned char one_page[]) { uint32_t pdp_idx = (addr >> 30) & 0x3; uint32_t pd_idx = (addr >> 21) & 0x1ff; uint32_t pt_idx = (addr >> 12) & 0x1ff; uint32_t pd_index, pde_value, pde_addr, pte_value, pte_addr; /* first map page directory */ pd_phyaddr &= 0xfffff000; /* get PDE entry */ lseek(devmem_fd, pd_phyaddr, SEEK_SET); if (read(devmem_fd, &pd_page[0], FOUR_PAGE_SIZE) != FOUR_PAGE_SIZE) { perror("Read page directory content from /dev/mem failed\n"); exit(-1); } /* get PTE entry */ pd_index = pdp_idx * PDE_COUNT_PER_PAGE + pd_idx; pde_value = (uint32_t)(pd_page[pd_index] & 0xfffff000); pde_addr = pde_value & 0xfffff000; lseek(devmem_fd, pde_addr, SEEK_SET); if (read(devmem_fd, &pt_page[0], 4096) != 4096) { perror("Read page table content from /dev/mem failed\n"); exit(-1); } pte_value = (uint32_t)pt_page[pt_idx]; /* printf("Batch buffer in PPGTT:(PD index %d(page %d, offset %d), entry 0x%08x)/(PT index %d, entry 0x%08x)\n", pd_index, pdp_idx, pd_idx, pde_value, pt_idx, pte_value); */ pte_addr = pte_value & 0xfffff000; lseek(devmem_fd, pte_addr, SEEK_SET); if (read(devmem_fd, &one_page[0], 4096) != 4096) { /* read the content */ perror("Read page table content from /dev/mem failed\n"); exit(-1); } return 0; } int process_dumpppgtt(char *cmdhdr,unsigned int stat_addr) { uint32_t ppgtt_addr; if (is_gen7) { printf("PPGTT is not supported on GEN7\n"); return 0; } CHECK_STRICT_DEVMEM; ppgtt_addr = get_ppgtt(stat_addr); printf("Page directory address 0x%08x\n", ppgtt_addr); print_ppgtt_mapping(ppgtt_addr); return 0; }