Messages in this thread Patch in this message | | | Date | Fri, 3 Jan 1997 14:43:57 +0100 (MET) | From | Ingo Molnar <> | Subject | XFree86,DGA,XQuake and Pentium 4MB pages, patch |
| |
the following patch is a (broken) way of using Pentium 4MB pages in user-space, for accessing memory-mapped framebuffers with one TLB entry. It should definitely crash when doing an mmunmap() on /dev/mem, but there is a (slight) chance that it works after XFree86+DGA+mmap("/dev/mem")+ xquake starts up.
BIG FAT WARNING:
missing the apropriate videocard i couldnt give this any testing, other than compiling it ... this pre-pre-pre-pre-patch against 2.1.20 is only intended for 4MB framebuffer cards. It might work for smaller cards too, if you remove the size checking.
this should cut down on TLB misses greatly btw. Dont know if it makes any difference.
flames ('it's already done','makes no sense'), comments ('it makes no difference','crashes') welcome,
Ingo
-------- patch starts in the next line --------> --- linux/drivers/char/mem.c.original Fri Jan 3 13:25:53 1997 +++ linux/drivers/char/mem.c Fri Jan 3 14:29:26 1997 @@ -112,6 +112,53 @@ */ if (x86 > 3 && offset >= __pa(high_memory)) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; + /* + * look for possible 4MB pages optimization. FIXME: this is a hack. + * + * the MMU part of it is very i386 specific + * + * it should crash hard in do_munmap(). [because do_munmap() assumes there + * is a page directory for this entry, and we cannot fix this even with + * the usage of mpnt->vm_ops->unmap()]. + */ + if (x86_capability & 8) { + unsigned long address, size = vma->vm_end-vma->vm_start; + pgd_t * dir; + + /* + * currently just for cards with exactly 4MB frame buffer. + * FIXME: N*4M support, and possible support for other sizes too. + */ + if (size != 4*1024*1024) { + printk("FIXME: probably a non 4M frame buffer.\n"); + return -ENXIO; + } + + /* + * get the appropriate root page directory entry + */ + dir = pgd_offset(current->mm, vma->vm_start); + + /* + * write the physical offset into it + */ + address = (offset >> (PAGE_SHIFT-2)) & 4*(PTRS_PER_PTE - 1); + + __asm__("movl %%cr4,%%eax\n\t" + "orl $16,%%eax\n\t" + "movl %%eax,%%cr4" + : : :"ax"); + + pgd_val(*dir) = _PAGE_TABLE + _PAGE_4M + __pa(address); + + /* + * lazyness rulez. overdoing TLB flush, and doing no error checking + */ + flush_tlb_all(); + vma->vm_inode = inode; + inode->i_count++; + return 0; + } #endif if (remap_page_range(vma->vm_start, offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN;
| |