--- arch/i386/kernel/vmlinux.lds | 45 +++++++++++++++++++++++++++++++++++++- arch/i386/kernel/vmlinux.lds.S | 4 +++ include/asm-generic/vmlinux.lds.h | 8 ++++++ include/asm-i386/highmem.h | 4 +++ include/asm-i386/pgtable.h | 32 +++++++++++++-------------- include/linux/mm.h | 4 ++- 6 files changed, 79 insertions(+), 18 deletions(-) Index: linux-2.6/arch/i386/kernel/vmlinux.lds =================================================================== --- linux-2.6.orig/arch/i386/kernel/vmlinux.lds 2007-09-20 22:11:33.000000000 -0700 +++ linux-2.6/arch/i386/kernel/vmlinux.lds 2007-09-20 22:49:10.000000000 -0700 @@ -149,6 +149,13 @@ /* Don't touch these, unless you really know what you're doing. */ /* Internal svga startup constants */ /* Physical address where kernel should be loaded. */ +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ /* * The Linux memory management assumes a three-level page table setup. On * the i386, we use that, but "fold" the mid level into the top-level page @@ -158,6 +165,42 @@ * This file contains the functions and defines necessary to modify and use * the i386 page table tree. */ +/* + * highmem.h: virtual kernel memory mappings for high memory + * + * Used in CONFIG_HIGHMEM systems for memory pages which + * are not addressable by direct kernel virtual addresses. + * + * Copyright (C) 1999 Gerhard Wichert, Siemens AG + * Gerhard.Wichert@pdb.siemens.de + * + * + * Redesigned the x86 32-bit VM architecture to deal with + * up to 16 Terabyte physical memory. With current x86 CPUs + * we now support up to 64 Gigabytes physical RAM. + * + * Copyright (C) 1999 Ingo Molnar + */ +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +/* + * Ordering is: + * + * FIXADDR_TOP + * fixed_addresses + * FIXADDR_START + * temp fixed addresses + * FIXADDR_BOOT_START + * Persistent kmap area + * PKMAP_BASE + * VMALLOC_END + * Vmalloc area + * VMALLOC_START + * high_memory + */ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(phys_startup_32) @@ -324,5 +367,5 @@ SECTIONS } .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } .debug 0 : { *(.debug) } .line 0 : { *(.line) } .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } - .vmalloc : AT(VMALLOC_START) { __vmalloc_start = . . = VMALLOC_END __vmalloc_end = . } + .vmalloc : AT((((unsigned long) high_memory + 2*(8*1024*1024)-1) & ~((8*1024*1024)-1))) { __vmalloc_start = . . = (( (FIXADDR_BOOT_START - (1UL << 12)*(1024 + 1)) & PMD_MASK )-2*(1UL << 12)) __vmalloc_end = . } } Index: linux-2.6/arch/i386/kernel/vmlinux.lds.S =================================================================== --- linux-2.6.orig/arch/i386/kernel/vmlinux.lds.S 2007-09-20 19:53:32.000000000 -0700 +++ linux-2.6/arch/i386/kernel/vmlinux.lds.S 2007-09-20 22:24:12.000000000 -0700 @@ -21,6 +21,8 @@ #include #include #include +#include +#include OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) @@ -210,4 +212,6 @@ SECTIONS STABS_DEBUG DWARF_DEBUG + + VMALLOC_SECTION } Index: linux-2.6/include/asm-generic/vmlinux.lds.h =================================================================== --- linux-2.6.orig/include/asm-generic/vmlinux.lds.h 2007-09-20 19:48:53.000000000 -0700 +++ linux-2.6/include/asm-generic/vmlinux.lds.h 2007-09-20 22:08:47.000000000 -0700 @@ -257,3 +257,11 @@ *(.data.percpu.shared_aligned) \ } \ __per_cpu_end = .; + +#define VMALLOC_SECTION \ + .vmalloc : AT(VMALLOC_START) { \ + __vmalloc_start = . \ + . = VMALLOC_END \ + __vmalloc_end = . \ + } + Index: linux-2.6/include/asm-i386/highmem.h =================================================================== --- linux-2.6.orig/include/asm-i386/highmem.h 2007-09-20 22:24:46.000000000 -0700 +++ linux-2.6/include/asm-i386/highmem.h 2007-09-20 22:42:29.000000000 -0700 @@ -20,6 +20,7 @@ #ifdef __KERNEL__ +#ifndef LOAD_OFFSET #include #include #include @@ -32,6 +33,7 @@ extern unsigned long highstart_pfn, high extern pte_t *kmap_pte; extern pgprot_t kmap_prot; extern pte_t *pkmap_page_table; +#endif /* * Right now we initialize only a single pte table. It can be extended @@ -63,6 +65,7 @@ extern pte_t *pkmap_page_table; #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) +#ifndef LOAD_OFFSET extern void * FASTCALL(kmap_high(struct page *page)); extern void FASTCALL(kunmap_high(struct page *page)); @@ -79,6 +82,7 @@ struct page *kmap_atomic_to_page(void *p #endif #define flush_cache_kmaps() do { } while (0) +#endif #endif /* __KERNEL__ */ Index: linux-2.6/include/asm-i386/pgtable.h =================================================================== --- linux-2.6.orig/include/asm-i386/pgtable.h 2007-09-20 22:25:53.000000000 -0700 +++ linux-2.6/include/asm-i386/pgtable.h 2007-09-20 22:48:52.000000000 -0700 @@ -2,6 +2,22 @@ #define _I386_PGTABLE_H +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_OFFSET (8*1024*1024) +#define VMALLOC_START (((unsigned long) high_memory + \ + 2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1)) +#ifdef CONFIG_HIGHMEM +# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) +#else +# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) +#endif + /* * The Linux memory management assumes a three-level page table setup. On * the i386, we use that, but "fold" the mid level into the top-level page @@ -71,22 +87,6 @@ void paging_init(void); #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT) #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS) -/* Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define VMALLOC_START (((unsigned long) high_memory + \ - 2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1)) -#ifdef CONFIG_HIGHMEM -# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) -#else -# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) -#endif - /* * _PAGE_PSE set in the page directory entry just means that * the page directory entry points directly to a 4MB-aligned block of Index: linux-2.6/include/linux/mm.h =================================================================== --- linux-2.6.orig/include/linux/mm.h 2007-09-20 19:40:17.000000000 -0700 +++ linux-2.6/include/linux/mm.h 2007-09-20 19:53:02.000000000 -0700 @@ -1174,8 +1174,10 @@ static inline unsigned long vma_pages(st static inline int is_vmalloc_addr(const void *x) { unsigned long addr = (unsigned long)x; + extern unsigned long __vmalloc_start; + extern unsigned long __vmalloc_end; - return addr >= VMALLOC_START && addr < VMALLOC_END; + return addr >= __vmalloc_start && addr < __vmalloc_end; } static inline void *page_to_addr(struct page *page)