diff options
Diffstat (limited to 'arch/sparc64/mm')
-rw-r--r-- | arch/sparc64/mm/asyncd.c | 13 | ||||
-rw-r--r-- | arch/sparc64/mm/fault.c | 53 | ||||
-rw-r--r-- | arch/sparc64/mm/init.c | 13 |
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); |