diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-03-09 14:26:03 +0000 |
---|---|---|
committer | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-03-09 14:26:03 +0000 |
commit | 8a477e509cd8e32ce7a5a2bc40c0e7f4bdb16cb7 (patch) | |
tree | 7c8352feb183164a75ce0916b550e36f4e95ae37 | |
parent | 821c383710943623e59b9f9779f2e4914f433c71 (diff) |
ttm: Check for invalid pfns while doing backdoor mapping.
-rw-r--r-- | linux-core/drm_pci.c | 2 | ||||
-rw-r--r-- | linux-core/drm_vm.c | 27 |
2 files changed, 19 insertions, 10 deletions
diff --git a/linux-core/drm_pci.c b/linux-core/drm_pci.c index dd9b0c8c2..c94d4d05b 100644 --- a/linux-core/drm_pci.c +++ b/linux-core/drm_pci.c @@ -39,6 +39,8 @@ #include <linux/pci.h> #include "drmP.h" +#define DRM_DEBUG_MEMORY 0 + /**********************************************************************/ /** \name PCI memory */ /*@{*/ diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 3a8cbe571..eec76af40 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -100,7 +100,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, } map = ((drm_map_list_t *) hash_val)->map; -#if DRM_LIST +#ifdef DRM_LIST list_for_each(list, &dev->maplist->head) { r_list = list_entry(list, drm_map_list_t, head); map = r_list->map; @@ -226,10 +226,21 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, #ifdef TTM_BACKDOOR if (page_flags & DRM_TTM_PAGE_UNCACHED) { + unsigned long pfn; + BUG_ON(!page); aper_loc = ttm->aperture_base + (page_flags & DRM_TTM_MASK_PFN); - page = pfn_to_page(aper_loc >> PAGE_SHIFT); + pfn = aper_loc >> PAGE_SHIFT; + + if (!pfn_valid(pfn)) { + DRM_ERROR("Invalid page encountered while trying to " + "map backdoor ttm page.\n"); + return NOPAGE_SIGBUS; + } + + page = pfn_to_page(pfn); + if (PageAnon(page)) { DRM_ERROR("Anonymous page trying to map aperture " "at 0x%08lx\n", (unsigned long) aper_loc); @@ -237,7 +248,6 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, } } #endif - if (!page) { page = ttm->pages[page_offset] = alloc_page(GFP_USER); @@ -245,12 +255,6 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, if (!page) return NOPAGE_OOM; - if (PageAnon(page)) { - DRM_ERROR("Anonymous page trying to map memory page " - "at pfn 0x%08lx\n", page_to_pfn(page) ); - return NOPAGE_SIGBUS; - } - SetPageLocked(page); get_page(page); @@ -272,6 +276,9 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, #endif } vma->vm_page_prot = default_prot; + + + return page; } @@ -788,7 +795,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) } map = ((drm_map_list_t *) hash_val)->map; -#if DRM_LIST +#ifdef DRM_LIST /* A sequential search of a linked list is fine here because: 1) there will only be |