diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-04-05 04:55:58 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-04-05 04:55:58 +0000 |
commit | 74a9f2e1b4d3ab45a9f72cb5b556c9f521524ab3 (patch) | |
tree | 7c4cdb103ab1b388c9852a88bd6fb1e73eba0b5c /arch/sparc | |
parent | ee6374c8b0d333c08061c6a97bc77090d7461225 (diff) |
Merge with Linux 2.4.3.
Note that mingetty does no longer work with serial console, you have to
switch to another getty like getty_ps. This commit also includes a
fix for a setitimer bug which did prevent getty_ps from working on
older kernels.
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/defconfig | 5 | ||||
-rw-r--r-- | arch/sparc/kernel/ptrace.c | 73 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc.c | 10 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sunos.c | 10 | ||||
-rw-r--r-- | arch/sparc/mm/fault.c | 20 | ||||
-rw-r--r-- | arch/sparc/mm/init.c | 230 | ||||
-rw-r--r-- | arch/sparc/mm/srmmu.c | 40 | ||||
-rw-r--r-- | arch/sparc/mm/sun4c.c | 32 |
8 files changed, 220 insertions, 200 deletions
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index 20c0782e7..79e281b96 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -105,8 +105,8 @@ CONFIG_SUN_AURORA=m # # CONFIG_SPARCAUDIO is not set # CONFIG_SPARCAUDIO_AMD7930 is not set -# CONFIG_SPARCAUDIO_CS4231 is not set # CONFIG_SPARCAUDIO_DBRI is not set +# CONFIG_SPARCAUDIO_CS4231 is not set # CONFIG_SPARCAUDIO_DUMMY is not set # @@ -126,7 +126,6 @@ CONFIG_BLK_DEV_NBD=m # CONFIG_MD_RAID1 is not set # CONFIG_MD_RAID5 is not set # CONFIG_BLK_DEV_LVM is not set -# CONFIG_LVM_PROC_FS is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y @@ -266,6 +265,8 @@ CONFIG_UNIX98_PTY_COUNT=256 # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set CONFIG_AFFS_FS=m diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index cba111a71..32f418f99 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -305,7 +305,13 @@ asmlinkage void do_ptrace(struct pt_regs *regs) goto out; } #endif - if(!(child = find_task_by_pid(pid))) { + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + + if (!child) { pt_error_return(regs, ESRCH); goto out; } @@ -319,7 +325,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) * You'll never be able to kill the process. ;-) */ pt_error_return(regs, EPERM); - goto out; + goto out_tsk; } if((!child->dumpable || (current->uid != child->euid) || @@ -330,12 +336,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs) (!cap_issubset(child->cap_permitted, current->cap_permitted)) || (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) { pt_error_return(regs, EPERM); - goto out; + goto out_tsk; } /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) { pt_error_return(regs, EPERM); - goto out; + goto out_tsk; } child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); @@ -347,21 +353,21 @@ asmlinkage void do_ptrace(struct pt_regs *regs) write_unlock_irqrestore(&tasklist_lock, flags); send_sig(SIGSTOP, child, 1); pt_succ_return(regs, 0); - goto out; + goto out_tsk; } if (!(child->ptrace & PT_PTRACED)) { pt_error_return(regs, ESRCH); - goto out; + goto out_tsk; } if(child->state != TASK_STOPPED) { if(request != PTRACE_KILL) { pt_error_return(regs, ESRCH); - goto out; + goto out_tsk; } } if(child->p_pptr != current) { pt_error_return(regs, ESRCH); - goto out; + goto out_tsk; } switch(request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -373,16 +379,16 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_os_succ_return(regs, tmp, (long *)data); else pt_error_return(regs, EIO); - goto out; + goto out_tsk; } case PTRACE_PEEKUSR: read_sunos_user(regs, addr, child, (long *) data); - goto out; + goto out_tsk; case PTRACE_POKEUSR: write_sunos_user(regs, addr, child); - goto out; + goto out_tsk; case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: { @@ -391,7 +397,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_succ_return(regs, 0); else pt_error_return(regs, EIO); - goto out; + goto out_tsk; } case PTRACE_GETREGS: { @@ -402,7 +408,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) rval = verify_area(VERIFY_WRITE, pregs, sizeof(struct pt_regs)); if(rval) { pt_error_return(regs, -rval); - goto out; + goto out_tsk; } __put_user(cregs->psr, (&pregs->psr)); __put_user(cregs->pc, (&pregs->pc)); @@ -414,7 +420,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) #ifdef DEBUG_PTRACE printk ("PC=%x nPC=%x o7=%x\n", cregs->pc, cregs->npc, cregs->u_regs [15]); #endif - goto out; + goto out_tsk; } case PTRACE_SETREGS: { @@ -429,7 +435,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) i = verify_area(VERIFY_READ, pregs, sizeof(struct pt_regs)); if(i) { pt_error_return(regs, -i); - goto out; + goto out_tsk; } __get_user(psr, (&pregs->psr)); __get_user(pc, (&pregs->pc)); @@ -446,7 +452,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) for(i = 1; i < 16; i++) __get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])); pt_succ_return(regs, 0); - goto out; + goto out_tsk; } case PTRACE_GETFPREGS: { @@ -466,7 +472,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) i = verify_area(VERIFY_WRITE, fps, sizeof(struct fps)); if(i) { pt_error_return(regs, -i); - goto out; + goto out_tsk; } for(i = 0; i < 32; i++) __put_user(child->thread.float_regs[i], (&fps->regs[i])); @@ -480,7 +486,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) __put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); } pt_succ_return(regs, 0); - goto out; + goto out_tsk; } case PTRACE_SETFPREGS: { @@ -500,7 +506,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) i = verify_area(VERIFY_READ, fps, sizeof(struct fps)); if(i) { pt_error_return(regs, -i); - goto out; + goto out_tsk; } copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long))); __get_user(child->thread.fsr, (&fps->fsr)); @@ -511,7 +517,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) __get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); } pt_succ_return(regs, 0); - goto out; + goto out_tsk; } case PTRACE_READTEXT: @@ -520,13 +526,13 @@ asmlinkage void do_ptrace(struct pt_regs *regs) if (res == data) { pt_succ_return(regs, 0); - goto out; + goto out_tsk; } /* Partial read is an IO failure */ if (res >= 0) res = -EIO; pt_error_return(regs, -res); - goto out; + goto out_tsk; } case PTRACE_WRITETEXT: @@ -535,13 +541,13 @@ asmlinkage void do_ptrace(struct pt_regs *regs) if (res == data) { pt_succ_return(regs, 0); - goto out; + goto out_tsk; } /* Partial write is an IO failure */ if (res >= 0) res = -EIO; pt_error_return(regs, -res); - goto out; + goto out_tsk; } case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ @@ -550,12 +556,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_CONT: { /* restart after signal. */ if ((unsigned long) data > _NSIG) { pt_error_return(regs, EIO); - goto out; + goto out_tsk; } if (addr != 1) { if (addr & 3) { pt_error_return(regs, EINVAL); - goto out; + goto out_tsk; } #ifdef DEBUG_PTRACE printk ("Original: %08lx %08lx\n", child->thread.kregs->pc, child->thread.kregs->npc); @@ -580,7 +586,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) #endif wake_up_process(child); pt_succ_return(regs, 0); - goto out; + goto out_tsk; } /* @@ -591,19 +597,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_KILL: { if (child->state == TASK_ZOMBIE) { /* already dead */ pt_succ_return(regs, 0); - goto out; + goto out_tsk; } wake_up_process(child); child->exit_code = SIGKILL; pt_succ_return(regs, 0); - goto out; + goto out_tsk; } case PTRACE_SUNDETACH: { /* detach a process that was attached. */ unsigned long flags; if ((unsigned long) data > _NSIG) { pt_error_return(regs, EIO); - goto out; + goto out_tsk; } child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); wake_up_process(child); @@ -614,15 +620,18 @@ asmlinkage void do_ptrace(struct pt_regs *regs) SET_LINKS(child); write_unlock_irqrestore(&tasklist_lock, flags); pt_succ_return(regs, 0); - goto out; + goto out_tsk; } /* PTRACE_DUMPCORE unsupported... */ default: pt_error_return(regs, EIO); - goto out; + goto out_tsk; } +out_tsk: + if (child) + free_task_struct(child); out: unlock_kernel(); } diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 498fdb26f..3b71c98e1 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.67 2000/11/30 08:37:31 anton Exp $ +/* $Id: sys_sparc.c,v 1.68 2001/03/24 09:36:10 davem Exp $ * linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that @@ -236,9 +236,9 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len, if (flags & MAP_SHARED) current->thread.flags |= SPARC_FLAG_MMAPSHARED; - down(¤t->mm->mmap_sem); + down_write(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up(¤t->mm->mmap_sem); + up_write(¤t->mm->mmap_sem); current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED); @@ -284,7 +284,7 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr, if (old_len > TASK_SIZE - PAGE_SIZE || new_len > TASK_SIZE - PAGE_SIZE) goto out; - down(¤t->mm->mmap_sem); + down_write(¤t->mm->mmap_sem); vma = find_vma(current->mm, addr); if (vma && (vma->vm_flags & VM_SHARED)) current->thread.flags |= SPARC_FLAG_MMAPSHARED; @@ -309,7 +309,7 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr, ret = do_mremap(addr, old_len, new_len, flags, new_addr); out_sem: current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED); - up(¤t->mm->mmap_sem); + up_write(¤t->mm->mmap_sem); out: return ret; } diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index adaae6062..5a9b4752a 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.132 2001/02/13 01:16:43 davem Exp $ +/* $Id: sys_sunos.c,v 1.133 2001/03/24 09:36:10 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -116,9 +116,9 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len, } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down(¤t->mm->mmap_sem); + down_write(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); - up(¤t->mm->mmap_sem); + up_write(¤t->mm->mmap_sem); if(!ret_type) retval = ((retval < PAGE_OFFSET) ? 0 : retval); @@ -145,7 +145,7 @@ asmlinkage int sunos_brk(unsigned long brk) unsigned long rlim; unsigned long newbrk, oldbrk; - down(¤t->mm->mmap_sem); + down_write(¤t->mm->mmap_sem); if(ARCH_SUN4C_SUN4) { if(brk >= 0x20000000 && brk < 0xe0000000) { goto out; @@ -208,7 +208,7 @@ asmlinkage int sunos_brk(unsigned long brk) do_brk(oldbrk, newbrk-oldbrk); retval = 0; out: - up(¤t->mm->mmap_sem); + up_write(¤t->mm->mmap_sem); return retval; } diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c index 1521d3246..764bca89b 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.118 2000/12/29 07:52:41 anton Exp $ +/* $Id: fault.c,v 1.119 2001/03/24 09:36:10 davem Exp $ * fault.c: Page fault handlers for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -224,7 +224,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, if (in_interrupt() || !mm) goto no_context; - down(&mm->mmap_sem); + down_read(&mm->mmap_sem); /* * The kernel referencing a bad kernel pointer can lock up @@ -274,7 +274,7 @@ good_area: default: goto out_of_memory; } - up(&mm->mmap_sem); + up_read(&mm->mmap_sem); return; /* @@ -282,7 +282,7 @@ good_area: * Fix it, but check if it's kernel or user first.. */ bad_area: - up(&mm->mmap_sem); + up_read(&mm->mmap_sem); bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ @@ -338,14 +338,14 @@ no_context: * us unable to handle the page fault gracefully. */ out_of_memory: - up(&mm->mmap_sem); + up_read(&mm->mmap_sem); printk("VM: killing process %s\n", tsk->comm); if (from_user) do_exit(SIGKILL); goto no_context; do_sigbus: - up(&mm->mmap_sem); + up_read(&mm->mmap_sem); info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRERR; @@ -479,7 +479,7 @@ inline void force_user_fault(unsigned long address, int write) printk("wf<pid=%d,wr=%d,addr=%08lx>\n", tsk->pid, write, address); #endif - down(&mm->mmap_sem); + down_read(&mm->mmap_sem); vma = find_vma(mm, address); if(!vma) goto bad_area; @@ -500,10 +500,10 @@ good_area: } if (!handle_mm_fault(mm, vma, address, write)) goto do_sigbus; - up(&mm->mmap_sem); + up_read(&mm->mmap_sem); return; bad_area: - up(&mm->mmap_sem); + up_read(&mm->mmap_sem); #if 0 printk("Window whee %s [%d]: segfaults at %08lx\n", tsk->comm, tsk->pid, address); @@ -518,7 +518,7 @@ bad_area: return; do_sigbus: - up(&mm->mmap_sem); + up_read(&mm->mmap_sem); info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRERR; diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index d27495bd6..89807b38a 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -1,10 +1,10 @@ -/* $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $ +/* $Id: init.c,v 1.97 2001/02/26 02:57:34 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) + * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au) */ #include <linux/config.h> @@ -53,7 +53,7 @@ extern unsigned int sparc_ramdisk_size; unsigned long highstart_pfn, highend_pfn; unsigned long totalram_pages; -static unsigned long totalhigh_pages; +unsigned long totalhigh_pages; /* * BAD_PAGE is the page that is used for page faults when linux @@ -134,42 +134,79 @@ void __init sparc_context_init(int numctx) #define DEBUG_BOOTMEM extern unsigned long cmdline_memory_size; -extern unsigned long last_valid_pfn; +unsigned long last_valid_pfn; + +unsigned long calc_highpages(void) +{ + int i; + int nr = 0; + + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; + unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; + + if (end_pfn <= max_low_pfn) + continue; + + if (start_pfn < max_low_pfn) + start_pfn = max_low_pfn; + + nr += end_pfn - start_pfn; + } + + return nr; +} + +unsigned long calc_max_low_pfn(void) +{ + int i; + unsigned long tmp = (SRMMU_MAXMEM >> PAGE_SHIFT); + unsigned long curr_pfn, last_pfn; + + last_pfn = (sp_banks[0].base_addr + sp_banks[0].num_bytes) >> PAGE_SHIFT; + for (i = 1; sp_banks[i].num_bytes != 0; i++) { + curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; -void __init bootmem_init(void) + if (curr_pfn >= tmp) { + if (last_pfn < tmp) + tmp = last_pfn; + break; + } + + last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; + } + + return tmp; +} + +unsigned long __init bootmem_init(unsigned long *pages_avail) { unsigned long bootmap_size, start_pfn, max_pfn; unsigned long end_of_phys_memory = 0UL; - unsigned long bootmap_pfn; + unsigned long bootmap_pfn, bytes_avail, size; int i; - /* XXX It is a bit ambiguous here, whether we should - * XXX treat the user specified mem=xxx as total wanted - * XXX physical memory, or as a limit to the upper - * XXX physical address we allow. For now it is the - * XXX latter. -DaveM - */ #ifdef DEBUG_BOOTMEM prom_printf("bootmem_init: Scan sp_banks, "); #endif + bytes_avail = 0UL; for (i = 0; sp_banks[i].num_bytes != 0; i++) { end_of_phys_memory = sp_banks[i].base_addr + sp_banks[i].num_bytes; + bytes_avail += sp_banks[i].num_bytes; if (cmdline_memory_size) { - if (end_of_phys_memory > cmdline_memory_size) { - if (cmdline_memory_size < sp_banks[i].base_addr) { - end_of_phys_memory = - sp_banks[i-1].base_addr + - sp_banks[i-1].num_bytes; + if (bytes_avail > cmdline_memory_size) { + unsigned long slack = bytes_avail - cmdline_memory_size; + + bytes_avail -= slack; + end_of_phys_memory -= slack; + + sp_banks[i].num_bytes -= slack; + if (sp_banks[i].num_bytes == 0) { sp_banks[i].base_addr = 0xdeadbeef; - sp_banks[i].num_bytes = 0; } else { - sp_banks[i].num_bytes -= - (end_of_phys_memory - - cmdline_memory_size); - end_of_phys_memory = cmdline_memory_size; - sp_banks[++i].base_addr = 0xdeadbeef; - sp_banks[i].num_bytes = 0; + sp_banks[i+1].num_bytes = 0; + sp_banks[i+1].base_addr = 0xdeadbeef; } break; } @@ -195,9 +232,9 @@ void __init bootmem_init(void) highstart_pfn = highend_pfn = max_pfn; if (max_low_pfn > (SRMMU_MAXMEM >> PAGE_SHIFT)) { - highstart_pfn = max_low_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT); - printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", - (highend_pfn - highstart_pfn) >> (20-PAGE_SHIFT)); + highstart_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT); + max_low_pfn = calc_max_low_pfn(); + printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", calc_highpages()); } #ifdef CONFIG_BLK_DEV_INITRD @@ -225,13 +262,14 @@ void __init bootmem_init(void) prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],mlpfn[%lx])\n", start_pfn, bootmap_pfn, max_low_pfn); #endif - bootmap_size = init_bootmem(bootmap_pfn, max_low_pfn); + bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, phys_base>>PAGE_SHIFT, max_low_pfn); /* Now register the available physical memory with the * allocator. */ + *pages_avail = 0; for (i = 0; sp_banks[i].num_bytes != 0; i++) { - unsigned long curr_pfn, last_pfn, size; + unsigned long curr_pfn, last_pfn; curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; if (curr_pfn >= max_low_pfn) @@ -249,7 +287,7 @@ void __init bootmem_init(void) continue; size = (last_pfn - curr_pfn) << PAGE_SHIFT; - + *pages_avail += last_pfn - curr_pfn; #ifdef DEBUG_BOOTMEM prom_printf("free_bootmem: base[%lx] size[%lx]\n", sp_banks[i].base_addr, @@ -259,29 +297,42 @@ void __init bootmem_init(void) size); } - /* Reserve the kernel text/data/bss, the bootmem bitmap and initrd. */ -#ifdef DEBUG_BOOTMEM #ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) + if (initrd_start) { + size = initrd_end - initrd_start; +#ifdef DEBUG_BOOTMEM prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - initrd_start, initrd_end - initrd_start); + initrd_start, size); #endif - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - phys_base, (start_pfn << PAGE_SHIFT) - phys_base); - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - (bootmap_pfn << PAGE_SHIFT), bootmap_size); -#endif -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) { - reserve_bootmem(initrd_start, initrd_end - initrd_start); + /* Reserve the initrd image area. */ + reserve_bootmem(initrd_start, size); + *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + initrd_start += PAGE_OFFSET; initrd_end += PAGE_OFFSET; } #endif - reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base); - reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size); + /* Reserve the kernel text/data/bss. */ + size = (start_pfn << PAGE_SHIFT) - phys_base; +#ifdef DEBUG_BOOTMEM + prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", phys_base, size); +#endif + reserve_bootmem(phys_base, size); + *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + + /* Reserve the bootmem map. We do not account for it + * in pages_avail because we will release that memory + * in free_all_bootmem. + */ + size = bootmap_size; +#ifdef DEBUG_BOOTMEM + prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", + (bootmap_pfn << PAGE_SHIFT), size); +#endif + reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size); + *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; - last_valid_pfn = max_pfn; + return max_pfn; } /* @@ -293,8 +344,6 @@ extern void sun4c_paging_init(void); extern void srmmu_paging_init(void); extern void device_scan(void); -unsigned long last_valid_pfn; - void __init paging_init(void) { switch(sparc_cpu_model) { @@ -359,71 +408,6 @@ static void __init taint_real_pages(void) } } -void __init free_mem_map_range(struct page *first, struct page *last) -{ - first = (struct page *) PAGE_ALIGN((unsigned long)first); - last = (struct page *) ((unsigned long)last & PAGE_MASK); -#ifdef DEBUG_BOOTMEM - prom_printf("[%p,%p] ", first, last); -#endif - while (first < last) { - ClearPageReserved(virt_to_page(first)); - set_page_count(virt_to_page(first), 1); - free_page((unsigned long)first); - totalram_pages++; - num_physpages++; - - first = (struct page *)((unsigned long)first + PAGE_SIZE); - } -} - -/* Walk through holes in sp_banks regions, if the mem_map array - * areas representing those holes consume a page or more, free - * up such pages. This helps a lot on machines where physical - * ram is configured such that it begins at some hugh value. - * - * The sp_banks array is sorted by base address. - */ -void __init free_unused_mem_map(void) -{ - int i; - -#ifdef DEBUG_BOOTMEM - prom_printf("free_unused_mem_map: "); -#endif - for (i = 0; sp_banks[i].num_bytes; i++) { - if (i == 0) { - struct page *first, *last; - - first = mem_map; - last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT]; - free_mem_map_range(first, last); - } else { - struct page *first, *last; - unsigned long prev_end; - - prev_end = sp_banks[i-1].base_addr + - sp_banks[i-1].num_bytes; - prev_end = PAGE_ALIGN(prev_end); - first = &mem_map[prev_end >> PAGE_SHIFT]; - last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT]; - - free_mem_map_range(first, last); - - if (!sp_banks[i+1].num_bytes) { - prev_end = sp_banks[i].base_addr + - sp_banks[i].num_bytes; - first = &mem_map[prev_end >> PAGE_SHIFT]; - last = &mem_map[last_valid_pfn]; - free_mem_map_range(first, last); - } - } - } -#ifdef DEBUG_BOOTMEM - prom_printf("\n"); -#endif -} - void map_high_region(unsigned long start_pfn, unsigned long end_pfn) { unsigned long tmp; @@ -458,9 +442,8 @@ void __init mem_init(void) /* Saves us work later. */ memset((void *)&empty_zero_page, 0, PAGE_SIZE); - i = last_valid_pfn >> (8 + 5); + i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5); i += 1; - sparc_valid_addr_bitmap = (unsigned long *) __alloc_bootmem(i << 2, SMP_CACHE_BYTES, 0UL); @@ -472,7 +455,7 @@ void __init mem_init(void) taint_real_pages(); - max_mapnr = last_valid_pfn; + max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT); high_memory = __va(max_low_pfn << PAGE_SHIFT); #ifdef DEBUG_BOOTMEM @@ -480,10 +463,6 @@ void __init mem_init(void) #endif num_physpages = totalram_pages = free_all_bootmem(); -#if 0 - free_unused_mem_map(); -#endif - for (i = 0; sp_banks[i].num_bytes != 0; i++) { unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; @@ -513,19 +492,6 @@ void __init mem_init(void) initpages << (PAGE_SHIFT-10), totalhigh_pages << (PAGE_SHIFT-10), (unsigned long)PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); - - /* NOTE NOTE NOTE NOTE - * Please keep track of things and make sure this - * always matches the code in mm/page_alloc.c -DaveM - */ - i = nr_free_pages() >> 7; - if (i < 48) - i = 48; - if (i > 256) - i = 256; - freepages.min = i; - freepages.low = i << 1; - freepages.high = freepages.low + i; } void free_initmem (void) diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index a5b2b117b..e2b6116ff 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.226 2001/02/13 01:16:44 davem Exp $ +/* $Id: srmmu.c,v 1.228 2001/03/16 06:56:20 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1124,6 +1124,15 @@ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry) unsigned long pstart = (sp_banks[sp_entry].base_addr & SRMMU_PGDIR_MASK); unsigned long vstart = (vbase & SRMMU_PGDIR_MASK); unsigned long vend = SRMMU_PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes); + /* Map "low" memory only */ + const unsigned long min_vaddr = PAGE_OFFSET; + const unsigned long max_vaddr = PAGE_OFFSET + SRMMU_MAXMEM; + + if (vstart < min_vaddr || vstart >= max_vaddr) + return vstart; + + if (vend > max_vaddr || vend < min_vaddr) + vend = max_vaddr; while(vstart < vend) { do_large_mapping(vstart, pstart); @@ -1159,10 +1168,11 @@ static inline void map_kernel(void) extern void sparc_context_init(int); extern int linux_num_cpus; +extern unsigned long totalhigh_pages; void (*poke_srmmu)(void) __initdata = NULL; -extern void bootmem_init(void); +extern unsigned long bootmem_init(unsigned long *pages_avail); extern void sun_serial_setup(void); void __init srmmu_paging_init(void) @@ -1172,6 +1182,7 @@ void __init srmmu_paging_init(void) pgd_t *pgd; pmd_t *pmd; pte_t *pte; + unsigned long pages_avail; sparc_iomap.start = SUN4M_IOBASE_VADDR; /* 16MB of IOSPACE on all sun4m's. */ @@ -1196,7 +1207,8 @@ void __init srmmu_paging_init(void) prom_halt(); } - bootmem_init(); + pages_avail = 0; + last_valid_pfn = bootmem_init(&pages_avail); srmmu_nocache_init(); srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE)); @@ -1245,11 +1257,25 @@ void __init srmmu_paging_init(void) kmap_init(); { - unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0}; + unsigned long zones_size[MAX_NR_ZONES]; + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long npages; + int znum; + + for (znum = 0; znum < MAX_NR_ZONES; znum++) + zones_size[znum] = zholes_size[znum] = 0; + + npages = max_low_pfn - (phys_base >> PAGE_SHIFT); + + zones_size[ZONE_DMA] = npages; + zholes_size[ZONE_DMA] = npages - pages_avail; + + npages = highend_pfn - max_low_pfn; + zones_size[ZONE_HIGHMEM] = npages; + zholes_size[ZONE_HIGHMEM] = npages - calc_highpages(); - zones_size[ZONE_DMA] = max_low_pfn; - zones_size[ZONE_HIGHMEM] = highend_pfn - max_low_pfn; - free_area_init(zones_size); + free_area_init_node(0, NULL, NULL, zones_size, + phys_base, zholes_size); } } diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index ef5157b05..91a1d571e 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.202 2000/12/01 03:17:31 anton Exp $ +/* $Id: sun4c.c,v 1.205 2001/03/16 06:57:41 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -15,6 +15,7 @@ #include <linux/mm.h> #include <linux/init.h> #include <linux/bootmem.h> +#include <linux/highmem.h> #include <asm/scatterlist.h> #include <asm/page.h> @@ -31,6 +32,7 @@ #include <asm/openprom.h> #include <asm/mmu_context.h> #include <asm/sun4paddr.h> +#include <asm/highmem.h> /* Because of our dynamic kernel TLB miss strategy, and how * our DVMA mapping allocation works, you _MUST_: @@ -2432,7 +2434,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p extern void sparc_context_init(int); extern unsigned long end; -extern void bootmem_init(void); +extern unsigned long bootmem_init(unsigned long *pages_avail); extern unsigned long last_valid_pfn; extern void sun_serial_setup(void); @@ -2441,13 +2443,14 @@ void __init sun4c_paging_init(void) int i, cnt; unsigned long kernel_end, vaddr; extern struct resource sparc_iomap; - unsigned long end_pfn; + unsigned long end_pfn, pages_avail; kernel_end = (unsigned long) &end; kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4); kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end); - bootmem_init(); + pages_avail = 0; + last_valid_pfn = bootmem_init(&pages_avail); end_pfn = last_valid_pfn; /* This does not logically belong here, but we need to @@ -2488,10 +2491,25 @@ void __init sun4c_paging_init(void) sparc_context_init(num_contexts); { - unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0}; + unsigned long zones_size[MAX_NR_ZONES]; + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long npages; + int znum; - zones_size[ZONE_DMA] = end_pfn; - free_area_init(zones_size); + for (znum = 0; znum < MAX_NR_ZONES; znum++) + zones_size[znum] = zholes_size[znum] = 0; + + npages = max_low_pfn - (phys_base >> PAGE_SHIFT); + + zones_size[ZONE_DMA] = npages; + zholes_size[ZONE_DMA] = npages - pages_avail; + + npages = highend_pfn - max_low_pfn; + zones_size[ZONE_HIGHMEM] = npages; + zholes_size[ZONE_HIGHMEM] = npages - calc_highpages(); + + free_area_init_node(0, NULL, NULL, zones_size, + phys_base, zholes_size); } cnt = 0; |