summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
commit0ae8dceaebe3659ee0c3352c08125f403e77ebca (patch)
tree5085c389f09da78182b899d19fe1068b619a69dd /arch
parent273767781288c35c9d679e908672b9996cda4c34 (diff)
Merge with 2.3.10.
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/config.in8
-rw-r--r--arch/alpha/kernel/ptrace.c263
-rw-r--r--arch/alpha/kernel/signal.c1
-rw-r--r--arch/alpha/kernel/smp.c2
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/time.c2
-rw-r--r--arch/arm/nwfpe/fpmodule.c1
-rw-r--r--arch/i386/boot/setup.S18
-rw-r--r--arch/i386/config.in8
-rw-r--r--arch/i386/defconfig28
-rw-r--r--arch/i386/kernel/irq.h2
-rw-r--r--arch/i386/kernel/process.c2
-rw-r--r--arch/i386/kernel/ptrace.c217
-rw-r--r--arch/i386/kernel/setup.c23
-rw-r--r--arch/i386/kernel/smp.c2
-rw-r--r--arch/i386/math-emu/fpu_emu.h2
-rw-r--r--arch/i386/mm/fault.c19
-rw-r--r--arch/mips/Makefile3
-rw-r--r--arch/mips/boot/elf2ecoff.c1
-rw-r--r--arch/mips/config.in4
-rw-r--r--arch/mips/defconfig31
-rw-r--r--arch/mips/defconfig-ip22297
-rw-r--r--arch/mips/kernel/irixelf.c75
-rw-r--r--arch/mips/kernel/irixioctl.c19
-rw-r--r--arch/mips/kernel/irixsig.c40
-rw-r--r--arch/mips/kernel/irq.c6
-rw-r--r--arch/mips/kernel/process.c18
-rw-r--r--arch/mips/kernel/ptrace.c233
-rw-r--r--arch/mips/kernel/r2300_fpu.S13
-rw-r--r--arch/mips/kernel/r4k_fpu.S16
-rw-r--r--arch/mips/kernel/r4k_misc.S6
-rw-r--r--arch/mips/kernel/setup.c12
-rw-r--r--arch/mips/kernel/signal.c438
-rw-r--r--arch/mips/kernel/syscalls.h8
-rw-r--r--arch/mips/mm/fault.c30
-rw-r--r--arch/mips/mm/r4xx0.c6
-rw-r--r--arch/mips/sgi/kernel/indy_sc.c3
-rw-r--r--arch/mips/tools/offset.c16
-rw-r--r--arch/mips64/arc/env.c2
-rw-r--r--arch/mips64/arc/identify.c2
-rw-r--r--arch/mips64/arc/tree.c14
-rw-r--r--arch/mips64/defconfig2
-rw-r--r--arch/mips64/kernel/Makefile2
-rw-r--r--arch/mips64/kernel/entry.S97
-rw-r--r--arch/mips64/kernel/mips64_ksyms.c5
-rw-r--r--arch/mips64/kernel/proc.c71
-rw-r--r--arch/mips64/kernel/process.c167
-rw-r--r--arch/mips64/kernel/r4k_fpu.S149
-rw-r--r--arch/mips64/kernel/setup.c4
-rw-r--r--arch/mips64/kernel/signal.c654
-rw-r--r--arch/mips64/kernel/traps.c562
-rw-r--r--arch/mips64/mm/fault.c30
-rw-r--r--arch/mips64/mm/r4xx0.c74
-rw-r--r--arch/mips64/sgi-ip22/ip22-int.c27
-rw-r--r--arch/mips64/sgi-ip22/ip22-reset.c36
-rw-r--r--arch/mips64/sgi-ip22/ip22-setup.c50
-rw-r--r--arch/mips64/sgi-ip22/ip22-timer.c2
-rw-r--r--arch/mips64/sgi-ip22/system.c10
-rw-r--r--arch/mips64/tools/offset.c13
-rw-r--r--arch/ppc/amiga/amiints.c2
-rw-r--r--arch/ppc/amiga/config.c1
-rw-r--r--arch/ppc/config.in8
-rw-r--r--arch/ppc/kernel/irq.c1
-rw-r--r--arch/ppc/kernel/pci.c1
-rw-r--r--arch/ppc/kernel/ppc-stub.c1
-rw-r--r--arch/ppc/kernel/prep_setup.c1
-rw-r--r--arch/ppc/kernel/process.c1
-rw-r--r--arch/ppc/kernel/setup.c1
-rw-r--r--arch/ppc/kernel/smp.c2
-rw-r--r--arch/sparc/ap1000/aplib.c1
-rw-r--r--arch/sparc/kernel/pcic.c2
-rw-r--r--arch/sparc/kernel/process.c1
-rw-r--r--arch/sparc/kernel/ptrace.c292
-rw-r--r--arch/sparc/kernel/sparc-stub.c1
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c1
-rw-r--r--arch/sparc/kernel/sun4d_smp.c2
-rw-r--r--arch/sparc/kernel/sun4m_smp.c2
-rw-r--r--arch/sparc/kernel/sunos_ioctl.c3
-rw-r--r--arch/sparc/kernel/sys_sunos.c1
-rw-r--r--arch/sparc/mm/asyncd.c2
-rw-r--r--arch/sparc/mm/fault.c3
-rw-r--r--arch/sparc/mm/srmmu.c2
-rw-r--r--arch/sparc/mm/sun4c.c5
-rw-r--r--arch/sparc64/config.in28
-rw-r--r--arch/sparc64/defconfig14
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c5
-rw-r--r--arch/sparc64/kernel/ioctl32.c6
-rw-r--r--arch/sparc64/kernel/psycho.c14
-rw-r--r--arch/sparc64/kernel/ptrace.c596
-rw-r--r--arch/sparc64/kernel/smp.c2
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c13
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c8
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c3
-rw-r--r--arch/sparc64/lib/Makefile5
-rw-r--r--arch/sparc64/lib/atomic.S32
-rw-r--r--arch/sparc64/lib/rwlock.S81
-rw-r--r--arch/sparc64/mm/asyncd.c2
-rw-r--r--arch/sparc64/mm/fault.c2
-rw-r--r--arch/sparc64/solaris/ioctl.c22
-rw-r--r--arch/sparc64/solaris/socksys.c1
100 files changed, 2908 insertions, 2111 deletions
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index 75b3e9563..eb9752970 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -188,13 +188,7 @@ tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
-tristate 'Parallel port support' CONFIG_PARPORT
-if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
- if [ "$CONFIG_PARPORT_PC" != "n" ]; then
- bool ' Support foreign hardware' CONFIG_PARPORT_OTHER
- fi
-fi
+source drivers/misc/Config.in
endmenu
source drivers/pnp/Config.in
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 3e20e7091..b590c0bdb 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -135,242 +135,18 @@ put_reg(struct task_struct *task, unsigned long regno, long data)
return 0;
}
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long
-get_long(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr)
-{
- pgd_t * pgdir;
- pmd_t * pgmiddle;
- pte_t * pgtable;
- unsigned long page;
-
- DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
- repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- page = pte_page(*pgtable);
- /* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- return *(unsigned long *) page;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it. -M.U-
- */
-static void
-put_long(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned long data)
-{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page;
-
- repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (!pgd_present(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- page = pte_page(*pgtable);
- if (!pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
-
- /* This is a hack for non-kernel-mapped video buffers and similar. */
- if (MAP_NR(page) < max_mapnr)
- *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-
- /* We're bypassing pagetables, so we have to set the dirty bit
- ourselves. This should also re-instate whatever read-only
- mode there was before. */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb();
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int
-read_long(struct task_struct * tsk, unsigned long addr, unsigned long * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- DBG(DBG_MEM_ALL, ("in read_long\n"));
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
- struct vm_area_struct * vma_high = vma;
- unsigned long low, align;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- align = addr & (sizeof(long) - 1);
- addr -= align;
- low = get_long(tsk, vma, addr);
- if (align) {
- unsigned long high;
-
- high = get_long(tsk, vma_high, addr + sizeof(long));
- low >>= align * 8;
- low |= high << (64 - align * 8);
- }
- *result = low;
- } else {
- long l = get_long(tsk, vma, addr);
-
- DBG(DBG_MEM_ALL, ("value is 0x%lx\n", l));
- *result = l;
- }
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int
-write_long(struct task_struct * tsk, unsigned long addr, unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low, high, align;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- align = addr & (sizeof(long) - 1);
- addr -= align;
- low = get_long(tsk, vma, addr);
- high = get_long(tsk, vma_high, addr + sizeof(long));
- low &= ~0UL >> (64 - align * 8);
- high &= ~0UL << (align * 8);
- low |= data << (align * 8);
- high |= data >> (64 - align * 8);
- put_long(tsk, vma, addr, low);
- put_long(tsk, vma_high, addr + sizeof(long), high);
- } else
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
-/*
- * Read a 32bit int from address space TSK.
- */
-static int
-read_int(struct task_struct * tsk, unsigned long addr, unsigned int *data)
+static inline int
+read_int(struct task_struct *task, unsigned long addr, int * data)
{
- unsigned long l, align;
- int res;
-
- align = addr & 0x7;
- addr &= ~0x7;
-
- res = read_long(tsk, addr, &l);
- if (res < 0)
- return res;
-
- if (align == 0) {
- *data = l;
- } else {
- *data = l >> 32;
- }
- return 0;
+ int copied = access_process_vm(task, addr, data, sizeof(int), 0);
+ return (copied == sizeof(int)) ? 0 : -EIO;
}
-/*
- * Write a 32bit word to address space TSK.
- *
- * For simplicity, do a read-modify-write of the 64bit word that
- * contains the 32bit word that we are about to write.
- */
-static int
-write_int(struct task_struct * tsk, unsigned long addr, unsigned int data)
+static inline int
+write_int(struct task_struct *task, unsigned long addr, int data)
{
- unsigned long l, align;
- int res;
-
- align = addr & 0x7;
- addr &= ~0x7;
-
- res = read_long(tsk, addr, &l);
- if (res < 0)
- return res;
-
- if (align == 0) {
- l = (l & 0xffffffff00000000UL) | ((unsigned long) data << 0);
- } else {
- l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
- }
- return write_long(tsk, addr, l);
+ int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
+ return (copied == sizeof(int)) ? 0 : -EIO;
}
/*
@@ -521,16 +297,17 @@ sys_ptrace(long request, long pid, long addr, long data,
switch (request) {
/* When I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA:
- down(&child->mm->mmap_sem);
- ret = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
- DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
- if (ret < 0)
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
goto out;
+
regs.r0 = 0; /* special return: no errors */
ret = tmp;
goto out;
+ }
/* Read register number ADDR. */
case PTRACE_PEEKUSR:
@@ -541,12 +318,12 @@ sys_ptrace(long request, long pid, long addr, long data,
/* When I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
- down(&child->mm->mmap_sem);
- ret = write_long(child, addr, data);
- up(&child->mm->mmap_sem);
+ case PTRACE_POKEDATA: {
+ unsigned long tmp = data;
+ int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
+ ret = (copied == sizeof(tmp)) ? 0 : -EIO;
goto out;
+ }
case PTRACE_POKEUSR: /* write the specified register */
DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index a477c2344..832d72ee0 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -16,7 +16,6 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
-#include <linux/signal.h>
#include <linux/stddef.h>
#include <asm/bitops.h>
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index e97021869..eef452e57 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -603,7 +603,7 @@ smp_percpu_timer_interrupt(struct pt_regs *regs)
update_one_process(current, 1, user, !user, cpu);
if (current->pid) {
- if (--current->counter < 0) {
+ if (--current->counter <= 0) {
current->counter = 0;
current->need_resched = 1;
}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 68bf5aa1f..ff0c548b4 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -27,9 +27,7 @@
#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/config.h>
-#include <linux/unistd.h>
#include <linux/delay.h>
-#include <linux/smp.h>
#include <linux/reboot.h>
#include <linux/init.h>
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index c874a1ba8..4e49885b8 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -23,8 +23,6 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index fb05fc6fb..e4a6a6911 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -36,7 +36,6 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/sched.h>
#include <linux/init.h>
#include <asm/system.h>
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index a2c8ecb37..e45fcda2d 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -753,19 +753,29 @@ bootsect_panic_mess:
! This routine checks that the keyboard command queue is empty
! (after emptying the output buffers)
!
-! No timeout is used - if this hangs there is something wrong with
-! the machine, and we probably couldn't proceed anyway.
+! Some machines have delusions that the keyboard buffer is always full
+! with no keyboard attached...
+
empty_8042:
+ push ecx
+ mov ecx,#0xFFFFFF
+
+empty_8042_loop:
+ dec ecx
+ jz empty_8042_end_loop
+
call delay
in al,#0x64 ! 8042 status port
test al,#1 ! output buffer?
jz no_output
call delay
in al,#0x60 ! read it
- jmp empty_8042
+ jmp empty_8042_loop
no_output:
test al,#2 ! is input buffer full?
- jnz empty_8042 ! yes - loop
+ jnz empty_8042_loop ! yes - loop
+empty_8042_end_loop:
+ pop ecx
ret
!
diff --git a/arch/i386/config.in b/arch/i386/config.in
index f0ac5e2c0..56b3fd802 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -92,13 +92,7 @@ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-tristate 'Parallel port support' CONFIG_PARPORT
-if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
- if [ "$CONFIG_PARPORT_PC" != "n" ]; then
- bool ' Support foreign hardware' CONFIG_PARPORT_OTHER
- fi
-fi
+source drivers/misc/Config.in
bool 'Advanced Power Management BIOS support' CONFIG_APM
if [ "$CONFIG_APM" = "y" ]; then
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 856ceecf3..3ff204313 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -70,11 +70,6 @@ CONFIG_BINFMT_MISC=y
# CONFIG_I2O_PROC is not set
#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
# Block devices
#
CONFIG_BLK_DEV_FD=y
@@ -98,7 +93,10 @@ CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_BLK_DEV_IDEDMA_PCI is not set
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_AEC6210 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_PIIX=y
# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_CPQ_DA is not set
#
# Additional Block Devices
@@ -214,9 +212,17 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# Network device support
#
CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
# CONFIG_ARCNET is not set
CONFIG_DUMMY=m
# CONFIG_EQUALIZER is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
@@ -236,14 +242,22 @@ CONFIG_EEXPRESS_PRO100=y
# CONFIG_VIA_RHINE is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
# CONFIG_TR is not set
+
+#
+# Wan interfaces
+#
# CONFIG_HOSTESS_SV11 is not set
# CONFIG_COSA is not set
-# CONFIG_RCPCI is not set
+# CONFIG_SEALEVEL_4021 is not set
+# CONFIG_DLCI is not set
# CONFIG_WAN_DRIVERS is not set
# CONFIG_LAPBETHER is not set
# CONFIG_X25_ASY is not set
diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h
index 6a19d9884..1023cd4da 100644
--- a/arch/i386/kernel/irq.h
+++ b/arch/i386/kernel/irq.h
@@ -238,7 +238,7 @@ SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
*/
static inline void x86_do_profile (unsigned long eip)
{
- if (prof_buffer && current->pid) {
+ if (prof_buffer) {
eip -= (unsigned long) &_stext;
eip >>= prof_shift;
/*
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index ad745f58a..08dde1ed7 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -26,9 +26,7 @@
#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/config.h>
-#include <linux/unistd.h>
#include <linux/delay.h>
-#include <linux/smp.h>
#include <linux/reboot.h>
#include <linux/init.h>
#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 09664ba81..9935cdf53 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -67,205 +67,6 @@ static inline int put_stack_long(struct task_struct *task, int offset,
return 0;
}
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pgd_t * pgdir;
- pmd_t * pgmiddle;
- pte_t * pgtable;
- unsigned long page;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- return *(unsigned long *) page;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it. -M.U-
- */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr,
- unsigned long data)
-{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (!pgd_present(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- page = pte_page(*pgtable);
- if (!pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) < max_mapnr)
- *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb();
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low,high;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
- high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
- switch (addr & (sizeof(long)-1)) {
- case 1:
- low >>= 8;
- low |= high << 24;
- break;
- case 2:
- low >>= 16;
- low |= high << 16;
- break;
- case 3:
- low >>= 24;
- low |= high << 8;
- break;
- }
- *result = low;
- } else
- *result = get_long(tsk, vma, addr);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low,high;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
- high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
- switch (addr & (sizeof(long)-1)) {
- case 0: /* shouldn't happen, but safety first */
- low = data;
- break;
- case 1:
- low &= 0x000000ff;
- low |= data << 8;
- high &= ~0xff;
- high |= data >> 24;
- break;
- case 2:
- low &= 0x0000ffff;
- low |= data << 16;
- high &= ~0xffff;
- high |= data >> 16;
- break;
- case 3:
- low &= 0x00ffffff;
- low |= data << 24;
- high &= ~0xffffff;
- high |= data >> 8;
- break;
- }
- put_long(tsk, vma, addr & ~(sizeof(long)-1),low);
- put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
- } else
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
static int putreg(struct task_struct *child,
unsigned long regno, unsigned long value)
{
@@ -402,12 +203,13 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
+ int copied;
- down(&child->mm->mmap_sem);
- ret = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
- if (ret >= 0)
- ret = put_user(tmp,(unsigned long *) data);
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ goto out;
+ ret = put_user(tmp,(unsigned long *) data);
goto out;
}
@@ -436,9 +238,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- down(&child->mm->mmap_sem);
- ret = write_long(child,addr,data);
- up(&child->mm->mmap_sem);
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ goto out;
+ ret = -EIO;
goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 202de42d7..c0721b482 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -11,7 +11,7 @@
* Zoltan Boszormenyi <zboszor@mol.hu> February 1999.
*
* Force Centaur C6 processors to report MTRR capability.
- * Bart Hartgers <bart@etpmod.phys.tue.nl>, May 199.
+ * Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999.
*
* Intel Mobile Pentium II detection fix. Sean Gilley, June 1999.
*/
@@ -690,8 +690,8 @@ static struct cpu_model_info cpu_models[] __initdata = {
NULL, NULL, NULL, NULL }},
{ X86_VENDOR_INTEL, 6,
{ "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)",
- NULL, "Pentium II (Deschutes)", "Mobile Pentium II", NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
+ NULL, "Pentium II (Deschutes)", "Mobile Pentium II", "Pentium III (Katmai)",
+ "Pentium III (Coppermine)", NULL, NULL, NULL, NULL, NULL, NULL }},
{ X86_VENDOR_AMD, 4,
{ NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB",
"486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT",
@@ -799,16 +799,15 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c))
/* Names for the Pentium II Celeron processors
detectable only by also checking the cache size */
if ((cpu_models[i].vendor == X86_VENDOR_INTEL)
- && (cpu_models[i].x86 == 6)){
- if(c->x86_model == 6 && c->x86_cache_size == 128) {
+ && (cpu_models[i].x86 == 6))
+ {
+ if(c->x86_model == 5 && c->x86_cache_size == 0)
+ p = "Celeron (Covington)";
+ else if(c->x86_model == 6 && c->x86_cache_size == 128)
p = "Celeron (Mendocino)";
- }
- else {
- if (c->x86_model == 5 && c->x86_cache_size == 0) {
- p = "Celeron (Covington)";
- }
- }
- }
+ else if(c->x86_model == 5 && c->x86_cache_size == 256)
+ p = "Celeron (Dixon)";
+ }
}
}
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 9d3a8b4b5..f092d0905 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -1792,7 +1792,7 @@ void smp_local_timer_interrupt(struct pt_regs * regs)
update_one_process(p, 1, user, system, cpu);
if (p->pid) {
p->counter -= 1;
- if (p->counter < 0) {
+ if (p->counter <= 0) {
p->counter = 0;
p->need_resched = 1;
}
diff --git a/arch/i386/math-emu/fpu_emu.h b/arch/i386/math-emu/fpu_emu.h
index e5734c82d..fe02425ec 100644
--- a/arch/i386/math-emu/fpu_emu.h
+++ b/arch/i386/math-emu/fpu_emu.h
@@ -165,8 +165,6 @@ extern u_char const data_sizes_16[32];
#define signpositive(a) ( (signbyte(a) & 0x80) == 0 )
#define signnegative(a) (signbyte(a) & 0x80)
-#include "fpu_proto.h"
-
static inline void reg_copy(FPU_REG const *x, FPU_REG *y)
{
*(short *)&(y->exp) = *(const short *)&(x->exp);
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 5a1f363bd..c3e423b21 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -50,7 +50,8 @@ good_area:
start &= PAGE_MASK;
for (;;) {
- handle_mm_fault(current,vma, start, 1);
+ if (handle_mm_fault(current, vma, start, 1) <= 0)
+ goto bad_area;
if (!size)
break;
size--;
@@ -162,8 +163,13 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- if (!handle_mm_fault(tsk, vma, address, write))
- goto do_sigbus;
+ {
+ int fault = handle_mm_fault(tsk, vma, address, write);
+ if (fault < 0)
+ goto out_of_memory;
+ if (!fault)
+ goto do_sigbus;
+ }
/*
* Did it hit the DOS screen memory VA from vm86 mode?
@@ -255,6 +261,13 @@ no_context:
* 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", tsk->comm);
+ if (error_code & 4)
+ do_exit(SIGKILL);
+ goto no_context;
+
do_sigbus:
up(&mm->mmap_sem);
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index e6e83b34a..f839b134f 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.19 1999/08/18 23:37:42 ralf Exp $
+# $Id: Makefile,v 1.20 1999/08/20 21:59:01 ralf Exp $
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
@@ -117,7 +117,6 @@ SUBDIRS += arch/mips/sgi/kernel arch/mips/arc
# 8kb aligned or the handling of the current variable will break.
#
LOADADDR += 0x88002000
-HOSTCC = cc
endif
#
diff --git a/arch/mips/boot/elf2ecoff.c b/arch/mips/boot/elf2ecoff.c
index 55f5896c5..dc8e981e6 100644
--- a/arch/mips/boot/elf2ecoff.c
+++ b/arch/mips/boot/elf2ecoff.c
@@ -35,7 +35,6 @@
#include <stdio.h>
#include <string.h>
-#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
diff --git a/arch/mips/config.in b/arch/mips/config.in
index f7fb7b2e9..9a1d95025 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.29 1999/08/18 23:37:42 ralf Exp $
+# $Id: config.in,v 1.30 1999/08/20 21:59:01 ralf Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -123,7 +123,7 @@ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
bool 'Sysctl support' CONFIG_SYSCTL
if [ "$CONFIG_SGI_IP22" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then
- tristate 'Parallel port support' CONFIG_PARPORT
+ source drivers/misc/Config.in
fi
endmenu
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 828f2477e..3aa72b746 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -28,6 +28,9 @@ CONFIG_CPU_R4X00=y
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
#
# General setup
@@ -63,11 +66,6 @@ CONFIG_KMOD=y
# CONFIG_I2O_PROC is not set
#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
# Block devices
#
CONFIG_BLK_DEV_FD=m
@@ -87,6 +85,7 @@ CONFIG_BLK_DEV_IDECD=m
# CONFIG_BLK_DEV_RZ1000 is not set
# CONFIG_BLK_DEV_IDEPCI is not set
# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_CPQ_DA is not set
#
# Additional Block Devices
@@ -202,9 +201,17 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# Network device support
#
CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
# CONFIG_EQUALIZER is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
@@ -217,7 +224,6 @@ CONFIG_PCNET32=y
# CONFIG_CS89x0 is not set
# CONFIG_DE4X5 is not set
# CONFIG_DEC_ELCP is not set
-# CONFIG_DEC_ELCP is not set
# CONFIG_DGRS is not set
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_NE2K_PCI is not set
@@ -225,14 +231,22 @@ CONFIG_PCNET32=y
# CONFIG_VIA_RHINE is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
# CONFIG_TR is not set
+
+#
+# Wan interfaces
+#
# CONFIG_HOSTESS_SV11 is not set
# CONFIG_COSA is not set
-# CONFIG_RCPCI is not set
+# CONFIG_SEALEVEL_4021 is not set
+# CONFIG_DLCI is not set
# CONFIG_WAN_DRIVERS is not set
# CONFIG_LAPBETHER is not set
# CONFIG_X25_ASY is not set
@@ -387,5 +401,4 @@ CONFIG_VGA_CONSOLE=y
#
# CONFIG_CROSSCOMPILE is not set
# CONFIG_MIPS_FPE_MODULE is not set
-# CONFIG_REMOTE_DEBUG is not set
# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22
new file mode 100644
index 000000000..6658c84ea
--- /dev/null
+++ b/arch/mips/defconfig-ip22
@@ -0,0 +1,297 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_OLIVETTI_M700 is not set
+CONFIG_SGI_IP22=y
+# CONFIG_SNI_RM200_PCI is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
+
+#
+# General setup
+#
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_ELF_KERNEL=y
+CONFIG_BINFMT_IRIX=y
+CONFIG_FORWARD_KEYBOARD=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+# CONFIG_FB is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_IDE is not set
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_CPQ_DA is not set
+
+#
+# Additional Block Devices
+#
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE_PARPORT=m
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_NETLINK is not set
+# CONFIG_FIREWALL is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_ALIAS is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_RARP is not set
+# CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CDrom)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SCSI_SGIWD93=y
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_SLIP is not set
+# CONFIG_PPP is not set
+CONFIG_SGISEEQ=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
+# USB drivers - not for the faint of heart
+#
+# CONFIG_USB is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+CONFIG_SGI_DISKLABEL=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_NLS is not set
+
+#
+# Console drivers
+#
+CONFIG_SGI_NEWPORT_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# SGI devices
+#
+CONFIG_SGI_SERIAL=y
+CONFIG_SERIAL=y
+CONFIG_SGI_DS1286=y
+# CONFIG_SGI_NEWPORT_GFX is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_MIPS_FPE_MODULE is not set
+# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 4b512e14b..3eadd1832 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -1,4 +1,4 @@
-/* $Id: irixelf.c,v 1.19 1999/08/04 05:28:51 ulfc Exp $
+/* $Id: irixelf.c,v 1.20 1999/08/04 14:54:04 ulfc Exp $
*
* irixelf.c: Code to load IRIX ELF executables which conform to
* the MIPS ABI.
@@ -624,9 +624,10 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
has_interp = has_ephdr = 0;
elf_ihdr = elf_ephdr = 0;
elf_ex = *((struct elfhdr *) bprm->buf);
-
- if(verify_binary(&elf_ex, bprm))
- return -ENOEXEC;
+ retval = -ENOEXEC;
+
+ if (verify_binary(&elf_ex, bprm))
+ goto out;
#ifdef DEBUG_ELF
print_elfhdr(&elf_ex);
@@ -634,15 +635,19 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
/* Now read in all of the header information */
size = elf_ex.e_phentsize * elf_ex.e_phnum;
+ if (size > 65536)
+ goto out;
elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
- if (elf_phdata == NULL)
- return -ENOMEM;
-
+ if (elf_phdata == NULL) {
+ retval = -ENOMEM;
+ goto out;
+ }
+
retval = read_exec(bprm->dentry, elf_ex.e_phoff,
(char *) elf_phdata, size, 1);
if (retval < 0)
- goto out_phdata;
-
+ goto out_free_ph;
+
#ifdef DEBUG_ELF
dump_phdrs(elf_phdata, elf_ex.e_phnum);
#endif
@@ -668,39 +673,39 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
elf_brk = 0;
retval = open_dentry(bprm->dentry, O_RDONLY);
if (retval < 0)
- goto out_phdata;
+ goto out_free_ph;
file = fget(elf_exec_fileno = retval);
-
+
elf_stack = 0xffffffff;
elf_interpreter = NULL;
start_code = 0xffffffff;
end_code = 0;
end_data = 0;
-
+
retval = look_for_irix_interpreter(&elf_interpreter,
&interpreter_dentry,
&interp_elf_ex, elf_phdata, bprm,
elf_ex.e_phnum);
if(retval)
- goto out_file;
-
+ goto out_free_file;
+
if(elf_interpreter) {
retval = verify_irix_interpreter(&interp_elf_ex);
if(retval)
- goto out_interp;
+ goto out_free_interp;
}
-
+
/* OK, we are done with that, now set up the arg stuff,
* and then start this sucker up.
*/
retval = -E2BIG;
if (!bprm->sh_bang && !bprm->p)
- goto out_interp;
-
+ goto out_free_interp;
+
/* Flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
if (retval)
- goto out_interp;
+ goto out_free_dentry;
/* OK, This is the point of no return */
current->mm->end_data = 0;
@@ -715,15 +720,16 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
current->mm->rss = 0;
setup_arg_pages(bprm);
current->mm->start_stack = bprm->p;
-
+
/* At this point, we assume that the image should be loaded at
* fixed address, not at a variable address.
*/
old_fs = get_fs();
set_fs(get_ds());
-
- map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr,
- &start_code, &elf_bss, &end_code, &end_data, &elf_brk);
+
+ map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack,
+ &load_addr, &start_code, &elf_bss, &end_code,
+ &end_data, &elf_brk);
if(elf_interpreter) {
retval = map_interpreter(elf_phdata, &interp_elf_ex,
@@ -740,7 +746,7 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
}
set_fs(old_fs);
-
+
kfree(elf_phdata);
fput(file);
sys_close(elf_exec_fileno);
@@ -805,17 +811,20 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
if (current->flags & PF_PTRACED)
send_sig(SIGTRAP, current, 0);
return 0;
+out:
+ return retval;
-out_interp:
- if(elf_interpreter) {
- kfree(elf_interpreter);
- }
-out_file:
+out_free_dentry:
+ dput(interpreter_dentry);
+out_free_interp:
+ if (elf_interpreter)
+ kfree(elf_interpreter);
+out_free_file:
fput(file);
sys_close(elf_exec_fileno);
-out_phdata:
+out_free_ph:
kfree (elf_phdata);
- return retval;
+ goto out;
}
static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
@@ -1069,11 +1078,11 @@ struct memelfnote
static int notesize(struct memelfnote *en)
{
int sz;
-
+
sz = sizeof(struct elf_note);
sz += roundup(strlen(en->name), 4);
sz += roundup(en->datasz, 4);
-
+
return sz;
}
diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c
index c05c6609a..10ca5b15e 100644
--- a/arch/mips/kernel/irixioctl.c
+++ b/arch/mips/kernel/irixioctl.c
@@ -1,4 +1,4 @@
-/* $Id: irixioctl.c,v 1.5 1999/02/01 01:28:55 ralf Exp $
+/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $
* irixioctl.c: A fucking mess...
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -29,20 +29,21 @@ extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
unsigned long arg);
extern asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count);
extern void start_tty(struct tty_struct *tty);
-
static struct tty_struct *get_tty(int fd)
{
struct file *filp;
+ struct tty_struct *ttyp = NULL;
- if(!(filp = fcheck(fd)))
- return ((struct tty_struct *) 0);
- if(filp->private_data) {
- struct tty_struct *ttyp = (struct tty_struct *) filp->private_data;
+ read_lock(&current->files->file_lock);
+ filp = fcheck(fd);
+ if(filp && filp->private_data) {
+ ttyp = (struct tty_struct *) filp->private_data;
- if(ttyp->magic == TTY_MAGIC)
- return ttyp;
+ if(ttyp->magic != TTY_MAGIC)
+ ttyp =NULL;
}
- return ((struct tty_struct *) 0);
+ read_unlock(&current->files->file_lock);
+ return ttyp;
}
static struct tty_struct *get_real_tty(struct tty_struct *tp)
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 693d72110..7ec7b175c 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: irixsig.c,v 1.10 1999/01/03 17:50:50 ralf Exp $
+ * $Id: irixsig.c,v 1.11 1999/06/17 13:25:46 ralf Exp $
*/
#include <linux/kernel.h>
@@ -114,17 +114,17 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
dump_irix5_sigctx(ctx);
#endif
- regs->regs[5] = 0; /* XXX sigcode XXX */
regs->regs[4] = (unsigned long) signr;
+ regs->regs[5] = 0; /* XXX sigcode XXX */
regs->regs[6] = regs->regs[29] = sp;
regs->regs[7] = (unsigned long) ka->sa.sa_handler;
- regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline;
+ regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa.sa_restorer;
return;
segv_and_exit:
- lock_kernel();
- do_exit(SIGSEGV);
- unlock_kernel();
+ if (signr == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
}
static void inline
@@ -300,11 +300,12 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
return 0;
}
-asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs)
+asmlinkage void
+irix_sigreturn(struct pt_regs *regs)
{
struct sigctx_irix5 *context, *magic;
unsigned long umask, mask;
- u64 *fregs, res;
+ u64 *fregs;
int sig, i, base = 0;
sigset_t blocked;
@@ -365,11 +366,7 @@ asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs)
/* Unreached */
badframe:
- lock_kernel();
- do_exit(SIGSEGV);
- unlock_kernel();
-
- return res;
+ force_sig(SIGSEGV, current);
}
struct sigact_irix5 {
@@ -390,7 +387,7 @@ static inline void dump_sigact_irix5(struct sigact_irix5 *p)
asmlinkage int
irix_sigaction(int sig, const struct sigaction *act,
- struct sigaction *oact, unsigned long trampoline)
+ struct sigaction *oact, void *trampoline)
{
struct k_sigaction new_ka, old_ka;
int ret;
@@ -410,15 +407,14 @@ irix_sigaction(int sig, const struct sigaction *act,
return -EFAULT;
__copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
- new_ka.ka_restorer = NULL;
- }
- /*
- * Hmmm... methinks IRIX libc always passes a valid trampoline
- * value for all invocations of sigaction. Will have to
- * investigate. POSIX POSIX, die die die...
- */
- current->tss.irix_trampoline = trampoline;
+ /*
+ * Hmmm... methinks IRIX libc always passes a valid trampoline
+ * value for all invocations of sigaction. Will have to
+ * investigate. POSIX POSIX, die die die...
+ */
+ new_ka.sa.sa_restorer = trampoline;
+ }
/* XXX Implement SIG_SETMASK32 for IRIX compatibility */
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 1b99fa99f..b083e3686 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.14 1999/02/15 02:16:50 ralf Exp $
+/* $Id: irq.c,v 1.15 1999/02/25 21:50:49 tsbogend Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -356,7 +356,7 @@ static int i8259_irq_cannonicalize(int irq)
return ((irq == 2) ? 9 : irq);
}
-__initfunc(static void i8259_init(void))
+static void __init i8259_init(void)
{
/* Init master interrupt controller */
outb(0x11, 0x20); /* Start init sequence */
@@ -376,7 +376,7 @@ __initfunc(static void i8259_init(void))
outb(cached_21, 0x21);
}
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
{
irq_cannonicalize = i8259_irq_cannonicalize;
/* i8259_init(); */
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index a8c59ff78..8e1afd78f 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.12 1999/06/17 13:25:46 ralf Exp $
+/* $Id: process.c,v 1.14 1999/08/09 19:43:14 harald Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -34,18 +34,6 @@ struct task_struct *last_task_used_math = NULL;
asmlinkage void ret_from_sys_call(void);
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
-{
- /* New thread looses kernel privileges. */
- regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|KU_MASK)) | KU_USER;
- regs->cp0_epc = pc;
- regs->regs[29] = sp;
- current->tss.current_ds = USER_DS;
-}
-
void exit_thread(void)
{
/* Forget lazy fpu state */
@@ -66,10 +54,6 @@ void flush_thread(void)
}
}
-void release_thread(struct task_struct *dead_task)
-{
-}
-
int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index c8e3d23b6..68084ab3d 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -1,4 +1,4 @@
-/* $Id: ptrace.c,v 1.15 1999/08/09 19:43:14 harald Exp $
+/* $Id: ptrace.c,v 1.16 1999/08/18 23:37:43 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -25,218 +25,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page, retval;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- page = pte_page(*pgtable);
- /* This is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= MAP_NR(high_memory))
- return 0;
- page += addr & ~PAGE_MASK;
- /* We can't use flush_page_to_ram() since we're running in
- * another context ...
- */
- flush_cache_all();
- retval = *(unsigned long *) page;
- flush_cache_all(); /* VCED avoidance */
- return retval;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it. -M.U-
- */
-static void put_long(struct task_struct *tsk,
- struct vm_area_struct * vma, unsigned long addr,
- unsigned long data)
-{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (!pgd_present(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- page = pte_page(*pgtable);
- if (!pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- /* This is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) < MAP_NR(high_memory))
- flush_cache_all();
- *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
- if (MAP_NR(page) < MAP_NR(high_memory))
- flush_cache_all();
- /*
- * We're bypassing pagetables, so we have to set the dirty bit
- * ourselves this should also re-instate whatever read-only mode
- * there was before
- */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr);
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low,high;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
- high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
- switch (addr & (sizeof(long)-1)) {
- case 1:
- low >>= 8;
- low |= high << 24;
- break;
- case 2:
- low >>= 16;
- low |= high << 16;
- break;
- case 3:
- low >>= 24;
- low |= high << 8;
- break;
- }
- *result = low;
- } else
- *result = get_long(tsk, vma, addr);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low,high;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
- high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
- switch (addr & (sizeof(long)-1)) {
- case 0: /* shouldn't happen, but safety first */
- low = data;
- break;
- case 1:
- low &= 0x000000ff;
- low |= data << 8;
- high &= ~0xff;
- high |= data >> 24;
- break;
- case 2:
- low &= 0x0000ffff;
- low |= data << 16;
- high &= ~0xffff;
- high |= data >> 16;
- break;
- case 3:
- low &= 0x00ffffff;
- low |= data << 24;
- high &= ~0xffffff;
- high |= data >> 8;
- break;
- }
- put_long(tsk, vma, addr & ~(sizeof(long)-1),low);
- put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
- } else
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
@@ -323,15 +111,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
+ int copied;
- down(&child->mm->mmap_sem);
- res = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
- if (res < 0)
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ res = -EIO;
+ if (copied != sizeof(tmp))
goto out;
res = put_user(tmp,(unsigned long *) data);
+
goto out;
- }
+ }
/* Read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -397,9 +186,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- down(&child->mm->mmap_sem);
- res = write_long(child,addr,data);
- up(&child->mm->mmap_sem);
+ res = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1)
+ == sizeof(data))
+ goto out;
+ res = -EIO;
goto out;
case PTRACE_POKEUSR: {
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
index 74671f58c..efb00dce1 100644
--- a/arch/mips/kernel/r2300_fpu.S
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -1,4 +1,5 @@
-/* $Id: r2300_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $
+/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $
+ *
* r2300_fpu.S: Save/restore floating point context for signal handlers.
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -14,6 +15,7 @@
* Copyright (c) 1998 Harald Koerfgen
*/
#include <asm/asm.h>
+#include <asm/errno.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
#include <asm/offset.h>
@@ -29,7 +31,7 @@
.set mips1
/* Save floating point context */
LEAF(save_fp_context)
-
+ li v0, 0 # assume success
cfc1 t1,fcr31
EX(swc1 $f0,(SC_FPREGS+0)(a0))
EX(swc1 $f1,(SC_FPREGS+8)(a0))
@@ -81,6 +83,7 @@ LEAF(save_fp_context)
* stack frame which might have been changed by the user.
*/
LEAF(restore_fp_context)
+ li v0, 0 # assume success
EX(lw t0,SC_FPC_CSR(a0))
EX(lwc1 $f0,(SC_FPREGS+0)(a0))
EX(lwc1 $f1,(SC_FPREGS+8)(a0))
@@ -117,3 +120,9 @@ LEAF(restore_fp_context)
jr ra
ctc1 t0,fcr31
END(restore_fp_context)
+
+ .type fault@function
+ .ent fault
+fault: li v0, -EFAULT
+ jr ra
+ .end fault
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 39ec93b57..4624416e7 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -1,4 +1,5 @@
-/*
+/* $Id: r4k_fpu.S,v 1.7 1999/08/18 23:37:44 ralf Exp $
+ *
* r4k_fpu.S: Save/restore floating point context for signal handlers.
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -9,10 +10,9 @@
*
* Multi-arch abstraction and asm macros for easier reading:
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: r4k_fpu.S,v 1.6 1999/08/09 19:43:15 harald Exp $
*/
#include <asm/asm.h>
+#include <asm/errno.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
#include <asm/offset.h>
@@ -21,13 +21,14 @@
#define EX(a,b) \
9: a,##b; \
.section __ex_table,"a"; \
- PTR 9b,bad_stack; \
+ PTR 9b, fault; \
.previous
.set noreorder
.set mips3
/* Save floating point context */
LEAF(save_fp_context)
+ li v0, 0 # assume success
cfc1 t1,fcr31
/* Store the 16 even double precision registers */
@@ -67,6 +68,7 @@ LEAF(save_fp_context)
* stack frame which might have been changed by the user.
*/
LEAF(restore_fp_context)
+ li v0, 0 # assume success
EX(lw t0,SC_FPC_CSR(a0))
/*
@@ -92,3 +94,9 @@ LEAF(restore_fp_context)
jr ra
ctc1 t0,fcr31
END(restore_fp_context)
+
+ .type fault@function
+ .ent fault
+fault: li v0, -EFAULT
+ jr ra
+ .end fault
diff --git a/arch/mips/kernel/r4k_misc.S b/arch/mips/kernel/r4k_misc.S
index c791f3275..d83f85b81 100644
--- a/arch/mips/kernel/r4k_misc.S
+++ b/arch/mips/kernel/r4k_misc.S
@@ -1,19 +1,17 @@
-/*
+/* $Id: r4k_misc.S,v 1.6 1999/08/18 23:37:44 ralf Exp $
+ *
* r4k_misc.S: Misc. exception handling code for r4k.
*
* Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
*
* Multi-cpu abstraction and reworking:
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: r4k_misc.S,v 1.5 1999/08/09 19:43:15 harald Exp $
*/
#include <asm/asm.h>
#include <asm/current.h>
#include <asm/offset.h>
#include <asm/bootinfo.h>
#include <asm/cachectl.h>
-#include <asm/current.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
#include <asm/page.h>
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index b8a2b4303..fd6650b1c 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.17 1999/08/20 21:59:02 ralf Exp $
+/* $Id: setup.c,v 1.18 1999/09/18 20:48:03 harald Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -30,7 +30,6 @@
#endif
#include <linux/ide.h>
#ifdef CONFIG_RTC
-#include <linux/ioport.h>
#include <linux/timex.h>
#endif
@@ -67,15 +66,6 @@ char cyclecounter_available;
*/
int EISA_bus = 0;
-/*
- * Milo passes some information to the kernel that looks like as if it
- * had been returned by a Intel PC BIOS. Milo doesn't fill the passed
- * drive_info and Linux can find out about this anyway, so I'm going to
- * remove this sometime. screen_info contains information about the
- * resolution of the text screen. For VGA graphics based machine this
- * information is being use to continue the screen output just below
- * the BIOS printed text and with the same text resolution.
- */
struct screen_info screen_info;
#ifdef CONFIG_BLK_DEV_FD
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 6c63bea25..0a7190412 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -1,11 +1,12 @@
-/* $Id: signal.c,v 1.20 1999/08/09 19:43:15 harald Exp $
+/* $Id: signal.c,v 1.21 1999/08/24 22:54:21 ralf Exp $
*
- * linux/arch/mips/kernel/signal.c
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
- *
- * XXX Handle lazy fp context switches correctly.
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
*/
#include <linux/config.h>
#include <linux/sched.h>
@@ -24,16 +25,17 @@
#include <asm/pgtable.h>
#include <asm/stackframe.h>
#include <asm/uaccess.h>
+#include <asm/ucontext.h>
#define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
int options, unsigned long *ru);
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
-extern asmlinkage void save_fp_context(struct sigcontext *sc);
-extern asmlinkage void restore_fp_context(struct sigcontext *sc);
+extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
+extern asmlinkage int save_fp_context(struct sigcontext *sc);
+extern asmlinkage int restore_fp_context(struct sigcontext *sc);
/*
* Atomically swap in the new signal mask, and wait for a signal.
@@ -52,6 +54,7 @@ sys_sigsuspend(struct pt_regs regs)
spin_lock_irq(&current->sigmask_lock);
saveset = current->blocked;
current->blocked = newset;
+ recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
regs.regs[2] = EINTR;
@@ -67,17 +70,25 @@ sys_sigsuspend(struct pt_regs regs)
asmlinkage int
sys_rt_sigsuspend(struct pt_regs regs)
{
- sigset_t *uset, saveset, newset;
+ sigset_t *unewset, saveset, newset;
+ size_t sigsetsize;
save_static(&regs);
- uset = (sigset_t *) regs.regs[4];
- if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+
+ /* XXX Don't preclude handling different sized sigset_t's. */
+ sigsetsize = regs.regs[5];
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ unewset = (sigset_t *) regs.regs[4];
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
saveset = current->blocked;
current->blocked = newset;
+ recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
regs.regs[2] = EINTR;
@@ -91,65 +102,74 @@ sys_rt_sigsuspend(struct pt_regs regs)
}
asmlinkage int
-sys_sigaction(int sig, const struct sigaction *act,
- struct sigaction *oact)
+sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
+ int err = 0;
if (act) {
- sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+ old_sigset_t mask;
+
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+ return -EFAULT;
+ err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
+ err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ err |= __get_user(mask, &act->sa_mask.sig[0]);
+ err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer);
+ if (err)
return -EFAULT;
- __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
- new_ka.ka_restorer = NULL;
+ siginitset(&new_ka.sa.sa_mask, mask);
}
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+ return -EFAULT;
+ err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
+ err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
+ err |= __put_user(0, &oact->sa_mask.sig[1]);
+ err |= __put_user(0, &oact->sa_mask.sig[2]);
+ err |= __put_user(0, &oact->sa_mask.sig[3]);
+ err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer);
+ if (err)
return -EFAULT;
- __copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask,
- sizeof(sigset_t));
}
return ret;
}
asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+sys_sigaltstack(struct pt_regs regs)
{
- struct pt_regs *regs = (struct pt_regs *) &uss;
+ const stack_t *uss = (const stack_t *) regs.regs[4];
+ stack_t *uoss = (stack_t *) regs.regs[5];
+ unsigned long usp = regs.regs[29];
- return do_sigaltstack(uss, uoss, regs->regs[29]);
+ return do_sigaltstack(uss, uoss, usp);
}
-/*
- * To do: this entire function should be accessed over a function pointer
- * such that we can handle stack frames for different ABIs.
- */
-
-asmlinkage void
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *context)
+asmlinkage int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
- long long reg;
int owned_fp;
+ int err = 0;
+ u64 reg;
- __get_user(regs->cp0_epc, &context->sc_pc);
+ err |= __get_user(regs->cp0_epc, &sc->sc_pc);
- __get_user(reg, &context->sc_mdhi);
+ err |= __get_user(reg, &sc->sc_mdhi);
regs->hi = (int) reg;
- __get_user(reg, &context->sc_mdlo);
+ err |= __get_user(reg, &sc->sc_mdlo);
regs->lo = (int) reg;
-#define restore_gp_reg(i) __get_user(reg, &context->sc_regs[i]); \
- regs->regs[i] = (int) reg;
+#define restore_gp_reg(i) do { \
+ err |= __get_user(reg, &sc->sc_regs[i]); \
+ regs->regs[i] = reg; \
+} while(0);
restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
@@ -163,55 +183,40 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *context)
restore_gp_reg(31);
#undef restore_gp_reg
- /* FP depends on what FPU in what mode we have. */
- __get_user(owned_fp, &context->sc_ownedfp);
-#if 0
+ err |= __get_user(owned_fp, &sc->sc_ownedfp);
if (owned_fp) {
- restore_fp_context(context);
+ err |= restore_fp_context(sc);
last_task_used_math = current;
}
-#endif
-restore_fp_context(context);
+
+ return err;
}
-/*
- * The structure sc describes the stackframe on the userstack. The frames
- * are identical for normal and realtime signal stackframes with the
- * exception of the additional struct ucontext for rt frames.
- */
struct sigframe {
- unsigned long ass[4]; /* argument save space for o32 */
- unsigned int code[4]; /* signal trampoline */
- struct sigcontext scc;
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_code[2]; /* signal trampoline */
+ struct sigcontext sf_sc;
+ sigset_t sf_mask;
};
struct rt_sigframe {
- unsigned long ass[4];
- unsigned int code[4];
- struct sigcontext scc;
- // struct ucontext uc;
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_code[2]; /* signal trampoline */
+ struct siginfo rs_info;
+ struct ucontext rs_uc;
};
-asmlinkage int sys_sigreturn(struct pt_regs regs)
+asmlinkage void
+sys_sigreturn(struct pt_regs regs)
{
- struct sigcontext *context;
+ struct sigframe *frame;
sigset_t blocked;
- context = (struct sigcontext *)(long) regs.regs[29];
- if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
- (regs.regs[29] & (SZREG - 1)))
- goto badframe;
-
-#if 1
- if (__get_user(blocked.sig[0], &context->sc_sigset[0]) ||
- __get_user(blocked.sig[1], &context->sc_sigset[1]) ||
- __get_user(blocked.sig[2], &context->sc_sigset[2]) ||
- __get_user(blocked.sig[3], &context->sc_sigset[3]))
+ frame = (struct sigframe *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
-#else
- if (__copy_from_user(&blocked, &context->sc_sigset, sizeof(blocked)))
+ if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
goto badframe;
-#endif
sigdelsetmask(&blocked, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
@@ -219,63 +224,79 @@ asmlinkage int sys_sigreturn(struct pt_regs regs)
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
- restore_sigcontext(&regs, context);
+ if (restore_sigcontext(&regs, &frame->sf_sc))
+ goto badframe;
/*
* Don't let your children do this ...
*/
__asm__ __volatile__(
- "move\t$29,%0\n\t"
+ "move\t$29, %0\n\t"
"j\tret_from_sys_call"
:/* no outputs */
:"r" (&regs));
/* Unreached */
badframe:
- lock_kernel();
- do_exit(SIGSEGV);
- unlock_kernel();
+ force_sig(SIGSEGV, current);
}
-/* same as sys_sigreturn for now */
-asmlinkage int sys_rt_sigreturn(struct pt_regs regs)
+asmlinkage void
+sys_rt_sigreturn(struct pt_regs regs)
{
- return -ENOSYS;
-}
+ struct rt_sigframe *frame;
+ sigset_t set;
+ stack_t st;
-#define scc_offset ((size_t)&((struct sigframe *)0)->scc)
+ frame = (struct rt_sigframe *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+ goto badframe;
-/*
- * Set up the return code ...
- *
- * .set noreorder
- * addiu sp,0x20
- * li v0,__NR_sigreturn
- * syscall
- * .set reorder
- */
-static void inline
-setup_trampoline(unsigned int *code)
-{
- __put_user(0x27bd0000 + scc_offset , code + 0);
- __put_user(0x24020000 + __NR_sigreturn, code + 1);
- __put_user(0x0000000c , code + 2);
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs.regs[29]);
/*
- * Flush caches so that the instructions will be correctly executed.
+ * Don't let your children do this ...
*/
- flush_cache_sigtramp((unsigned long) code);
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tret_from_sys_call"
+ :/* no outputs */
+ :"r" (&regs));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
}
-static void inline
-setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set)
+static int inline
+setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
int owned_fp;
+ int err = 0;
+ u64 reg;
- __put_user(regs->cp0_epc, &sc->sc_pc);
- __put_user(regs->cp0_status, &sc->sc_status); /* Status register */
+ err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __put_user(regs->cp0_status, &sc->sc_status);
-#define save_gp_reg(i) __put_user(regs->regs[(i)], &sc->sc_regs[(i)])
+#define save_gp_reg(i) { \
+ reg = regs->regs[i]; \
+ err |= __put_user(reg, &sc->sc_regs[i]); \
+} while(0)
__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
@@ -287,57 +308,93 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set)
save_gp_reg(31);
#undef save_gp_reg
- __put_user(regs->hi, &sc->sc_mdhi);
- __put_user(regs->lo, &sc->sc_mdlo);
- __put_user(regs->cp0_cause, &sc->sc_cause);
+ err |= __put_user(regs->hi, &sc->sc_mdhi);
+ err |= __put_user(regs->lo, &sc->sc_mdlo);
+ err |= __put_user(regs->cp0_cause, &sc->sc_cause);
+ err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
owned_fp = (current == last_task_used_math);
- __put_user(owned_fp, &sc->sc_ownedfp);
+ err |= __put_user(owned_fp, &sc->sc_ownedfp);
-#if 0
if (current->used_math) { /* fp is active. */
set_cp0_status(ST0_CU1, ST0_CU1);
- save_fp_context(sc); /* CPU-dependent */
+ err |= save_fp_context(sc);
last_task_used_math = NULL;
regs->cp0_status &= ~ST0_CU1;
current->used_math = 0;
}
-#endif
-set_cp0_status(ST0_CU1, ST0_CU1);
-save_fp_context(sc); /* CPU-dependent */
- __put_user(set->sig[0], &sc->sc_sigset[0]);
- __put_user(set->sig[1], &sc->sc_sigset[1]);
- __put_user(set->sig[2], &sc->sc_sigset[2]);
- __put_user(set->sig[3], &sc->sc_sigset[3]);
+ return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+ unsigned long sp;
+
+ /* Default to using normal stack */
+ sp = regs->regs[29];
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *)((sp - frame_size) & ALMASK);
}
static void inline
setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
- int signr, sigset_t *oldmask)
+ int signr, sigset_t *set)
{
struct sigframe *frame;
- struct sigcontext *sc;
-
- /* Align the stackframe to an adequate boundary for the architecture. */
- frame = (struct sigframe *) (long) regs->regs[29];
- frame--;
- frame = (struct sigframe *)((unsigned long)frame & ALMASK);
-
- if (verify_area(VERIFY_WRITE, frame, sizeof (*frame)))
- goto segv_and_exit;
- sc = &frame->scc;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub already
+ in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER)
+ regs->regs[31] = (unsigned long) ka->sa.sa_restorer;
+ else {
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_sigreturn
+ * syscall
+ */
+ err |= __put_user(0x24020000 + __NR_sigreturn,
+ frame->sf_code + 0);
+ err |= __put_user(0x0000000c ,
+ frame->sf_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->sf_code);
+ }
- setup_trampoline(frame->code);
- setup_sigcontext(regs, &frame->scc, oldmask);
+ err |= setup_sigcontext(regs, &frame->sf_sc);
+ err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
- regs->regs[4] = signr; /* arguments */
- regs->regs[5] = 0; /* should be cause */
- regs->regs[6] = (long) frame; /* ptr to sigcontext */
- regs->regs[29] = (unsigned long) frame; /* Stack pointer */
- regs->regs[31] = (unsigned long) frame->code; /* Return address */
- regs->cp0_epc = (unsigned long) ka->sa.sa_handler; /* handler address */
- regs->regs[25] = regs->cp0_epc; /* PIC shit... */
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to struct sigcontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to the
+ * struct sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = 0;
+ regs->regs[ 6] = (unsigned long) &frame->sf_sc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->sf_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
@@ -345,22 +402,90 @@ setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
#endif
return;
-segv_and_exit:
- lock_kernel();
- do_exit(SIGSEGV);
- unlock_kernel();
+give_sigsegv:
+ if (signr == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
}
static void inline
setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
- int signr, sigset_t *oldmask, siginfo_t *info)
+ int signr, sigset_t *set, siginfo_t *info)
{
- printk("Aiee: setup_tr_frame wants to be written");
-}
+ struct rt_sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub already
+ in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER)
+ regs->regs[31] = (unsigned long) ka->sa.sa_restorer;
+ else {
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_sigreturn
+ * syscall
+ */
+ err |= __put_user(0x24020000 + __NR_sigreturn,
+ frame->rs_code + 0);
+ err |= __put_user(0x0000000c ,
+ frame->rs_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->rs_code);
+ }
-/* ------------------------------------------------------------------------- */
+ /* Create siginfo. */
+ err |= __copy_to_user(&frame->rs_info, info, sizeof(*info));
-static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->rs_uc.uc_flags);
+ err |= __put_user(0, &frame->rs_uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->rs_uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->regs[29]),
+ &frame->rs_uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size,
+ &frame->rs_uc.uc_stack.ss_size);
+ err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
+ err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to ucontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to
+ * the struct rt_sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = (unsigned long) &frame->rs_info;
+ regs->regs[ 6] = (unsigned long) &frame->rs_uc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->rs_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
+ current->comm, current->pid, frame, regs->cp0_epc, frame->code);
+#endif
+ return;
+
+give_sigsegv:
+ if (signr == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+static inline void
+handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
if (ka->sa.sa_flags & SA_SIGINFO)
@@ -379,7 +504,8 @@ static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
}
}
-static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
+static inline void
+syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
{
switch(regs->regs[0]) {
case ERESTARTNOHAND:
@@ -407,7 +533,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
siginfo_t info;
#ifdef CONFIG_BINFMT_IRIX
- if (current->personality != PER_LINUX) /* XXX */
+ if (current->personality != PER_LINUX)
return do_irix_signal(oldset, regs);
#endif
@@ -533,13 +659,3 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
}
return 0;
}
-
-/*
- * Compatibility syscall. Can be replaced in libc.
- */
-asmlinkage int sys_pause(void)
-{
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- return -ERESTARTNOHAND;
-}
diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h
index 07a49ee8b..ef593845e 100644
--- a/arch/mips/kernel/syscalls.h
+++ b/arch/mips/kernel/syscalls.h
@@ -1,4 +1,4 @@
-/* $Id: syscalls.h,v 1.15 1998/09/19 19:16:17 ralf Exp $
+/* $Id: syscalls.h,v 1.16 1999/07/11 23:56:29 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -44,7 +44,7 @@ SYS(sys_stime, 1) /* 4025 */
SYS(sys_ptrace, 4)
SYS(sys_alarm, 1)
SYS(sys_fstat, 2)
-SYS(sys_pause, 0)
+SYS(sys_ni_syscall, 0)
SYS(sys_utime, 2) /* 4030 */
SYS(sys_ni_syscall, 0)
SYS(sys_ni_syscall, 0)
@@ -214,14 +214,14 @@ SYS(sys_rt_sigprocmask, 4) /* 4195 */
SYS(sys_rt_sigpending, 2)
SYS(sys_rt_sigtimedwait, 4)
SYS(sys_rt_sigqueueinfo, 3)
-SYS(sys_rt_sigsuspend, 2)
+SYS(sys_rt_sigsuspend, 0)
SYS(sys_pread, 6) /* 4200 */
SYS(sys_pwrite, 6)
SYS(sys_chown, 3)
SYS(sys_getcwd, 2)
SYS(sys_capget, 2)
SYS(sys_capset, 2) /* 4205 */
-SYS(sys_sigaltstack, 2)
+SYS(sys_sigaltstack, 0)
SYS(sys_sendfile, 3)
SYS(sys_ni_syscall, 0)
SYS(sys_ni_syscall, 0)
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index cacb97115..f7cbbfc71 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.10 1999/08/09 19:43:16 harald Exp $
+/* $Id: fault.c,v 1.11 1999/08/18 23:37:45 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -43,7 +43,7 @@ unsigned long asid_cache = ASID_FIRST_VERSION;
* and the problem, and then passes it off to one of the appropriate
* routines.
*/
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
unsigned long address)
{
struct vm_area_struct * vma;
@@ -59,7 +59,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
goto no_context;
#if 0
printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
- address, writeaccess, regs->cp0_epc);
+ address, write, regs->cp0_epc);
#endif
down(&mm->mmap_sem);
vma = find_vma(mm, address);
@@ -76,7 +76,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
* we can handle it..
*/
good_area:
- if (writeaccess) {
+ if (write) {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
} else {
@@ -89,8 +89,13 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- if (!handle_mm_fault(tsk, vma, address, writeaccess))
- goto do_sigbus;
+ {
+ int fault = handle_mm_fault(tsk, vma, address, write);
+ if (fault < 0)
+ goto out_of_memory;
+ if (!fault)
+ goto do_sigbus;
+ }
up(&mm->mmap_sem);
return;
@@ -104,12 +109,12 @@ bad_area:
if (user_mode(regs)) {
tsk->tss.cp0_badvaddr = address;
- tsk->tss.error_code = writeaccess;
+ tsk->tss.error_code = write;
#if 0
printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n"
"%08lx (epc == %08lx, ra == %08lx)\n",
tsk->comm,
- writeaccess ? "writeaccess to" : "readaccess from",
+ write ? "write access to" : "read access from",
address,
(unsigned long) regs->cp0_epc,
(unsigned long) regs->regs[31]);
@@ -140,13 +145,20 @@ no_context:
printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
"address %08lx, epc == %08lx, ra == %08lx\n",
address, regs->cp0_epc, regs->regs[31]);
- die("Oops", regs, writeaccess);
+ die("Oops", regs, write);
do_exit(SIGKILL);
/*
* 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", tsk->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+
do_sigbus:
up(&mm->mmap_sem);
diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c
index be843351e..e1c3251f8 100644
--- a/arch/mips/mm/r4xx0.c
+++ b/arch/mips/mm/r4xx0.c
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.22 1999/06/17 13:25:51 ralf Exp $
+/* $Id: r4xx0.c,v 1.23 1999/08/09 19:43:16 harald Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -2202,7 +2202,7 @@ static void r4600v20k_flush_cache_sigtramp(unsigned long addr)
unsigned int flags;
daddr = addr & ~(dc_lsize - 1);
- save_and_cli(flags);
+ __save_and_cli(flags);
/* Clear internal cache refill buffer */
*(volatile unsigned int *)KSEG1;
@@ -2212,7 +2212,7 @@ static void r4600v20k_flush_cache_sigtramp(unsigned long addr)
iaddr = addr & ~(ic_lsize - 1);
protected_flush_icache_line(iaddr);
protected_flush_icache_line(iaddr + ic_lsize);
- restore_flags(flags);
+ __restore_flags(flags);
}
#undef DEBUG_TLB
diff --git a/arch/mips/sgi/kernel/indy_sc.c b/arch/mips/sgi/kernel/indy_sc.c
index 2aff56637..1fecee23f 100644
--- a/arch/mips/sgi/kernel/indy_sc.c
+++ b/arch/mips/sgi/kernel/indy_sc.c
@@ -1,4 +1,4 @@
-/* $Id: indy_sc.c,v 1.8 1999/05/10 17:40:16 ulfc Exp $
+/* $Id: indy_sc.c,v 1.9 1999/05/12 21:57:49 ulfc Exp $
*
* indy_sc.c: Indy cache managment functions.
*
@@ -9,7 +9,6 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/autoconf.h>
#include <asm/bcache.h>
#include <asm/sgi.h>
diff --git a/arch/mips/tools/offset.c b/arch/mips/tools/offset.c
index f32f3e76e..ede1d5f93 100644
--- a/arch/mips/tools/offset.c
+++ b/arch/mips/tools/offset.c
@@ -1,9 +1,10 @@
-/* $Id: offset.c,v 1.9 1998/08/25 09:14:52 ralf Exp $
+/* $Id: offset.c,v 1.10 1999/08/18 23:37:46 ralf Exp $
*
* offset.c: Calculate pt_regs and task_struct offsets.
*
* Copyright (C) 1996 David S. Miller
- * Made portable by Ralf Baechle
+ * Copyright (C) 1997, 1998, 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
*/
#include <linux/types.h>
@@ -126,20 +127,17 @@ void output_mm_defines(void)
void output_sc_defines(void)
{
text("/* Linux sigcontext offsets. */");
- offset("#define SC_REGMASK ", struct sigcontext, sc_regmask);
- offset("#define SC_STATUS ", struct sigcontext, sc_status);
- offset("#define SC_PC ", struct sigcontext, sc_pc);
offset("#define SC_REGS ", struct sigcontext, sc_regs);
offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
+ offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+ offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
+ offset("#define SC_PC ", struct sigcontext, sc_pc);
+ offset("#define SC_STATUS ", struct sigcontext, sc_status);
offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp);
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
- offset("#define SC_SSFLAGS ", struct sigcontext, sc_ssflags);
- offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
- offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
- offset("#define SC_SIGSET ", struct sigcontext, sc_sigset);
linefeed;
}
diff --git a/arch/mips64/arc/env.c b/arch/mips64/arc/env.c
index 062a1e2c7..17ae2631b 100644
--- a/arch/mips64/arc/env.c
+++ b/arch/mips64/arc/env.c
@@ -16,7 +16,7 @@
#include <asm/sgialib.h>
CHAR * __init
-ArcArcGetEnvironmentVariable(CHAR *name)
+ArcGetEnvironmentVariable(CHAR *name)
{
return (CHAR *) ARC_CALL1(get_evar, name);
}
diff --git a/arch/mips64/arc/identify.c b/arch/mips64/arc/identify.c
index 958a38595..f87de0bda 100644
--- a/arch/mips64/arc/identify.c
+++ b/arch/mips64/arc/identify.c
@@ -62,7 +62,7 @@ prom_identify_arch(void)
/* The root component tells us what machine architecture we
have here. */
- p = prom_getchild(PROM_NULL_COMPONENT);
+ p = ArcGetChild(PROM_NULL_COMPONENT);
printk("ARCH: %s\n", p->iname);
mach = string_to_mach(p->iname);
diff --git a/arch/mips64/arc/tree.c b/arch/mips64/arc/tree.c
index ec53c1ac0..36045cbdd 100644
--- a/arch/mips64/arc/tree.c
+++ b/arch/mips64/arc/tree.c
@@ -105,10 +105,10 @@ static void __init
traverse(pcomponent *p, int op)
{
dump_component(p);
- if(prom_getchild(p))
- traverse(prom_getchild(p), 1);
- if(prom_getsibling(p) && op)
- traverse(prom_getsibling(p), 1);
+ if(ArcGetChild(p))
+ traverse(ArcGetChild(p), 1);
+ if(ArcGetPeer(p) && op)
+ traverse(ArcGetPeer(p), 1);
}
void __init
@@ -116,12 +116,12 @@ prom_testtree(void)
{
pcomponent *p;
- p = prom_getchild(PROM_NULL_COMPONENT);
+ p = ArcGetChild(PROM_NULL_COMPONENT);
dump_component(p);
- p = prom_getchild(p);
+ p = ArcGetChild(p);
while(p) {
dump_component(p);
- p = prom_getsibling(p);
+ p = ArcGetPeer(p);
}
prom_printf("press a key\n");
prom_getchar();
diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig
index 919219576..084678b49 100644
--- a/arch/mips64/defconfig
+++ b/arch/mips64/defconfig
@@ -53,6 +53,7 @@ CONFIG_KMOD=y
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_CPQ_DA is not set
#
# Additional Block Devices
@@ -123,6 +124,7 @@ CONFIG_VT_CONSOLE=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_UNIX98_PTYS is not set
# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
# CONFIG_MOUSE is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_WATCHDOG is not set
diff --git a/arch/mips64/kernel/Makefile b/arch/mips64/kernel/Makefile
index 0fada481d..f61a7139b 100644
--- a/arch/mips64/kernel/Makefile
+++ b/arch/mips64/kernel/Makefile
@@ -12,7 +12,7 @@
all: kernel.o head.o init_task.o
O_TARGET := kernel.o
-O_OBJS := entry.o setup.o
+O_OBJS := entry.o proc.o r4k_fpu.o setup.o signal.o traps.o
OX_OBJS := mips64_ksyms.o
clean:
diff --git a/arch/mips64/kernel/entry.S b/arch/mips64/kernel/entry.S
index dc8a6d4bc..297c41840 100644
--- a/arch/mips64/kernel/entry.S
+++ b/arch/mips64/kernel/entry.S
@@ -18,9 +18,9 @@
#include <asm/mipsregs.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/processor.h>
-#include <asm/regdef.h>
#include <asm/fpregdef.h>
#include <asm/unistd.h>
@@ -102,7 +102,7 @@ LEAF(spurious_interrupt)
cfc1 a1, fcr31
li a2, ~(0x3f << 13)
and a2, a1
- ctc a2, fcr31
+ ctc1 a2, fcr31
STI
.endm
@@ -112,48 +112,51 @@ LEAF(spurious_interrupt)
KMODE
.endm
-#define __BUILD_silent(exception)
-
-#define fmt "Got %s at %08lx.\n"
-
-#define __BUILD_verbose(exception) \
- la a1,8f; \
- TEXT (#exception); \
- ld a2, PT_EPC(sp); \
- PRINT(fmt)
-#define __BUILD_count(exception) \
- .set reorder; \
- lw t0,exception_count_##exception; \
- addiu t0, 1; \
- sw t0,exception_count_##exception; \
- .set noreorder; \
- .data; \
-EXPORT(exception_count_##exception); \
- .word 0; \
- .previous;
-#define BUILD_HANDLER(exception,handler,clear,verbose) \
- .align 5; \
- NESTED(handle_##exception, PT_SIZE, sp); \
- .set noat; \
- SAVE_ALL; \
- __BUILD_clear_##clear exception; \
- .set at; \
- __BUILD_##verbose(exception); \
- jal do_##handler; \
- move a0,sp; \
- j ret_from_sys_call; \
- nop; \
- END(handle_##exception)
-
- BUILD_HANDLER(adel,ade,ade,silent) /* #4 */
- BUILD_HANDLER(ades,ade,ade,silent) /* #5 */
- BUILD_HANDLER(ibe,ibe,cli,verbose) /* #6 */
- BUILD_HANDLER(dbe,dbe,cli,silent) /* #7 */
- BUILD_HANDLER(bp,bp,sti,silent) /* #9 */
- BUILD_HANDLER(ri,ri,sti,silent) /* #10 */
- BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */
- BUILD_HANDLER(ov,ov,sti,silent) /* #12 */
- BUILD_HANDLER(tr,tr,sti,silent) /* #13 */
- BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */
- BUILD_HANDLER(watch,watch,sti,verbose) /* #23 */
- BUILD_HANDLER(reserved,reserved,sti,verbose) /* others */
+ .macro __BUILD_silent exception
+ .endm
+
+ /* Gas tries to parse the PRINT argument as a string containing
+ string escapes and emits bogus warnings if it believes to
+ recognize an unknown escape code. So make the arguments
+ start with an n and gas will believe \n is ok ... */
+ .macro __BUILD_verbose nexception
+ ld a1, PT_EPC(sp)
+ PRINT("Got \nexception at %016lx")
+ .endm
+
+ .macro __BUILD_count exception
+ .set reorder
+ ld t0,exception_count_\exception
+ daddiu t0, 1
+ sd t0,exception_count_\exception
+ .set noreorder
+ .comm exception_count\exception, 8, 8
+ .endm
+
+ .macro BUILD_HANDLER exception handler clear verbose
+ .align 5
+ NESTED(handle_\exception, PT_SIZE, sp)
+ .set noat
+ SAVE_ALL
+ __BUILD_clear_\clear
+ .set at
+ __BUILD_\verbose \exception
+ jal do_\handler
+ move a0,sp
+ j ret_from_sys_call
+ nop
+ END(handle_\exception)
+ .endm
+
+ BUILD_HANDLER adel ade ade silent /* #4 */
+ BUILD_HANDLER ades ade ade silent /* #5 */
+ BUILD_HANDLER ibe ibe cli verbose /* #6 */
+ BUILD_HANDLER dbe dbe cli silent /* #7 */
+ BUILD_HANDLER bp bp sti silent /* #9 */
+ BUILD_HANDLER ri ri sti silent /* #10 */
+ BUILD_HANDLER cpu cpu sti silent /* #11 */
+ BUILD_HANDLER ov ov sti silent /* #12 */
+ BUILD_HANDLER tr tr sti silent /* #13 */
+ BUILD_HANDLER fpe fpe fpe silent /* #15 */
+ BUILD_HANDLER watch watch sti verbose /* #23 */
+ BUILD_HANDLER reserved reserved sti verbose /* others */
diff --git a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c
index fc422788e..355f34115 100644
--- a/arch/mips64/kernel/mips64_ksyms.c
+++ b/arch/mips64/kernel/mips64_ksyms.c
@@ -86,11 +86,6 @@ EXPORT_SYMBOL(dma_cache_inv);
EXPORT_SYMBOL(invalid_pte_table);
/*
- * Base address of ports for Intel style I/O.
- */
-EXPORT_SYMBOL(mips_io_port_base);
-
-/*
* Kernel hacking ...
*/
#include <asm/branch.h>
diff --git a/arch/mips64/kernel/proc.c b/arch/mips64/kernel/proc.c
new file mode 100644
index 000000000..6fba1b756
--- /dev/null
+++ b/arch/mips64/kernel/proc.c
@@ -0,0 +1,71 @@
+/* $Id: proc.c,v 1.1 1999/09/27 16:01:37 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1999 Ralf Baechle
+ *
+ * XXX Rewrite this mess.
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/processor.h>
+#include <asm/watch.h>
+
+unsigned long unaligned_instructions;
+unsigned int vced_count, vcei_count;
+
+/*
+ * BUFFER is PAGE_SIZE bytes long.
+ *
+ * Currently /proc/cpuinfo is being abused to print data about the
+ * number of date/instruction cacheflushes.
+ */
+int get_cpuinfo(char *buffer)
+{
+ char fmt [64];
+ size_t len;
+
+ len = sprintf(buffer, "cpu\t\t\t: MIPS\n");
+#if 0
+ len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n",
+ cpu_name[mips_cputype <= CPU_LAST ?
+ mips_cputype :
+ CPU_UNKNOWN],
+ (version >> 4) & 0x0f,
+ version & 0x0f);
+ len += sprintf(buffer + len, "system type\t\t: %s %s\n",
+ mach_group_names[mips_machgroup],
+ mach_group_to_name[mips_machgroup][mips_machtype]);
+#endif
+ len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n",
+ (loops_per_sec + 2500) / 500000,
+ ((loops_per_sec + 2500) / 5000) % 100);
+#if defined (__MIPSEB__)
+ len += sprintf(buffer + len, "byteorder\t\t: big endian\n");
+#endif
+#if defined (__MIPSEL__)
+ len += sprintf(buffer + len, "byteorder\t\t: little endian\n");
+#endif
+ len += sprintf(buffer + len, "unaligned accesses\t: %lu\n",
+ unaligned_instructions);
+ len += sprintf(buffer + len, "wait instruction\t: %s\n",
+ wait_available ? "yes" : "no");
+ len += sprintf(buffer + len, "microsecond timers\t: %s\n",
+ cyclecounter_available ? "yes" : "no");
+ len += sprintf(buffer + len, "extra interrupt vector\t: %s\n",
+ dedicated_iv_available ? "yes" : "no");
+ len += sprintf(buffer + len, "hardware watchpoint\t: %s\n",
+ watch_available ? "yes" : "no");
+
+ sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
+ vce_available ? "%d" : "not available");
+ len += sprintf(buffer + len, fmt, 'D', vced_count);
+ len += sprintf(buffer + len, fmt, 'I', vcei_count);
+
+ return len;
+}
diff --git a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c
new file mode 100644
index 000000000..8002c4f64
--- /dev/null
+++ b/arch/mips64/kernel/process.c
@@ -0,0 +1,167 @@
+/* $Id: process.c,v 1.1 1999/09/27 16:01:37 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999 by Ralf Baechle and others.
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/mman.h>
+#include <linux/sys.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+
+#include <asm/bootinfo.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/processor.h>
+#include <asm/stackframe.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/elf.h>
+
+struct task_struct *last_task_used_math = NULL;
+
+asmlinkage void ret_from_sys_call(void);
+
+void exit_thread(void)
+{
+ /* Forget lazy fpu state */
+ if (last_task_used_math == current) {
+ set_cp0_status(ST0_CU1, ST0_CU1);
+ __asm__ __volatile__("cfc1\t$0,$31");
+ last_task_used_math = NULL;
+ }
+}
+
+void flush_thread(void)
+{
+ /* Forget lazy fpu state */
+ if (last_task_used_math == current) {
+ set_cp0_status(ST0_CU1, ST0_CU1);
+ __asm__ __volatile__("cfc1\t$0,$31");
+ last_task_used_math = NULL;
+ }
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ struct task_struct * p, struct pt_regs * regs)
+{
+ struct pt_regs * childregs;
+ long childksp;
+
+ childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
+
+ if (last_task_used_math == current) {
+ set_cp0_status(ST0_CU1, ST0_CU1);
+ r4xx0_save_fp(p);
+ }
+ /* set up new TSS. */
+ childregs = (struct pt_regs *) childksp - 1;
+ *childregs = *regs;
+ childregs->regs[7] = 0; /* Clear error flag */
+ if(current->personality == PER_LINUX) {
+ childregs->regs[2] = 0; /* Child gets zero as return value */
+ regs->regs[2] = p->pid;
+ } else {
+ /* Under IRIX things are a little different. */
+ childregs->regs[2] = 0;
+ childregs->regs[3] = 1;
+ regs->regs[2] = p->pid;
+ regs->regs[3] = 0;
+ }
+ if (childregs->cp0_status & ST0_CU0) {
+ childregs->regs[28] = (unsigned long) p;
+ childregs->regs[29] = childksp;
+ p->tss.current_ds = KERNEL_DS;
+ } else {
+ childregs->regs[29] = usp;
+ p->tss.current_ds = USER_DS;
+ }
+ p->tss.reg29 = (unsigned long) childregs;
+ p->tss.reg31 = (unsigned long) ret_from_sys_call;
+
+ /*
+ * New tasks loose permission to use the fpu. This accelerates context
+ * switching for most programs since they don't use the fpu.
+ */
+ p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
+ ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU);
+ childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1);
+ p->mm->context = 0;
+
+ return 0;
+}
+
+/* Fill in the fpu structure for a core dump.. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
+{
+ /* We actually store the FPU info in the task->tss
+ * area.
+ */
+ if(regs->cp0_status & ST0_CU1) {
+ memcpy(r, &current->tss.fpu, sizeof(current->tss.fpu));
+ return 1;
+ }
+ return 0; /* Task didn't use the fpu at all. */
+}
+
+/* Fill in the user structure for a core dump.. */
+void dump_thread(struct pt_regs *regs, struct user *dump)
+{
+ dump->magic = CMAGIC;
+ dump->start_code = current->mm->start_code;
+ dump->start_data = current->mm->start_data;
+ dump->start_stack = regs->regs[29] & ~(PAGE_SIZE - 1);
+ dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
+ dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) >> PAGE_SHIFT;
+ dump->u_ssize =
+ (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ memcpy(&dump->regs[0], regs, sizeof(struct pt_regs));
+ memcpy(&dump->regs[EF_SIZE/4], &current->tss.fpu, sizeof(current->tss.fpu));
+}
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+ long retval;
+
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ "move\t$6, $sp\n\t"
+ "move\t$4, %5\n\t"
+ "li\t$2, %1\n\t"
+ "syscall\n\t"
+ "beq\t$6, $sp, 1f\n\t"
+ " dsubu\t$sp, 32\n\t"
+ "jalr\t%4\n\t"
+ " move\t$4, %3\n\t"
+ "move\t$4, $2\n\t"
+ "li\t$2, %2\n\t"
+ "syscall\n"
+ "1:\tdaddiu\t$sp, 32\n\t"
+ "move\t%0, $2\n\t"
+ ".set\treorder"
+ :"=r" (retval)
+ :"i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn),
+ "r" (flags | CLONE_VM)
+
+ /* The called subroutine might have destroyed any of the
+ * at, result, argument or temporary registers ... */
+ :"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+ "$9","$10","$11","$12","$13","$14","$15","$24","$25");
+
+ return retval;
+}
diff --git a/arch/mips64/kernel/r4k_fpu.S b/arch/mips64/kernel/r4k_fpu.S
new file mode 100644
index 000000000..609b9fd0a
--- /dev/null
+++ b/arch/mips64/kernel/r4k_fpu.S
@@ -0,0 +1,149 @@
+/* $Id: r4k_fpu.S,v 1.1 1999/09/27 16:01:38 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Save/restore floating point context for signal handlers.
+ *
+ * Copyright (C) 1996, 1998, 1999 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/errno.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+ .macro EX insn, reg, src
+ .set push
+ .set nomacro
+.ex\@: \insn \reg, \src
+ .set pop
+ .section __ex_table,"a"
+ PTR .ex\@, fault
+ .previous
+ .endm
+
+ .set noreorder
+ /* Save floating point context */
+LEAF(save_fp_context)
+ mfc0 t1,CP0_STATUS
+ sll t2,t1,5
+
+ bgez t2,1f
+ cfc1 t1,fcr31
+ /* Store the 16 odd double precision registers */
+ EX sdc1 $f1, SC_FPREGS+8(a0)
+ EX sdc1 $f3, SC_FPREGS+24(a0)
+ EX sdc1 $f5, SC_FPREGS+40(a0)
+ EX sdc1 $f7, SC_FPREGS+56(a0)
+ EX sdc1 $f9, SC_FPREGS+72(a0)
+ EX sdc1 $f11, SC_FPREGS+88(a0)
+ EX sdc1 $f13, SC_FPREGS+104(a0)
+ EX sdc1 $f15, SC_FPREGS+120(a0)
+ EX sdc1 $f17, SC_FPREGS+136(a0)
+ EX sdc1 $f19, SC_FPREGS+152(a0)
+ EX sdc1 $f21, SC_FPREGS+168(a0)
+ EX sdc1 $f23, SC_FPREGS+184(a0)
+ EX sdc1 $f25, SC_FPREGS+200(a0)
+ EX sdc1 $f27, SC_FPREGS+216(a0)
+ EX sdc1 $f29, SC_FPREGS+232(a0)
+ EX sdc1 $f31, SC_FPREGS+248(a0)
+
+ /* Store the 16 even double precision registers */
+1:
+ EX sdc1 $f0, SC_FPREGS+0(a0)
+ EX sdc1 $f2, SC_FPREGS+16(a0)
+ EX sdc1 $f4, SC_FPREGS+32(a0)
+ EX sdc1 $f6, SC_FPREGS+48(a0)
+ EX sdc1 $f8, SC_FPREGS+64(a0)
+ EX sdc1 $f10, SC_FPREGS+80(a0)
+ EX sdc1 $f12, SC_FPREGS+96(a0)
+ EX sdc1 $f14, SC_FPREGS+112(a0)
+ EX sdc1 $f16, SC_FPREGS+128(a0)
+ EX sdc1 $f18, SC_FPREGS+144(a0)
+ EX sdc1 $f20, SC_FPREGS+160(a0)
+ EX sdc1 $f22, SC_FPREGS+176(a0)
+ EX sdc1 $f24, SC_FPREGS+192(a0)
+ EX sdc1 $f26, SC_FPREGS+208(a0)
+ EX sdc1 $f28, SC_FPREGS+224(a0)
+ EX sdc1 $f30, SC_FPREGS+240(a0)
+ EX sw t1, SC_FPC_CSR(a0)
+ cfc1 t0,$0 # implementation/version
+ EX sw t0,SC_FPC_EIR(a0)
+
+ jr ra
+ li v0, 0 # success
+ END(save_fp_context)
+
+/*
+ * Restore FPU state:
+ * - fp gp registers
+ * - cp1 status/control register
+ *
+ * We base the decision which registers to restore from the signal stack
+ * frame on the current content of c0_status, not on the content of the
+ * stack frame which might have been changed by the user.
+ */
+LEAF(restore_fp_context)
+ mfc0 t1, CP0_STATUS
+ sll t0,t1,5
+ bgez t0,1f
+ EX lw t0, SC_FPC_CSR(a0)
+
+ /* Restore the 16 odd double precision registers only
+ * when enabled in the cp0 status register.
+ */
+ EX ldc1 $f1, SC_FPREGS+8(a0)
+ EX ldc1 $f3, SC_FPREGS+24(a0)
+ EX ldc1 $f5, SC_FPREGS+40(a0)
+ EX ldc1 $f7, SC_FPREGS+56(a0)
+ EX ldc1 $f9, SC_FPREGS+72(a0)
+ EX ldc1 $f11, SC_FPREGS+88(a0)
+ EX ldc1 $f13, SC_FPREGS+104(a0)
+ EX ldc1 $f15, SC_FPREGS+120(a0)
+ EX ldc1 $f17, SC_FPREGS+136(a0)
+ EX ldc1 $f19, SC_FPREGS+152(a0)
+ EX ldc1 $f21, SC_FPREGS+168(a0)
+ EX ldc1 $f23, SC_FPREGS+184(a0)
+ EX ldc1 $f25, SC_FPREGS+200(a0)
+ EX ldc1 $f27, SC_FPREGS+216(a0)
+ EX ldc1 $f29, SC_FPREGS+232(a0)
+ EX ldc1 $f31, SC_FPREGS+248(a0)
+
+ /*
+ * Restore the 16 even double precision registers
+ * when cp1 was enabled in the cp0 status register.
+ */
+1: EX ldc1 $f0, SC_FPREGS+0(a0)
+ EX ldc1 $f2, SC_FPREGS+16(a0)
+ EX ldc1 $f4, SC_FPREGS+32(a0)
+ EX ldc1 $f6, SC_FPREGS+48(a0)
+ EX ldc1 $f8, SC_FPREGS+64(a0)
+ EX ldc1 $f10, SC_FPREGS+80(a0)
+ EX ldc1 $f12, SC_FPREGS+96(a0)
+ EX ldc1 $f14, SC_FPREGS+112(a0)
+ EX ldc1 $f16, SC_FPREGS+128(a0)
+ EX ldc1 $f18, SC_FPREGS+144(a0)
+ EX ldc1 $f20, SC_FPREGS+160(a0)
+ EX ldc1 $f22, SC_FPREGS+176(a0)
+ EX ldc1 $f24, SC_FPREGS+192(a0)
+ EX ldc1 $f26, SC_FPREGS+208(a0)
+ EX ldc1 $f28, SC_FPREGS+224(a0)
+ EX ldc1 $f30, SC_FPREGS+240(a0)
+ ctc1 t0,fcr31
+ jr ra
+ li v0, 0 # success
+ END(restore_fp_context)
+
+ .type fault@function
+ .ent fault
+fault: li v0, -EFAULT
+ jr ra
+ .end fault
diff --git a/arch/mips64/kernel/setup.c b/arch/mips64/kernel/setup.c
index dc5b4e902..f7904551e 100644
--- a/arch/mips64/kernel/setup.c
+++ b/arch/mips64/kernel/setup.c
@@ -37,6 +37,10 @@
struct mips_cpuinfo boot_cpu_data;
+#ifdef CONFIG_VT
+struct screen_info screen_info;
+#endif
+
/*
* Not all of the MIPS CPUs have the "wait" instruction available. This
* is set to true if it is available. The wait instruction stops the
diff --git a/arch/mips64/kernel/signal.c b/arch/mips64/kernel/signal.c
new file mode 100644
index 000000000..e7950553d
--- /dev/null
+++ b/arch/mips64/kernel/signal.c
@@ -0,0 +1,654 @@
+/* $Id: signal.c,v 1.1 1999/09/27 16:01:38 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+
+#include <asm/asm.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/stackframe.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+ int options, unsigned long *ru);
+extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
+extern asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage inline int
+sys_sigsuspend(struct pt_regs regs)
+{
+ sigset_t *uset, saveset, newset;
+
+ save_static(&regs);
+ uset = (sigset_t *) regs.regs[4];
+ if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sigmask_lock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, &regs))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_rt_sigsuspend(struct pt_regs regs)
+{
+ sigset_t *unewset, saveset, newset;
+ size_t sigsetsize;
+
+ save_static(&regs);
+
+ /* XXX Don't preclude handling different sized sigset_t's. */
+ sigsetsize = regs.regs[5];
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ unewset = (sigset_t *) regs.regs[4];
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sigmask_lock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, &regs))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+ int err = 0;
+
+ if (act) {
+ old_sigset_t mask;
+
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+ return -EFAULT;
+ err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
+ err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ err |= __get_user(mask, &act->sa_mask.sig[0]);
+ err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer);
+ if (err)
+ return -EFAULT;
+
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+ return -EFAULT;
+ err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
+ err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
+ err |= __put_user(0, &oact->sa_mask.sig[1]);
+ err |= __put_user(0, &oact->sa_mask.sig[2]);
+ err |= __put_user(0, &oact->sa_mask.sig[3]);
+ err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer);
+ if (err)
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(struct pt_regs regs)
+{
+ const stack_t *uss = (const stack_t *) regs.regs[4];
+ stack_t *uoss = (stack_t *) regs.regs[5];
+ unsigned long usp = regs.regs[29];
+
+ return do_sigaltstack(uss, uoss, usp);
+}
+
+asmlinkage int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+ int owned_fp;
+ int err = 0;
+
+ err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __get_user(regs->hi, &sc->sc_mdhi);
+ err |= __get_user(regs->lo, &sc->sc_mdlo);
+
+#define restore_gp_reg(i) do { \
+ err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
+} while(0)
+ restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
+ restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
+ restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
+ restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+ restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+ restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+ restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+ restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+ restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+ restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+ restore_gp_reg(31);
+#undef restore_gp_reg
+
+ err |= __get_user(owned_fp, &sc->sc_ownedfp);
+ if (owned_fp) {
+ err |= restore_fp_context(sc);
+ last_task_used_math = current;
+ }
+
+ return err;
+}
+
+struct sigframe {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_code[2]; /* signal trampoline */
+ struct sigcontext sf_sc;
+ sigset_t sf_mask;
+};
+
+struct rt_sigframe {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_code[2]; /* signal trampoline */
+ struct siginfo rs_info;
+ struct ucontext rs_uc;
+};
+
+asmlinkage void
+sys_sigreturn(struct pt_regs regs)
+{
+ struct sigframe *frame;
+ sigset_t blocked;
+
+ frame = (struct sigframe *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
+ goto badframe;
+
+ sigdelsetmask(&blocked, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = blocked;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (restore_sigcontext(&regs, &frame->sf_sc))
+ goto badframe;
+
+ /*
+ * Don't let your children do this ...
+ */
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tret_from_sys_call"
+ :/* no outputs */
+ :"r" (&regs));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+asmlinkage void
+sys_rt_sigreturn(struct pt_regs regs)
+{
+ struct rt_sigframe *frame;
+ sigset_t set;
+ stack_t st;
+
+ frame = (struct rt_sigframe *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs.regs[29]);
+
+ /*
+ * Don't let your children do this ...
+ */
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tret_from_sys_call"
+ :/* no outputs */
+ :"r" (&regs));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+static int inline
+setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+ int owned_fp;
+ int err = 0;
+
+ err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __put_user(regs->cp0_status, &sc->sc_status);
+
+#define save_gp_reg(i) { \
+ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
+} while(0)
+ __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+ save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+ save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+ save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+ save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+ save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+ save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+ save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+ save_gp_reg(31);
+#undef save_gp_reg
+
+ err |= __put_user(regs->hi, &sc->sc_mdhi);
+ err |= __put_user(regs->lo, &sc->sc_mdlo);
+ err |= __put_user(regs->cp0_cause, &sc->sc_cause);
+ err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
+
+ owned_fp = (current == last_task_used_math);
+ err |= __put_user(owned_fp, &sc->sc_ownedfp);
+
+ if (current->used_math) { /* fp is active. */
+ set_cp0_status(ST0_CU1, ST0_CU1);
+ err |= save_fp_context(sc);
+ last_task_used_math = NULL;
+ regs->cp0_status &= ~ST0_CU1;
+ current->used_math = 0;
+ }
+
+ return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+ unsigned long sp;
+
+ /* Default to using normal stack */
+ sp = regs->regs[29];
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *)((sp - frame_size) & ALMASK);
+}
+
+static void inline
+setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *set)
+{
+ struct sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub already
+ in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER)
+ regs->regs[31] = (unsigned long) ka->sa.sa_restorer;
+ else {
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_sigreturn
+ * syscall
+ */
+ err |= __put_user(0x24020000 + __NR_sigreturn,
+ frame->sf_code + 0);
+ err |= __put_user(0x0000000c ,
+ frame->sf_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->sf_code);
+ }
+
+ err |= setup_sigcontext(regs, &frame->sf_sc);
+ err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to struct sigcontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to the
+ * struct sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = 0;
+ regs->regs[ 6] = (unsigned long) &frame->sf_sc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->sf_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
+ current->comm, current->pid, frame, regs->cp0_epc, frame->code);
+#endif
+ return;
+
+give_sigsegv:
+ if (signr == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+static void inline
+setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *set, siginfo_t *info)
+{
+ struct rt_sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub already
+ in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER)
+ regs->regs[31] = (unsigned long) ka->sa.sa_restorer;
+ else {
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_sigreturn
+ * syscall
+ */
+ err |= __put_user(0x24020000 + __NR_sigreturn,
+ frame->rs_code + 0);
+ err |= __put_user(0x0000000c ,
+ frame->rs_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->rs_code);
+ }
+
+ /* Create siginfo. */
+ err |= __copy_to_user(&frame->rs_info, info, sizeof(*info));
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->rs_uc.uc_flags);
+ err |= __put_user(0, &frame->rs_uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->rs_uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->regs[29]),
+ &frame->rs_uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size,
+ &frame->rs_uc.uc_stack.ss_size);
+ err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
+ err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to ucontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to
+ * the struct rt_sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = (unsigned long) &frame->rs_info;
+ regs->regs[ 6] = (unsigned long) &frame->rs_uc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->rs_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
+ current->comm, current->pid, frame, regs->cp0_epc, frame->code);
+#endif
+ return;
+
+give_sigsegv:
+ if (signr == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+static inline void
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(ka, regs, sig, oldset, info);
+ else
+ setup_frame(ka, regs, sig, oldset);
+
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&current->sigmask_lock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+ }
+}
+
+static inline void
+syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
+{
+ switch(regs->regs[0]) {
+ case ERESTARTNOHAND:
+ regs->regs[2] = EINTR;
+ break;
+ case ERESTARTSYS:
+ if(!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->regs[2] = EINTR;
+ break;
+ }
+ /* fallthrough */
+ case ERESTARTNOINTR: /* Userland will reload $v0. */
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 8;
+ }
+
+ regs->regs[0] = 0; /* Don't deal with this again. */
+}
+
+extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
+
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+ struct k_sigaction *ka;
+ siginfo_t info;
+
+#ifdef CONFIG_BINFMT_IRIX
+ if (current->personality != PER_LINUX)
+ return do_irix_signal(oldset, regs);
+#endif
+
+ if (!oldset)
+ oldset = &current->blocked;
+
+ for (;;) {
+ unsigned long signr;
+
+ spin_lock_irq(&current->sigmask_lock);
+ signr = dequeue_signal(&current->blocked, &info);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (!signr)
+ break;
+
+ if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ /* Let the debugger run. */
+ current->exit_code = signr;
+ current->state = TASK_STOPPED;
+ notify_parent(current, SIGCHLD);
+ schedule();
+
+ /* We're back. Did the debugger cancel the sig? */
+ if (!(signr = current->exit_code))
+ continue;
+ current->exit_code = 0;
+
+ /* The debugger continued. Ignore SIGSTOP. */
+ if (signr == SIGSTOP)
+ continue;
+
+ /* Update the siginfo structure. Is this good? */
+ if (signr != info.si_signo) {
+ info.si_signo = signr;
+ info.si_errno = 0;
+ info.si_code = SI_USER;
+ info.si_pid = current->p_pptr->pid;
+ info.si_uid = current->p_pptr->uid;
+ }
+
+ /* If the (new) signal is now blocked, requeue it. */
+ if (sigismember(&current->blocked, signr)) {
+ send_sig_info(signr, &info, current);
+ continue;
+ }
+ }
+
+ ka = &current->sig->action[signr-1];
+ if (ka->sa.sa_handler == SIG_IGN) {
+ if (signr != SIGCHLD)
+ continue;
+ /* Check for SIGCHLD: it's special. */
+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+ /* nothing */;
+ continue;
+ }
+
+ if (ka->sa.sa_handler == SIG_DFL) {
+ int exit_code = signr;
+
+ /* Init gets no signals it doesn't want. */
+ if (current->pid == 1)
+ continue;
+
+ switch (signr) {
+ case SIGCONT: case SIGCHLD: case SIGWINCH:
+ continue;
+
+ case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ if (is_orphaned_pgrp(current->pgrp))
+ continue;
+ /* FALLTHRU */
+
+ case SIGSTOP:
+ current->state = TASK_STOPPED;
+ current->exit_code = signr;
+ if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+ notify_parent(current, SIGCHLD);
+ schedule();
+ continue;
+
+ case SIGQUIT: case SIGILL: case SIGTRAP:
+ case SIGABRT: case SIGFPE: case SIGSEGV:
+ case SIGBUS:
+ lock_kernel();
+ if (current->binfmt
+ && current->binfmt->core_dump
+ && current->binfmt->core_dump(signr, regs))
+ exit_code |= 0x80;
+ unlock_kernel();
+ /* FALLTHRU */
+
+ default:
+ lock_kernel();
+ sigaddset(&current->signal, signr);
+ recalc_sigpending(current);
+ current->flags |= PF_SIGNALED;
+ do_exit(exit_code);
+ /* NOTREACHED */
+ }
+ }
+
+ if (regs->regs[0])
+ syscall_restart(regs, ka);
+ /* Whee! Actually deliver the signal. */
+ handle_signal(signr, ka, &info, oldset, regs);
+ return 1;
+ }
+
+ /*
+ * Who's code doesn't conform to the restartable syscall convention
+ * dies here!!! The li instruction, a single machine instruction,
+ * must directly be followed by the syscall instruction.
+ */
+ if (regs->regs[0]) {
+ if (regs->regs[2] == ERESTARTNOHAND ||
+ regs->regs[2] == ERESTARTSYS ||
+ regs->regs[2] == ERESTARTNOINTR) {
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 8;
+ }
+ }
+ return 0;
+}
diff --git a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c
new file mode 100644
index 000000000..ea700e5ef
--- /dev/null
+++ b/arch/mips64/kernel/traps.c
@@ -0,0 +1,562 @@
+/* $Id: traps.c,v 1.1 1999/09/27 16:01:38 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999 by Ralf Baechle
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ * Copyright (C) 1998 Ulf Carlsson
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/branch.h>
+#include <asm/cachectl.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/watch.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+static inline void console_verbose(void)
+{
+ extern int console_loglevel;
+ console_loglevel = 15;
+}
+
+extern asmlinkage void r4k_handle_mod(void);
+extern asmlinkage void r4k_handle_tlbl(void);
+extern asmlinkage void r4k_handle_tlbs(void);
+extern asmlinkage void handle_adel(void);
+extern asmlinkage void handle_ades(void);
+extern asmlinkage void handle_ibe(void);
+extern asmlinkage void handle_dbe(void);
+extern asmlinkage void handle_sys(void);
+extern asmlinkage void handle_bp(void);
+extern asmlinkage void handle_ri(void);
+extern asmlinkage void handle_cpu(void);
+extern asmlinkage void handle_ov(void);
+extern asmlinkage void handle_tr(void);
+extern asmlinkage void handle_fpe(void);
+extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_reserved(void);
+
+static char *cpu_names[] = CPU_NAMES;
+
+char watch_available = 0;
+char dedicated_iv_available = 0;
+char vce_available = 0;
+
+void (*ibe_board_handler)(struct pt_regs *regs);
+void (*dbe_board_handler)(struct pt_regs *regs);
+
+int kstack_depth_to_print = 24;
+
+/*
+ * These constant is for searching for possible module text segments.
+ * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
+ */
+#define MODULE_RANGE (8*1024*1024)
+
+/*
+ * This routine abuses get_user()/put_user() to reference pointers
+ * with at least a bit of error checking ...
+ */
+void show_stack(unsigned int *sp)
+{
+ int i;
+ unsigned int *stack;
+
+ stack = sp;
+ i = 0;
+
+ printk("Stack:");
+ while ((unsigned long) stack & (PAGE_SIZE - 1)) {
+ unsigned long stackdata;
+
+ if (__get_user(stackdata, stack++)) {
+ printk(" (Bad stack address)");
+ break;
+ }
+
+ printk(" %08lx", stackdata);
+
+ if (++i > 40) {
+ printk(" ...");
+ break;
+ }
+
+ if (i % 8 == 0)
+ printk("\n ");
+ }
+}
+
+void show_trace(unsigned int *sp)
+{
+ int i;
+ unsigned int *stack;
+ unsigned long kernel_start, kernel_end;
+ unsigned long module_start, module_end;
+ extern char _stext, _etext;
+
+ stack = sp;
+ i = 0;
+
+ kernel_start = (unsigned long) &_stext;
+ kernel_end = (unsigned long) &_etext;
+ module_start = VMALLOC_START;
+ module_end = module_start + MODULE_RANGE;
+
+ printk("\nCall Trace:");
+
+ while ((unsigned long) stack & (PAGE_SIZE -1)) {
+ unsigned long addr;
+
+ if (__get_user(addr, stack++)) {
+ printk(" (Bad stack address)\n");
+ break;
+ }
+
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+
+ if ((addr >= kernel_start && addr < kernel_end) ||
+ (addr >= module_start && addr < module_end)) {
+
+ printk(" [<%08lx>]", addr);
+ if (++i > 40) {
+ printk(" ...");
+ break;
+ }
+ }
+ }
+}
+
+void show_code(unsigned int *pc)
+{
+ long i;
+
+ printk("\nCode:");
+
+ for(i = -3 ; i < 6 ; i++) {
+ unsigned long insn;
+ if (__get_user(insn, pc + i)) {
+ printk(" (Bad address in epc)\n");
+ break;
+ }
+ printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
+ }
+}
+
+void die(const char * str, struct pt_regs * regs, unsigned long err)
+{
+ if (user_mode(regs)) /* Just return if in user mode. */
+ return;
+
+ console_verbose();
+ printk("%s: %04lx\n", str, err & 0xffff);
+ show_regs(regs);
+ printk("Process %s (pid: %ld, stackpage=%08lx)\n",
+ current->comm, current->pid, (unsigned long) current);
+ show_stack((unsigned int *) regs->regs[29]);
+ show_trace((unsigned int *) regs->regs[29]);
+ show_code((unsigned int *) regs->cp0_epc);
+ printk("\n");
+ do_exit(SIGSEGV);
+}
+
+void die_if_kernel(const char * str, struct pt_regs * regs, unsigned long err)
+{
+ if (!user_mode(regs))
+ die(str, regs, err);
+}
+
+static void default_be_board_handler(struct pt_regs *regs)
+{
+ /*
+ * Assume it would be too dangerous to continue ...
+ */
+ force_sig(SIGBUS, current);
+}
+
+void do_ibe(struct pt_regs *regs)
+{
+show_regs(regs); while(1);
+ ibe_board_handler(regs);
+}
+
+void do_dbe(struct pt_regs *regs)
+{
+show_regs(regs); while(1);
+ dbe_board_handler(regs);
+}
+
+void do_ov(struct pt_regs *regs)
+{
+ if (compute_return_epc(regs))
+ return;
+ force_sig(SIGFPE, current);
+}
+
+#ifdef CONFIG_MIPS_FPE_MODULE
+static void (*fpe_handler)(struct pt_regs *regs, unsigned int fcr31);
+
+/*
+ * Register_fpe/unregister_fpe are for debugging purposes only. To make
+ * this hack work a bit better there is no error checking.
+ */
+int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31))
+{
+ fpe_handler = handler;
+ return 0;
+}
+
+int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31))
+{
+ fpe_handler = NULL;
+ return 0;
+}
+#endif
+
+/*
+ * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
+ */
+void do_fpe(struct pt_regs *regs, unsigned long fcr31)
+{
+ unsigned long pc;
+ unsigned int insn;
+
+#ifdef CONFIG_MIPS_FPE_MODULE
+ if (fpe_handler != NULL) {
+ fpe_handler(regs, fcr31);
+ return;
+ }
+#endif
+ lock_kernel();
+ if (fcr31 & 0x20000) {
+ /* Retry instruction with flush to zero ... */
+ if (!(fcr31 & (1<<24))) {
+ printk("Setting flush to zero for %s.\n",
+ current->comm);
+ fcr31 &= ~0x20000;
+ fcr31 |= (1<<24);
+ __asm__ __volatile__(
+ "ctc1\t%0,$31"
+ : /* No outputs */
+ : "r" (fcr31));
+ goto out;
+ }
+ pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
+ if (get_user(insn, (unsigned int *)pc)) {
+ /* XXX Can this happen? */
+ force_sig(SIGSEGV, current);
+ }
+
+ printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n",
+ insn, regs->cp0_epc, current->comm);
+ simfp(insn);
+ }
+
+ if (compute_return_epc(regs))
+ goto out;
+ //force_sig(SIGFPE, current);
+ printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
+
+out:
+ unlock_kernel();
+}
+
+static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
+{
+ unsigned int *epc;
+
+ epc = (unsigned int *) (unsigned long) regs->cp0_epc;
+ if (regs->cp0_cause & CAUSEF_BD)
+ epc += 4;
+
+ if (verify_area(VERIFY_READ, epc, 4)) {
+ force_sig(SIGSEGV, current);
+ return 1;
+ }
+ *opcode = *epc;
+
+ return 0;
+}
+
+void do_bp(struct pt_regs *regs)
+{
+ unsigned int opcode, bcode;
+
+ /*
+ * There is the ancient bug in the MIPS assemblers that the break
+ * code starts left to bit 16 instead to bit 6 in the opcode.
+ * Gas is bug-compatible ...
+ */
+ if (get_insn_opcode(regs, &opcode))
+ return;
+ bcode = ((opcode >> 16) & ((1 << 20) - 1));
+
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+ * insns, even for break codes that indicate arithmetic failures.
+ * Weird ...)
+ */
+ force_sig(SIGTRAP, current);
+}
+
+void do_tr(struct pt_regs *regs)
+{
+ unsigned int opcode, bcode;
+
+ if (get_insn_opcode(regs, &opcode))
+ return;
+ bcode = ((opcode >> 6) & ((1 << 20) - 1));
+
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+ * insns, even for break codes that indicate arithmetic failures.
+ * Wiered ...)
+ */
+ force_sig(SIGTRAP, current);
+}
+
+void do_ri(struct pt_regs *regs)
+{
+ lock_kernel();
+ printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+ current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+ unlock_kernel();
+ if (compute_return_epc(regs))
+ return;
+ force_sig(SIGILL, current);
+}
+
+void do_cpu(struct pt_regs *regs)
+{
+ u32 cpid;
+
+ cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
+ if (cpid != 1)
+ goto bad_cid;
+
+ regs->cp0_status |= ST0_CU1;
+ if (last_task_used_math == current)
+ return;
+
+ if (current->used_math) { /* Using the FPU again. */
+ r4xx0_lazy_fpu_switch(last_task_used_math);
+ } else { /* First time FPU user. */
+
+ r4xx0_init_fpu();
+ current->used_math = 1;
+ }
+ last_task_used_math = current;
+ return;
+
+bad_cid:
+ force_sig(SIGILL, current);
+}
+
+void do_watch(struct pt_regs *regs)
+{
+ /*
+ * We use the watch exception where available to detect stack
+ * overflows.
+ */
+ show_regs(regs);
+ panic("Caught WATCH exception - probably caused by stack overflow.");
+}
+
+void do_reserved(struct pt_regs *regs)
+{
+ /*
+ * Game over - no way to handle this if it ever occurs.
+ * Most probably caused by a new unknown cpu type or
+ * after another deadly hard/software error.
+ */
+ panic("Caught reserved exception - should not happen.");
+}
+
+static inline void watch_init(unsigned long cputype)
+{
+ switch(cputype) {
+ case CPU_R10000:
+ case CPU_R4000MC:
+ case CPU_R4400MC:
+ case CPU_R4000SC:
+ case CPU_R4400SC:
+ case CPU_R4000PC:
+ case CPU_R4400PC:
+ case CPU_R4200:
+ case CPU_R4300:
+ set_except_vector(23, handle_watch);
+ watch_available = 1;
+ break;
+ }
+}
+
+/*
+ * Some MIPS CPUs have a dedicated interrupt vector which reduces the
+ * interrupt processing overhead. Use it where available.
+ * FIXME: more CPUs than just the Nevada have this feature.
+ */
+static inline void setup_dedicated_int(void)
+{
+ extern void except_vec4(void);
+ switch(mips_cputype) {
+ case CPU_NEVADA:
+ memcpy((void *)(KSEG0 + 0x200), except_vec4, 8);
+ set_cp0_cause(CAUSEF_IV, CAUSEF_IV);
+ dedicated_iv_available = 1;
+ }
+}
+
+unsigned long exception_handlers[32];
+
+/*
+ * As a side effect of the way this is implemented we're limited
+ * to interrupt handlers in the address range from
+ * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ...
+ */
+void set_except_vector(int n, void *addr)
+{
+ unsigned handler = (unsigned long) addr;
+ exception_handlers[n] = handler;
+ if (n == 0 && dedicated_iv_available) {
+ *(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
+ (0x03ffffff & (handler >> 2));
+ flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
+ }
+}
+
+asmlinkage void (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage void r4k_save_fp_context(struct sigcontext *sc);
+
+asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
+extern asmlinkage void r4k_restore_fp_context(struct sigcontext *sc);
+
+extern asmlinkage void *r4xx0_resume(void *last, void *next);
+
+void __init trap_init(void)
+{
+ extern char except_vec0_nevada, except_vec0_r4000;
+ extern char except_vec0_r4600, except_vec0_r2300;
+ extern char except_vec1_generic, except_vec2_generic;
+ extern char except_vec3_generic, except_vec3_r4000;
+ unsigned long i;
+
+ /* Copy the generic exception handler code to it's final destination. */
+ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
+ memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
+
+ /*
+ * Setup default vectors
+ */
+ for(i = 0; i <= 31; i++)
+ set_except_vector(i, handle_reserved);
+
+ /*
+ * Only some CPUs have the watch exceptions or a dedicated
+ * interrupt vector.
+ */
+ watch_init(mips_cputype);
+ setup_dedicated_int();
+
+ /*
+ * Handling the following exceptions depends mostly of the cpu type
+ */
+ switch(mips_cputype) {
+ case CPU_R10000:
+ /*
+ * The R10000 is in most aspects similar to the R4400. It
+ * should get some special optimizations.
+ */
+ write_32bit_cp0_register(CP0_FRAMEMASK, 0);
+ set_cp0_status(ST0_XX, ST0_XX);
+ /*
+ * The R10k might even work for Linux/MIPS - but we're paranoid
+ * and refuse to run until this is tested on real silicon
+ */
+ panic("CPU too expensive - making holiday in the ANDES!");
+ break;
+ case CPU_R4000MC:
+ case CPU_R4400MC:
+ case CPU_R4000SC:
+ case CPU_R4400SC:
+ vce_available = 1;
+ /* Fall through ... */
+ case CPU_R4000PC:
+ case CPU_R4400PC:
+ case CPU_R4200:
+ case CPU_R4300:
+ case CPU_R4600:
+ case CPU_R5000:
+ case CPU_NEVADA:
+ if(mips_cputype == CPU_NEVADA) {
+ memcpy((void *)KSEG0, &except_vec0_nevada, 0x80);
+ } else if (mips_cputype == CPU_R4600)
+ memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
+ else
+ memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
+
+ /* Cache error vector */
+ memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
+
+ if (vce_available) {
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
+ 0x180);
+ } else {
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
+ 0x100);
+ }
+
+ save_fp_context = r4k_save_fp_context;
+ restore_fp_context = r4k_restore_fp_context;
+ resume = r4xx0_resume;
+ set_except_vector(1, r4k_handle_mod);
+ set_except_vector(2, r4k_handle_tlbl);
+ set_except_vector(3, r4k_handle_tlbs);
+ set_except_vector(4, handle_adel);
+ set_except_vector(5, handle_ades);
+
+ /*
+ * The following two are signaled by onboard hardware and
+ * should get board specific handlers to get maximum
+ * available information.
+ */
+ set_except_vector(6, handle_ibe);
+ set_except_vector(7, handle_dbe);
+
+ set_except_vector(8, handle_sys);
+ set_except_vector(9, handle_bp);
+ set_except_vector(10, handle_ri);
+ set_except_vector(11, handle_cpu);
+ set_except_vector(12, handle_ov);
+ set_except_vector(13, handle_tr);
+ set_except_vector(15, handle_fpe);
+ break;
+
+ case CPU_R8000:
+ panic("unsupported CPU type %s.\n", cpu_names[mips_cputype]);
+ break;
+
+ case CPU_UNKNOWN:
+ default:
+ panic("Unknown CPU type");
+ }
+ flush_icache_range(KSEG0, KSEG0 + 0x200);
+}
diff --git a/arch/mips64/mm/fault.c b/arch/mips64/mm/fault.c
index 1e34de13c..49f26d7b1 100644
--- a/arch/mips64/mm/fault.c
+++ b/arch/mips64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: fault.c,v 1.1 1999/08/18 23:37:47 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -45,7 +45,7 @@ unsigned long asid_cache;
* routines.
*/
asmlinkage void
-do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+do_page_fault(struct pt_regs *regs, unsigned long write,
unsigned long address)
{
struct vm_area_struct * vma;
@@ -61,7 +61,7 @@ do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
goto no_context;
#if 0
printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
- address, writeaccess, regs->cp0_epc);
+ address, write, regs->cp0_epc);
#endif
down(&mm->mmap_sem);
vma = find_vma(mm, address);
@@ -78,7 +78,7 @@ do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
* we can handle it..
*/
good_area:
- if (writeaccess) {
+ if (write) {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
} else {
@@ -91,8 +91,13 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- if (!handle_mm_fault(tsk, vma, address, writeaccess))
- goto do_sigbus;
+ {
+ int fault = handle_mm_fault(tsk, vma, address, write);
+ if (fault < 0)
+ goto out_of_memory;
+ if (!fault)
+ goto do_sigbus;
+ }
up(&mm->mmap_sem);
return;
@@ -106,12 +111,12 @@ bad_area:
if (user_mode(regs)) {
tsk->tss.cp0_badvaddr = address;
- tsk->tss.error_code = writeaccess;
+ tsk->tss.error_code = write;
#if 0
printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n"
"%08lx (epc == %08lx, ra == %08lx)\n",
tsk->comm,
- writeaccess ? "writeaccess to" : "readaccess from",
+ write ? "write access to" : "read access from",
address,
(unsigned long) regs->cp0_epc,
(unsigned long) regs->regs[31]);
@@ -142,13 +147,20 @@ no_context:
printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
"address %08lx, epc == %08lx, ra == %08lx\n",
address, regs->cp0_epc, regs->regs[31]);
- die("Oops", regs, writeaccess);
+ die("Oops", regs, write);
do_exit(SIGKILL);
/*
* 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", tsk->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+
do_sigbus:
up(&mm->mmap_sem);
diff --git a/arch/mips64/mm/r4xx0.c b/arch/mips64/mm/r4xx0.c
index a3a55fc33..8631ab7db 100644
--- a/arch/mips64/mm/r4xx0.c
+++ b/arch/mips64/mm/r4xx0.c
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.1 1999/08/18 23:37:48 ralf Exp $
+/* $Id: r4xx0.c,v 1.2 1999/08/21 22:19:16 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -702,81 +702,81 @@ static inline void r4k_flush_cache_all_s16d16i16(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache16(); blast_icache16(); blast_scache16();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_s32d16i16(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache16(); blast_icache16(); blast_scache32();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_s64d16i16(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache16(); blast_icache16(); blast_scache64();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_s128d16i16(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache16(); blast_icache16(); blast_scache128();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_s32d32i32(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache32(); blast_icache32(); blast_scache32();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_s64d32i32(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache32(); blast_icache32(); blast_scache64();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_s128d32i32(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache32(); blast_icache32(); blast_scache128();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_d16i16(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache16(); blast_icache16();
- restore_flags(flags);
+ __restore_flags(flags);
}
static inline void r4k_flush_cache_all_d32i32(void)
{
unsigned long flags;
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache32(); blast_icache32();
- restore_flags(flags);
+ __restore_flags(flags);
}
static void
@@ -803,7 +803,7 @@ r4k_flush_cache_range_s16d16i16(struct mm_struct *mm, unsigned long start,
pte_t *pte;
int text;
- save_and_cli(flags);
+ __save_and_cli(flags);
text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
@@ -1838,9 +1838,9 @@ static void r4k_flush_page_to_ram_d16i16(unsigned long page)
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache16_page(page);
- restore_flags(flags);
+ __restore_flags(flags);
}
}
@@ -1853,9 +1853,9 @@ static void r4k_flush_page_to_ram_d32i32(unsigned long page)
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
+ __save_and_cli(flags);
blast_dcache32_page(page);
- restore_flags(flags);
+ __restore_flags(flags);
}
}
@@ -1880,7 +1880,7 @@ r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size)
flush_cache_all();
} else {
/* Workaround for R4600 bug. See comment above. */
- save_and_cli(flags);
+ __save_and_cli(flags);
*(volatile unsigned long *)KSEG1;
a = addr & ~(dc_lsize - 1);
@@ -1890,7 +1890,7 @@ r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size)
if (a == end) break;
a += dc_lsize;
}
- restore_flags(flags);
+ __restore_flags(flags);
}
bcops->bc_wback_inv(addr, size);
}
@@ -1924,7 +1924,7 @@ r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size)
flush_cache_all();
} else {
/* Workaround for R4600 bug. See comment above. */
- save_and_cli(flags);
+ __save_and_cli(flags);
*(volatile unsigned long *)KSEG1;
a = addr & ~(dc_lsize - 1);
@@ -1934,7 +1934,7 @@ r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size)
if (a == end) break;
a += dc_lsize;
}
- restore_flags(flags);
+ __restore_flags(flags);
}
bcops->bc_inv(addr, size);
@@ -1989,7 +1989,7 @@ static void r4600v20k_flush_cache_sigtramp(unsigned long addr)
unsigned int flags;
daddr = addr & ~(dc_lsize - 1);
- save_and_cli(flags);
+ __save_and_cli(flags);
/* Clear internal cache refill buffer */
*(volatile unsigned int *)KSEG1;
@@ -1999,7 +1999,7 @@ static void r4600v20k_flush_cache_sigtramp(unsigned long addr)
iaddr = addr & ~(ic_lsize - 1);
protected_flush_icache_line(iaddr);
protected_flush_icache_line(iaddr + ic_lsize);
- restore_flags(flags);
+ __restore_flags(flags);
}
#undef DEBUG_TLB
@@ -2103,7 +2103,7 @@ static void r4k_flush_tlb_range(struct mm_struct *mm, unsigned long start,
if(mm == current->mm)
set_entryhi(mm->context & 0xff);
}
- restore_flags(flags);
+ __restore_flags(flags);
}
}
@@ -2190,7 +2190,7 @@ static void r4k_update_mmu_cache(struct vm_area_struct * vma,
}
#endif
- save_and_cli(flags);
+ __save_and_cli(flags);
address &= (PAGE_MASK << 1);
set_entryhi(address | (pid));
pgdp = pgd_offset(vma->vm_mm, address);
@@ -2213,7 +2213,7 @@ static void r4k_update_mmu_cache(struct vm_area_struct * vma,
BARRIER;
set_entryhi(pid);
BARRIER;
- restore_flags(flags);
+ __restore_flags(flags);
}
#if 0
@@ -2226,7 +2226,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
pte_t *ptep;
int idx;
- save_and_cli(flags);
+ __save_and_cli(flags);
address &= (PAGE_MASK << 1);
set_entryhi(address | (get_entryhi() & 0xff));
pgdp = pgd_offset(vma->vm_mm, address);
@@ -2242,7 +2242,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
else
tlb_write_indexed();
BARRIER;
- restore_flags(flags);
+ __restore_flags(flags);
}
#endif
@@ -2328,7 +2328,7 @@ static int __init probe_scache(unsigned long config)
/* This is such a bitch, you'd think they would make it
* easy to do this. Away you daemons of stupidity!
*/
- save_and_cli(flags);
+ __save_and_cli(flags);
/* Fill each size-multiple cache line with a valid tag. */
pow2 = (64 * 1024);
@@ -2364,7 +2364,7 @@ static int __init probe_scache(unsigned long config)
break;
pow2 <<= 1;
}
- restore_flags(flags);
+ __restore_flags(flags);
addr -= begin;
printk("Secondary cache sized at %dK linesize %d\n",
(int) (addr >> 10), sc_lsize);
diff --git a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c
index c6aa35747..e6fe49354 100644
--- a/arch/mips64/sgi-ip22/ip22-int.c
+++ b/arch/mips64/sgi-ip22/ip22-int.c
@@ -49,6 +49,7 @@ static char lc2msk_to_irqnr[256];
static char lc3msk_to_irqnr[256];
extern asmlinkage void indyIRQ(void);
+int (*irq_cannonicalize)(int irq);
#ifdef CONFIG_REMOTE_DEBUG
extern void rs_kgdb_hook(int);
@@ -416,19 +417,6 @@ void free_irq(unsigned int irq, void *dev_id)
printk("Trying to free free IRQ%d\n",irq);
}
-int (*irq_cannonicalize)(int irq);
-
-static int indy_irq_cannonicalize(int irq)
-{
- return irq; /* Sane hardware, sane code ... */
-}
-
-void __init init_IRQ(void)
-{
- irq_cannonicalize = indy_irq_cannonicalize;
- irq_setup();
-}
-
void indy_local0_irqdispatch(struct pt_regs *regs)
{
struct irqaction *action;
@@ -502,7 +490,7 @@ int probe_irq_off (unsigned long irqs)
return 0;
}
-void __init sgint_init(void)
+static inline void sgint_init(void)
{
int i;
#ifdef CONFIG_REMOTE_DEBUG
@@ -606,3 +594,14 @@ void __init sgint_init(void)
}
#endif
}
+
+static int indy_irq_cannonicalize(int irq)
+{
+ return irq; /* Sane hardware, sane code ... */
+}
+
+void __init init_IRQ(void)
+{
+ irq_cannonicalize = indy_irq_cannonicalize;
+ sgint_init();
+}
diff --git a/arch/mips64/sgi-ip22/ip22-reset.c b/arch/mips64/sgi-ip22/ip22-reset.c
index dc4fd0936..cd521291f 100644
--- a/arch/mips64/sgi-ip22/ip22-reset.c
+++ b/arch/mips64/sgi-ip22/ip22-reset.c
@@ -38,26 +38,26 @@ static unsigned char sgi_volume;
static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer;
static int shuting_down, has_paniced;
-static void sgi_machine_restart(char *command) __attribute__((noreturn));
-static void sgi_machine_halt(void) __attribute__((noreturn));
-static void sgi_machine_power_off(void) __attribute__((noreturn));
+static void ip22_machine_restart(char *command) __attribute__((noreturn));
+static void ip22_machine_halt(void) __attribute__((noreturn));
+static void ip22_machine_power_off(void) __attribute__((noreturn));
/* XXX How to pass the reboot command to the firmware??? */
-static void sgi_machine_restart(char *command)
+static void ip22_machine_restart(char *command)
{
if (shuting_down)
- sgi_machine_power_off();
- prom_reboot();
+ ip22_machine_power_off();
+ ArcReboot();
}
-static void sgi_machine_halt(void)
+static void ip22_machine_halt(void)
{
if (shuting_down)
- sgi_machine_power_off();
- prom_imode();
+ ip22_machine_power_off();
+ ArcEnterInteractiveMode();
}
-static void sgi_machine_power_off(void)
+static void ip22_machine_power_off(void)
{
struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS;
@@ -79,7 +79,7 @@ static void sgi_machine_power_off(void)
static void power_timeout(unsigned long data)
{
- sgi_machine_power_off();
+ ip22_machine_power_off();
}
static void blink_timeout(unsigned long data)
@@ -106,7 +106,7 @@ static void debounce(unsigned long data)
}
if (has_paniced)
- prom_reboot();
+ ArcReboot();
enable_irq(9);
}
@@ -118,7 +118,7 @@ static inline void power_button(void)
if (shuting_down || kill_proc(1, SIGINT, 1)) {
/* No init process or button pressed twice. */
- sgi_machine_power_off();
+ ip22_machine_power_off();
}
shuting_down = 1;
@@ -131,7 +131,7 @@ static inline void power_button(void)
add_timer(&power_timer);
}
-void inline sgi_volume_set(unsigned char volume)
+void inline ip22_volume_set(unsigned char volume)
{
sgi_volume = volume;
@@ -139,7 +139,7 @@ void inline sgi_volume_set(unsigned char volume)
hpc3c0->pbus_extregs[2][1] = sgi_volume;
}
-void inline sgi_volume_get(unsigned char *volume)
+void inline ip22_volume_get(unsigned char *volume)
{
*volume = sgi_volume;
}
@@ -235,9 +235,9 @@ void ip22_reboot_setup(void)
return;
setup_done = 1;
- _machine_restart = sgi_machine_restart;
- _machine_halt = sgi_machine_halt;
- _machine_power_off = sgi_machine_power_off;
+ _machine_restart = ip22_machine_restart;
+ _machine_halt = ip22_machine_halt;
+ _machine_power_off = ip22_machine_power_off;
request_irq(9, panel_int, 0, "Front Panel", NULL);
init_timer(&blink_timer);
diff --git a/arch/mips64/sgi-ip22/ip22-setup.c b/arch/mips64/sgi-ip22/ip22-setup.c
index 6657d0592..c3c41c387 100644
--- a/arch/mips64/sgi-ip22/ip22-setup.c
+++ b/arch/mips64/sgi-ip22/ip22-setup.c
@@ -34,47 +34,47 @@
#include <asm/sgi/sgint23.h>
extern struct rtc_ops indy_rtc_ops;
-void indy_reboot_setup(void);
-void sgi_volume_set(unsigned char);
+extern void ip22_reboot_setup(void);
+extern void ip22_volume_set(unsigned char);
#define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64))
#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
-static void sgi_request_region(void)
+static void ip22_request_region(void)
{
/* No I/O ports are being used on the Indy. */
}
-static int sgi_request_irq(void (*handler)(int, void *, struct pt_regs *))
+static int ip22_request_irq(void (*handler)(int, void *, struct pt_regs *))
{
/* Dirty hack, this get's called as a callback from the keyboard
driver. We piggyback the initialization of the front panel
button handling on it even though they're technically not
related with the keyboard driver in any way. Doing it from
indy_setup wouldn't work since kmalloc isn't initialized yet. */
- indy_reboot_setup();
+ ip22_reboot_setup();
return request_irq(SGI_KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
}
-static int sgi_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
+static int ip22_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
{
/* Nothing to do, interrupt is shared with the keyboard hw */
return 0;
}
-static void sgi_aux_free_irq(void)
+static void ip22_aux_free_irq(void)
{
/* Nothing to do, interrupt is shared with the keyboard hw */
}
-static unsigned char sgi_read_input(void)
+static unsigned char ip22_read_input(void)
{
return sgi_kh->data;
}
-static void sgi_write_output(unsigned char val)
+static void ip22_write_output(unsigned char val)
{
int status;
@@ -84,7 +84,7 @@ static void sgi_write_output(unsigned char val)
sgi_kh->data = val;
}
-static void sgi_write_command(unsigned char val)
+static void ip22_write_command(unsigned char val)
{
int status;
@@ -94,37 +94,30 @@ static void sgi_write_command(unsigned char val)
sgi_kh->command = val;
}
-static unsigned char sgi_read_status(void)
+static unsigned char ip22_read_status(void)
{
return sgi_kh->command;
}
struct kbd_ops sgi_kbd_ops = {
- sgi_request_region,
- sgi_request_irq,
+ ip22_request_region,
+ ip22_request_irq,
- sgi_aux_request_irq,
- sgi_aux_free_irq,
+ ip22_aux_request_irq,
+ ip22_aux_free_irq,
- sgi_read_input,
- sgi_write_output,
- sgi_write_command,
- sgi_read_status
+ ip22_read_input,
+ ip22_write_output,
+ ip22_write_command,
+ ip22_read_status
};
-static void __init sgi_irq_setup(void)
-{
- sgint_init();
-}
-
void __init ip22_setup(void)
{
#ifdef CONFIG_SERIAL_CONSOLE
char *ctype;
#endif
- irq_setup = sgi_irq_setup;
-
/* Init the INDY HPC I/O controller. Need to call this before
* fucking with the memory controller because it needs to know the
* boardID and whether this is a Guiness or a FullHouse machine.
@@ -142,7 +135,7 @@ void __init ip22_setup(void)
* graphics console, it is set to "d" for the first serial
* line and "d2" for the second serial line.
*/
- ctype = prom_getenv("console");
+ ctype = ArcArcGetEnvironmentVariable("console");
if(*ctype == 'd') {
if(*(ctype+1)=='2')
console_setup ("ttyS1");
@@ -154,7 +147,8 @@ void __init ip22_setup(void)
console_setup("ttyS0");
#endif
- sgi_volume_set(simple_strtoul(prom_getenv("volume"), NULL, 10));
+ ip22_volume_set(simple_strtoul(ArcGetEnvironmentVariable("volume"),
+ NULL, 10));
#ifdef CONFIG_VT
#ifdef CONFIG_SGI_NEWPORT_CONSOLE
diff --git a/arch/mips64/sgi-ip22/ip22-timer.c b/arch/mips64/sgi-ip22/ip22-timer.c
index c22651b86..3302ba1a7 100644
--- a/arch/mips64/sgi-ip22/ip22-timer.c
+++ b/arch/mips64/sgi-ip22/ip22-timer.c
@@ -268,7 +268,7 @@ void indy_8254timer_irq(void)
kstat.irqs[0][irq]++;
printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
prom_getchar();
- prom_imode();
+ ArcEnterInteractiveMode();
hardirq_exit(cpu);
}
diff --git a/arch/mips64/sgi-ip22/system.c b/arch/mips64/sgi-ip22/system.c
index 69237a9f5..bd2a313f0 100644
--- a/arch/mips64/sgi-ip22/system.c
+++ b/arch/mips64/sgi-ip22/system.c
@@ -66,10 +66,10 @@ void __init sgi_sysinit(void)
/* The root component tells us what machine architecture we
* have here.
*/
- p = prom_getchild(PROM_NULL_COMPONENT);
+ p = ArcGetChild(PROM_NULL_COMPONENT);
/* Now scan for cpu(s). */
- toplev = p = prom_getchild(p);
+ toplev = p = ArcGetChild(p);
while(p) {
int ncpus = 0;
@@ -84,7 +84,7 @@ void __init sgi_sysinit(void)
cpup = p;
cputype = string_to_cpu(cpup->iname);
}
- p = prom_getsibling(p);
+ p = ArcGetPeer(p);
}
if(cputype == -1) {
prom_printf("\nYeee, could not find cpu ARCS component\n");
@@ -92,7 +92,7 @@ void __init sgi_sysinit(void)
prom_getchar();
romvec->imode();
}
- p = prom_getchild(cpup);
+ p = ArcGetChild(cpup);
while(p) {
switch(p->class) {
case processor:
@@ -129,7 +129,7 @@ void __init sgi_sysinit(void)
default:
break;
};
- p = prom_getsibling(p);
+ p = ArcGetPeer(p);
}
printk("\n");
}
diff --git a/arch/mips64/tools/offset.c b/arch/mips64/tools/offset.c
index c8645babc..c7aa64967 100644
--- a/arch/mips64/tools/offset.c
+++ b/arch/mips64/tools/offset.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: offset.c,v 1.1 1999/08/18 23:37:48 ralf Exp $
*
* offset.c: Calculate pt_regs and task_struct offsets.
*
@@ -127,20 +127,17 @@ void output_mm_defines(void)
void output_sc_defines(void)
{
text("/* Linux sigcontext offsets. */");
- offset("#define SC_REGMASK ", struct sigcontext, sc_regmask);
- offset("#define SC_STATUS ", struct sigcontext, sc_status);
- offset("#define SC_PC ", struct sigcontext, sc_pc);
offset("#define SC_REGS ", struct sigcontext, sc_regs);
offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
+ offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+ offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
+ offset("#define SC_PC ", struct sigcontext, sc_pc);
+ offset("#define SC_STATUS ", struct sigcontext, sc_status);
offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp);
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
- offset("#define SC_SSFLAGS ", struct sigcontext, sc_ssflags);
- offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
- offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
- offset("#define SC_SIGSET ", struct sigcontext, sc_sigset);
linefeed;
}
diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c
index e8f72f298..a221dc59b 100644
--- a/arch/ppc/amiga/amiints.c
+++ b/arch/ppc/amiga/amiints.c
@@ -108,7 +108,7 @@ __initfunc(void amiga_init_IRQ(void))
custom.intreq = 0x7fff;
#ifdef CONFIG_APUS
- /* Clear any inter-CPU interupt requests. Circumvents bug in
+ /* Clear any inter-CPU interrupt requests. Circumvents bug in
Blizzard IPL emulation HW (or so it appears). */
APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK);
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
index 2335adfb9..5a38fa7f0 100644
--- a/arch/ppc/amiga/config.c
+++ b/arch/ppc/amiga/config.c
@@ -30,7 +30,6 @@ void (*kbd_reset_setup) (char *, int) __initdata = 0;
#include <linux/kd.h>
#include <linux/tty.h>
#include <linux/console.h>
-#include <linux/init.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 05c69f6c4..66eeedcc8 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -66,13 +66,7 @@ define_bool CONFIG_BINFMT_ELF y
define_bool CONFIG_KERNEL_ELF y
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-tristate 'Parallel port support' CONFIG_PARPORT
-if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
- if [ "$CONFIG_PARPORT_PC" != "n" ]; then
- bool ' Support foreign hardware' CONFIG_PARPORT_OTHER
- fi
-fi
+source drivers/misc/Config.in
bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
bool 'Support for frame buffer devices' CONFIG_FB
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index b9cdca892..5d906f62a 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -50,7 +50,6 @@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
-#include <asm/bitops.h>
#include <asm/gg2.h>
#include <asm/cache.h>
#include <asm/prom.h>
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index ccef5f36a..985abf6e6 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -9,7 +9,6 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/config.h>
-#include <linux/pci.h>
#include <linux/openpic.h>
#include <asm/processor.h>
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
index 462e50691..d7fef0869 100644
--- a/arch/ppc/kernel/ppc-stub.c
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -107,7 +107,6 @@
#include <asm/system.h>
#include <asm/signal.h>
-#include <asm/system.h>
#include <asm/kgdb.h>
#include <asm/pgtable.h>
#include <asm/ptrace.h>
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index 05d46a698..c99f6bbd7 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -40,7 +40,6 @@
#include <asm/residual.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <linux/ide.h>
#include <asm/ide.h>
#include <asm/cache.h>
#include <asm/dma.h>
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index dcf6d9b9d..e39c2f7e0 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -31,7 +31,6 @@
#include <linux/malloc.h>
#include <linux/user.h>
#include <linux/elf.h>
-#include <linux/elf.h>
#include <linux/init.h>
#include <asm/pgtable.h>
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index a0d67c98e..f3d2b9039 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -32,7 +32,6 @@
#endif
#include <asm/bootx.h>
#include <asm/machdep.h>
-#include <asm/ide.h>
extern void pmac_init(unsigned long r3,
unsigned long r4,
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index f40d8d7cc..a22275135 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -85,7 +85,7 @@ void smp_local_timer_interrupt(struct pt_regs * regs)
update_one_process(p, 1, user, system, cpu);
p->counter -= 1;
- if (p->counter < 0) {
+ if (p->counter <= 0) {
p->counter = 0;
current->need_resched = 1;
}
diff --git a/arch/sparc/ap1000/aplib.c b/arch/sparc/ap1000/aplib.c
index 2c36a5ae1..4e476aba3 100644
--- a/arch/sparc/ap1000/aplib.c
+++ b/arch/sparc/ap1000/aplib.c
@@ -27,7 +27,6 @@
#include <asm/segment.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <asm/ap1000/pgtapmmu.h>
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index a4ae9497e..461773e96 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -20,7 +20,6 @@
#include <asm/ebus.h>
#include <asm/sbus.h> /* for sanity check... */
#include <asm/swift.h> /* for cache flushing. */
-
#include <asm/io.h>
#undef PROM_DEBUG
@@ -39,7 +38,6 @@
#include <linux/timex.h>
#include <linux/interrupt.h>
-#include <asm/io.h>
#include <asm/irq.h>
#include <asm/oplib.h>
#include <asm/pcic.h>
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 301747c22..f6a6315a4 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -37,7 +37,6 @@
#include <asm/delay.h>
#include <asm/processor.h>
#include <asm/psr.h>
-#include <asm/system.h>
#include <asm/elf.h>
extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 92c8c464f..f7b6cdfd0 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -24,202 +24,6 @@
#define MAGIC_CONSTANT 0x80000000
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pgd_t * pgdir;
- pmd_t * pgmiddle;
- pte_t * pgtable;
- unsigned long page, retval;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- retval = *(unsigned long *) page;
- flush_page_to_ram(page);
- return retval;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it. -M.U-
- */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned long data)
-{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (!pgd_present(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- page = pte_page(*pgtable);
- if (!pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
-/* this is a hack for non-kernel-mapped video buffers and similar */
- flush_cache_page(vma, addr);
- if (MAP_NR(page) < max_mapnr) {
- *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
- flush_page_to_ram(page);
- }
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr);
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- *result = get_long(tsk, vma, addr);
- return 0;
-}
-
-static int read_byte(struct task_struct *tsk, unsigned long addr,
- unsigned char *result)
-{
- struct vm_area_struct *vma = find_extend_vma(tsk, addr&~3);
- unsigned long tmp;
-
- if(!vma)
- return -EIO;
- tmp = get_long(tsk, vma, (addr & ~3));
- switch(addr & 3) {
- case 0:
- *result = (tmp & 0xff000000)>>24;
- break;
- case 1:
- *result = (tmp & 0x00ff0000)>>16;
- break;
- case 2:
- *result = (tmp & 0x0000ff00)>>8;
- break;
- case 3:
- *result = (tmp & 0x000000ff);
- break;
- }
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
-static int write_byte(struct task_struct * tsk, unsigned long addr,
- unsigned char data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, (addr & ~3));
- unsigned long tmp;
-
- if (!vma)
- return -EIO;
- tmp = get_long(tsk, vma, (addr & ~3));
- switch(addr & 3) {
- case 0:
- tmp &= 0x00ffffff;
- tmp |= (data << 24);
- break;
- case 1:
- tmp &= 0xff00ffff;
- tmp |= ((data << 16) & 0x00ff0000);
- break;
- case 2:
- tmp &= 0xffff00ff;
- tmp |= ((data << 8) & 0x0000ff00);
- break;
- case 3:
- tmp &= 0xffffff00;
- tmp |= (data & 0x000000ff);
- break;
- }
- put_long(tsk, vma, (addr & ~3), tmp);
- return 0;
-}
/* Returning from ptrace is a bit tricky because the syscall return
* low level code assumes any value returned which is negative and
@@ -565,24 +369,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
- int res;
-
- /* XXX Find out what is really going on. */
- flush_cache_all();
- /* Non-word alignment _not_ allowed on Sparc. */
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
- if (res < 0) {
- pt_error_return(regs, -res);
- goto out;
- }
- pt_os_succ_return(regs, tmp, (long *) data);
+ if (access_process_vm(child, addr,
+ &tmp, sizeof(tmp), 0) == sizeof(tmp))
+ pt_os_succ_return(regs, tmp, (long *)data);
+ else
+ pt_error_return(regs, EIO);
goto out;
}
@@ -596,22 +388,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: {
- struct vm_area_struct *vma;
- int res;
-
- /* Non-word alignment _not_ allowed on Sparc. */
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- vma = find_extend_vma(child, addr);
- res = write_long(child, addr, data);
- up(&child->mm->mmap_sem);
- if(res < 0)
- pt_error_return(regs, -res);
+ if (access_process_vm(child, addr,
+ &data, sizeof(data), 1) == sizeof(data))
+ pt_succ_return(regs, 0);
else
- pt_succ_return(regs, res);
+ pt_error_return(regs, EIO);
goto out;
}
@@ -737,56 +518,31 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_READTEXT:
case PTRACE_READDATA: {
- unsigned char *dest = (unsigned char *) addr2;
- unsigned long src = addr;
- unsigned char tmp;
- int res, len = data;
-
- res = verify_area(VERIFY_WRITE, dest, len);
- if(res) {
- pt_error_return(regs, -res);
+ int res = ptrace_readdata(child, addr, (void *) addr2, data);
+
+ if (res == data) {
+ pt_succ_return(regs, 0);
goto out;
}
- while(len) {
- down(&child->mm->mmap_sem);
- res = read_byte(child, src, &tmp);
- up(&child->mm->mmap_sem);
- if(res < 0) {
- pt_error_return(regs, -res);
- goto out;
- }
- __put_user(tmp, dest);
- src++; dest++; len--;
- }
- pt_succ_return(regs, 0);
+ /* Partial read is an IO failure */
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto out;
}
case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA: {
- unsigned char *src = (unsigned char *) addr2;
- unsigned long dest = addr;
- int res, len = data;
+ int res = ptrace_writedata(child, (void *) addr2, addr, data);
- res = verify_area(VERIFY_READ, src, len);
- if(res) {
- pt_error_return(regs, -res);
+ if (res == data) {
+ pt_succ_return(regs, 0);
goto out;
}
- while(len) {
- unsigned long tmp;
-
- __get_user(tmp, src);
- down(&child->mm->mmap_sem);
- res = write_byte(child, dest, tmp);
- up(&child->mm->mmap_sem);
- if(res < 0) {
- pt_error_return(regs, -res);
- goto out;
- }
- src++; dest++; len--;
- }
- pt_succ_return(regs, 0);
+ /* Partial write is an IO failure */
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto out;
}
diff --git a/arch/sparc/kernel/sparc-stub.c b/arch/sparc/kernel/sparc-stub.c
index 9426ec0d9..a78b16f57 100644
--- a/arch/sparc/kernel/sparc-stub.c
+++ b/arch/sparc/kernel/sparc-stub.c
@@ -105,7 +105,6 @@
#include <asm/oplib.h>
#include <asm/head.h>
#include <asm/traps.h>
-#include <asm/system.h>
#include <asm/vac-ops.h>
#include <asm/kgdb.h>
#include <asm/pgtable.h>
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index b043d647d..99a1f9242 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -40,7 +40,6 @@
#include <asm/dma.h>
#endif
#include <asm/a.out.h>
-#include <asm/spinlock.h>
#include <asm/io-unit.h>
struct poll {
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index edd736b41..64ef31bbb 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -473,7 +473,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
if(current->pid) {
update_one_process(current, 1, user, !user, cpu);
- if(--current->counter < 0) {
+ if(--current->counter <= 0) {
current->counter = 0;
current->need_resched = 1;
}
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index c9acf609c..3fb1044f4 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -454,7 +454,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
if(current->pid) {
update_one_process(current, 1, user, !user, cpu);
- if(--current->counter < 0) {
+ if(--current->counter <= 0) {
current->counter = 0;
current->need_resched = 1;
}
diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c
index 2f0fe9ed7..d85bbe2d9 100644
--- a/arch/sparc/kernel/sunos_ioctl.c
+++ b/arch/sparc/kernel/sunos_ioctl.c
@@ -36,11 +36,10 @@ extern asmlinkage int sys_setsid(void);
asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg)
{
- struct file *filp;
int ret = -EBADF;
lock_kernel();
- if (fd >= SUNOS_NR_OPEN || !(filp = current->files->fd [fd]))
+ if (fd >= SUNOS_NR_OPEN || !fcheck(fd))
goto out;
/* First handle an easy compat. case for tty ldisc. */
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index e8475ffeb..0e276362e 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -26,7 +26,6 @@
#include <linux/signal.h>
#include <linux/uio.h>
#include <linux/utsname.h>
-#include <linux/fs.h>
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/malloc.h>
diff --git a/arch/sparc/mm/asyncd.c b/arch/sparc/mm/asyncd.c
index 1ae532b7c..300f5aa0a 100644
--- a/arch/sparc/mm/asyncd.c
+++ b/arch/sparc/mm/asyncd.c
@@ -1,4 +1,4 @@
-/* $Id: asyncd.c,v 1.13 1999/05/12 11:11:34 davem Exp $
+/* $Id: asyncd.c,v 1.15 1999/07/04 04:35:50 davem Exp $
* The asyncd kernel daemon. This handles paging on behalf of
* processes that receive page faults due to remote (async) memory
* accesses.
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index a6110b886..0f1f3d983 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.101 1999/01/04 06:24:52 jj Exp $
+/* $Id: fault.c,v 1.103 1999/07/04 04:35:51 davem Exp $
* fault.c: Page fault handlers for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -14,7 +14,6 @@
#include <linux/mman.h>
#include <linux/tasks.h>
#include <linux/kernel.h>
-#include <linux/smp.h>
#include <linux/signal.h>
#include <linux/mm.h>
#include <linux/smp.h>
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 5b63aa11a..66d3c535d 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -2076,6 +2076,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
goto done;
inode = file->f_dentry->d_inode;
offset = (address & PAGE_MASK) - vma->vm_start;
+ spin_lock(&inode->i_shared_lock);
vmaring = inode->i_mmap;
do {
/* Do not mistake ourselves as another mapping. */
@@ -2109,6 +2110,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
}
}
} while ((vmaring = vmaring->vm_next_share) != NULL);
+ spin_unlock(&inode->i_shared_lock);
if(alias_found && ((pte_val(pte) & SRMMU_CACHE) != 0)) {
pgdp = srmmu_pgd_offset(vma->vm_mm, address);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index d6387d473..c6bf02fc0 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -2682,8 +2682,10 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr
inode = dentry->d_inode;
if(inode) {
unsigned long offset = (address & PAGE_MASK) - vma->vm_start;
- struct vm_area_struct *vmaring = inode->i_mmap;
+ struct vm_area_struct *vmaring;
int alias_found = 0;
+ spin_lock(&inode->i_shared_lock);
+ vmaring = inode->i_mmap;
do {
unsigned long vaddr = vmaring->vm_start + offset;
unsigned long start;
@@ -2712,6 +2714,7 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr
}
}
} while ((vmaring = vmaring->vm_next_share) != NULL);
+ spin_unlock(&inode->i_shared_lock);
if(alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
pgdp = sun4c_pgd_offset(vma->vm_mm, address);
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index c501884ed..e03e9b427 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.66 1999/03/29 05:08:42 davem Exp $
+# $Id: config.in,v 1.67 1999/05/01 09:17:37 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -68,20 +68,8 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
fi
if [ "$CONFIG_PCI" = "y" ]; then
- tristate 'Parallel port support' CONFIG_PARPORT
- if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate ' Ultra/AX-style hardware' CONFIG_PARPORT_AX $CONFIG_PARPORT
- if [ "$CONFIG_PARPORT_AX" = "m" ]; then
- define_bool CONFIG_PARPORT_LOWLEVEL_MODULE y
- fi
- if [ "$CONFIG_PARPORT_AX" != "n" ]; then
- bool ' Support foreign hardware' CONFIG_PARPORT_OTHER
- fi
- dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
- if [ "$CONFIG_PRINTER" != "n" ]; then
- bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
- fi
- fi
+ source drivers/misc/Config.in
+ dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
tristate 'SUNW,envctrl support' CONFIG_ENVCTRL
fi
endmenu
@@ -235,6 +223,16 @@ if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
fi
endmenu
+mainmenu_option next_comment
+comment 'Video For Linux'
+tristate 'Video For Linux' CONFIG_VIDEO_DEV
+if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
+ if [ "$CONFIG_PCI" != "n" ]; then
+ dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+ fi
+fi
+endmenu
+
source fs/Config.in
mainmenu_option next_comment
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 8e3402e2c..6d865228d 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -93,11 +93,13 @@ CONFIG_BINFMT_ELF32=y
CONFIG_BINFMT_MISC=m
CONFIG_SOLARIS_EMUL=m
CONFIG_PARPORT=m
-CONFIG_PARPORT_AX=m
-CONFIG_PARPORT_LOWLEVEL_MODULE=y
+# CONFIG_PARPORT_PC is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
CONFIG_PRINTER=m
-CONFIG_PRINTER_READBACK=y
CONFIG_ENVCTRL=m
#
@@ -262,6 +264,12 @@ CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
#
+# Video For Linux
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_BT848=y
+
+#
# Filesystems
#
# CONFIG_QUOTA is not set
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index 7d638c5da..bc77266f9 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -311,9 +311,10 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
fd = open_dentry(bprm->dentry, O_RDONLY);
if (fd < 0)
return fd;
- file = fcheck(fd);
+ file = fget(fd);
if (!file->f_op || !file->f_op->mmap) {
+ fput(fd);
sys_close(fd);
do_brk(0, ex.a_text+ex.a_data);
read_exec(bprm->dentry, fd_offset,
@@ -327,6 +328,7 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
fd_offset);
if (error != N_TXTADDR(ex)) {
+ fput(file);
sys_close(fd);
send_sig(SIGKILL, current, 0);
return error;
@@ -336,6 +338,7 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
+ fput(file);
sys_close(fd);
if (error != N_DATADDR(ex)) {
send_sig(SIGKILL, current, 0);
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 6759f74d4..833331202 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1696,9 +1696,9 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
int error = -EBADF;
lock_kernel();
- filp = fcheck(fd);
+ filp = fget(fd);
if(!filp)
- goto out;
+ goto out2;
if (!filp->f_op || !filp->f_op->ioctl) {
error = sys_ioctl (fd, cmd, arg);
@@ -2381,6 +2381,8 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
break;
}
out:
+ fput(filp);
+out2:
unlock_kernel();
return error;
}
diff --git a/arch/sparc64/kernel/psycho.c b/arch/sparc64/kernel/psycho.c
index 7df9a5882..392ddab55 100644
--- a/arch/sparc64/kernel/psycho.c
+++ b/arch/sparc64/kernel/psycho.c
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.85 1999/04/02 14:54:28 davem Exp $
+/* $Id: psycho.c,v 1.86 1999/07/01 10:39:43 davem Exp $
* psycho.c: Ultra/AX U2P PCI controller support.
*
* Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -68,7 +68,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus,
#include <linux/smp_lock.h>
#include <linux/pci.h>
-#include <asm/io.h>
#include <asm/oplib.h>
#include <asm/pbm.h>
#include <asm/apb.h>
@@ -757,13 +756,15 @@ static void __init apb_init(struct linux_psycho *sabre)
unsigned short stmp;
unsigned int itmp;
+#if 0
for(pdev = pci_devices; pdev; pdev = pdev->next) {
if(pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
break;
}
}
+#endif
for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -795,13 +796,14 @@ static void __init apb_init(struct linux_psycho *sabre)
pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp);
itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp);
-
+#if 0
/* Don't mess with the retry limit and PIO/DMA latency
* timer settings. But do set primary and secondary
* latency timers.
*/
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
- pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 128);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+ pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
+#endif
}
}
}
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 476d53558..61a6a6bfa 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -28,242 +28,6 @@
#define MAGIC_CONSTANT 0x80000000
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static pte_t *ptrace_get_page(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr, int write)
-{
- pgd_t * pgdir;
- pmd_t * pgmiddle;
- pte_t * pgtable;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
-
- /* Seems non-intuitive but the page copy/clear routines always
- * check current's value.
- */
- current->mm->segments = (void *) (addr & PAGE_SIZE);
-
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %016lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %016lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- if (write && !pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- return pgtable;
-}
-
-/* We must bypass the L1-cache to avoid alias issues. -DaveM */
-static __inline__ unsigned long read_user_long(unsigned long kvaddr)
-{
- unsigned long ret;
-
- __asm__ __volatile__("ldxa [%1] %2, %0"
- : "=r" (ret)
- : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
- return ret;
-}
-
-static __inline__ unsigned int read_user_int(unsigned long kvaddr)
-{
- unsigned int ret;
-
- __asm__ __volatile__("lduwa [%1] %2, %0"
- : "=r" (ret)
- : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
- return ret;
-}
-
-static __inline__ void write_user_long(unsigned long kvaddr, unsigned long val)
-{
- __asm__ __volatile__("stxa %0, [%1] %2"
- : /* no outputs */
- : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
-}
-
-static __inline__ void write_user_int(unsigned long kvaddr, unsigned int val)
-{
- __asm__ __volatile__("stwa %0, [%1] %2"
- : /* no outputs */
- : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
-}
-
-static inline unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pte_t * pgtable;
- unsigned long page, retval;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 0))) return 0;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- retval = read_user_long(page);
- flush_page_to_ram(page);
- return retval;
-}
-
-static inline void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned long data)
-{
- pte_t *pgtable;
- unsigned long page;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 1))) return;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- flush_cache_page(vma, addr);
- if (MAP_NR(page) < max_mapnr) {
- unsigned long pgaddr;
-
- pgaddr = page + (addr & ~PAGE_MASK);
- write_user_long(pgaddr, data);
-
- __asm__ __volatile__("
- membar #StoreStore
- flush %0
-" : : "r" (pgaddr & ~7) : "memory");
- }
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr);
-}
-
-static inline unsigned int get_int(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pte_t * pgtable;
- unsigned long page;
- unsigned int retval;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 0))) return 0;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- retval = read_user_int(page);
- flush_page_to_ram(page);
- return retval;
-}
-
-static inline void put_int(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned int data)
-{
- pte_t *pgtable;
- unsigned long page;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 1))) return;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- flush_cache_page(vma, addr);
- if (MAP_NR(page) < max_mapnr) {
- unsigned long pgaddr;
-
- pgaddr = page + (addr & ~PAGE_MASK);
- write_user_int(pgaddr, data);
-
- __asm__ __volatile__("
- membar #StoreStore
- flush %0
-" : : "r" (pgaddr & ~7) : "memory");
- }
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr);
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- *result = get_long(tsk, vma, addr);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_int() to read a int.
- */
-static int read_int(struct task_struct * tsk, unsigned long addr,
- unsigned int * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- *result = get_int(tsk, vma, addr);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_int() to write a int.
- */
-static int write_int(struct task_struct * tsk, unsigned long addr,
- unsigned int data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- put_int(tsk, vma, addr, data);
- return 0;
-}
-
/* Returning from ptrace is a bit tricky because the syscall return
* low level code assumes any value returned which is negative and
* is a valid errno will mean setting the condition codes to indicate
@@ -310,175 +74,6 @@ pt_os_succ_return (struct pt_regs *regs, unsigned long val, long *addr)
pt_succ_return_linux (regs, val, addr);
}
-#if 0
-/* XXX: Implement this some day */
-/* Fuck me gently with a chainsaw... */
-static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
- struct task_struct *tsk, long *addr)
-{
- struct pt_regs *cregs = tsk->tss.kregs;
- struct thread_struct *t = &tsk->tss;
- int v;
-
- if(offset >= 1024)
- offset -= 1024; /* whee... */
- if(offset & ((sizeof(unsigned int) - 1))) {
- pt_error_return(regs, EIO);
- return;
- }
- if(offset >= 16 && offset < 784) {
- offset -= 16; offset >>= 2;
- if (t->w_saved)
- pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
- return;
- }
- if(offset >= 784 && offset < 832) {
- offset -= 784; offset >>= 2;
- if (t->w_saved)
- pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
- return;
- }
- switch(offset) {
- case 0:
- v = t->ksp;
- break;
-#if 0
- case 4:
- v = t->kpc;
- break;
-#endif
- case 8:
- v = t->kpsr;
- break;
- case 12:
- v = t->uwinmask;
- break;
- case 832:
- v = t->w_saved;
- break;
- case 896:
- v = cregs->u_regs[UREG_I0];
- break;
- case 900:
- v = cregs->u_regs[UREG_I1];
- break;
- case 904:
- v = cregs->u_regs[UREG_I2];
- break;
- case 908:
- v = cregs->u_regs[UREG_I3];
- break;
- case 912:
- v = cregs->u_regs[UREG_I4];
- break;
- case 916:
- v = cregs->u_regs[UREG_I5];
- break;
- case 920:
- v = cregs->u_regs[UREG_I6];
- break;
- case 924:
- if(tsk->tss.flags & MAGIC_CONSTANT)
- v = cregs->u_regs[UREG_G1];
- else
- v = 0;
- break;
- case 940:
- v = cregs->u_regs[UREG_I0];
- break;
- case 944:
- v = cregs->u_regs[UREG_I1];
- break;
-
- case 948:
- /* Isn't binary compatibility _fun_??? */
- if(cregs->psr & PSR_C)
- v = cregs->u_regs[UREG_I0] << 24;
- else
- v = 0;
- break;
-
- /* Rest of them are completely unsupported. */
- default:
- printk("%s [%d]: Wants to read user offset %ld\n",
- current->comm, current->pid, offset);
- pt_error_return(regs, EIO);
- return;
- }
- pt_os_succ_return_linux (regs, v, addr);
- return;
-}
-
-static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
- struct task_struct *tsk)
-{
- struct pt_regs *cregs = tsk->tss.kregs;
- struct thread_struct *t = &tsk->tss;
- unsigned int value = regs->u_regs[UREG_I3];
-
- if(offset >= 1024)
- offset -= 1024; /* whee... */
- if(offset & ((sizeof(unsigned long) - 1)))
- goto failure;
- if(offset >= 16 && offset < 784) {
- offset -= 16; offset >>= 2;
- if (t->w_saved)
- *(((unsigned long *)(&t->reg_window[0]))+offset) = value;
- goto success;
- }
- if(offset >= 784 && offset < 832) {
- offset -= 784; offset >>= 2;
- if (t->w_saved)
- *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
- goto success;
- }
- switch(offset) {
- case 896:
- cregs->u_regs[UREG_I0] = value;
- break;
- case 900:
- cregs->u_regs[UREG_I1] = value;
- break;
- case 904:
- cregs->u_regs[UREG_I2] = value;
- break;
- case 908:
- cregs->u_regs[UREG_I3] = value;
- break;
- case 912:
- cregs->u_regs[UREG_I4] = value;
- break;
- case 916:
- cregs->u_regs[UREG_I5] = value;
- break;
- case 920:
- cregs->u_regs[UREG_I6] = value;
- break;
- case 924:
- cregs->u_regs[UREG_I7] = value;
- break;
- case 940:
- cregs->u_regs[UREG_I0] = value;
- break;
- case 944:
- cregs->u_regs[UREG_I1] = value;
- break;
-
- /* Rest of them are completely unsupported or "no-touch". */
- default:
- printk("%s [%d]: Wants to write user offset %ld\n",
- current->comm, current->pid, offset);
- goto failure;
- }
-success:
- pt_succ_return(regs, 0);
- return;
-failure:
- pt_error_return(regs, EIO);
- return;
-}
-#endif
-
/* #define ALLOW_INIT_TRACING */
/* #define DEBUG_PTRACE */
@@ -642,76 +237,54 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
switch(request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int res;
+ unsigned long tmp64;
+ unsigned int tmp32;
+ int res, copied;
- /* Non-word alignment _not_ allowed on Sparc. */
+ res = -EIO;
if (current->tss.flags & SPARC_FLAG_32BIT) {
- unsigned int x;
- if(addr & (sizeof(unsigned int) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = read_int(child, addr, &x);
- up(&child->mm->mmap_sem);
- tmp = x;
+ copied = access_process_vm(child, addr,
+ &tmp32, sizeof(tmp32), 0);
+ tmp64 = (unsigned long) tmp32;
+ if (copied == sizeof(tmp32))
+ res = 0;
} else {
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
+ copied = access_process_vm(child, addr,
+ &tmp64, sizeof(tmp64), 0);
+ if (copied == sizeof(tmp64))
+ res = 0;
}
- if (res < 0) {
+ if (res < 0)
pt_error_return(regs, -res);
- goto out;
- }
- pt_os_succ_return(regs, tmp, (long *) data);
- goto out;
+ else
+ pt_os_succ_return(regs, tmp64, (long *) data);
+ goto flush_and_out;
}
- case PTRACE_PEEKUSR:
-#if 0
- read_sunos_user(regs, addr, child, (long *) data);
-#endif
- goto out;
-
- case PTRACE_POKEUSR:
-#if 0
- write_sunos_user(regs, addr, child);
-#endif
- goto out;
-
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: {
- int res;
+ unsigned long tmp64;
+ unsigned int tmp32;
+ int copied, res = -EIO;
- /* Non-word alignment _not_ allowed on Sparc. */
if (current->tss.flags & SPARC_FLAG_32BIT) {
- if(addr & (sizeof(unsigned int) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = write_int(child, addr, data);
- up(&child->mm->mmap_sem);
+ tmp32 = data;
+ copied = access_process_vm(child, addr,
+ &tmp32, sizeof(tmp32), 1);
+ if (copied == sizeof(tmp32))
+ res = 0;
} else {
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = write_long(child, addr, data);
- up(&child->mm->mmap_sem);
+ tmp64 = data;
+ copied = access_process_vm(child, addr,
+ &tmp64, sizeof(tmp64), 1);
+ if (copied == sizeof(tmp64))
+ res = 0;
}
if(res < 0)
pt_error_return(regs, -res);
else
pt_succ_return(regs, res);
- goto out;
+ goto flush_and_out;
}
case PTRACE_GETREGS: {
@@ -926,98 +499,31 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_READTEXT:
case PTRACE_READDATA: {
- unsigned char *dest = (unsigned char *) addr2;
- unsigned long src = addr;
- int len = data, curlen;
- struct vm_area_struct *vma;
- pte_t *pgtable;
- unsigned long page;
-
- while(len) {
- down(&child->mm->mmap_sem);
- vma = find_extend_vma(child, src);
- if (!vma) {
- up(&child->mm->mmap_sem);
- pt_error_return(regs, EIO);
- goto flush_and_out;
- }
- pgtable = ptrace_get_page (child, vma, src, 0);
- up(&child->mm->mmap_sem);
- if (src & ~PAGE_MASK) {
- curlen = PAGE_SIZE - (src & ~PAGE_MASK);
- if (curlen > len) curlen = len;
- } else if (len > PAGE_SIZE)
- curlen = PAGE_SIZE;
- else
- curlen = len;
- if (pgtable && MAP_NR(page = pte_page(*pgtable)) < max_mapnr) {
- if (copy_to_user (dest, ((char *)page) + (src & ~PAGE_MASK), curlen)) {
- flush_page_to_ram(page);
- pt_error_return(regs, EFAULT);
- goto flush_and_out;
- }
- flush_page_to_ram(page);
- } else {
- if (clear_user (dest, curlen)) {
- pt_error_return(regs, EFAULT);
- goto flush_and_out;
- }
- }
- src += curlen;
- dest += curlen;
- len -= curlen;
+ int res = ptrace_readdata(child, addr,
+ (void *)addr2, data);
+ if (res == data) {
+ pt_succ_return(regs, 0);
+ goto flush_and_out;
}
- pt_succ_return(regs, 0);
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto flush_and_out;
}
case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA: {
- unsigned char *src = (unsigned char *) addr2;
- unsigned long dest = addr;
- int len = data, curlen;
- struct vm_area_struct *vma;
- pte_t *pgtable;
- unsigned long page;
-
- while(len) {
- down(&child->mm->mmap_sem);
- vma = find_extend_vma(child, dest);
- if (!vma) {
- up(&child->mm->mmap_sem);
- pt_error_return(regs, EIO);
- goto flush_and_out;
- }
- pgtable = ptrace_get_page (child, vma, dest, 1);
- up(&child->mm->mmap_sem);
- if (dest & ~PAGE_MASK) {
- curlen = PAGE_SIZE - (dest & ~PAGE_MASK);
- if (curlen > len) curlen = len;
- } else if (len > PAGE_SIZE)
- curlen = PAGE_SIZE;
- else
- curlen = len;
- if (pgtable && MAP_NR(page = pte_page(*pgtable)) < max_mapnr) {
- flush_cache_page(vma, dest);
- if (copy_from_user (((char *)page) + (dest & ~PAGE_MASK), src, curlen)) {
- flush_page_to_ram(page);
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, dest);
- pt_error_return(regs, EFAULT);
- goto flush_and_out;
- }
- flush_page_to_ram(page);
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, dest);
- }
- src += curlen;
- dest += curlen;
- len -= curlen;
+ int res = ptrace_writedata(child, (void *) addr2,
+ addr, data);
+ if (res == data) {
+ pt_succ_return(regs, 0);
+ goto flush_and_out;
}
- pt_succ_return(regs, 0);
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto flush_and_out;
}
-
case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
addr = 1;
@@ -1105,6 +611,14 @@ flush_and_out:
unsigned long va;
for(va = 0; va < (PAGE_SIZE << 1); va += 32)
spitfire_put_dcache_tag(va, 0x0);
+ if (request == PTRACE_PEEKTEXT ||
+ request == PTRACE_POKETEXT ||
+ request == PTRACE_READTEXT ||
+ request == PTRACE_WRITETEXT) {
+ for(va = 0; va < (PAGE_SIZE << 1); va += 32)
+ spitfire_put_icache_tag(va, 0x0);
+ __asm__ __volatile__("flush %g6");
+ }
}
out:
unlock_kernel();
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index b0e92d50b..a0e8f7e69 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -615,7 +615,7 @@ do { hardirq_enter(cpu); \
unsigned int *inc, *inc2;
update_one_process(current, 1, user, !user, cpu);
- if(--current->counter < 0) {
+ if(--current->counter <= 0) {
current->counter = 0;
current->need_resched = 1;
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 6d6043617..91277fc4a 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.58 1999/05/08 03:00:31 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.60 1999/07/03 22:11:12 davem Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -45,7 +45,6 @@
#include <asm/ebus.h>
#endif
#include <asm/a.out.h>
-#include <asm/svr4.h>
struct poll {
int fd;
@@ -118,6 +117,12 @@ __attribute__((section("__ksymtab"))) = \
/* used by various drivers */
#ifdef __SMP__
+/* Out of line rw-locking implementation. */
+EXPORT_SYMBOL_PRIVATE(read_lock);
+EXPORT_SYMBOL_PRIVATE(read_unlock);
+EXPORT_SYMBOL_PRIVATE(write_lock);
+EXPORT_SYMBOL_PRIVATE(write_unlock);
+
/* Kernel wide locking */
EXPORT_SYMBOL(kernel_flag);
@@ -158,6 +163,10 @@ EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
#endif
+/* Atomic counter implementation. */
+EXPORT_SYMBOL_PRIVATE(atomic_add);
+EXPORT_SYMBOL_PRIVATE(atomic_sub);
+
EXPORT_SYMBOL(ivector_table);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 77d2ddc6c..0e42e2c32 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -17,7 +17,6 @@
#include <linux/utime.h>
#include <linux/resource.h>
#include <linux/times.h>
-#include <linux/utime.h>
#include <linux/utsname.h>
#include <linux/timex.h>
#include <linux/smp.h>
@@ -32,18 +31,15 @@
#include <linux/smb_mount.h>
#include <linux/ncp_fs.h>
#include <linux/quota.h>
-#include <linux/file.h>
#include <linux/module.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h>
-#include <linux/module.h>
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
-#include <linux/timex.h>
#include <asm/types.h>
#include <asm/ipc.h>
@@ -2328,8 +2324,8 @@ static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
break;
}
/* Bump the usage count and install the file. */
- atomic_inc(&fp[i]->f_count);
- current->files->fd[new_fd] = fp[i];
+ get_file(fp[i]);
+ fd_install(new_fd, fp[i]);
}
if (i > 0) {
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 9ea1ffcc2..156d1d8ee 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -25,7 +25,6 @@
#include <linux/signal.h>
#include <linux/uio.h>
#include <linux/utsname.h>
-#include <linux/fs.h>
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/malloc.h>
@@ -712,7 +711,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
struct inode *inode;
struct file *file;
- file = current->files->fd [fd];
+ file = fcheck(fd);
if(!file)
return 0;
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 2a3c63e91..90d1c4e7c 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.18 1998/10/13 09:07:24 davem Exp $
+# $Id: Makefile,v 1.19 1999/07/03 22:11:08 davem Exp $
# Makefile for Sparc library files..
#
@@ -6,7 +6,8 @@ CFLAGS := $(CFLAGS)
OBJS = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
- VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o VISsave.o
+ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o VISsave.o \
+ atomic.o rwlock.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
new file mode 100644
index 000000000..3c0dce16a
--- /dev/null
+++ b/arch/sparc64/lib/atomic.S
@@ -0,0 +1,32 @@
+/* $Id: atomic.S,v 1.1 1999/07/03 22:11:04 davem Exp $
+ * atomic.S: These things are too big to do inline.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/asi.h>
+
+ .text
+ .align 64
+
+ .globl __atomic_add
+__atomic_add:
+ lduw [%g1], %g5
+ add %g5, %g2, %g7
+ cas [%g1], %g5, %g7
+ cmp %g5, %g7
+ bne,pn %icc, __atomic_add
+ nop
+ jmpl %g3 + 8, %g0
+ add %g7, %g2, %g2
+
+ .globl __atomic_sub
+__atomic_sub:
+ lduw [%g1], %g5
+ sub %g5, %g2, %g7
+ cas [%g1], %g5, %g7
+ cmp %g5, %g7
+ bne,pn %icc, __atomic_sub
+ nop
+ jmpl %g3 + 8, %g0
+ sub %g7, %g2, %g2
diff --git a/arch/sparc64/lib/rwlock.S b/arch/sparc64/lib/rwlock.S
new file mode 100644
index 000000000..cee94eef0
--- /dev/null
+++ b/arch/sparc64/lib/rwlock.S
@@ -0,0 +1,81 @@
+/* $Id: rwlock.S,v 1.1 1999/07/03 22:11:06 davem Exp $
+ * rwlocks.S: These things are too big to do inline.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+ .text
+ .align 64
+
+ /* The non-contention read lock usage is 2 cache lines. */
+
+ .globl __read_lock, __read_unlock
+ /* g1=lock, g3=retpc, g5/g7=scratch */
+__read_lock:
+ ldsw [%g1], %g5
+ brlz,pn %g5, __read_wait_for_writer
+4: add %g5, 1, %g7
+ cas [%g1], %g5, %g7
+ cmp %g5, %g7
+ bne,pn %icc, __read_lock
+ membar #StoreLoad | #StoreStore
+99: jmpl %g3 + 8, %g0
+ nop
+__read_unlock:
+ lduw [%g1], %g5
+ sub %g5, 1, %g7
+ cas [%g1], %g5, %g7
+ cmp %g5, %g7
+ be,pt %xcc, 99b
+ membar #StoreLoad | #StoreStore
+ b,a,pt %xcc, __read_unlock
+
+__read_wait_for_writer:
+ ldsw [%g1], %g5
+ brlz,pt %g5, __read_wait_for_writer
+ membar #LoadLoad
+ b,a,pt %xcc, 4b
+__write_wait_for_writer:
+ ldsw [%g1], %g5
+ brlz,pt %g5, __write_wait_for_writer
+ membar #LoadLoad
+ b,a,pt %xcc, 4f
+
+ /* Similarly, 2 cache lines for non-contention write locks. */
+
+ .align 64
+ .globl __write_unlock
+ /* g1=lock, g3=retpc, g2/g5/g7=scratch */
+__write_unlock:
+ sethi %hi(0x80000000), %g2
+1: lduw [%g1], %g5
+ andn %g5, %g2, %g7
+ cas [%g1], %g5, %g7
+ cmp %g5, %g7
+ be,pt %icc, 99b
+ membar #StoreLoad | #StoreStore
+ b,a,pt %xcc, 1b
+
+ .globl __write_lock
+__write_lock:
+ sethi %hi(0x80000000), %g2
+1: ldsw [%g1], %g5
+4: brnz,pn %g5, 5f
+ or %g5, %g2, %g7
+ cas [%g1], %g5, %g7
+ cmp %g5, %g7
+ be,pt %icc, 99b
+ membar #StoreLoad | #StoreStore
+
+ b,a,pt %xcc, 1b
+5: brlz %g5, __write_wait_for_writer
+ or %g5, %g2, %g7
+ cas [%g1], %g5, %g7
+ cmp %g5, %g7
+ bne,pn %icc, 5b
+8: ldsw [%g1], %g5
+ cmp %g5, %g2
+ be,pn %icc, 99b
+ membar #LoadLoad
+ b,a,pt %xcc, 99b
+
diff --git a/arch/sparc64/mm/asyncd.c b/arch/sparc64/mm/asyncd.c
index d1c7f5d20..e9607cb8f 100644
--- a/arch/sparc64/mm/asyncd.c
+++ b/arch/sparc64/mm/asyncd.c
@@ -1,4 +1,4 @@
-/* $Id: asyncd.c,v 1.6 1999/05/12 11:11:48 davem Exp $
+/* $Id: asyncd.c,v 1.8 1999/07/04 04:35:55 davem Exp $
* The asyncd kernel daemon. This handles paging on behalf of
* processes that receive page faults due to remote (async) memory
* accesses.
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 88fd55e03..04aa8284e 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.34 1999/03/16 12:12:28 jj Exp $
+/* $Id: fault.c,v 1.36 1999/07/04 04:35:56 davem Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index 9f1c0f4d1..82a583c29 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -367,15 +367,8 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
int len, int *len_p)
{
- struct file *filp;
struct inode *ino;
int ret;
-
- filp = current->files->fd[fd];
- if (! filp ||
- ! (ino = filp->f_dentry->d_inode) ||
- ! ino->i_sock)
- return TBADF;
switch (cmd & 0xff) {
case 141: /* TI_OPTMGMT */
@@ -459,7 +452,7 @@ static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
return TNOTSUPPORT;
}
-static inline int solaris_S(unsigned int fd, unsigned int cmd, u32 arg)
+static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg)
{
char *p;
int ret;
@@ -470,9 +463,7 @@ static inline int solaris_S(unsigned int fd, unsigned int cmd, u32 arg)
struct sol_socket_struct *sock;
struct module_info *mi;
- filp = current->files->fd[fd];
- if (! filp ||
- ! (ino = filp->f_dentry->d_inode) ||
+ if (! (ino = filp->f_dentry->d_inode) ||
! ino->i_sock)
return -EBADF;
sock = filp->private_data;
@@ -696,14 +687,14 @@ asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
struct file *filp;
int error = -EBADF;
- lock_kernel();
- filp = fcheck(fd);
+ filp = fget(fd);
if (!filp)
goto out;
+ lock_kernel();
error = -EFAULT;
switch ((cmd >> 8) & 0xff) {
- case 'S': error = solaris_S(fd, cmd, arg); break;
+ case 'S': error = solaris_S(filp, fd, cmd, arg); break;
case 'T': error = solaris_T(fd, cmd, arg); break;
case 'i': error = solaris_i(fd, cmd, arg); break;
case 'r': error = solaris_r(fd, cmd, arg); break;
@@ -714,6 +705,8 @@ asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
error = -ENOSYS;
break;
}
+ unlock_kernel();
+ fput(filp);
out:
if (error == -ENOSYS) {
unsigned char c = cmd>>8;
@@ -723,6 +716,5 @@ out:
(int)fd, (unsigned int)cmd, c, (unsigned int)arg);
error = -EINVAL;
}
- unlock_kernel();
return error;
}
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index dbdbcd1a2..f6d31920e 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -16,7 +16,6 @@
#include <linux/file.h>
#include <linux/init.h>
#include <linux/poll.h>
-#include <linux/file.h>
#include <linux/malloc.h>
#include <asm/uaccess.h>