0e5c9f39f6
I don't think we need to call hugetlb_clean_stale_pgtable() anymore in 2.6.13 because of the rework with free_pgtables(). It now collect all the pte page at the time of munmap. It used to only collect page table pages when entire one pgd can be freed and left with staled pte pages. Not anymore with 2.6.13. This function will never be called and We should turn it into a BUG_ON. I also spotted two problems here, not Adam's fault :-) (1) in huge_pte_alloc(), it looks like a bug to me that pud is not checked before calling pmd_alloc() (2) in hugetlb_clean_stale_pgtable(), it also missed a call to pmd_free_tlb. I think a tlb flush is required to flush the mapping for the page table itself when we clear out the pmd pointing to a pte page. However, since hugetlb_clean_stale_pgtable() is never called, so it won't trigger the bug. Signed-off-by: Ken Chen <kenneth.w.chen@intel.com> Cc: Adam Litke <agl@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
147 lines
4.2 KiB
C
147 lines
4.2 KiB
C
#ifndef _I386_PAGE_H
|
|
#define _I386_PAGE_H
|
|
|
|
/* PAGE_SHIFT determines the page size */
|
|
#define PAGE_SHIFT 12
|
|
#define PAGE_SIZE (1UL << PAGE_SHIFT)
|
|
#define PAGE_MASK (~(PAGE_SIZE-1))
|
|
|
|
#define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
|
|
#define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
|
|
|
|
#ifdef __KERNEL__
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <linux/config.h>
|
|
|
|
#ifdef CONFIG_X86_USE_3DNOW
|
|
|
|
#include <asm/mmx.h>
|
|
|
|
#define clear_page(page) mmx_clear_page((void *)(page))
|
|
#define copy_page(to,from) mmx_copy_page(to,from)
|
|
|
|
#else
|
|
|
|
/*
|
|
* On older X86 processors it's not a win to use MMX here it seems.
|
|
* Maybe the K6-III ?
|
|
*/
|
|
|
|
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
|
|
#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
|
|
|
|
#endif
|
|
|
|
#define clear_user_page(page, vaddr, pg) clear_page(page)
|
|
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
|
|
|
|
#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
|
|
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
|
|
|
|
/*
|
|
* These are used to make use of C type-checking..
|
|
*/
|
|
extern int nx_enabled;
|
|
#ifdef CONFIG_X86_PAE
|
|
extern unsigned long long __supported_pte_mask;
|
|
typedef struct { unsigned long pte_low, pte_high; } pte_t;
|
|
typedef struct { unsigned long long pmd; } pmd_t;
|
|
typedef struct { unsigned long long pgd; } pgd_t;
|
|
typedef struct { unsigned long long pgprot; } pgprot_t;
|
|
#define pmd_val(x) ((x).pmd)
|
|
#define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
|
|
#define __pmd(x) ((pmd_t) { (x) } )
|
|
#define HPAGE_SHIFT 21
|
|
#else
|
|
typedef struct { unsigned long pte_low; } pte_t;
|
|
typedef struct { unsigned long pgd; } pgd_t;
|
|
typedef struct { unsigned long pgprot; } pgprot_t;
|
|
#define boot_pte_t pte_t /* or would you rather have a typedef */
|
|
#define pte_val(x) ((x).pte_low)
|
|
#define HPAGE_SHIFT 22
|
|
#endif
|
|
#define PTE_MASK PAGE_MASK
|
|
|
|
#ifdef CONFIG_HUGETLB_PAGE
|
|
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
|
|
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
|
|
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
|
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
|
|
#endif
|
|
|
|
#define pgd_val(x) ((x).pgd)
|
|
#define pgprot_val(x) ((x).pgprot)
|
|
|
|
#define __pte(x) ((pte_t) { (x) } )
|
|
#define __pgd(x) ((pgd_t) { (x) } )
|
|
#define __pgprot(x) ((pgprot_t) { (x) } )
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
|
/* to align the pointer to the (next) page boundary */
|
|
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
|
|
|
|
/*
|
|
* This handles the memory map.. We could make this a config
|
|
* option, but too many people screw it up, and too few need
|
|
* it.
|
|
*
|
|
* A __PAGE_OFFSET of 0xC0000000 means that the kernel has
|
|
* a virtual address space of one gigabyte, which limits the
|
|
* amount of physical memory you can use to about 950MB.
|
|
*
|
|
* If you want more physical memory than this then see the CONFIG_HIGHMEM4G
|
|
* and CONFIG_HIGHMEM64G options in the kernel configuration.
|
|
*/
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
/*
|
|
* This much address space is reserved for vmalloc() and iomap()
|
|
* as well as fixmap mappings.
|
|
*/
|
|
extern unsigned int __VMALLOC_RESERVE;
|
|
|
|
extern int sysctl_legacy_va_layout;
|
|
|
|
extern int page_is_ram(unsigned long pagenr);
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#ifdef __ASSEMBLY__
|
|
#define __PAGE_OFFSET (0xC0000000)
|
|
#define __PHYSICAL_START CONFIG_PHYSICAL_START
|
|
#else
|
|
#define __PAGE_OFFSET (0xC0000000UL)
|
|
#define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START)
|
|
#endif
|
|
#define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START)
|
|
|
|
|
|
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
|
|
#define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
|
|
#define MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
|
|
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
|
|
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
|
|
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
|
#ifdef CONFIG_FLATMEM
|
|
#define pfn_to_page(pfn) (mem_map + (pfn))
|
|
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
|
|
#define pfn_valid(pfn) ((pfn) < max_mapnr)
|
|
#endif /* CONFIG_FLATMEM */
|
|
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
|
|
|
|
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
|
|
|
#define VM_DATA_DEFAULT_FLAGS \
|
|
(VM_READ | VM_WRITE | \
|
|
((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
|
|
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#include <asm-generic/page.h>
|
|
|
|
#endif /* _I386_PAGE_H */
|