summaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-04-05 04:55:58 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-04-05 04:55:58 +0000
commit74a9f2e1b4d3ab45a9f72cb5b556c9f521524ab3 (patch)
tree7c4cdb103ab1b388c9852a88bd6fb1e73eba0b5c /arch/sparc
parentee6374c8b0d333c08061c6a97bc77090d7461225 (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/defconfig5
-rw-r--r--arch/sparc/kernel/ptrace.c73
-rw-r--r--arch/sparc/kernel/sys_sparc.c10
-rw-r--r--arch/sparc/kernel/sys_sunos.c10
-rw-r--r--arch/sparc/mm/fault.c20
-rw-r--r--arch/sparc/mm/init.c230
-rw-r--r--arch/sparc/mm/srmmu.c40
-rw-r--r--arch/sparc/mm/sun4c.c32
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(&current->mm->mmap_sem);
+ down_write(&current->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- up(&current->mm->mmap_sem);
+ up_write(&current->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(&current->mm->mmap_sem);
+ down_write(&current->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(&current->mm->mmap_sem);
+ up_write(&current->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(&current->mm->mmap_sem);
+ down_write(&current->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, off);
- up(&current->mm->mmap_sem);
+ up_write(&current->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(&current->mm->mmap_sem);
+ down_write(&current->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(&current->mm->mmap_sem);
+ up_write(&current->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;