diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 668dbe8..d62b72e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -35,6 +35,10 @@ #include #include #include +#include +#include +#include + #define TTM_BO_VM_NUM_PREFAULT 16 @@ -69,6 +73,142 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup_rb(struct ttm_bo_device *bdev, return best_bo; } +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]); +} static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct ttm_buffer_object *bo = (struct ttm_buffer_object *) @@ -183,10 +323,12 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } else if (unlikely(!page)) { break; } - pfn = page_to_pfn(page); + pfn = page_to_pfn(page, pfn, 0); } - + printk(KERN_INFO "iomem?:%d\n", iomem); + print_pte(vma, "before", page, pfn, 0); ret = vm_insert_mixed(vma, address, pfn); + print_pte(vma, "after", page, pfn, address); /* * Somebody beat us to this PTE or prefaulting to * an already populated PTE, or prefaulting error.