diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 22:06:10 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 22:06:10 +0000 |
commit | aba4e552a2f2c1492441acbccedd8e0a4c53f916 (patch) | |
tree | 23921efb2b4af590160f034a89ff3da2ecca6e47 /arch/sparc64/mm | |
parent | 9e17e1aa1cf1cb497d2f67147a51831888affcf3 (diff) |
Merge with Linux 2.3.43.
Diffstat (limited to 'arch/sparc64/mm')
-rw-r--r-- | arch/sparc64/mm/Makefile | 4 | ||||
-rw-r--r-- | arch/sparc64/mm/asyncd.c | 283 |
2 files changed, 2 insertions, 285 deletions
diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile index a7448f1db..d97c47778 100644 --- a/arch/sparc64/mm/Makefile +++ b/arch/sparc64/mm/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.5 1998/07/26 03:02:54 davem Exp $ +# $Id: Makefile,v 1.6 2000/01/31 01:30:49 davem Exp $ # Makefile for the linux Sparc64-specific parts of the memory manager. # # Note! Dependencies are done automagically by 'make dep', which also @@ -14,6 +14,6 @@ $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o O_TARGET := mm.o -O_OBJS := ultra.o fault.o init.o generic.o asyncd.o extable.o modutil.o +O_OBJS := ultra.o fault.o init.o generic.o extable.o modutil.o include $(TOPDIR)/Rules.make diff --git a/arch/sparc64/mm/asyncd.c b/arch/sparc64/mm/asyncd.c deleted file mode 100644 index b87efd590..000000000 --- a/arch/sparc64/mm/asyncd.c +++ /dev/null @@ -1,283 +0,0 @@ -/* $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. - * - * Idea and skeleton code courtesy of David Miller (bless his cotton socks) - * - * Implemented by tridge - */ - -#include <linux/mm.h> -#include <linux/malloc.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/kernel_stat.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/stat.h> -#include <linux/swap.h> -#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() */ -#include <asm/segment.h> /* for memcpy_to/fromfs */ -#include <asm/bitops.h> -#include <asm/pgalloc.h> -#include <asm/pgtable.h> - -#define DEBUG 0 - -#define WRITE_LIMIT 100 -#define LOOP_LIMIT 200 - -static struct { - int faults, read, write, success, failure, errors; -} stats; - -/* - * The wait queue for waking up the async daemon: - */ -static DECLARE_WAIT_QUEUE_HEAD(asyncd_wait); - -struct async_job { - volatile struct async_job *next; - int taskid; - struct mm_struct *mm; - unsigned long address; - int write; - void (*callback)(int,unsigned long,int,int); -}; - -static volatile struct async_job *async_queue = NULL; -static volatile struct async_job *async_queue_end = NULL; - -static void add_to_async_queue(int taskid, - struct mm_struct *mm, - unsigned long address, - int write, - void (*callback)(int,unsigned long,int,int)) -{ - struct async_job *a = kmalloc(sizeof(*a),GFP_ATOMIC); - - if (!a) { - printk("ERROR: out of memory in asyncd\n"); - a->callback(taskid,address,write,1); - return; - } - - if (write) - stats.write++; - else - stats.read++; - - a->next = NULL; - a->taskid = taskid; - a->mm = mm; - a->address = address; - a->write = write; - a->callback = callback; - - if (!async_queue) { - async_queue = a; - } else { - async_queue_end->next = a; - } - async_queue_end = a; -} - - -void async_fault(unsigned long address, int write, int taskid, - void (*callback)(int,unsigned long,int,int)) -{ -#warning Need some fixing here... -DaveM - struct task_struct *tsk = current /* XXX task[taskid] */; - struct mm_struct *mm = tsk->mm; - - stats.faults++; - -#if 0 - printk("paging in %x for task=%d\n",address,taskid); -#endif - - add_to_async_queue(taskid, mm, address, write, callback); - wake_up(&asyncd_wait); - mark_bh(TQUEUE_BH); -} - -static int fault_in_page(int taskid, - struct vm_area_struct *vma, - unsigned long address, int write) -{ - 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; - pmd_t *pmd; - pte_t *pte; - - if (!tsk || !tsk->mm) - return 1; - - if (!vma || (write && !(vma->vm_flags & VM_WRITE))) - goto bad_area; - if (vma->vm_start > address) - goto bad_area; - - if (address == last_address && taskid == last_task) { - loop_counter++; - } else { - loop_counter = 0; - last_address = address; - last_task = taskid; - } - - if (loop_counter == WRITE_LIMIT && !write) { - printk("MSC bug? setting write request\n"); - stats.errors++; - write = 1; - } - - if (loop_counter == LOOP_LIMIT) { - printk("MSC bug? failing request\n"); - stats.errors++; - return 1; - } - - pgd = pgd_offset(vma->vm_mm, address); - pmd = pmd_alloc(pgd,address); - if(!pmd) - goto no_memory; - pte = pte_alloc(pmd, address); - if(!pte) - goto no_memory; - if(!pte_present(*pte)) { - handle_mm_fault(tsk, vma, address, write); - goto finish_up; - } - set_pte(pte, pte_mkyoung(*pte)); - flush_tlb_page(vma, address); - if(!write) - goto finish_up; - if(pte_write(*pte)) { - set_pte(pte, pte_mkdirty(*pte)); - flush_tlb_page(vma, address); - goto finish_up; - } - handle_mm_fault(tsk, vma, address, write); - - /* Fall through for do_wp_page */ -finish_up: - stats.success++; - return 0; - -no_memory: - stats.failure++; - oom(tsk); - return 1; - -bad_area: - stats.failure++; - 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; -} - - -/* Note the semaphore operations must be done here, and _not_ - * in async_fault(). - */ -static void run_async_queue(void) -{ - int ret; - unsigned flags; - - while (async_queue) { - volatile struct async_job *a; - struct mm_struct *mm; - struct vm_area_struct *vma; - - save_flags(flags); cli(); - a = async_queue; - async_queue = async_queue->next; - restore_flags(flags); - - mm = a->mm; - - down(&mm->mmap_sem); - vma = find_vma(mm, a->address); - ret = fault_in_page(a->taskid,vma,a->address,a->write); -#if DEBUG - printk("fault_in_page(task=%d addr=%x write=%d) = %d\n", - a->taskid,a->address,a->write,ret); -#endif - a->callback(a->taskid,a->address,a->write,ret); - up(&mm->mmap_sem); - kfree_s((void *)a,sizeof(*a)); - } -} - - -#if CONFIG_AP1000 -static void asyncd_info(void) -{ - printk("CID(%d) faults: total=%d read=%d write=%d success=%d fail=%d err=%d\n", - mpp_cid(),stats.faults, stats.read, stats.write, stats.success, - stats.failure, stats.errors); -} -#endif - - -/* - * The background async daemon. - * Started as a kernel thread from the init process. - */ -int asyncd(void *unused) -{ - current->session = 1; - current->pgrp = 1; - sprintf(current->comm, "asyncd"); - - sigfillset(¤t->blocked); /* block all signals */ - recalc_sigpending(current); - - /* Give asyncd a realtime priority. */ - current->policy = SCHED_FIFO; - current->priority = 32; /* Fixme --- we need to standardise our - namings for POSIX.4 realtime scheduling - priorities. */ - - printk("Started asyncd\n"); - -#if CONFIG_AP1000 - bif_add_debug_key('a',asyncd_info,"stats on asyncd"); -#endif - - while (1) { - unsigned flags; - - save_flags(flags); cli(); - - while (!async_queue) { - spin_lock(¤t->sigmask_lock); - flush_signals(current); - spin_unlock(¤t->sigmask_lock); - interruptible_sleep_on(&asyncd_wait); - __sti(); cli(); /* acquire gloabl_irq_lock */ - } - - restore_flags(flags); - - run_async_queue(); - } -} - |