diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fba37e9..cfcaafd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -33,6 +33,8 @@ #include "intel_drv.h" #include #include +#include +#include #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) @@ -1145,6 +1147,143 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, return 0; } +void print_pte(struct vm_area_struct *vma, char *what, struct page *page, unsigned int pfn, unsigned long address) +{ + static const char * const level_name[] = + { "NONE", "4K", "2M", "1G", "NUM" }; + unsigned long addr = 0; + pte_t *pte = NULL; + pteval_t val = (pteval_t)0; + unsigned int level = 0; + unsigned offset; + unsigned long phys; + pgprotval_t prot; + char buf[90]; + char *str; + + str = buf; + // Figure out if the address is pagetable. + if (address == 0 && !page && pfn>0) { + page = pfn_to_page(pfn); + } + if (address == 0 && page) + addr = (u64)page_address(page); + + if (address && !page) + addr = address; + + if (address && page) { + addr = (u64)page_address(page); + if (address != addr) { + if (addr == 0) { + str += sprintf(str, "addr(page)==0"); + addr = address; + } + } + } + + if (pfn != 0 && page) { + if (pfn != page_to_pfn(page)) // Gosh!? + str += sprintf(str, "pfn!=pfn(page)"); + } + if (pfn != 0 && addr != 0) { + if (pfn != virt_to_pfn(addr)) + str += sprintf(str,"pfn(addr)!=pfn"); + } + pte = lookup_address(addr, &level); + if (!pte) { + str += sprintf(str,"!pte(addr)"); + goto print; + } + offset = addr & ~PAGE_MASK; + + if (xen_domain()) { + phys = (pte_mfn(*pte) << PAGE_SHIFT) + offset; + val = pte_val_ma(*pte); + + if (pfn > 0) { + if (pte_mfn(*pte) == pfn) { + if (vma->vm_flags && VM_IO) + str += sprintf(str,"PHYS"); + else + str += sprintf(str,"BUG: VM_IO not set!"); + } + /* It is a pseudo page ... and the VM_IO flag is set */ + if (pte_mfn(*pte) != pfn) { + if (vma->vm_flags && VM_IO) + str += sprintf(str,"BUG: VM_IO flag set!"); + else + str += sprintf(str, "PSEUDO"); + } + } else { + str += sprintf(str,"pfn==0"); + } + + } else { + phys = (pte_pfn(*pte) << PAGE_SHIFT) + offset; + val = pte_val(*pte); + } + prot = pgprot_val(pte_pgprot(*pte)); + + if (!prot) + str += sprintf(str, "Not present."); + else { + if (prot & _PAGE_USER) + str += sprintf(str, "USR "); + else + str += sprintf(str, " "); + if (prot & _PAGE_RW) + str += sprintf(str, "RW "); + else + str += sprintf(str, "ro "); + if (prot & _PAGE_PWT) + str += sprintf(str, "PWT "); + else + str += sprintf(str, " "); + if (prot & _PAGE_PCD) + str += sprintf(str, "PCD "); + else + str += sprintf(str, " "); + + /* Bit 9 has a different meaning on level 3 vs 4 */ + if (level <= 3) { + if (prot & _PAGE_PSE) + str += sprintf(str, "PSE "); + else + str += sprintf(str, " "); + } else { + if (prot & _PAGE_PAT) + str += sprintf(str, "pat "); + else + str += sprintf(str, " "); + } + if (prot & _PAGE_GLOBAL) + str += sprintf(str, "GLB "); + else + str += sprintf(str, " "); + if (prot & _PAGE_NX) + str += sprintf(str, "NX "); + else + str += sprintf(str, "x "); +#ifdef _PAGE_IOMEM + if (prot & _PAGE_IOMEM) + str += sprintf(str, "IO "); + else + str += sprintf(str, " "); +#endif + + } + +print: + printk(KERN_INFO "[%16s]PFN: 0x%lx PTE: 0x%lx (val:%lx): [%s] [%s]\n", + what, + (unsigned long)pfn, + (pte) ? (unsigned long)(pte->pte) : 0, + (unsigned long)val, + buf, + level_name[level]); +} + /** * i915_gem_fault - fault a page into the GTT * vma: VMA in question @@ -1200,8 +1339,10 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + page_offset; + print_pte(vma,"before", NULL, pfn, 0); /* Finally, remap it using the new GTT offset */ ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); + print_pte(vma, "after", NULL, pfn, (unsigned long) vmf->virtual_address); unlock: mutex_unlock(&dev->struct_mutex);