summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/mm')
-rw-r--r--arch/sparc64/mm/asyncd.c13
-rw-r--r--arch/sparc64/mm/fault.c53
-rw-r--r--arch/sparc64/mm/init.c13
3 files changed, 57 insertions, 22 deletions
diff --git a/arch/sparc64/mm/asyncd.c b/arch/sparc64/mm/asyncd.c
index f23a04ede..b87efd590 100644
--- a/arch/sparc64/mm/asyncd.c
+++ b/arch/sparc64/mm/asyncd.c
@@ -1,4 +1,4 @@
-/* $Id: asyncd.c,v 1.11 2000/01/08 20:22:19 davem Exp $
+/* $Id: asyncd.c,v 1.12 2000/01/21 11:39:13 jj Exp $
* The asyncd kernel daemon. This handles paging on behalf of
* processes that receive page faults due to remote (async) memory
* accesses.
@@ -20,6 +20,7 @@
#include <linux/fs.h>
#include <linux/config.h>
#include <linux/interrupt.h>
+#include <linux/signal.h>
#include <asm/dma.h>
#include <asm/system.h> /* for cli()/sti() */
@@ -113,6 +114,7 @@ static int fault_in_page(int taskid,
{
static unsigned last_address;
static int last_task, loop_counter;
+ siginfo_t info;
#warning Need some fixing here... -DaveM
struct task_struct *tsk = current /* XXX task[taskid] */;
pgd_t *pgd;
@@ -181,9 +183,12 @@ no_memory:
bad_area:
stats.failure++;
- tsk->thread.sig_address = address;
- tsk->thread.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, tsk, 1);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = (void *)address;
+ info.si_trapno = 0;
+ send_sig_info(SIGSEGV, &info, tsk);
return 1;
}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 1835b874f..226246980 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.40 1999/12/01 10:44:53 davem Exp $
+/* $Id: fault.c,v 1.42 2000/01/21 11:39:13 jj Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -149,10 +149,13 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, in
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned int insn = 0;
+ siginfo_t info;
#ifdef DEBUG_LOCKUPS
static unsigned long lastaddr, lastpc;
static int lastwrite, lockcnt;
#endif
+
+ info.si_code = SEGV_MAPERR;
/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -233,6 +236,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, in
* we can handle it..
*/
good_area:
+ info.si_code = SEGV_ACCERR;
if(write) {
if(!(vma->vm_flags & VM_WRITE))
goto bad_area;
@@ -242,8 +246,14 @@ good_area:
goto bad_area;
}
current->mm->segments = (void *) (address & PAGE_SIZE);
- if (!handle_mm_fault(current, vma, address, write))
- goto do_sigbus;
+ {
+ int fault = handle_mm_fault(current, vma, address, write);
+
+ if (fault < 0)
+ goto out_of_memory;
+ if (!fault)
+ goto do_sigbus;
+ }
up(&mm->mmap_sem);
return;
/*
@@ -324,20 +334,45 @@ do_kernel_fault:
while(1)
barrier();
#endif
- current->thread.sig_address = address;
- current->thread.sig_desc = SUBSIG_NOMAPPING;
- force_sig(SIGSEGV, current);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code set above to make clear whether
+ this was a SEGV_MAPERR or SEGV_ACCERR fault. */
+ info.si_addr = (void *)address;
+ info.si_trapno = 0;
+ force_sig_info (SIGSEGV, &info, current);
return;
}
unhandled_fault (address, current, regs);
}
return;
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ up(&mm->mmap_sem);
+ printk("VM: killing process %s\n", current->comm);
+ if (!(regs->tstate & TSTATE_PRIV))
+ do_exit(SIGKILL);
+ goto do_kernel_fault;
+
do_sigbus:
up(&mm->mmap_sem);
- current->thread.sig_address = address;
- current->thread.sig_desc = SUBSIG_MISCERROR;
- force_sig(SIGBUS, current);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ info.si_trapno = 0;
+ force_sig_info (SIGBUS, &info, current);
+
+ /* Kernel mode? Handle exceptions or die */
if (regs->tstate & TSTATE_PRIV)
goto do_kernel_fault;
}
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 1be2716f5..b4306d9ab 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.143 1999/12/16 16:15:14 davem Exp $
+/* $Id: init.c,v 1.144 2000/01/23 07:16:11 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -40,8 +40,6 @@ unsigned long *sparc64_valid_addr_bitmap;
/* Ugly, but necessary... -DaveM */
unsigned long phys_base;
-static unsigned long totalram_pages = 0;
-
/* get_new_mmu_context() uses "cache + 1". */
spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
@@ -125,7 +123,7 @@ void show_mem(void)
show_free_areas();
printk("Free swap: %6dkB\n",
nr_swap_pages << (PAGE_SHIFT-10));
- printk("%ld pages of RAM\n", totalram_pages);
+ printk("%ld pages of RAM\n", num_physpages);
printk("%d free pages\n", nr_free_pages());
printk("%d pages in page table cache\n",pgtable_cache_size);
#ifndef __SMP__
@@ -1088,7 +1086,6 @@ void __init free_mem_map_range(struct page *first, struct page *last)
ClearPageReserved(mem_map + MAP_NR(first));
set_page_count(mem_map + MAP_NR(first), 1);
free_page((unsigned long)first);
- totalram_pages++;
num_physpages++;
first = (struct page *)((unsigned long)first + PAGE_SIZE);
@@ -1180,7 +1177,7 @@ void __init mem_init(void)
#ifdef DEBUG_BOOTMEM
prom_printf("mem_init: Calling free_all_bootmem().\n");
#endif
- num_physpages = totalram_pages = free_all_bootmem();
+ num_physpages = free_all_bootmem();
#if 0
free_unused_mem_map();
#endif
@@ -1202,7 +1199,6 @@ void __init mem_init(void)
memset(empty_pg_dir, 0, sizeof(empty_pg_dir));
addr += alias_base;
free_pgd_fast((pgd_t *)addr);
- totalram_pages++;
num_physpages++;
}
#endif
@@ -1245,14 +1241,13 @@ void free_initmem (void)
ClearPageReserved(p);
set_page_count(p, 1);
__free_page(p);
- totalram_pages++;
num_physpages++;
}
}
void si_meminfo(struct sysinfo *val)
{
- val->totalram = totalram_pages;
+ val->totalram = num_physpages;
val->sharedram = 0;
val->freeram = nr_free_pages();
val->bufferram = atomic_read(&buffermem_pages);