/* * 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. * * Author: * Yuan Shengquan */ #include #include #include #include #include #include #include #include #include #include #ifndef ANDROID #include #include #endif #include "igdbg.yacc.h" #include "i915_reg.h" #include "main.h" int iopl(int level); int ioperm(unsigned long from, unsigned long num, int turn_on); int yyparse(); int devmem_fd = -1; int devmem_strict = 0; unsigned short devid, is_gen7=0, is_gen8=0; uint32_t phy_mmio,phy_fb, stolen_base; unsigned char *linear_mmio,*linear_gtt,*linear_fb;/* linear mmio,fb,gtt */ unsigned int stolen_size, gtt_size, gtt_mapable_size; int verbose=0; char *cmd_buf=NULL,*cmd_ptr=NULL,*cmd_end=NULL; void print_bin_fmt(unsigned int value,int space) { char buf[33]; int i=0; unsigned int n = value; memset(buf,(int)'0',32); buf[32]='\0'; do { buf[i++] = (n&1)+'0'; n/=2; } while(n); #define print_four_bits(from) printf("|%c%c%c%c| ",buf[from],buf[from-1],buf[from-2],buf[from-3]) for (i=0;i=3;i=i-4) print_four_bits(i); printf("\n"); for (i=0;i=0;i--) { printf(" 0x%1x ", 0xf & (value >> (i*4))); } printf("\n"); } int intel_gmch_probe(unsigned int gpu_devid) { uint16_t gmch_ctrl, snb_gmch_ctrl; uint32_t gtt_base; pci_read_config_word(2, SNB_GMCH_CTRL, snb_gmch_ctrl); //chv_get_stolen_size gmch_ctrl = snb_gmch_ctrl; gmch_ctrl >>= SNB_GMCH_GMS_SHIFT; gmch_ctrl &= SNB_GMCH_GMS_MASK; /* * 0x0 to 0x10: 32MB increments starting at 0MB * 0x11 to 0x16: 4MB increments starting at 8MB * 0x17 to 0x1d: 4MB increments start at 36MB */ if (gmch_ctrl < 0x11) stolen_size = gmch_ctrl << 25; else if (gmch_ctrl < 0x17) stolen_size = (gmch_ctrl - 0x11 + 2) << 22; else stolen_size = (gmch_ctrl - 0x17 + 9) << 22; /* Read Graphics Base of Stolen Memory directly */ pci_read_config_dword(2, 0x5c, stolen_base); stolen_base &= ~((1<<20) - 1); /* get GTT size */ //chv_get_total_gtt_size gmch_ctrl = snb_gmch_ctrl; gmch_ctrl >>= SNB_GMCH_GGMS_SHIFT; gmch_ctrl &= SNB_GMCH_GGMS_MASK; if (is_gen7) gtt_size = 1<<20; if (is_gen8) { if (gmch_ctrl) gtt_size = 1 << (20 + gmch_ctrl); } gtt_mapable_size = (gtt_size/8)*4096; /* Read Graphics Translate Talbe Base */ pci_read_config_dword(2, 0x70, gtt_base); gtt_base &= ~((1<<20) - 1); printf("Stolen size =%dK (physical base=[0x%x~0x%x](%dM~%dM))\n", stolen_size/1024, stolen_base, stolen_base+stolen_size, stolen_base>>20, (stolen_base+stolen_size)>>20); printf("GTT size = %dK (Can map %dM memory), location at 0x%x (%dM)\n", gtt_size/1024, gtt_mapable_size>>20, gtt_base, gtt_base>>20); return 0; } unsigned int check_deviceid(void) { switch (devid) { case 0x0152: case 0x0162: case 0x0156: case 0x0166: case 0x015a: case 0x016a: is_gen7 = 1; printf("Found Ivybridge(GEN7)\n"); return devid; case 0x0a06: case 0x0a16: case 0x0a26: case 0x0d06: case 0x0d16: case 0x0d26: is_gen7 = 1; printf("Found Haswell(GEN7)\n"); return devid; case 0x22b0: case 0x22b1: case 0x22b2: case 0x22b3: is_gen8 = 1; printf("Found CherryView(GEN8)\n"); return devid; } return 0; } /* 00:02.0 Class 0300: Device 8086:22b0 (rev 14) Subsystem: Device 8086:7270 Flags: bus master, fast devsel, latency 0, IRQ 133 Memory at 90000000 (64-bit, non-prefetchable) [size=16M] Memory at 80000000 (64-bit, prefetchable) [size=256M] I/O ports at 1000 [size=64] Expansion ROM at [disabled] Capabilities: [d0] Power Management version 2 Capabilities: [90] MSI: Enable+ Count=1/1 Maskable- 64bit- Capabilities: [b0] Vendor Specific Information: Len=07 Kernel driver in use: i915 */ static int setup_devmem(void) { uint32_t value_dw0; /* the first DWORD of PCI config */ int fd=devmem_fd, mmio_size; /* Allow read/write to ALL io ports */ ioperm(0, 1024, 1); iopl(3); /* get the physical mmio address */ value_dw0 = pci_get_long(0,(2<<3),0/*PCI_DEVICE_ID*/); devid = (value_dw0 >> 16) & 0xffff; /* byte 2/3 is device ID */ if (check_deviceid() == 0) { fprintf(stderr,"Chip id=0x%x,not supported,exit\n",devid); return 1; } /* pci base0: mmio/gtt * pci base2: aperture */ phy_mmio = pci_get_long(0,2<<3, PCI_BASE_ADDRESS_0); printf("MMADR: PCI base0 for MMIO/GTT is 0x%08x\n", phy_mmio); phy_fb = pci_get_long(0,2<<3, PCI_BASE_ADDRESS_2); printf("GMADR: PCI base2 for Aperture is 0x%08x\n", phy_fb); phy_mmio &= ~4095; phy_fb &= ~4095; /* map mmio/gtt to user space */ if (is_gen7) mmio_size = 2 << 20; if (is_gen8) mmio_size = 8 << 20; linear_mmio = (unsigned char *)mmap64(NULL, mmio_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, phy_mmio); linear_gtt = (unsigned char *)mmap64(NULL, mmio_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, phy_mmio + mmio_size); if ((linear_mmio == MAP_FAILED) || (linear_gtt == MAP_FAILED)) { fprintf(stderr, "Mapping mmio or gtt address 0x%x failed, reason %s\n", phy_mmio, strerror(errno)); fprintf(stderr, "Please try \"nopat\" in kernel boot command line?\n"); return 1; } /* map frame buffer to user space */ linear_fb = (unsigned char *)mmap64(NULL,FB_MMAP_MB<<20, PROT_READ|PROT_WRITE, MAP_SHARED, fd, phy_fb); if (linear_fb == MAP_FAILED) { fprintf(stderr, "Mapping framebuffer address 0x%x failed, reason %s\n", phy_fb, strerror(errno)); return 1; } intel_gmch_probe(devid); unsigned char dummy[16]; lseek(fd, 0x1000000, SEEK_SET); /* kernel code address */ if (read(fd, dummy, 16) == -1) { fprintf(stderr, "CONFIG_STRICT_DEVMEM is enabled and system RAM dump is disabled\n"); devmem_strict = 1; } return 0; } static int process_exit(char *cmdhdr) { exit(0); return 0; } static int process_help(char *cmdhdr) { printf("igdbg -v -d -c \n"); printf(" Device by defalt is /dev/mem which may forbit RAM dump due to kernel CONFIG_STRICT_DEVMEM\n"); printf(" Kernel module in linux/ provide a similar /dev/mem which is not restricted by STRICT_DEVMEM kernel config \n"); printf(" Command is a single command which is executed immediately. Without it, it will display a prompt to enter the command\n"); printf(" Command list\n"); printf(" exit: exit igdbg\n"); printf(" help: dump this help infomation\n"); printf(" verbose: verbose display\n"); printf(" irq