diff -prauN pgcl-2.6.0-test5-bk3-14/arch/i386/kernel/numaq.c pgcl-2.6.0-test5-bk3-15/arch/i386/kernel/numaq.c --- pgcl-2.6.0-test5-bk3-14/arch/i386/kernel/numaq.c 2003-09-14 23:49:19.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-15/arch/i386/kernel/numaq.c 2003-11-27 09:49:44.000000000 -0800 @@ -57,8 +57,20 @@ static void __init smp_dump_qct(void) eq->hi_shrd_mem_start - eq->priv_mem_size); node_end_pfn[node] = MB_TO_PAGES( eq->hi_shrd_mem_start + eq->hi_shrd_mem_size); - } + printk("hi_shrd_mem_start[%d] = 0x%x\n" + "priv_mem_size[%d] = 0x%x\n" + "hi_shrd_mem_size[%d] = 0x%x\n" + "node_start_pfn[%d] = 0x%lx\n" + "node_end_pfn[%d] = 0x%lx\n", + node, eq->hi_shrd_mem_start, + node, eq->priv_mem_size, + node, eq->hi_shrd_mem_size, + node, node_start_pfn[node], + node, node_end_pfn[node]); + } else + printk("node %d not present\n", node); } + printk("%d nodes found in QCT\n", numnodes); } /* diff -prauN pgcl-2.6.0-test5-bk3-14/arch/i386/mm/discontig.c pgcl-2.6.0-test5-bk3-15/arch/i386/mm/discontig.c --- pgcl-2.6.0-test5-bk3-14/arch/i386/mm/discontig.c 2003-09-14 23:49:19.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-15/arch/i386/mm/discontig.c 2003-11-27 09:52:41.000000000 -0800 @@ -62,7 +62,6 @@ unsigned long node_end_pfn[MAX_NUMNODES] extern unsigned long find_max_low_pfn(void); extern void find_max_pfn(void); -extern void one_highpage_init(struct page *, int, int); extern struct e820map e820; extern char _end; @@ -271,6 +270,9 @@ unsigned long __init setup_memory(void) printk("fixmapspace = [0x%lx, 0x%lx)\n", FIXADDR_START, FIXADDR_TOP); printk("MAXMEM = 0x%lx\n", MAXMEM); + for (nid = 0; nid < numnodes; ++nid) + printk("node %d at pfns [0x%lx, 0x%lx)\n", + nid, node_start_pfn[nid], node_end_pfn[nid]); NODE_DATA(0)->bdata = &node0_bdata; @@ -417,10 +419,27 @@ void __init set_highmem_pages_init(int b /* * Note: zone->spanned_pages is in PAGE_SIZE units. */ - for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) + for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) { + if (page_to_pfn(&zone_mem_map[node_pfn]) + != zone_start_pfn + PAGE_MMUCOUNT*node_pfn) { + static int complained_once = 0; + if (!complained_once) { + complained_once = 1; + printk("mismatching page/pfn!!!\n" + "page = %p sees pfn 0x%lx " + "but pfn 0x%lx calculated\n", + &zone_mem_map[node_pfn], + page_to_pfn(&zone_mem_map[node_pfn]), + zone_start_pfn + PAGE_MMUCOUNT*node_pfn); + } + } + if (page_to_pfn(&zone_mem_map[node_pfn])/PAGE_MMUCOUNT + == 0xffd38/PAGE_MMUCOUNT) + printk("saw the bad page!\n"); one_highpage_init(&zone_mem_map[node_pfn], - zone_start_pfn + node_pfn*PAGE_MMUCOUNT, + zone_start_pfn + PAGE_MMUCOUNT*node_pfn, bad_ppro); + } } totalram_pages += totalhigh_pages; #endif diff -prauN pgcl-2.6.0-test5-bk3-14/arch/i386/mm/fault.c pgcl-2.6.0-test5-bk3-15/arch/i386/mm/fault.c --- pgcl-2.6.0-test5-bk3-14/arch/i386/mm/fault.c 2003-11-26 03:26:06.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/arch/i386/mm/fault.c 2003-11-27 07:54:57.000000000 -0800 @@ -4,6 +4,8 @@ * Copyright (C) 1995 Linus Torvalds */ +#define DEBUG + #include #include #include diff -prauN pgcl-2.6.0-test5-bk3-14/arch/i386/mm/highmem.c pgcl-2.6.0-test5-bk3-15/arch/i386/mm/highmem.c --- pgcl-2.6.0-test5-bk3-14/arch/i386/mm/highmem.c 2003-11-25 10:55:02.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/arch/i386/mm/highmem.c 2003-11-27 10:42:28.000000000 -0800 @@ -1,4 +1,5 @@ #include +#include /* * XXX: resurrect kmap_pte @@ -44,17 +45,31 @@ void *kmap_atomic(struct page *page, enu idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_END) + PAGE_SIZE*idx; - WARN_ON(vaddr > __fix_to_virt(FIX_KMAP_BEGIN)); - WARN_ON(vaddr < __fix_to_virt(FIX_KMAP_END)); + BUG_ON(vaddr > __fix_to_virt(FIX_KMAP_BEGIN)); + BUG_ON(vaddr < __fix_to_virt(FIX_KMAP_END)); + pfn = page_to_pfn(page); + if (pfn/PAGE_MMUCOUNT == 0xffd38/PAGE_MMUCOUNT) { + printk("saw bad pfn in kmap_atomic()!\n"); + BUG(); + } + addr = vaddr; pgd = pgd_offset_k(addr); pmd = pmd_offset(pgd, addr); + + /* barf on highmem-allocated pagetables */ + BUG_ON((pmd_val(*pmd) >> MMUPAGE_SHIFT) >= max_low_pfn); + pte = pte_offset_kernel(pmd, addr); + for (k = 0; k < PAGE_MMUCOUNT; ++k, addr += MMUPAGE_SIZE) { #ifdef CONFIG_DEBUG_HIGHMEM BUG_ON(!pte_none(pte[k])); #endif + BUG_ON(addr < vaddr); + BUG_ON(addr - vaddr >= PAGE_SIZE); + BUG_ON(!pfn_valid(pfn + k)); if (pte_pfn(pte[k]) == pfn + k) continue; @@ -125,7 +140,7 @@ unsigned long kmap_atomic_to_pfn(void *p void kmap_atomic_sg(pte_t *ptes[], pte_addr_t paddrs[], enum km_type type) { enum fixed_addresses idx; - unsigned long vaddr; + unsigned long vaddr, base; pgd_t *pgd; pmd_t *pmd; pte_t *pte; @@ -133,7 +148,9 @@ void kmap_atomic_sg(pte_t *ptes[], pte_a inc_preempt_count(); idx = type + KM_TYPE_NR*smp_processor_id(); - vaddr = __fix_to_virt(FIX_KMAP_END) + PAGE_SIZE*idx; + base = vaddr = __fix_to_virt(FIX_KMAP_END) + PAGE_SIZE*idx; + BUG_ON(vaddr > __fix_to_virt(FIX_KMAP_BEGIN)); + BUG_ON(vaddr < __fix_to_virt(FIX_KMAP_END)); pgd = pgd_offset_k(vaddr); pmd = pmd_offset(pgd, vaddr); @@ -141,11 +158,16 @@ void kmap_atomic_sg(pte_t *ptes[], pte_a for (k = 0; k < PAGE_MMUCOUNT; ++k, vaddr += MMUPAGE_SIZE) { unsigned long pfn = paddrs[k]/MMUPAGE_SIZE; + BUG_ON(pfn/PAGE_MMUCOUNT == 0xffd38/PAGE_MMUCOUNT); + if (!paddrs[k]) { ptes[k] = NULL; continue; } ptes[k] = (pte_t *)(vaddr + ((u32)paddrs[k] & ~MMUPAGE_MASK)); + BUG_ON(!pfn_valid(pfn)); + BUG_ON((u32)ptes[k] < base); + BUG_ON((u32)ptes[k] - base >= PAGE_SIZE); if (pte_pfn(pte[k]) != pfn) { set_pte(&pte[k], pfn_pte(pfn, kmap_prot)); diff -prauN pgcl-2.6.0-test5-bk3-14/arch/i386/mm/init.c pgcl-2.6.0-test5-bk3-15/arch/i386/mm/init.c --- pgcl-2.6.0-test5-bk3-14/arch/i386/mm/init.c 2003-11-18 05:23:44.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/arch/i386/mm/init.c 2003-11-27 09:51:26.000000000 -0800 @@ -179,7 +179,15 @@ static inline int page_kills_ppro(unsign static inline int page_is_ram(unsigned long pagenr) { - int i; + int i, noise = 0; + unsigned long begin_pfn, end_pfn; + + /* check the whole range of pfn's spanned by the page */ + begin_pfn = pagenr & ~(PAGE_MMUCOUNT - 1); + end_pfn = begin_pfn + PAGE_MMUCOUNT - 1; + + if (begin_pfn <= 0xffd38 && 0xffd38 < end_pfn) + noise = 1; for (i = 0; i < e820.nr_map; i++) { unsigned long addr, end; @@ -191,11 +199,18 @@ static inline int page_is_ram(unsigned l * are not. Notably the 640->1Mb area. We need a sanity * check here. */ - addr = (e820.map[i].addr+MMUPAGE_SIZE-1) >> MMUPAGE_SHIFT; - end = (e820.map[i].addr+e820.map[i].size) >> MMUPAGE_SHIFT; - if ((pagenr >= addr) && (pagenr < end)) + addr = MMUPAGE_ALIGN(e820.map[i].addr)/MMUPAGE_SIZE; + end = (e820.map[i].addr + e820.map[i].size)/MMUPAGE_SIZE; + if (begin_pfn >= addr && end_pfn < end) { + if (noise) { + printk("thought the bad page was good!!!\n"); + printk("addr = 0x%lx, end = 0x%lx\n",addr,end); + } return 1; + } } + if (noise) + printk("properly skipped the bad page\n"); return 0; } @@ -209,7 +224,7 @@ void __init permanent_kmaps_init(pgd_t * page_table_range_init(PKMAP_BASE, PKMAP_BASE + PAGE_SIZE*LAST_PKMAP, pgd_base); } -void __init one_highpage_init(struct page *page, int pfn, int bad_ppro) +void __init one_highpage_init(struct page *page, unsigned long pfn, int bad_ppro) { if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) { ClearPageReserved(page); diff -prauN pgcl-2.6.0-test5-bk3-14/fs/binfmt_elf.c pgcl-2.6.0-test5-bk3-15/fs/binfmt_elf.c --- pgcl-2.6.0-test5-bk3-14/fs/binfmt_elf.c 2003-09-14 23:49:20.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-15/fs/binfmt_elf.c 2003-11-27 06:53:03.000000000 -0800 @@ -9,6 +9,8 @@ * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). */ +#define DEBUG + #include #include #include @@ -103,10 +105,12 @@ static void padzero(unsigned long elf_bs unsigned long nbyte; nbyte = ELF_PAGEOFFSET(elf_bss); + pr_debug("padzero(0x%lx) about to clear %lu bytes\n", elf_bss, nbyte); if (nbyte) { nbyte = ELF_MIN_ALIGN - nbyte; clear_user((void *) elf_bss, nbyte); } + pr_debug("padzero(0x%lx) survived clear %lu bytes\n", elf_bss, nbyte); } /* Let's use some macros to make this stack manipulation a litle clearer */ @@ -291,6 +295,8 @@ static unsigned long load_elf_interp(str unsigned long error = ~0UL; int retval, i, size; + pr_debug("entering load_elf_interp()\n"); + /* First of all, some simple consistency checks */ if (interp_elf_ex->e_type != ET_EXEC && interp_elf_ex->e_type != ET_DYN) @@ -318,11 +324,15 @@ static unsigned long load_elf_interp(str if (!elf_phdata) goto out; + pr_debug("about to kernel_read() interpreter\n"); retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size); + pr_debug("survived kernel_read() of interpreter\n"); + error = retval; if (retval < 0) goto out_close; + pr_debug("about to loop over sections of interpreter\n"); eppnt = elf_phdata; for (i=0; ie_phnum; i++, eppnt++) { if (eppnt->p_type == PT_LOAD) { @@ -364,6 +374,7 @@ static unsigned long load_elf_interp(str last_bss = k; } } + pr_debug("survived looping over sections of interpreter\n"); /* * Now fill out the bss section. First pad the last page up @@ -374,9 +385,11 @@ static unsigned long load_elf_interp(str padzero(elf_bss); elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); /* What we have mapped so far */ + pr_debug("about to do_brk()\n"); /* Map the last of the bss segment */ if (last_bss > elf_bss) do_brk(elf_bss, last_bss - elf_bss); + pr_debug("survived do_brk()\n"); *interp_load_addr = load_addr; error = ((unsigned long) interp_elf_ex->e_entry) + load_addr; @@ -384,6 +397,7 @@ static unsigned long load_elf_interp(str out_close: kfree(elf_phdata); out: + pr_debug("leaving load_elf_interp()\n"); return error; } @@ -460,6 +474,8 @@ static int load_elf_binary(struct linux_ struct elfhdr interp_elf_ex; struct exec interp_ex; char passed_fileno[6]; + + pr_debug("about to load_elf_binary()\n"); /* Get the exec-header */ elf_ex = *((struct elfhdr *) bprm->buf); @@ -728,6 +744,7 @@ static int load_elf_binary(struct linux_ end_data += load_bias; if (elf_interpreter) { + pr_debug("loading interpreter\n"); if (interpreter_type == INTERPRETER_AOUT) elf_entry = load_aout_interp(&interp_ex, interpreter); @@ -748,17 +765,22 @@ static int load_elf_binary(struct linux_ goto out; } reloc_func_desc = interp_load_addr; + pr_debug("finished loading interpreter\n"); } else { + pr_debug("static executable, not loading interpreter\n"); elf_entry = elf_ex.e_entry; } + pr_debug("cleaning up load-time data\n"); kfree(elf_phdata); if (interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); set_binfmt(&elf_format); + pr_debug("finished cleaning up load-time data\n"); + pr_debug("setting up current process structure\n"); compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; create_elf_tables(bprm, &elf_ex, (interpreter_type == INTERPRETER_AOUT), @@ -771,15 +793,21 @@ static int load_elf_binary(struct linux_ current->mm->start_data = start_data; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; + pr_debug("finished setting up current process structure\n"); /* Calling set_brk effectively mmaps the pages that we need * for the bss and break sections */ + pr_debug("about to set up the bss/break sections\n"); set_brk(elf_bss, elf_brk); + pr_debug("finished setting up the bss/break sections\n"); + pr_debug("about to pad the bss with zeros\n"); padzero(elf_bss); + pr_debug("survived padding the bss with zeros\n"); if (current->personality & MMAP_PAGE_ZERO) { + pr_debug("mapping page 0\n"); /* Why this, you ask??? Well SVr4 maps page 0 as read-only, and some applications "depend" upon this behavior. Since we do not have the power to recompile these, we @@ -788,6 +816,7 @@ static int load_elf_binary(struct linux_ error = do_mmap(NULL, 0, MMUPAGE_SIZE, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); up_write(¤t->mm->mmap_sem); + pr_debug("survived mapping page 0\n"); } #ifdef ELF_PLAT_INIT @@ -801,9 +830,12 @@ static int load_elf_binary(struct linux_ * the regs structure is required as well as any relocations to the * function descriptor entries when executing dynamically links apps. */ + pr_debug("about to ELF_PLAT_INIT()\n"); ELF_PLAT_INIT(regs, reloc_func_desc); + pr_debug("survived ELF_PLAT_INIT()\n"); #endif + pr_debug("about to fiddle with threads and ptrace\n"); start_thread(regs, elf_entry, bprm->p); if (unlikely(current->ptrace & PT_PTRACED)) { if (current->ptrace & PT_TRACE_EXEC) @@ -811,8 +843,10 @@ static int load_elf_binary(struct linux_ else send_sig(SIGTRAP, current, 0); } + pr_debug("survived fiddling with threads and ptrace\n"); retval = 0; out: + pr_debug("leaving load_elf_binary()\n"); return retval; /* error cleanup */ @@ -826,6 +860,7 @@ out_free_file: sys_close(elf_exec_fileno); out_free_ph: kfree(elf_phdata); + pr_debug("survived error cleanups, exiting with error\n"); goto out; } diff -prauN pgcl-2.6.0-test5-bk3-14/fs/exec.c pgcl-2.6.0-test5-bk3-15/fs/exec.c --- pgcl-2.6.0-test5-bk3-14/fs/exec.c 2003-11-26 03:46:13.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/fs/exec.c 2003-11-27 06:15:17.000000000 -0800 @@ -22,6 +22,8 @@ * formats. */ +#define DEBUG + #include #include #include diff -prauN pgcl-2.6.0-test5-bk3-14/include/asm-i386/highmem.h pgcl-2.6.0-test5-bk3-15/include/asm-i386/highmem.h --- pgcl-2.6.0-test5-bk3-14/include/asm-i386/highmem.h 2003-11-24 23:32:49.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/include/asm-i386/highmem.h 2003-11-27 09:31:11.000000000 -0800 @@ -33,6 +33,8 @@ extern pte_t *kmap_pte; extern pgprot_t kmap_prot; extern pte_t *pkmap_page_table; +void one_highpage_init(struct page *, unsigned long, int); + void kmap_init(void); void *FASTCALL(kmap_high(struct page *page)); void FASTCALL(kunmap_high(struct page *page)); diff -prauN pgcl-2.6.0-test5-bk3-14/include/asm-i386/pgtable.h pgcl-2.6.0-test5-bk3-15/include/asm-i386/pgtable.h --- pgcl-2.6.0-test5-bk3-14/include/asm-i386/pgtable.h 2003-11-26 16:12:20.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/include/asm-i386/pgtable.h 2003-11-27 11:40:04.000000000 -0800 @@ -394,7 +394,7 @@ do { \ ((pte_addr_t)pte_offset_kernel(pmd, addr)) #endif -#if defined(CONFIG_HIGHMEM64) && defined(CONFIG_HIGHPTE) +#if defined(CONFIG_HIGHMEM64G) && defined(CONFIG_HIGHPTE) typedef u64 pte_addr_t; #else typedef u32 pte_addr_t; diff -prauN pgcl-2.6.0-test5-bk3-14/include/linux/binfmts.h pgcl-2.6.0-test5-bk3-15/include/linux/binfmts.h --- pgcl-2.6.0-test5-bk3-14/include/linux/binfmts.h 2003-09-14 23:49:20.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-15/include/linux/binfmts.h 2003-11-27 06:41:39.000000000 -0800 @@ -15,9 +15,10 @@ struct pt_regs; * PAGE_SIZE exceeds that, we're in trouble. */ #if PAGE_MMUCOUNT <= 32 -#define MAX_ARG_PAGES (32/PAGE_MMUCOUNT) +#define MAX_ARG_PAGES (32/PAGE_MMUCOUNT) #else -#error PAGE_SIZE too large to enforce MAX_ARG_PAGES! +/* #error PAGE_SIZE too large to enforce MAX_ARG_PAGES! */ +#define MAX_ARG_PAGES 1 #endif /* sizeof(linux_binprm->buf) */ diff -prauN pgcl-2.6.0-test5-bk3-14/include/linux/folio.h pgcl-2.6.0-test5-bk3-15/include/linux/folio.h --- pgcl-2.6.0-test5-bk3-14/include/linux/folio.h 2003-11-26 10:01:47.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/include/linux/folio.h 2003-11-27 11:37:16.000000000 -0800 @@ -18,6 +18,11 @@ #if PAGE_MMUSHIFT +#include + +#define bad_paddr_check(__paddr__) \ + BUG_ON(__paddr__/PAGE_SIZE == 0xffd38/PAGE_MMUCOUNT); + /* * Test whether pte2 indicates the same page as pte1. */ @@ -82,6 +87,8 @@ static int prepare_folio(pte_addr_t foli pmd_t *pmd; int reprep = 0; + bad_paddr_check(ptep); + suboffset = vma_suboffset(vma, address); base = (address - suboffset) & MMUPAGE_MASK; subnr = suboffset >> MMUPAGE_SHIFT; @@ -90,8 +97,10 @@ static int prepare_folio(pte_addr_t foli /* First approximation: set full vector of probable pteps */ ptep -= subnr*sizeof(pte_t); - for (j = 0; j < PAGE_MMUCOUNT; j++) + for (j = 0; j < PAGE_MMUCOUNT; j++) { folio[j] = ptep + j*sizeof(pte_t); + bad_paddr_check(folio[j]); + } j = 0; /* Second approximation: wipe pteps which don't belong to vma; @@ -151,8 +160,10 @@ static int prepare_folio(pte_addr_t foli } if (ptep != NOPTE) { for (; j < limit; j++) { - if (folio[j] != NOPTE) + if (folio[j] != NOPTE) { folio[j] = ptep + j*sizeof(pte_t); + bad_paddr_check(folio[j]); + } } } else { for (; j < limit; j++) @@ -177,8 +188,10 @@ static int prepare_folio(pte_addr_t foli if (ptep) { ptep -= PAGE_MMUCOUNT*sizeof(pte_t); for (; j < limit; j++) { - if (folio[j] != NOPTE) + if (folio[j] != NOPTE) { folio[j] = ptep + j*sizeof(pte_t); + bad_paddr_check(folio[j]); + } } } else { for (; j < limit; j++) @@ -223,12 +236,32 @@ static struct page *private_folio_page(p if (swap_page) { swap_pte = mk_pte(swap_page, PAGE_KERNEL); folio[fcount] = &swap_pte; + pr_debug("%d: putting swap_pte = 0x%p at fcount %d\n", + current->pid, &swap_pte, fcount); fcount++; } j = 0; pr_debug("%d: starting fcount = %d\n", current->pid, fcount); while (j < fcount) { + pr_debug("%d: folio[%d] = %p\n", current->pid, j, folio[j]); + if (folio[j]) { + pgd_t *pgd; + pmd_t *pmd; + pgd = pgd_offset_k((u32)folio[j]); + pmd = pmd_offset(pgd, (u32)folio[j]); + +#define pmd_pfn(pmd) ({ (unsigned long)(pmd_val(pmd)/MMUPAGE_SIZE); }) + + if (pmd_pfn(*pmd) >= max_low_pfn) + pr_debug("%d: pmd pfn 0x%lx >= 0x%lx\n", + current->pid,pmd_pfn(*pmd),max_low_pfn); + else { + pte_t*pte=pte_offset_kernel(pmd,(u32)folio[j]); + pr_debug("%d: folio[%d] maps pfn 0x%lx\n", + current->pid, j, pte_pfn(*pte)); + } + } if (!folio[j] || !pte_present(*folio[j])) { pr_debug("%d: skipping folio[%d] = %p (0x%Lx), " "presence = %d\n", @@ -546,7 +579,7 @@ static /* inline */ void flush_folio(pte flush_tlb_range(vma, start, end); } -#if 1 +#ifdef DEBUG_RMAP static inline void __adjust_page_count(const char *file, int line, const char *func, diff -prauN pgcl-2.6.0-test5-bk3-14/include/linux/mm.h pgcl-2.6.0-test5-bk3-15/include/linux/mm.h --- pgcl-2.6.0-test5-bk3-14/include/linux/mm.h 2003-11-26 11:44:20.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/include/linux/mm.h 2003-11-27 06:28:25.000000000 -0800 @@ -254,6 +254,7 @@ int page_truly_private(struct page *, st BUG_ON(page_count(p) <= 0); \ atomic_dec_and_test(&(p)->count); \ }) +#ifdef DEBUG_RMAP #define _put_page_testzero(file, line, func, p) \ ({ \ struct page *__page__ = p; \ @@ -268,6 +269,9 @@ int page_truly_private(struct page *, st page_count_expected(__page__)); \ __put_page_testzero(__page__); \ }) +#else +#define _put_page_testzero(file, line, func, p) __put_page_testzero(p) +#endif #define put_page_testzero(p) \ _put_page_testzero(__FILE__, __LINE__, __FUNCTION__, p) @@ -324,6 +328,7 @@ static inline void __get_page(struct pag * whether to do printk's or not. */ +#ifdef DEBUG_RMAP #define _put_page(file, line, func, p) \ do { \ struct page *__page__ = p; \ @@ -338,11 +343,15 @@ do { \ page_count_expected(__page__)); \ ___put_page(__page__); \ } while (0) +#else +#define _put_page(file, line, func, p) ___put_page(p) +#endif +#ifdef DEBUG_RMAP #define _get_page(file, line, func, p) \ do { \ struct page *__page__ = p; \ - pr_debug("%d: get_page(0x%lx) in %s, %s:%d with " \ + pr_debug("%d: get_page(0x%lx) in %s, %s:%d with " \ "count %d (expected %d)\n", \ current->pid, \ page_to_pfn(__page__), \ @@ -353,6 +362,9 @@ do { \ page_count_expected(__page__)); \ __get_page(__page__); \ } while (0) +#else +#define _get_page(file, line, func, p) __get_page(p) +#endif /* * Wrapper layer for grabbing __FILE__, __LINE__, etc. diff -prauN pgcl-2.6.0-test5-bk3-14/include/linux/pagemap.h pgcl-2.6.0-test5-bk3-15/include/linux/pagemap.h --- pgcl-2.6.0-test5-bk3-14/include/linux/pagemap.h 2003-11-26 03:20:02.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/include/linux/pagemap.h 2003-11-27 06:32:11.000000000 -0800 @@ -49,6 +49,7 @@ static inline void mapping_set_gfp_mask( #define PAGE_CACHE_MMUSHIFT (PAGE_CACHE_SHIFT - MMUPAGE_SHIFT) #define PAGE_CACHE_MMUCOUNT (PAGE_CACHE_SIZE/MMUPAGE_SIZE) +#ifdef DEBUG_RMAP #define __page_cache_get__(file, line, func, pg) \ do { \ struct page *__page__ = pg; \ @@ -63,7 +64,11 @@ do { \ page_count_expected(__page__)); \ __get_page(__page__); \ } while (0) +#else +#define __page_cache_get__(file, line, func, p) __get_page(p) +#endif +#ifdef DEBUG_RMAP #define __page_cache_release__(file, line, func, pg) \ do { \ struct page *__page__ = pg; \ @@ -78,6 +83,9 @@ do { \ page_count_expected(__page__)); \ ___put_page(__page__); \ } while (0) +#else +#define __page_cache_release__(file, line, func, p) ___put_page(p) +#endif #define page_cache_get(page) \ __page_cache_get__(__FILE__, __LINE__, __FUNCTION__, page) diff -prauN pgcl-2.6.0-test5-bk3-14/mm/memory.c pgcl-2.6.0-test5-bk3-15/mm/memory.c --- pgcl-2.6.0-test5-bk3-14/mm/memory.c 2003-11-26 10:21:44.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/mm/memory.c 2003-11-27 12:20:55.000000000 -0800 @@ -36,6 +36,8 @@ * (Gerhard.Wichert@pdb.siemens.de) */ +#define DEBUG + #include #include #include @@ -1454,7 +1456,7 @@ do_no_page(struct mm_struct *mm, struct struct page *page, *new_page; pte_addr_t folio[PAGE_MMUCOUNT+1] = { [0 ... PAGE_MMUCOUNT] = 0 }; struct address_space *mapping = NULL; - struct pte_chain *pte_chain; + struct pte_chain *pte_chain = NULL; int ret, rss, sequence = 0; pr_debug("%d: do_no_page(%p, %p, %lx, %d, %p, %p)\n", @@ -1480,7 +1482,8 @@ retry: return VM_FAULT_OOM; } - pte_chain = pte_chain_alloc(GFP_KERNEL); + if (!pte_chain) + pte_chain = pte_chain_alloc(GFP_KERNEL); if (!pte_chain) goto oom; @@ -1540,8 +1543,13 @@ retry: flush_icache_page(vma, page); rss = set_folio_page(folio, page, vma->vm_page_prot, write_access ? (_PAGE_RW|_PAGE_DIRTY) : 0); - pte_chain = rmap_add_folio(page, folio, pte_chain); + BUG_ON(!pte_chain); if (!PageReserved(page)) { + /* + * Ignores PageReserved() internally but best to dodge + * the function call overhead. + */ + pte_chain = rmap_add_folio(page, folio, pte_chain); adjust_page_count(page, rss - 1); mm->rss += rss; } diff -prauN pgcl-2.6.0-test5-bk3-14/mm/page_alloc.c pgcl-2.6.0-test5-bk3-15/mm/page_alloc.c --- pgcl-2.6.0-test5-bk3-14/mm/page_alloc.c 2003-11-18 05:30:34.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/mm/page_alloc.c 2003-11-27 10:15:50.000000000 -0800 @@ -221,6 +221,11 @@ static inline void free_pages_check(cons { int bad = 0; + if (page_to_pfn(page)/PAGE_MMUCOUNT == 0xffd38/PAGE_MMUCOUNT) { + printk("magically bad page\n"); + bad = 1; + } + if (unlikely(PageDirect(page))) { printk("PageDirect(page)\n"); bad = 1; @@ -382,6 +387,9 @@ static void prep_new_page(struct page *p 1 << PG_writeback ))) bad_page(__FUNCTION__, page); + if (page_to_pfn(page)/PAGE_MMUCOUNT == 0xffd38/PAGE_MMUCOUNT) + bad_page(__FUNCTION__, page); + page->flags &= ~( 1<< PG_uptodate | 1 << PG_error | 1 << PG_referenced | 1 << PG_arch_1 | diff -prauN pgcl-2.6.0-test5-bk3-14/mm/rmap.c pgcl-2.6.0-test5-bk3-15/mm/rmap.c --- pgcl-2.6.0-test5-bk3-14/mm/rmap.c 2003-11-26 03:24:33.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-15/mm/rmap.c 2003-11-27 13:17:19.000000000 -0800 @@ -66,12 +66,22 @@ * and in turn * N >= (PAGE_MMUCOUNT*sizeof(pte_addr_t)+sizeof(long)+L1_CACHE_BYTES-1) * /L1_CACHE_BYTES + * + * In order for the pte_chain_next_and_idx() etc. algorithms to work, + * NRPTE must be of the form 2**N - 1. */ +#if 0 #define __NL1CB__ (PAGE_MMUCOUNT*sizeof(pte_addr_t) + sizeof(long)) #define __NL1CL__ ((__NL1CB__ + L1_CACHE_BYTES - 1)/L1_CACHE_BYTES) -#define _NL1CL_ (__NL1CL__ > 0 ? __NL1CL__ : __NL1CL__) +#define _NL1CL_ (__NL1CL__ > 0 ? __NL1CL__ : 1) #define NRPTE ((_NL1CL_*L1_CACHE_BYTES - sizeof(long))/sizeof(pte_addr_t)) +#else +#define _NRPTE0 (2*PAGE_MMUCOUNT*sizeof(pte_addr_t)) +#define _NRPTE1 (L1_CACHE_BYTES) +#define _NRPTE2 (_NRPTE0 > _NRPTE1 ? _NRPTE0 : _NRPTE1) +#define NRPTE ((_NRPTE2 - sizeof(long))/sizeof(pte_addr_t)) +#endif /* * next_and_idx encodes both the address of the next pte_chain and the @@ -299,6 +309,7 @@ __page_add_rmap(struct page *page, pte_a if (PageDirect(page)) { /* Convert a direct pointer into a pte_chain */ ClearPageDirect(page); + BUG_ON(!pte_chain); pte_chain->ptes[NRPTE-1] = page->pte.direct; pte_chain->ptes[NRPTE-2] = pte_paddr; pte_chain->next_and_idx = pte_chain_encode(NULL, NRPTE-2); @@ -309,6 +320,7 @@ __page_add_rmap(struct page *page, pte_a } cur_pte_chain = page->pte.chain; + BUG_ON(!cur_pte_chain); if (cur_pte_chain->ptes[0]) { /* It's full */ pte_chain->next_and_idx = pte_chain_encode(cur_pte_chain, NRPTE - 1); @@ -348,18 +360,26 @@ struct pte_chain *rmap_add_folio(struct { int k; + BUG_ON(!page); + BUG_ON(!pte_chain); if (!pfn_valid(page_to_pfn(page)) || PageReserved(page)) return pte_chain; pte_chain_lock(page); for (k = 0; k < PAGE_MMUCOUNT; ++k) { + if (!folio[k]) + continue; + else { + pte_t *pte = rmap_ptep_map(folio[k]); + BUG_ON(pte_page(*pte) != page); + rmap_ptep_unmap(pte); + } /* * I'd like to BUG_ON(!pte_chain) here, but we can * consume the goddamn thing in __page_add_rmap() * while still being able to accomplish insertions. */ - if (folio[k]) - pte_chain = __page_add_rmap(page, folio[k], pte_chain); + pte_chain = __page_add_rmap(page, folio[k], pte_chain); } pte_chain_unlock(page); return pte_chain; @@ -522,8 +542,8 @@ static int try_to_unmap_one(struct page * Store the swap location in the pte. * See handle_pte_fault() ... */ - swp_entry_t entry = { .val = page->index*PAGE_MMUCOUNT - + (pte_pfn(pte) % PAGE_MMUCOUNT) }; + swp_entry_t entry = { .val = page->index*PAGE_CACHE_MMUCOUNT + + (pte_pfn(pte)%PAGE_CACHE_MMUCOUNT) }; swap_duplicate(entry); set_pte(ptep, swp_entry_to_pte(entry)); BUG_ON(pte_file(*ptep)); @@ -533,11 +553,12 @@ static int try_to_unmap_one(struct page * If a nonlinear mapping then store the file page offset * in the pte. */ - pgidx = (address - vma->vm_start) >> MMUPAGE_SHIFT; - pgidx += vma->vm_pgoff; - pgidx >>= PAGE_CACHE_SHIFT - MMUPAGE_SHIFT; - if (page->index != pgidx) { - set_pte(ptep, pgoff_to_pte(page->index*PAGE_MMUCOUNT)); + pgidx = (address - vma->vm_start)/MMUPAGE_SIZE + vma->vm_pgoff; + if (page->index != pgidx/PAGE_CACHE_MMUCOUNT) { + unsigned long f_pgoff; + f_pgoff = PAGE_CACHE_MMUCOUNT*page->index + + (pte_pfn(pte) % PAGE_CACHE_MMUCOUNT); + set_pte(ptep, pgoff_to_pte(f_pgoff)); BUG_ON(!pte_file(*ptep)); } }