Index: linux-2.6.21-rc5-mm2/arch/ia64/Kconfig =================================================================== --- linux-2.6.21-rc5-mm2.orig/arch/ia64/Kconfig 2007-03-31 23:00:40.000000000 -0700 +++ linux-2.6.21-rc5-mm2/arch/ia64/Kconfig 2007-03-31 23:01:15.000000000 -0700 @@ -350,6 +350,10 @@ config ARCH_SPARSEMEM_ENABLE def_bool y depends on ARCH_DISCONTIGMEM_ENABLE +config SPARSE_VIRTUAL + def_bool y + depends on ARCH_SPARSEMEM_ENABLE + config ARCH_DISCONTIGMEM_DEFAULT def_bool y if (IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) depends on ARCH_DISCONTIGMEM_ENABLE Index: linux-2.6.21-rc5-mm2/arch/ia64/kernel/ivt.S =================================================================== --- linux-2.6.21-rc5-mm2.orig/arch/ia64/kernel/ivt.S 2007-03-31 23:00:40.000000000 -0700 +++ linux-2.6.21-rc5-mm2/arch/ia64/kernel/ivt.S 2007-03-31 23:39:24.000000000 -0700 @@ -388,12 +388,28 @@ ENTRY(alt_dtlb_miss) (p8) br.cond.dptk dtlb_fault #endif cmp.ge p10,p11=r16,r24 // access to per_cpu_data? + tbit.nz p6,p7=r16,59 // Access to VMEMMAP? tbit.z p12,p0=r16,61 // access to region 6? mov r25=PERCPU_PAGE_SHIFT << 2 mov r26=PERCPU_PAGE_SIZE - nop.m 0 - nop.b 0 ;; + // + // VMemmap lookup of the granule + // +(p6) extr r25=r16, IA64_GRANULE_SHIFT, 32 + LOAD_PHYSICAL(p6, r26, vmemmap_table) + ;; +(p6) shl r25=r25,2 + ;; +(p6) add r26=r26,r25 // Index into vmemmap table + ;; +(p6) ld4 r25=[r26] // Get 32 bit descriptor */ + ;; +(p6) shl r19=r25, 12 // Shift to ppn field +(p6) tbit.z p7,p11=r25, 31 // Present bit set? +(p7) br.cond.dptk page_fault // Page not present + ;; + .pred.rel "mutex", p11, p10 (p10) mov r19=IA64_KR(PER_CPU_DATA) (p11) and r19=r19,r16 // clear non-ppn fields extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl Index: linux-2.6.21-rc5-mm2/arch/ia64/mm/discontig.c =================================================================== --- linux-2.6.21-rc5-mm2.orig/arch/ia64/mm/discontig.c 2007-03-31 23:00:40.000000000 -0700 +++ linux-2.6.21-rc5-mm2/arch/ia64/mm/discontig.c 2007-03-31 23:22:12.000000000 -0700 @@ -44,6 +44,57 @@ struct early_node_data { unsigned long max_pfn; }; +#ifdef CONFIG_SPARSE_VIRTUAL +#define PAGE_STRUCT_SHIFT 6 + +/* + * The vmemmap_table contains the number of the granule used to map + * that section of the virtual memmap. + * + * We support 50 address bits, 14 bits are used for the page size this + * leaves 36 bits (64G) for the pfn. Using page structs this is going to + * take around 4TB. + * + * We are mapping these 4 TB using 16M granule size which makes us end up + * less than 256k entries. + * + * Thus the common size of the needed vmemmap_table will be less than 1M. + */ + +#define VMEMMAP_SIZE ((1UL << (MAX_PHYSMEM_BITS - PAGE_SHIFT)) \ + * sizeof(struct page)) + +/* + * Each vmemma_table entry describes a 16M block of memory. We have + * 32 bit here and use one bit to indicate that a page is present. + * That means 31 + 24 = 55 bits which is larger than + * the maximum memory (1 petabyte) supported by IA64. + */ + +#define VMEMMAP_PRESENT (1UL << 31) +u32 vmemmap_table[ALIGN(VMEMMAP_SIZE, IA64_GRANULE_SIZE)]; + +void vmemmap_populate(struct page *start, unsigned long nr, int node) +{ + unsigned addr = GRANULEROUNDDOWN((unsigned long)start); + unsigned end = GRANULEROUNDUP((unsigned long)(start + nr)); + + BUG_ON(sizeof(struct page) > (1 << PAGE_STRUCT_SHIFT)); + + for(; addr < end; addr += IA64_GRANULE_SIZE) { + u32 *vmem_pp = + vmemmap_table + (addr >> IA64_GRANULE_SHIFT); + + if (*vmem_pp & VMEMMAP_PRESENT) + continue; + + *vmem_pp = VMEMMAP_PRESENT | + (__pa(vmemmap_alloc_block(IA64_GRANULE_SIZE, node)) + >> IA64_GRANULE_SHIFT); + } +} +#endif + static struct early_node_data mem_data[MAX_NUMNODES] __initdata; static nodemask_t memory_less_mask __initdata; Index: linux-2.6.21-rc5-mm2/include/asm-ia64/page.h =================================================================== --- linux-2.6.21-rc5-mm2.orig/include/asm-ia64/page.h 2007-03-31 23:00:40.000000000 -0700 +++ linux-2.6.21-rc5-mm2/include/asm-ia64/page.h 2007-03-31 23:01:15.000000000 -0700 @@ -98,6 +98,9 @@ do { \ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE +#define ARCH_POPULATES_VIRTUAL_MEMMAP +#define vmemmap ((struct page *)(RGN_BASE(RGN_KERNEL) + (1UL << 59))) + #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #ifdef CONFIG_VIRTUAL_MEM_MAP