Index: linux-2.6.18-mm3/arch/ia64/kernel/ivt.S =================================================================== --- linux-2.6.18-mm3.orig/arch/ia64/kernel/ivt.S 2006-10-10 17:52:26.824631601 -0700 +++ linux-2.6.18-mm3/arch/ia64/kernel/ivt.S 2006-10-10 19:10:40.295621762 -0700 @@ -443,19 +443,64 @@ ENTRY(nested_dtlb_miss) movl r22=(1< + // 1 256k + // 2 1M + // 3 4M + // 4 16M + // 5 64M + // 6 256M + // 7 1GB + ;; + mov r21=IA64_VKP_FIRST_SIZE-2 + extr r22=r16,IA64_RGN_MAP_SHIFT,3 // Get page size bits srlz.d - LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + LOAD_PHYSICAL(p0, r19, sizes_pg_dir) // And the right pg dir ;; -nested_dtlb: - // r17 = region - // r18 = page size (and ITIR is set to that size) - // r16 = faulting address - // r19 = pgd pointer + dep r19=r22,r19,PAGE_SHIFT-3,3 // Fix up pgd to point to subsection + dep r16=0,r16,IA64_RGN_MAP_SHIFT,3 // Clear page size bits + ;; + shladd r22=r22,1,r21 // KVP_INDEX_TO_SHIFT(...) + ;; + dep r18=r22,r18,2,6 // Fix up itir + ;; + mov cr.itir=r18 // Set new page size + ;; + mov r18=r22 // page size + ;; + add r22=-PAGE_SHIFT,r18 // page order + ;; + add r18=PGDIR_SHIFT-PAGE_SHIFT,r18 + shr.u r22=r16,r22 // page number within region + ;; + shr.u r18=r16,r18 // Calculate PGD offset + mov r21=r0 // Make sure test succeeds + ;; + dep r17=r18,r19,3,(PAGE_SHIFT-6) // r17=pgd_offset for region 5 + br.cond.spnt.many nested_dtlb // Continue +kernel_pgd: + srlz.d + LOAD_PHYSICAL(p0, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + ;; +default_pagesize: + extr.u r18=r18,2,6 // get the faulting page size + ;; add r22=-PAGE_SHIFT,r18 // page order ;; add r18=PGDIR_SHIFT-PAGE_SHIFT+3,r18 // Compensated shift for r21 @@ -463,13 +508,14 @@ nested_dtlb: ;; shr.u r18=r21,r18 (p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place - + ;; .pred.rel "mutex", p6, p7 (p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT (p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 - ;; (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5 (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4] + ;; +nested_dtlb: cmp.eq p7,p6=0,r21 // unused address bits all zeroes? #ifdef CONFIG_PGTABLE_4 shr.u r18=r22,PUD_SHIFT // shift pud index into position @@ -500,49 +546,6 @@ nested_dtlb: br.sptk.many b0 // return to continuation point END(nested_dtlb_miss) - // We vary the page size depending on the 3 bits above those - // used for the mapping. - // - // The following page sizes are possible. Each supports a 128TB of - // address spaces - // - // PS-Bits Pagesize - // 0 - // 1 256k - // 2 1M - // 3 4M - // 4 16M - // 5 64M - // 6 256M - // 7 1GB - // - // Input - // r18 = ITIR - // Output - // r18 = page size - // -ENTRY(vary_pagesize) - cmp.eq p6,p7=4,r17 // Huge region? -(p7) br.cond.spnt page_fault // Hmm... illegal address... - ;; - mov r21=IA64_VKP_FIRST_SIZE - 2 - extr r22=r16,IA64_RGN_MAP_SHIFT,3 // Get page size bits - srlz.d - LOAD_PHYSICAL(p0, r19, sizes_pg_dir) - ;; - dep r16=0,r16,IA64_RGN_MAP_SHIFT,3 // Clear page size bits in r16 - ;; - shladd r22=r22,1,r21 // KVP_INDEX_TO_SHIFT(...) - ;; - dep r18=r22,r18,2,6 // Fix up itir - ;; - mov cr.itir=r18 // Set new page size - ;; - mov r18=r22 // r18 must have page size on return - shl r21=r16,3 // realign r21. - br.cond.spnt.many nested_dtlb // Continue -END(vary_pagesize) - .org ia64_ivt+0x1800 ///////////////////////////////////////////////////////////////////////////////////////// // 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24) Index: linux-2.6.18-mm3/include/asm-ia64/pgtable.h =================================================================== --- linux-2.6.18-mm3.orig/include/asm-ia64/pgtable.h 2006-10-10 17:52:29.833235246 -0700 +++ linux-2.6.18-mm3/include/asm-ia64/pgtable.h 2006-10-10 18:45:01.232511829 -0700 @@ -179,7 +179,7 @@ #define VKP_VALID(addr) (REGION_NUMBER(addr) == RGN_HPAGE && VKP_ADDR_TO_INDEX(addr)) -#define pgd_offset_vkp(addr) (sizes_pg_dir +\ +#define pgd_offset_vkp(addr) (sizes_pg_dir + (VKP_ADDR_TO_INDEX(addr) << (PAGE_SHIFT-6)) +\ ((VKP_ADDR_TO_OFFSET(addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))) #ifdef CONFIG_VIRTUAL_MEM_MAP_HUGE