diff -urpN pgcl-2.6.0-test5-bk3-3/arch/i386/Kconfig pgcl-2.6.0-test5-bk3-4/arch/i386/Kconfig --- pgcl-2.6.0-test5-bk3-3/arch/i386/Kconfig 2003-11-05 18:48:00.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/arch/i386/Kconfig 2003-11-05 18:50:36.000000000 -0800 @@ -1336,6 +1336,18 @@ config FRAME_POINTER If you don't debug the kernel, you can say N, but we may not be able to solve problems without frame pointers. +config EARLY_CONSOLE_3F8 + bool "Early printk() on serial I/O port 0x3F8" + +config EARLY_CONSOLE_3E8 + bool "Early printk() on serial I/O port 0x3E8" + +config EARLY_CONSOLE_VGA + bool "Early printk() on VGA text console" + +config EARLY_CONSOLE_BOCHS_E9_HACK + bool "Early printk() via the bochs 0xE9 hack" + config X86_EXTRA_IRQS bool depends on X86_LOCAL_APIC || X86_VOYAGER diff -urpN pgcl-2.6.0-test5-bk3-3/arch/i386/kernel/traps.c pgcl-2.6.0-test5-bk3-4/arch/i386/kernel/traps.c --- pgcl-2.6.0-test5-bk3-3/arch/i386/kernel/traps.c 2003-11-05 18:48:00.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/arch/i386/kernel/traps.c 2003-11-05 18:50:36.000000000 -0800 @@ -840,15 +840,20 @@ int EISA_bus; void __init trap_init(void) { #ifdef CONFIG_EISA + printk("trap_init(): about to check for ISA bus\n"); if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) { EISA_bus = 1; } + printk("trap_init(): survived checking for ISA bus\n"); #endif #ifdef CONFIG_X86_LOCAL_APIC + printk("trap_init(): about to init_apic_mappings()\n"); init_apic_mappings(); + printk("trap_init(): survived init_apic_mappings()\n"); #endif + printk("trap_init(): about to set IDT gates\n"); set_trap_gate(0,÷_error); set_intr_gate(1,&debug); set_intr_gate(2,&nmi); @@ -880,11 +885,16 @@ void __init trap_init(void) */ set_call_gate(&default_ldt[0],lcall7); set_call_gate(&default_ldt[4],lcall27); + printk("trap_init(): survived setting IDT gates\n"); /* * Should be a barrier for any external CPU state. */ + printk("trap_init(): about to cpu_init()\n"); cpu_init(); + printk("trap_init(): survived cpu_init()\n"); + printk("trap_init(): about to trap_init_hook()\n"); trap_init_hook(); + printk("trap_init(): survived trap_init_hook()\n"); } diff -urpN pgcl-2.6.0-test5-bk3-3/arch/i386/kernel/vmlinux.lds.S pgcl-2.6.0-test5-bk3-4/arch/i386/kernel/vmlinux.lds.S --- pgcl-2.6.0-test5-bk3-3/arch/i386/kernel/vmlinux.lds.S 2003-09-08 12:49:56.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-4/arch/i386/kernel/vmlinux.lds.S 2003-11-06 19:50:19.000000000 -0800 @@ -48,7 +48,7 @@ SECTIONS _edata = .; /* End of data section */ - . = ALIGN(8192); /* init_task */ + . = ALIGN(16384); /* init_task */ .data.init_task : { *(.data.init_task) } /* will be freed after init */ diff -urpN pgcl-2.6.0-test5-bk3-3/arch/i386/mm/fault.c pgcl-2.6.0-test5-bk3-4/arch/i386/mm/fault.c --- pgcl-2.6.0-test5-bk3-3/arch/i386/mm/fault.c 2003-11-05 18:49:39.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/arch/i386/mm/fault.c 2003-11-05 22:11:33.000000000 -0800 @@ -4,6 +4,8 @@ * Copyright (C) 1995 Linus Torvalds */ +#define DEBUG + #include #include #include @@ -71,7 +73,7 @@ asmlinkage void do_invalid_op(struct pt_ */ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) { - struct task_struct *tsk; + struct task_struct *tsk = current; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long address; @@ -81,15 +83,17 @@ asmlinkage void do_page_fault(struct pt_ /* get the address */ __asm__("movl %%cr2,%0":"=r" (address)); - pr_debug("faulted on %lx,", address); + printk("%d: faulted on %lx, EIP = 0x%lx\n", + tsk->pid, + address, + regs->eip); /* It's safe to allow irq's after cr2 has been saved */ if (regs->eflags & X86_EFLAGS_IF) local_irq_enable(); - tsk = current; - - pr_debug(" pid = %d\n", current->pid); + if (!tsk->pid) + dump_stack(); /* * We fault-in kernel-space virtual memory on-demand. The @@ -112,16 +116,17 @@ asmlinkage void do_page_fault(struct pt_ if (1) { pgd_t *pgd = pgd_offset(mm, address); pmd_t *pmd = pmd_offset(pgd, address); - pr_debug("fault handled by PGD at vaddr %p, %Lx\n", - pgd, (u64)pgd_val(*pgd)); - pr_debug("fault handled by PMD at vaddr %p, %Lx\n", - pmd, (u64)pmd_val(*pmd)); + printk("%d: fault handled by PGD at vaddr %p, %Lx\n", + current->pid, pgd, (u64)pgd_val(*pgd)); + printk("%d: fault handled by PMD at vaddr %p, %Lx\n", + current->pid, pmd, (u64)pmd_val(*pmd)); if (pmd_present(*pmd)) { - pr_debug("fault will be handled by PTE at paddr %Lx\n", + printk("%d: fault will be handled by PTE at paddr %Lx\n", + current->pid, (u64)(pmd_val(*pmd) & MMUPAGE_MASK) + pte_index(address)*sizeof(pte_t)); } else - pr_debug("pmd not present\n"); + printk("pmd not present\n"); } /* * If we're in an interrupt, have no user context or are running in an @@ -130,17 +135,18 @@ asmlinkage void do_page_fault(struct pt_ if (in_atomic() || !mm) goto no_context; + printk("%d: about to down_read(&mm->mmap_sem)\n", current->pid); down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) { - pr_debug("no vma, goto bad_area\n"); + printk("no vma, goto bad_area\n"); goto bad_area; } if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) { - pr_debug("VM_GROWSDOWN not in vma->vm_flags, goto bad_area\n"); + printk("VM_GROWSDOWN not in vma->vm_flags, goto bad_area\n"); goto bad_area; } if (error_code & 4) { @@ -151,12 +157,12 @@ asmlinkage void do_page_fault(struct pt_ * doesn't show up until later.. */ if (address + 32 < regs->esp) { - pr_debug("postdecrement on stack, goto bad_area\n"); + printk("postdecrement on stack, goto bad_area\n"); goto bad_area; } } if (expand_stack(vma, address)) { - pr_debug("expand_stack() failed, goto bad_area\n"); + printk("expand_stack() failed, goto bad_area\n"); goto bad_area; } /* @@ -170,22 +176,22 @@ good_area: default: /* 3: write, present */ #ifdef TEST_VERIFY_AREA if (regs->cs == KERNEL_CS) - pr_debug("WP fault at %08lx\n", regs->eip); + printk("WP fault at %08lx\n", regs->eip); #endif /* fall through */ case 2: /* write, not present */ if (!(vma->vm_flags & VM_WRITE)) { - pr_debug("vma not writable, goto bad_area\n"); + printk("vma not writable, goto bad_area\n"); goto bad_area; } write++; break; case 1: /* read, present */ - pr_debug("NFI what happened, goto bad_area\n"); + printk("NFI what happened, goto bad_area\n"); goto bad_area; case 0: /* read, not present */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) { - pr_debug("vma not read/exec, goto bad_area\n"); + printk("vma not read/exec, goto bad_area\n"); goto bad_area; } } @@ -387,7 +393,7 @@ do_sigbus: * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - pr_debug("sending SIGBUS\n"); + printk("sending SIGBUS\n"); tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; @@ -422,7 +428,7 @@ vmalloc_fault: goto no_context; } - pr_debug("took vmalloc fault on address %lx\n", address); + printk("took vmalloc fault on address %lx\n", address); asm("movl %%cr3,%0":"=r" (pgd)); pgd = index + (pgd_t *)__va(pgd); diff -urpN pgcl-2.6.0-test5-bk3-3/arch/i386/mm/highmem.c pgcl-2.6.0-test5-bk3-4/arch/i386/mm/highmem.c --- pgcl-2.6.0-test5-bk3-3/arch/i386/mm/highmem.c 2003-11-05 18:49:39.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/arch/i386/mm/highmem.c 2003-11-05 18:50:36.000000000 -0800 @@ -171,8 +171,3 @@ void kmap_atomic_sg(pte_t *ptes[], pte_a } } } - -void kunmap_atomic_sg(pte_t *ptes[], enum km_type type) -{ - dec_preempt_count(); -} diff -urpN pgcl-2.6.0-test5-bk3-3/arch/i386/mm/init.c pgcl-2.6.0-test5-bk3-4/arch/i386/mm/init.c --- pgcl-2.6.0-test5-bk3-3/arch/i386/mm/init.c 2003-11-05 18:48:00.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/arch/i386/mm/init.c 2003-11-05 18:50:36.000000000 -0800 @@ -473,6 +473,7 @@ void __init mem_init(void) zero_page = alloc_page(GFP_ATOMIC|GFP_DMA); clear_page(page_address(zero_page)); SetPageReserved(zero_page); + printk("zero_page at pfn 0x%lx\n", page_to_pfn(zero_page)); tlb_init(); totalram_pages--; diff -urpN pgcl-2.6.0-test5-bk3-3/drivers/char/Makefile pgcl-2.6.0-test5-bk3-4/drivers/char/Makefile --- pgcl-2.6.0-test5-bk3-3/drivers/char/Makefile 2003-09-08 12:50:32.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-4/drivers/char/Makefile 2003-11-05 18:50:36.000000000 -0800 @@ -7,7 +7,7 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o +obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o early_consoles.o obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o consolemap_deftbl.o selection.o keyboard.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o diff -urpN pgcl-2.6.0-test5-bk3-3/drivers/char/early_consoles.c pgcl-2.6.0-test5-bk3-4/drivers/char/early_consoles.c --- pgcl-2.6.0-test5-bk3-3/drivers/char/early_consoles.c 1969-12-31 16:00:00.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/drivers/char/early_consoles.c 2003-11-05 18:50:36.000000000 -0800 @@ -0,0 +1,385 @@ +/* + * Early console drivers. + * (C) Nov 2001, William Irwin, IBM + * + * These are low-level pseudodrivers to enable early console output + * to aid in debugging during early boot. + * + * They are crude, but hopefully effective. They rely on the fact + * that consoles are largely unused prior to the true console_init(), + * and that printk() uses the ->write callback and that callback + * only during its operation. + * + * Serial port routines are derived from Linux serial.c, and + * vga_putc() is derived from vsta, (C) Andrew Valencia. + */ + +#include +#include +#include +#include +#include + +/* + * I/O ports are not linearly mapped on all architectures. + * On IA64 in particular, port I/O is just reading/writing from + * an uncached address, but ioremap there requires ia64_io_base + * to be initialized, which does not happen until the middle of + * setup_arch(). So a port remapping macro is provided here. + * + * The IA64 case is not handled here, although the port remapping + * is demonstrated for the purposes of understanding its necessity. + * The IO_BASE is taken from Lion systems; in general, this varies. + * True handling for IA64 will be merged in given testing. + */ + +#ifdef CONFIG_IA64 + +#define IO_BASE 0xC0000FFFFC000000UL +#define MK_PORT(port) ((char *)(IO_BASE|(((port)>>2)<<12)|((port) & 0xFFF))) + +#else + +/* + * This works for i386, but not everywhere. + * Other architectures with port I/O mapping needs will need to + * add to the preprocessor case analysis above. + */ + +#define MK_PORT(port) (port) + +#endif + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + + +/* + * This serial output driver derived from the one appearing + * in serial.c + * + * It is a simple "bitbanging" style output routine, with + * initialization performed at every call. + */ + +#if defined(CONFIG_EARLY_CONSOLE_3F8) || defined(CONFIG_EARLY_CONSOLE_3E8) + +static inline __init void wait_for_readiness(unsigned port) +{ + unsigned retries; + unsigned char status; + + /* + * Wait for transmitter holding and shift registers to empty, + * which is required for output to succeed. If the retries are + * exceeded, this deliberately fails to ensure termination. + */ + for(retries = 0; retries < 65536; ++retries) { + status = inb(MK_PORT(port + 5)); + if((status & BOTH_EMPTY) == BOTH_EMPTY) + break; + } +} + +static void __init write_serial_io_port(unsigned port, + const char *s, + unsigned n) +{ + unsigned k; + + wait_for_readiness(port); + + /* + * Disable interrupts. + */ + outb(0x0, MK_PORT(port + 1)); + + /* + * Set the baud rate divisor's LSB. + */ + outb(0x83, MK_PORT(port + 3)); + + /* + * Set the baud rate divisor's MSB. + */ + outb(0x1, MK_PORT(port)); + + /* + * Set no parity, 8 bits, 1 stop bit, and select + * interrupt enable register. + */ + outb(0x3, MK_PORT(port + 3)); + + /* + * Set data terminal ready and request to send. + */ + + for(k = 0; k < n; ++k) { + wait_for_readiness(port); + outb(s[k], MK_PORT(port)); + if(s[k] == '\n') { + wait_for_readiness(port); + outb('\r', MK_PORT(port)); + } + } +} + +#endif /* CONFIG_EARLY_CONSOLE_3F8 || CONFIG_EARLY_CONSOLE_3E8 */ + + + +/* + * On Intel-derived architectures it is customary for onboard serial + * ports to have I/O ports at these two port addresses. + */ + +#ifdef CONFIG_EARLY_CONSOLE_3F8 +static void __init write_3F8(struct console *c, const char *s, unsigned n) +{ + write_serial_io_port(0x3F8, s, n); +} + +static struct console __initdata early_console_3F8 = +{ + write: write_3F8 +}; +#endif + +#ifdef CONFIG_EARLY_CONSOLE_3E8 +static void __init write_3E8(struct console *c, const char *s, unsigned n) +{ + write_serial_io_port(0x3E8, s, n); +} + +static struct console __initdata early_console_3E8 = +{ + write: write_3E8 +}; +#endif + + + + +/* + * This should work for a variety of Intel-derived architectures, + * as it is customary for VGA memory to reside in this address range. + * vga_putc() is derived from vsta sources, (C) Andrew Valencia. + * + * Several forms of functionality are intentionally omitted in the + * interest of robustness, in particular, cursor movement and cursor + * position determination. + */ + +#ifdef CONFIG_EARLY_CONSOLE_VGA + +#define VGA_MAXCOL 80 +#define VGA_MAXROW 25 +#define VGA_SCRNSZ (VGA_MAXCOL * VGA_MAXROW) +#define VGA_REG_PORT 0x3D4 +#define VGA_VAL_PORT 0x3D5 +#define VGA_TEXT_BUFFER 0xB8000 + +#define VGA_CHAR(_row_, _col_) vga_mem[(_row_)*VGA_MAXCOL + (_col_)].c + +struct vga_char_desc +{ + unsigned char c; + unsigned char color; +}; + +static struct vga_char_desc * vga_mem __initdata = + (struct vga_char_desc *)(VGA_TEXT_BUFFER + PAGE_OFFSET); + +/* + * The characters displayed at a screen position can be discerned by + * reading from the corresponding memory location. This can be used + * to simulate scrolling movement. Line blanking is simulated by + * overwriting the displayed characters with the space character. + * + * In the interest of robustness, cursor movement is also omitted. + */ +static void __inline__ __init vga_scroll_up(void) +{ + unsigned k; + + for(k = 0; k < (VGA_SCRNSZ - VGA_MAXCOL); ++k) + vga_mem[k].c = vga_mem[k + VGA_MAXCOL].c; + + for(k = VGA_SCRNSZ - VGA_MAXCOL; k < VGA_SCRNSZ; ++k) + vga_mem[k].c = ' '; +} + +/* + * The screen position can actually be determined by port I/O, + * but in the interest of robustness, these are always initialized + * to the (0, 0) position. These position indices must always be + * strictly less than the bounds VGA_MAXROW and VGA_MAXCOL. + */ +static unsigned short __initdata row; +static unsigned short __initdata col; + + +/* + * Line advancement must preserve the invariant that the row and + * column indices are in-bounds. The semantics of this mean that + * when line advancement "beyond" the last line results in scrolling. + */ +static inline void __init vga_line_advance(void) +{ + ++row; + + if(row >= VGA_MAXROW) { + row = VGA_MAXROW - 1; + vga_scroll_up(); + } +} + + +/* + * Character advancement must once again preserve the in-bounds + * invariants, and in so doing line wrapping and advancement may occur. + */ +static inline void __init vga_char_advance(void) +{ + ++col; + + if(col >= VGA_MAXCOL) { + col = 0; + vga_line_advance(); + } +} + + +/* + * Derived from vsta sources (C) Andrew Valencia. + * Here the interpretation of several common special characters occurs, + * namely linefeeds, newlines, tabs, and backspaces. The position + * indices are updated using the vga_char_advance() and vga_line_advance() + * routines, and a vga_char_advance() is triggered on the printing of + * each ordinary character. The special characters have specialized + * position update semantics in order to be faithful to their customary + * cursor movement effects, although the cursor position is not updated. + */ +static void __init vga_putc(char c) +{ + unsigned k; + switch(c) { + case '\t': + for(k = 0; k < 8; ++k) { + VGA_CHAR(row, col) = ' '; + vga_char_advance(); + } + break; + + case '\r': + col = 0; + break; + + case '\n': + col = 0; + vga_line_advance(); + break; + + case '\b': + if(col > 0) { + --col; + VGA_CHAR(row, col) = ' '; + } + break; + + default: + VGA_CHAR(row, col) = c; + vga_char_advance(); + break; + } +} + + +/* + * write_vga(), given a NUL-terminated character array, writes + * characters to VGA space in bulk, and is the callback used for the + * driver structure. + */ +static void __init write_vga(struct console *c, const char *s, unsigned n) +{ + unsigned k; + for(k = 0; k < n; ++k) + vga_putc(s[k]); +} + +static struct console __initdata early_console_vga = +{ + write: write_vga +}; + +#endif /* CONFIG_EARLY_CONSOLE_VGA */ + + +/* + * The bochs x86 simulator has an optional feature for enabling + * debugging output through a normally unused ISA I/O port. The + * protocol for communicating with the simulated device is simply + * using port I/O writes to write a stream of characters to the + * device, and these are then relayed by the simulator to the + * controlling terminal of the simulator process. + */ +#ifdef CONFIG_EARLY_CONSOLE_BOCHS_E9_HACK +static void __init write_bochs(struct console *c, const char *s, unsigned n) +{ + unsigned k; + + for(k = 0; k < n; ++k) + outb(s[k], MK_PORT(0xE9)); +} + +static struct console __initdata early_console_bochs = +{ + write: write_bochs +}; +#endif /* CONFIG_EARLY_CONSOLE_BOCHS_E9_HACK */ + + +/* + * In order to minimize the number of #ifdefs whch must + * appear in-line, this direct-mapped, NULL-terminated table + * of console entries is used to provide a configuration-independent + * structure which may be traversed to discover all of the available + * early console devices for registration and unregistration. + * + * This is the ugliest part of the code, thanks to #ifdef + */ +static struct console * __initdata early_console_table[] = + { +#ifdef CONFIG_EARLY_CONSOLE_3F8 + &early_console_3F8, +#endif +#ifdef CONFIG_EARLY_CONSOLE_3E8 + &early_console_3E8, +#endif +#ifdef CONFIG_EARLY_CONSOLE_VGA + &early_console_vga, +#endif +#ifdef CONFIG_EARLY_CONSOLE_BOCHS_E9_HACK + &early_console_bochs, +#endif + NULL + }; + + +/* + * The above implementations are quite far from complete console + * devices, but printk() only requires the ->write callback, so this is + * somewhat deceptive, but still cleaner than editing printk.c itself. + */ +void __init register_early_consoles(void) +{ + struct console **c = early_console_table; + while(*c) + register_console(*c++); +} + +void __init unregister_early_consoles(void) +{ + struct console **c = early_console_table; + while(*c) + unregister_console(*c++); +} diff -urpN pgcl-2.6.0-test5-bk3-3/fs/exec.c pgcl-2.6.0-test5-bk3-4/fs/exec.c --- pgcl-2.6.0-test5-bk3-3/fs/exec.c 2003-11-05 18:49:39.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/fs/exec.c 2003-11-06 20:55:53.000000000 -0800 @@ -288,7 +288,7 @@ int copy_strings_kernel(int argc,char ** * * task->mm->mmap_sem is held for writing. */ -void put_dirty_page(struct task_struct *task, struct page *page, int min_subpfn, +void put_dirty_page(task_t *task, struct page *page, int min_subpfn, unsigned long addr, pgprot_t prot) { unsigned long page_pfn, subpfn; @@ -296,6 +296,10 @@ void put_dirty_page(struct task_struct * struct mm_struct *mm = task->mm; page_pfn = page_to_pfn(page); + + printk("%d: put_dirty_page: page = %p, start pfn = 0x%lx, min_subpfn = 0x%x, addr = 0x%lx, prot = %lx\n", + current->pid, page, page_pfn, min_subpfn, addr, pgprot_val(prot)); + spin_lock(&mm->page_table_lock); addr += MMUPAGE_SIZE * min_subpfn; @@ -323,11 +327,15 @@ void put_dirty_page(struct task_struct * goto out; if (!pte_none(*pte)) { pte_unmap(pte); + printk("%d: put_dirty_page: skipping addr 0x%lx\n", + current->pid, addr); continue; } pfn = page_pfn + subpfn; set_pte(pte, pte_mkdirty(pte_mkwrite(pfn_pte(pfn, prot)))); pte_chain = page_add_rmap(page, pte, pte_chain); + printk("%d: put_dirty_page translating 0x%lx to pfn 0x%lx\n", + current->pid, addr, pfn); page_cache_get(page); pte_unmap(pte); task->mm->rss++; @@ -428,7 +436,8 @@ int setup_arg_pages(struct linux_binprm mpnt->vm_start = stack_base; mpnt->vm_end = MMUPAGE_ALIGN((unsigned long)bprm->p); #else - mpnt->vm_start = MMUPAGE_MASK & (unsigned long)bprm->p; + /* mpnt->vm_start = MMUPAGE_MASK & (unsigned long)bprm->p; */ + mpnt->vm_start = PAGE_MASK & (unsigned long)bprm->p; mpnt->vm_end = STACK_TOP; #endif mpnt->vm_page_prot = protection_map[VM_STACK_FLAGS & 0x7]; diff -urpN pgcl-2.6.0-test5-bk3-3/include/asm-generic/rmap.h pgcl-2.6.0-test5-bk3-4/include/asm-generic/rmap.h --- pgcl-2.6.0-test5-bk3-3/include/asm-generic/rmap.h 2003-11-05 18:48:00.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/include/asm-generic/rmap.h 2003-11-05 18:50:36.000000000 -0800 @@ -88,15 +88,32 @@ static inline struct mm_struct * ptep_to static inline unsigned long ptep_to_address(pte_t * ptep) { - struct page *page; unsigned long kvaddr = (unsigned long)ptep; unsigned long swpage_voff = kvaddr/sizeof(pte_t); - WARN_ON(kvaddr > (unsigned long)(-PAGE_SIZE)); - - page = kmap_atomic_to_page(ptep); - swpage_voff %= MMUPAGES_MAPPED_PER_PTE_PAGE; - return page->index + MMUPAGE_SIZE*swpage_voff; + if (1) { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned long pfn; + struct page *page; + + pgd = pgd_offset_k(kvaddr); + pmd = pmd_offset(pgd, kvaddr); + pte = pte_offset_kernel(pmd, kvaddr); + pfn = pte_pfn(*pte); + page = pfn_to_page(pfn); + return page->index + PMD_SIZE*(pfn % PAGE_MMUCOUNT) + + MMUPAGE_SIZE*(swpage_voff % PTRS_PER_PTE); + } else { + struct page *page = kmap_atomic_to_page(ptep); + + WARN_ON(kvaddr > (unsigned long)(-PAGE_SIZE)); + + swpage_voff %= MMUPAGES_MAPPED_PER_PTE_PAGE; + /* WARN_ON(swpage_voff != pfn - page_to_pfn(page)); */ + return page->index + MMUPAGE_SIZE*swpage_voff; + } } #ifdef CONFIG_HIGHPTE diff -urpN pgcl-2.6.0-test5-bk3-3/include/asm-i386/highmem.h pgcl-2.6.0-test5-bk3-4/include/asm-i386/highmem.h --- pgcl-2.6.0-test5-bk3-3/include/asm-i386/highmem.h 2003-11-05 18:48:48.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/include/asm-i386/highmem.h 2003-11-05 19:09:44.000000000 -0800 @@ -43,12 +43,12 @@ void *kmap_atomic(struct page *page, enu void kmap_atomic_sg(pte_t *[], pte_addr_t [], enum km_type); #ifndef CONFIG_DEBUG_HIGHMEM -static inline void kunmap_atomic_sg(pte_t *[], enum km_type) +static inline void kunmap_atomic_sg(pte_t *ptes[], enum km_type type) { dec_preempt_count(); } -static inline void kunmap_atomic(void *kvaddr, enum km_type) +static inline void kunmap_atomic(void *kvaddr, enum km_type type) { dec_preempt_count(); } diff -urpN pgcl-2.6.0-test5-bk3-3/include/asm-i386/thread_info.h pgcl-2.6.0-test5-bk3-4/include/asm-i386/thread_info.h --- pgcl-2.6.0-test5-bk3-3/include/asm-i386/thread_info.h 2003-11-05 18:48:00.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/include/asm-i386/thread_info.h 2003-11-05 18:51:56.000000000 -0800 @@ -53,7 +53,8 @@ struct thread_info { #endif #define PREEMPT_ACTIVE 0x4000000 -#define THREAD_SIZE (2*MMUPAGE_SIZE) +#define THREAD_SIZE (4*MMUPAGE_SIZE) +#define INIT_THREAD_SIZE THREAD_SIZE /* * macros/functions for gaining access to the thread information structure diff -urpN pgcl-2.6.0-test5-bk3-3/include/linux/folio.h pgcl-2.6.0-test5-bk3-4/include/linux/folio.h --- pgcl-2.6.0-test5-bk3-3/include/linux/folio.h 2003-11-05 18:49:39.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/include/linux/folio.h 2003-11-06 20:30:13.000000000 -0800 @@ -21,7 +21,7 @@ /* * Test whether pte2 indicates the same page as pte1. */ -static inline int pte_match(pte_t *pte1, pte_t *pte2) +static /* inline */ int pte_match(pte_t *pte1, pte_t *pte2) { if (pte_none(*pte1)) return pte_none(*pte2); @@ -38,7 +38,7 @@ static inline int pte_match(pte_t *pte1, /* * Test whether nearby vma2 could ever share a private page with vma1. */ -static inline int vma_neighbourly(struct vm_area_struct *vma1, +static /* inline */ int vma_neighbourly(struct vm_area_struct *vma1, struct vm_area_struct *vma2) { if ((vma1->vm_flags | vma2->vm_flags) & VM_MAYSHARE) @@ -187,10 +187,14 @@ static struct page *private_folio_page(p int fcount, pcount, scount, tcount; int i, j; + printk("%d: private_folio_page(%p, %p)\n", + current->pid, paddrs, swap_page); + kmap_atomic_sg(folio, paddrs, KM_FOLIO); - for (j = PAGE_MMUCOUNT - 1; !folio[j]; j--) - ; + for (j = PAGE_MMUCOUNT - 1; !folio[j]; j--) { + printk("%d: skipping %d\n", current->pid, j); + } fcount = j + 1; /* * The easiest way to handle the do_swap_page() case is @@ -205,8 +209,16 @@ static struct page *private_folio_page(p } j = 0; + printk("%d: starting fcount = %d\n", current->pid, fcount); while (j < fcount) { if (!folio[j] || !pte_present(*folio[j])) { + printk("%d: skipping folio[%d] = %p (0x%Lx), " + "presence = %d\n", + current->pid, + j, + folio[j], + folio[j] ? (u64)pte_val(*folio[j]) : 0, + folio[j] ? !!pte_present(*folio[j]) : 0); j++; continue; } @@ -268,16 +280,19 @@ static struct page *private_folio_page(p if (scount) continue; kunmap_atomic_sg(folio, KM_FOLIO); + printk("private_folio_page: page=%p, fcount=%d, pcount=%d, scount=%d, tcount=%d\n", page, fcount, pcount, scount, tcount); return page; } kunmap_atomic_sg(folio, KM_FOLIO); + printk("%d: private_folio_page: page=NULL, j=%d, fcount=%d\n", + current->pid, j, fcount); return NULL; } /* * Replace page just allocated by private folio page if it has one. */ -static inline struct page *private_folio_page_xchg(pte_addr_t folio[], struct page *new_page) +static /* inline */ struct page *private_folio_page_xchg(pte_addr_t folio[], struct page *new_page) { struct page *folio_page = private_folio_page(folio, NULL); if (!folio_page) @@ -297,15 +312,34 @@ static void restrict_folio(pte_addr_t pa unsigned long addr; int j; + printk("%d: restrict_folio(%p, %p = [0x%lx,0x%lx), 0x%lx, %p)\n", + current->pid, paddrs, vma, vma->vm_start, vma->vm_end, + address, ptep); + kmap_atomic_sg(folio, paddrs, KM_FOLIO); addr = address - vma_suboffset(vma, address); for (j = 0; j < PAGE_MMUCOUNT; j++, addr += MMUPAGE_SIZE) { - if (!folio[j]) + if (!folio[j]) { + printk("%d: restrict_folio() saw folio[%d], addr 0x%lx NULL\n", + current->pid, j, addr); continue; - if (addr < vma->vm_start || addr >= vma->vm_end || - !pte_match(folio[j], ptep)) + } + if (addr < vma->vm_start || addr >= vma->vm_end) { + printk("%d: restrict_folio() saw folio[%d], addr 0x%lx outside vma\n", + current->pid, j, addr); + folio[j] = NULL; + paddrs[j] = NOPTE; + } else if (!pte_match(folio[j], ptep)) { + printk("%d: restrict_folio() saw folio[%d], addr 0x%lx not match, folio[j] = 0x%Lx, ptep = 0x%Lx\n", + current->pid, j, addr, + (u64)pte_val(*folio[j]), (u64)pte_val(*ptep)); folio[j] = NULL; + paddrs[j] = NOPTE; + } else + printk("%d: restrict folio saw folio[%d], addr 0x%lx = 0x%Lx match with ptep = %Lx\n", + current->pid, j, addr, + (u64)pte_val(*folio[j]), (u64)pte_val(*ptep)); } kunmap_atomic_sg(folio, KM_FOLIO); } @@ -313,22 +347,60 @@ static void restrict_folio(pte_addr_t pa /* * Copy (or clear) folio of mmupages from src_page to dst_page. */ +#if 0 +static void copy_folio(pte_addr_t paddrs[], struct page *dst_page, + struct page *src_page, unsigned long address) +{ + pte_t *folio[PAGE_MMUCOUNT]; + unsigned long pfns[PAGE_MMUCOUNT]; + char *src, *dst; + int k; + + kmap_atomic_sg(folio, paddrs, KM_FOLIO); + for (k = 0; k < PAGE_MMUCOUNT; ++k) { + if (!folio[k]) + pfns[k] = 0; + else { + pfns[k] = pte_pfn(*folio[k]); + if (pfn_to_page(pfns[k]) == ZERO_PAGE(address)) + pfns[k] = 0; + } + } + kunmap_atomic_sg(folio, KM_FOLIO); + src = kmap_atomic_pfns(pfns, KM_USER0); + dst = kmap_atomic(dst_page, KM_USER1) + for (k = 0; k < PAGE_MMUCOUNT; ++k) { + if (pfns[k]) + memcpy(&dst[MMUPAGE_SIZE*k], &src[MMUPAGE_SIZE*k], MMUPAGE_SIZE); + else + memset(&dst[MMUPAGE_SIZE*k], 0, MMUPAGE_SIZE); + } + kunmap_atomic(dst, KM_USER1); + kunmap_atomic_pfns(pfns, KM_USER0); +} +#else static void copy_folio(pte_addr_t paddrs[], struct page *dst_page, struct page *src_page, unsigned long address) { pte_t *folio[PAGE_MMUCOUNT+1]; char *src, *dst; - unsigned int size; - unsigned int offset = 0; + unsigned int size, offset = 0; + unsigned long src_pfn, dst_pfn; int j = 0; kmap_atomic_sg(folio, paddrs, KM_FOLIO); dst = kmap_atomic(dst_page, KM_USER0); - if (src_page != ZERO_PAGE(address)) + dst_pfn = page_to_pfn(dst_page); + if (src_page != ZERO_PAGE(address)) { src = kmap_atomic(src_page, KM_USER1); - else + src_pfn = page_to_pfn(src_page); + printk("%d: copying nonzero page\n", current->pid); + } else { src = NULL; + src_pfn = 0; + printk("%d: zeroing out page\n", current->pid); + } while (j < PAGE_MMUCOUNT) { if (!folio[j]) { offset += MMUPAGE_SIZE; @@ -344,10 +416,19 @@ static void copy_folio(pte_addr_t paddrs /* We assume one long op is faster than several shorts. * But ia64 sh sparc64 need to use clear/copy_user_page. */ - if (src) + if (src) { + printk("%d: copying %d mmupages from pfn " + "0x%lx to 0x%lx\n", + current->pid, size/MMUPAGE_SIZE, + src_pfn + offset/MMUPAGE_SIZE, + dst_pfn + offset/MMUPAGE_SIZE); memcpy(dst + offset, src + offset, size); - else + } else { + printk("%d: zeroing %d mmupages at pfn 0x%lx\n", + current->pid, size/MMUPAGE_SIZE, + dst_pfn + offset/MMUPAGE_SIZE); memset(dst + offset, 0, size); + } offset += size; } if (src) @@ -355,25 +436,35 @@ static void copy_folio(pte_addr_t paddrs kunmap_atomic(dst, KM_USER0); kunmap_atomic_sg(folio, KM_FOLIO); } +#endif /* * Update page table entries of the folio, counting how many done. */ -static inline unsigned long +static /* inline */ unsigned long set_folio_page(pte_addr_t paddrs[], struct page *page, pgprot_t prot, unsigned long flags) { pte_t *folio[PAGE_MMUCOUNT+1]; - unsigned long offset = 0, rss = 0, pfn = page_to_pfn(page); + unsigned long rss = 0, pfn = page_to_pfn(page); int j; kmap_atomic_sg(folio, paddrs, KM_FOLIO); - for (j = 0; j < PAGE_MMUCOUNT; j++, offset += MMUPAGE_SIZE) { + for (j = 0; j < PAGE_MMUCOUNT; j++) { + pte_t old_pte; + if (!folio[j]) continue; + old_pte = *folio[j]; set_pte(folio[j], pfn_pte(pfn + j, __pgprot(prot.pgprot | flags))); + printk("%d: translating vaddr 0x%lx to pfn 0x%lx, " + "new pte = 0x%Lx, old pte = 0x%Lx\n", + current->pid, + ptep_to_address(folio[j]), pfn + j, + (u64)pte_val(*folio[j]), + (u64)pte_val(old_pte)); rss++; } kunmap_atomic_sg(folio, KM_FOLIO); @@ -383,7 +474,7 @@ set_folio_page(pte_addr_t paddrs[], stru /* * Flush TLB entries for the folio (if ptes were present before). */ -static inline void flush_folio(pte_addr_t folio[], struct vm_area_struct *vma, +static /* inline */ void flush_folio(pte_addr_t folio[], struct vm_area_struct *vma, unsigned long address) { unsigned long start, end; @@ -403,7 +494,7 @@ static inline void flush_folio(pte_addr_ #else /* PAGE_MMUSHIFT 0 */ -static inline int prepare_folio(pte_t *folio[], struct vm_area_struct *vma, +static /* inline */ int prepare_folio(pte_t *folio[], struct vm_area_struct *vma, unsigned long address, pte_t *ptep, int wide) { folio[0] = ptep; @@ -413,7 +504,7 @@ static inline int prepare_folio(pte_t *f /* * Calling convention different if !PAGE_MMUSHIFT: page always passed in */ -static inline struct page *private_folio_page(pte_t *folio[], struct page *page) +static /* inline */ struct page *private_folio_page(pte_t *folio[], struct page *page) { int doing_wp = pte_present(*folio[0]); int count; @@ -448,7 +539,7 @@ static inline struct page *private_folio #define restrict_folio(folio, vma, address, ptep) \ do {} while (0) -static inline void copy_folio(pte_t *folio[], struct page *dst_page, +static /* inline */ void copy_folio(pte_t *folio[], struct page *dst_page, struct page *src_page, unsigned long address) { char *dst = kmap(dst_page); @@ -461,7 +552,7 @@ static inline void copy_folio(pte_t *fol kunmap(dst_page); } -static inline unsigned long set_folio(pte_t *folio[], pte_t pte) +static /* inline */ unsigned long set_folio(pte_t *folio[], pte_t pte) { set_pte(folio[0], pte); return 1; diff -urpN pgcl-2.6.0-test5-bk3-3/include/linux/kernel.h pgcl-2.6.0-test5-bk3-4/include/linux/kernel.h --- pgcl-2.6.0-test5-bk3-3/include/linux/kernel.h 2003-09-08 12:49:51.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-4/include/linux/kernel.h 2003-11-05 18:50:36.000000000 -0800 @@ -88,6 +88,9 @@ extern unsigned long long memparse(char extern int kernel_text_address(unsigned long addr); extern int session_of_pgrp(int pgrp); +extern void register_early_consoles(void); +extern void unregister_early_consoles(void); + asmlinkage int printk(const char * fmt, ...) __attribute__ ((format (printf, 1, 2))); diff -urpN pgcl-2.6.0-test5-bk3-3/init/main.c pgcl-2.6.0-test5-bk3-4/init/main.c --- pgcl-2.6.0-test5-bk3-3/init/main.c 2003-11-05 18:49:39.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/init/main.c 2003-11-05 18:52:52.000000000 -0800 @@ -358,6 +358,9 @@ static void __init smp_init(void) #endif +extern void register_early_consoles(void); +extern void unregister_early_consoles(void); + /* * We need to finalize in a non-__init function or else race conditions * between the root thread and the init thread may cause start_kernel to @@ -387,6 +390,7 @@ asmlinkage void __init start_kernel(void * enable them */ lock_kernel(); + register_early_consoles(); printk(linux_banner); setup_arch(&command_line); setup_per_zone_pages_min(); @@ -404,7 +408,9 @@ asmlinkage void __init start_kernel(void parse_args("Booting kernel", command_line, __start___param, __stop___param - __start___param, &unknown_bootoption); + printk("survived parse_args(), calling trap_init()\n"); trap_init(); + printk("survived trap_init(), calling rcu_init()\n"); rcu_init(); init_IRQ(); pidhash_init(); @@ -417,6 +423,7 @@ asmlinkage void __init start_kernel(void * we've done PCI setups etc, and console_init() must be aware of * this. But we do want output early, in case something goes wrong. */ + unregister_early_consoles(); console_init(); profile_init(); local_irq_enable(); diff -urpN pgcl-2.6.0-test5-bk3-3/kernel/fork.c pgcl-2.6.0-test5-bk3-4/kernel/fork.c --- pgcl-2.6.0-test5-bk3-3/kernel/fork.c 2003-11-05 18:48:01.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/kernel/fork.c 2003-11-05 18:56:59.000000000 -0800 @@ -1087,6 +1087,8 @@ long do_fork(unsigned long clone_flags, int trace = 0; long pid; + printk("%d: do_fork()\n", current->pid); + if (unlikely(current->ptrace)) { trace = fork_traceflag (clone_flags); if (trace) @@ -1137,6 +1139,7 @@ long do_fork(unsigned long clone_flags, */ set_need_resched(); } + printk("%d: do_fork() = %ld\n", current->pid, pid); return pid; } diff -urpN pgcl-2.6.0-test5-bk3-3/kernel/params.c pgcl-2.6.0-test5-bk3-4/kernel/params.c --- pgcl-2.6.0-test5-bk3-3/kernel/params.c 2003-09-08 12:50:21.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-4/kernel/params.c 2003-11-05 18:50:36.000000000 -0800 @@ -112,13 +112,20 @@ int parse_args(const char *name, unsigned num, int (*unknown)(char *param, char *val)) { + int k; char *param, *val; + printk("parsing args, trying to print the string\n"); + printk("args=\"%s\"\n", args); + DEBUGP("Parsing ARGS: %s\n", args); + printk("survived parsing args\n"); + k = 0; while (*args) { int ret; + printk("parse_args(): entering iteration %d\n", k); args = next_arg(args, ¶m, &val); ret = parse_one(param, val, params, num, unknown); switch (ret) { @@ -139,8 +146,11 @@ int parse_args(const char *name, name, val ?: "", param); return ret; } + printk("parse_args(): exiting iteration %d\n", k); + ++k; } + printk("parse_args(): iterated %d times\n", k); /* All parsed OK. */ return 0; } diff -urpN pgcl-2.6.0-test5-bk3-3/kernel/printk.c pgcl-2.6.0-test5-bk3-4/kernel/printk.c --- pgcl-2.6.0-test5-bk3-3/kernel/printk.c 2003-09-08 12:50:43.000000000 -0700 +++ pgcl-2.6.0-test5-bk3-4/kernel/printk.c 2003-11-05 18:50:36.000000000 -0800 @@ -433,7 +433,7 @@ asmlinkage int printk(const char *fmt, . log_level_unknown = 1; } - if (!cpu_online(smp_processor_id())) { + if (0 && !cpu_online(smp_processor_id())) { /* * Some console drivers may assume that per-cpu resources have * been allocated. So don't allow them to be called by this diff -urpN pgcl-2.6.0-test5-bk3-3/mm/memory.c pgcl-2.6.0-test5-bk3-4/mm/memory.c --- pgcl-2.6.0-test5-bk3-3/mm/memory.c 2003-11-05 18:49:39.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/mm/memory.c 2003-11-06 19:27:22.000000000 -0800 @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -56,6 +55,8 @@ #include #include #include +#include +#include #ifndef CONFIG_DISCONTIGMEM /* use the per-pgdat data instead for discontigmem - mbligh */ @@ -1027,8 +1028,8 @@ static int do_wp_page(struct mm_struct * pte_addr_t folio[PAGE_MMUCOUNT+1]; int reprep, rss, ret; - printk("do_wp_page(%p, %p, 0x%lx, %p, %p, %Lx\n", - mm, vma, address, page_table, pmd, pte_val(pte)); + printk("%d: do_wp_page(%p, %p, 0x%lx, %p, %p, %Lx\n", + current->pid, mm, vma, address, page_table, pmd, (u64)pte_val(pte)); if (unlikely(!pfn_valid(pfn))) { /* @@ -1045,6 +1046,7 @@ static int do_wp_page(struct mm_struct * reprep = prepare_folio(folio, vma, address, ptep_to_paddr(page_table), 1); new_page = private_folio_page(folio, PAGE_MMUSHIFT ? NULL : old_page); if (new_page) { + printk("%d: got private page\n", current->pid); page_cache_get(new_page); goto got_page; } @@ -1058,6 +1060,9 @@ static int do_wp_page(struct mm_struct * if (!pte_chain) goto no_mem; new_page = alloc_page(GFP_HIGHUSER); + printk("%d: allocated page at 0x%lx\n", + current->pid, + page_to_pfn(new_page)); if (!new_page) goto no_mem; @@ -1066,12 +1071,21 @@ static int do_wp_page(struct mm_struct * */ spin_lock(&mm->page_table_lock); page_table = pte_offset_map(pmd, address); - if (reprep) + if (!pte_same(*page_table, pte)) { + printk("%d: pte changed, back out of fault\n", current->pid); + page_cache_release(new_page); + return VM_FAULT_MINOR; + } + + if (reprep) { + printk("%d: reprepping folio\n", current->pid); prepare_folio(folio, vma, address, ptep_to_paddr(page_table), 1); + } new_page = private_folio_page_xchg(folio, new_page); got_page: restrict_folio(folio, vma, address, page_table); if (new_page != old_page) { + printk("%d: copying folio\n", current->pid); copy_folio(folio, new_page, old_page, address); flush_cache_page(vma, address); } @@ -1097,7 +1111,7 @@ oom: out: spin_unlock(&mm->page_table_lock); pte_chain_free(pte_chain); - printk("return from do_wp_page()\n"); + printk("%d: return from do_wp_page()\n", current->pid); return ret; } @@ -1254,8 +1268,8 @@ static int do_swap_page(struct mm_struct int rss, ret = VM_FAULT_MINOR; struct pte_chain *pte_chain = NULL; - printk("do_swap_page(%p, %p, %lx, %p, %p, %Lx, %d)\n", - mm, vma, address, page_table, pmd, pte_val(orig_pte), write_access); + printk("%d: do_swap_page(%p, %p, %lx, %p, %p, %Lx, %d)\n", + current->pid, mm, vma, address, page_table, pmd, (u64)pte_val(orig_pte), write_access); pte_unmap(page_table); spin_unlock(&mm->page_table_lock); @@ -1344,7 +1358,7 @@ static int do_swap_page(struct mm_struct spin_unlock(&mm->page_table_lock); out: pte_chain_free(pte_chain); - printk("return from do_swap_page()\n"); + printk("%d: return from do_swap_page()\n", current->pid); return ret; } @@ -1363,8 +1377,8 @@ do_anonymous_page(struct mm_struct *mm, struct pte_chain *pte_chain; int ret; - printk("do_anonymous_page(%p, %p, %p, %p, %d, %lx)\n", - mm, vma, page_table, pmd, write_access, addr); + printk("%d: do_anonymous_page(%p, %p, %p, %p, %d, %lx)\n", + current->pid, mm, vma, page_table, pmd, write_access, addr); pte_chain = pte_chain_alloc(GFP_ATOMIC); if (!pte_chain) { @@ -1384,6 +1398,9 @@ do_anonymous_page(struct mm_struct *mm, spin_unlock(&mm->page_table_lock); new_page = alloc_page(GFP_HIGHUSER); + printk("%d: allocated page at 0x%lx\n", + current->pid, + page_to_pfn(new_page)); if (!new_page) goto no_mem; @@ -1430,7 +1447,7 @@ no_mem: ret = VM_FAULT_OOM; out: pte_chain_free(pte_chain); - printk("return from do_anonymous_page()\n"); + printk("%d: return from do_anonymous_page()\n", current->pid); return ret; } @@ -1450,14 +1467,14 @@ static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access, pte_t *page_table, pmd_t *pmd) { - struct page *page, *new_page = NULL; + struct page *page, *new_page; pte_addr_t folio[PAGE_MMUCOUNT+1]; struct address_space *mapping = NULL; struct pte_chain *pte_chain; int ret, rss, sequence = 0; - printk("do_no_page(%p, %p, %lx, %d, %p, %p)\n", - mm, vma, address, write_access, page_table, pmd); + printk("%d: do_no_page(%p, %p, %lx, %d, %p, %p)\n", + current->pid, mm, vma, address, write_access, page_table, pmd); pte_unmap(page_table); spin_unlock(&mm->page_table_lock); @@ -1472,10 +1489,10 @@ retry: /* no page was available -- either SIGBUS or OOM */ if (page == NOPAGE_SIGBUS) { - printk("return VM_FAULT_SIGBUS from do_no_page()\n"); + printk("%d: return VM_FAULT_SIGBUS from do_no_page()\n", current->pid); return VM_FAULT_SIGBUS; } else if (page == NOPAGE_OOM) { - printk("return VM_FAULT_OOM from do_no_page()\n"); + printk("%d: return VM_FAULT_OOM from do_no_page()\n", current->pid); return VM_FAULT_OOM; } @@ -1486,17 +1503,19 @@ retry: /* * Should we do an early C-O-W break? */ - if (write_access && !(vma->vm_flags & VM_SHARED)) { - if (page_count(page) > 1 || PageReserved(page)) { - new_page = alloc_page(GFP_HIGHUSER); - if (!new_page) { - page_cache_release(page); - goto oom; - } - lru_cache_add_active(new_page); + if ((write_access && !(vma->vm_flags & VM_SHARED)) && + (page_count(page) > 1 || PageReserved(page))) { + new_page = alloc_page(GFP_HIGHUSER); + printk("%d: allocated page at 0x%lx\n", + current->pid, + page_to_pfn(new_page)); + if (!new_page) { + page_cache_release(page); + goto oom; } + lru_cache_add_active(new_page); } else - new_page = page; + new_page = NULL; spin_lock(&mm->page_table_lock); /* @@ -1549,7 +1568,7 @@ oom: ret = VM_FAULT_OOM; out: pte_chain_free(pte_chain); - printk("return %d from do_no_page()\n", ret); + printk("%d: return %d from do_no_page()\n", current->pid, ret); return ret; } @@ -1564,8 +1583,8 @@ static int do_file_page(struct mm_struct unsigned long pgoff; int err; - printk("do_file_page(%p, %p, %lx, %d, %p, %p)\n", - mm, vma, address, write_access, pte, pmd); + printk("%d: do_file_page(%p, %p, %lx, %d, %p, %p)\n", + current->pid, mm, vma, address, write_access, pte, pmd); BUG_ON(!vma->vm_ops || !vma->vm_ops->nopage); /* @@ -1584,7 +1603,7 @@ static int do_file_page(struct mm_struct spin_unlock(&mm->page_table_lock); err = vma->vm_ops->populate(vma, address & MMUPAGE_MASK, MMUPAGE_SIZE, vma->vm_page_prot, pgoff, 0); - printk("return from do_file_page()\n"); + printk("%d: return from do_file_page()\n", current->pid); if (err == -ENOMEM) return VM_FAULT_OOM; if (err) @@ -1658,8 +1677,11 @@ int handle_mm_fault(struct mm_struct *mm pgd_t *pgd; pmd_t *pmd; - printk("handle_mm_fault(%p, %p, %lx, %d)\n", - mm, vma, address, write_access); + address &= MMUPAGE_MASK; + + printk("%d: handle_mm_fault(%p, %p = [%lx, %lx), %lx, %d)\n", + current->pid, mm, vma, vma->vm_start, vma->vm_end, + address, write_access); __set_current_state(TASK_RUNNING); pgd = pgd_offset(mm, address); diff -urpN pgcl-2.6.0-test5-bk3-3/mm/mmap.c pgcl-2.6.0-test5-bk3-4/mm/mmap.c --- pgcl-2.6.0-test5-bk3-3/mm/mmap.c 2003-11-05 18:48:01.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/mm/mmap.c 2003-11-05 18:50:36.000000000 -0800 @@ -923,7 +923,8 @@ int expand_stack(struct vm_area_struct * * is required to hold the mmap_sem in read mode. We need to get * the spinlock only before relocating the vma range ourself. */ - address &= MMUPAGE_MASK; + /* address &= MMUPAGE_MASK; */ + address &= PAGE_MASK; spin_lock(&vma->vm_mm->page_table_lock); grow = (vma->vm_start - address) >> MMUPAGE_SHIFT; diff -urpN pgcl-2.6.0-test5-bk3-3/mm/page_alloc.c pgcl-2.6.0-test5-bk3-4/mm/page_alloc.c --- pgcl-2.6.0-test5-bk3-3/mm/page_alloc.c 2003-11-05 18:48:01.000000000 -0800 +++ pgcl-2.6.0-test5-bk3-4/mm/page_alloc.c 2003-11-05 18:50:36.000000000 -0800 @@ -72,7 +72,8 @@ static int bad_range(struct zone *zone, static void bad_page(const char *function, struct page *page) { - printk("Bad page state for 0x%p at %s\n", page, function); + printk("Bad page state for 0x%p (pfn=0x%lx) at %s\n", + page, page_to_pfn(page), function); printk("flags:0x%08lx mapping:%p mapped:%d count:%d\n", page->flags, page->mapping, page_mapped(page), page_count(page));