summaryrefslogtreecommitdiffstats
path: root/arch/mips64
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
commit1d67e90f19a7acfd9a05dc59678e7d0c5090bd0d (patch)
tree357efc7b93f8f5102110d20d293f41360ec212fc /arch/mips64
parentaea27b2e18d69af87e673972246e66657b4fa274 (diff)
Merge with Linux 2.3.21.
Diffstat (limited to 'arch/mips64')
-rw-r--r--arch/mips64/Makefile8
-rw-r--r--arch/mips64/boot/Makefile2
-rw-r--r--arch/mips64/config.in83
-rw-r--r--arch/mips64/defconfig75
-rw-r--r--arch/mips64/kernel/Makefile5
-rw-r--r--arch/mips64/kernel/binfmt_elf32.c101
-rw-r--r--arch/mips64/kernel/branch.c194
-rw-r--r--arch/mips64/kernel/entry.S115
-rw-r--r--arch/mips64/kernel/head.S35
-rw-r--r--arch/mips64/kernel/init_task.c2
-rw-r--r--arch/mips64/kernel/mips64_ksyms.c7
-rw-r--r--arch/mips64/kernel/process.c48
-rw-r--r--arch/mips64/kernel/ptrace.c37
-rw-r--r--arch/mips64/kernel/r4k_cache.S28
-rw-r--r--arch/mips64/kernel/r4k_genex.S167
-rw-r--r--arch/mips64/kernel/r4k_switch.S170
-rw-r--r--arch/mips64/kernel/r4k_tlb_debug.c90
-rw-r--r--arch/mips64/kernel/r4k_tlb_glue.S41
-rw-r--r--arch/mips64/kernel/scall_64.S342
-rw-r--r--arch/mips64/kernel/scall_o32.S415
-rw-r--r--arch/mips64/kernel/semaphore.c129
-rw-r--r--arch/mips64/kernel/setup.c43
-rw-r--r--arch/mips64/kernel/signal.c18
-rw-r--r--arch/mips64/kernel/softfp.S668
-rw-r--r--arch/mips64/kernel/syscall.c341
-rw-r--r--arch/mips64/kernel/traps.c92
-rw-r--r--arch/mips64/kernel/unaligned.c405
-rw-r--r--arch/mips64/ld.script.elf3216
-rw-r--r--arch/mips64/lib/Makefile5
-rw-r--r--arch/mips64/lib/csum_partial.S2
-rw-r--r--arch/mips64/lib/csum_partial_copy.c2
-rw-r--r--arch/mips64/lib/dump_tlb.c125
-rw-r--r--arch/mips64/lib/floppy-no.c2
-rw-r--r--arch/mips64/lib/floppy-std.c2
-rw-r--r--arch/mips64/lib/ide-no.c2
-rw-r--r--arch/mips64/lib/ide-std.c2
-rw-r--r--arch/mips64/lib/kbd-no.c2
-rw-r--r--arch/mips64/lib/kbd-std.c2
-rw-r--r--arch/mips64/lib/memcpy.S12
-rw-r--r--arch/mips64/lib/memset.S6
-rw-r--r--arch/mips64/lib/rtc-no.c2
-rw-r--r--arch/mips64/lib/rtc-std.c2
-rw-r--r--arch/mips64/lib/strlen_user.S33
-rw-r--r--arch/mips64/lib/strncpy_user.S47
-rw-r--r--arch/mips64/lib/strnlen_user.S47
-rw-r--r--arch/mips64/lib/watch.S2
-rw-r--r--arch/mips64/mm/Makefile2
-rw-r--r--arch/mips64/mm/andes.c8
-rw-r--r--arch/mips64/mm/extable.c4
-rw-r--r--arch/mips64/mm/fault.c6
-rw-r--r--arch/mips64/mm/init.c160
-rw-r--r--arch/mips64/mm/loadmmu.c9
-rw-r--r--arch/mips64/mm/r4xx0.c62
-rw-r--r--arch/mips64/mm/tfp.c7
-rw-r--r--arch/mips64/mm/umap.c2
-rw-r--r--arch/mips64/sgi-ip22/Makefile2
-rw-r--r--arch/mips64/sgi-ip22/ip22-hpc.c5
-rw-r--r--arch/mips64/sgi-ip22/ip22-int.c6
-rw-r--r--arch/mips64/sgi-ip22/ip22-irq.S2
-rw-r--r--arch/mips64/sgi-ip22/ip22-mc.c6
-rw-r--r--arch/mips64/sgi-ip22/ip22-reset.c27
-rw-r--r--arch/mips64/sgi-ip22/ip22-rtc.c2
-rw-r--r--arch/mips64/sgi-ip22/ip22-sc.c85
-rw-r--r--arch/mips64/sgi-ip22/ip22-setup.c3
-rw-r--r--arch/mips64/sgi-ip22/ip22-timer.c18
-rw-r--r--arch/mips64/sgi-ip22/system.c8
-rw-r--r--arch/mips64/sgi-ip22/time.c2
-rw-r--r--arch/mips64/tools/Makefile2
-rw-r--r--arch/mips64/tools/offset.c6
69 files changed, 3862 insertions, 546 deletions
diff --git a/arch/mips64/Makefile b/arch/mips64/Makefile
index 3e4df1276..20685e5e3 100644
--- a/arch/mips64/Makefile
+++ b/arch/mips64/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 1999/08/18 23:37:46 ralf Exp $
+# $Id: Makefile,v 1.3 1999/10/19 20:51:44 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
@@ -71,10 +71,10 @@ LIBS += arch/mips64/sgi-ip22/sgikern.a arch/mips64/arc/arclib.a
SUBDIRS += arch/mips64/sgi-ip22 arch/mips64/arc
#
# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
-# 0x88002000 for production kernels. Note that the value must be
-# 8kb aligned or the handling of the current variable will break.
+# 0x88004000 for production kernels. Note that the value must be
+# 16kb aligned or the handling of the current variable will break.
#
-LOADADDR += 0x88002000
+LOADADDR += 0x88004000
endif
#
diff --git a/arch/mips64/boot/Makefile b/arch/mips64/boot/Makefile
index b71412e12..078918695 100644
--- a/arch/mips64/boot/Makefile
+++ b/arch/mips64/boot/Makefile
@@ -1,4 +1,4 @@
-# $Id$
+# $Id: Makefile,v 1.1 1999/08/18 21:46:52 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
diff --git a/arch/mips64/config.in b/arch/mips64/config.in
index 866c330d4..7ee2b2a42 100644
--- a/arch/mips64/config.in
+++ b/arch/mips64/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.3 1999/08/21 22:19:13 ralf Exp $
+# $Id: config.in,v 1.8 1999/11/23 17:12:49 ralf Exp $
#
# For a description of the syntax of this configuration file,
# see the Configure script.
@@ -23,8 +23,8 @@ unset CONFIG_ARC32
unset CONFIG_ARC64
if [ "$CONFIG_SGI_IP22" = "y" ]; then
- define_bool CONFIG_BOOT_ELF32 y
- define_bool CONFIG_ARC32 y
+ define_bool CONFIG_BOOT_ELF32 y
+ define_bool CONFIG_ARC32 y
fi
mainmenu_option next_comment
@@ -42,6 +42,9 @@ endmenu
mainmenu_option next_comment
comment 'General setup'
+if [ "$CONFIG_CPU_R10000" = "y" ]; then
+ bool 'Support for large 64-bit configurations' CONFIG_MIPS_INSANE_LARGE
+fi
bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
define_bool CONFIG_BINFMT_AOUT n
@@ -57,12 +60,12 @@ mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
- bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
- bool 'Kernel module loader' CONFIG_KMOD
+ bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+ bool 'Kernel module loader' CONFIG_KMOD
fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'Support for frame buffer devices (EXPERIMENTAL)' CONFIG_FB
+ bool 'Support for frame buffer devices (EXPERIMENTAL)' CONFIG_FB
fi
endmenu
@@ -70,7 +73,7 @@ endmenu
source drivers/block/Config.in
if [ "$CONFIG_NET" = "y" ]; then
- source net/Config.in
+ source net/Config.in
fi
mainmenu_option next_comment
@@ -79,22 +82,32 @@ comment 'SCSI support'
tristate 'SCSI support' CONFIG_SCSI
if [ "$CONFIG_SCSI" != "n" ]; then
- source drivers/scsi/Config.in
+ source drivers/scsi/Config.in
fi
endmenu
if [ "$CONFIG_NET" = "y" ]; then
- mainmenu_option next_comment
- comment 'Network device support'
-
- bool 'Network device support' CONFIG_NETDEVICES
- if [ "$CONFIG_NETDEVICES" = "y" ]; then
- source drivers/net/Config.in
+ mainmenu_option next_comment
+ comment 'Network device support'
+
+ bool 'Network device support' CONFIG_NETDEVICES
+ if [ "$CONFIG_NETDEVICES" = "y" ]; then
+ source drivers/net/Config.in
+ if [ "$CONFIG_SGI_IP22" = "y" ]; then
+ bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ
+ fi
+ if [ "$CONFIG_DECSTATION" = "y" ]; then
+ bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE
+ fi
+ if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
+ tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE
+ tristate 'Baget Backplane Shared Memory support' CONFIG_BAGETBSM
+ fi
if [ "$CONFIG_ATM" = "y" ]; then
- source drivers/atm/Config.in
+ source drivers/atm/Config.in
fi
- fi
- endmenu
+ fi
+ endmenu
fi
source net/ax25/Config.in
@@ -105,10 +118,10 @@ mainmenu_option next_comment
comment 'ISDN subsystem'
if [ "$CONFIG_NET" != "n" ]; then
- tristate 'ISDN support' CONFIG_ISDN
- if [ "$CONFIG_ISDN" != "n" ]; then
- source drivers/isdn/Config.in
- fi
+ tristate 'ISDN support' CONFIG_ISDN
+ if [ "$CONFIG_ISDN" != "n" ]; then
+ source drivers/isdn/Config.in
+ fi
fi
endmenu
@@ -117,7 +130,7 @@ comment 'Old CD-ROM drivers (not SCSI, not IDE)'
bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
- source drivers/cdrom/Config.in
+ source drivers/cdrom/Config.in
fi
endmenu
@@ -125,18 +138,20 @@ source drivers/char/Config.in
source drivers/usb/Config.in
+# drivers/misc has currently only i386 specific devices.
+#source drivers/misc/Config.in
+
source fs/Config.in
if [ "$CONFIG_VT" = "y" ]; then
- mainmenu_option next_comment
- comment 'Console drivers'
- # XXX cleanup
- if [ "$CONFIG_SGI_IP22" = "y" ]; then
- tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE
- if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then
- define_bool CONFIG_DUMMY_CONSOLE y
- fi
- fi
+ mainmenu_option next_comment
+ comment 'Console drivers'
+ if [ "$CONFIG_SGI_IP22" = "y" ]; then
+ tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE
+ if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then
+ define_bool CONFIG_DUMMY_CONSOLE y
+ fi
+ fi
endmenu
fi
@@ -145,12 +160,12 @@ comment 'Sound'
tristate 'Sound card support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
-source drivers/sound/Config.in
+ source drivers/sound/Config.in
fi
endmenu
if [ "$CONFIG_SGI_IP22" = "y" ]; then
- source drivers/sgi/Config.in
+ source drivers/sgi/Config.in
fi
mainmenu_option next_comment
@@ -159,7 +174,7 @@ comment 'Kernel hacking'
#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE
if [ "$CONFIG_MODULES" = "y" ]; then
- bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE
+ bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE
fi
bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig
index 6f7ef08e5..71fac0fc9 100644
--- a/arch/mips64/defconfig
+++ b/arch/mips64/defconfig
@@ -39,9 +39,7 @@ CONFIG_SYSVIPC=y
#
# Loadable module support
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
#
# Block devices
@@ -53,7 +51,6 @@ 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
@@ -64,7 +61,6 @@ CONFIG_KMOD=y
# 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
@@ -76,7 +72,22 @@ CONFIG_PARIDE_PARPORT=m
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
-# CONFIG_INET is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP 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_SKB_LARGE=y
#
#
@@ -92,7 +103,48 @@ CONFIG_UNIX=y
#
# Network device support
#
-# CONFIG_NETDEVICES is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_FDDI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring driver support
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network devices
+#
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_RAYCS is not set
+CONFIG_SGISEEQ=y
#
# Amateur Radio support
@@ -185,6 +237,14 @@ CONFIG_EXT2_FS=y
#
# Network File Systems
#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
#
# Partition Types
@@ -219,6 +279,5 @@ CONFIG_SGI_DS1286=y
# 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/mips64/kernel/Makefile b/arch/mips64/kernel/Makefile
index f61a7139b..9856524c3 100644
--- a/arch/mips64/kernel/Makefile
+++ b/arch/mips64/kernel/Makefile
@@ -12,7 +12,10 @@
all: kernel.o head.o init_task.o
O_TARGET := kernel.o
-O_OBJS := entry.o proc.o r4k_fpu.o setup.o signal.o traps.o
+O_OBJS := binfmt_elf32.o branch.o entry.o proc.o process.o ptrace.o \
+ r4k_cache.o r4k_fpu.o r4k_genex.o r4k_switch.o r4k_tlb_debug.o \
+ r4k_tlb_glue.o scall_64.o scall_o32.o semaphore.o setup.o signal.o \
+ softfp.o syscall.o traps.o unaligned.o
OX_OBJS := mips64_ksyms.o
clean:
diff --git a/arch/mips64/kernel/binfmt_elf32.c b/arch/mips64/kernel/binfmt_elf32.c
new file mode 100644
index 000000000..3494f4cf0
--- /dev/null
+++ b/arch/mips64/kernel/binfmt_elf32.c
@@ -0,0 +1,101 @@
+/* $Id: binfmt_elf32.c,v 1.1 1999/11/24 06:56:13 ralf Exp $
+ *
+ * Support for 32-bit Linux/MIPS ELF binaries.
+ *
+ * Copyright (C) 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Heavily inspired by the 32-bit Sparc compat code which is
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#define ELF_ARCH EM_MIPS
+#define ELF_CLASS ELFCLASS32
+#ifdef __MIPSEB__
+#define ELF_DATA ELFDATA2MSB;
+#else /* __MIPSEL__ */
+#define ELF_DATA ELFDATA2LSB;
+#endif
+
+/* ELF register definitions */
+#define ELF_NGREG 45
+#define ELF_NFPREG 33
+
+typedef unsigned int elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+#define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_MIPS_RS4_BE)
+
+#define TASK32_SIZE 0x80000000UL
+#undef ELF_ET_DYN_BASE
+#define ELF_ET_DYN_BASE (2 * TASK32_SIZE / 3)
+
+#include <asm/processor.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/elfcore.h>
+
+struct timeval32
+{
+ unsigned int tv_sec, tv_usec;
+};
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+ struct elf_siginfo pr_info; /* Info associated with signal */
+ short pr_cursig; /* Current signal */
+ unsigned int pr_sigpend; /* Set of pending signals */
+ unsigned int pr_sighold; /* Set of held signals */
+ pid_t pr_pid;
+ pid_t pr_ppid;
+ pid_t pr_pgrp;
+ pid_t pr_sid;
+ struct timeval32 pr_utime; /* User time */
+ struct timeval32 pr_stime; /* System time */
+ struct timeval32 pr_cutime; /* Cumulative user time */
+ struct timeval32 pr_cstime; /* Cumulative system time */
+ elf_gregset_t pr_reg; /* GP registers */
+ int pr_fpvalid; /* True if math co-processor being used. */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+ char pr_state; /* numeric process state */
+ char pr_sname; /* char for pr_state */
+ char pr_zomb; /* zombie */
+ char pr_nice; /* nice val */
+ unsigned int pr_flag; /* flags */
+ u16 pr_uid;
+ u16 pr_gid;
+ pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* filename of executable */
+ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
+};
+
+#define elf_addr_t u32
+#define elf_caddr_t u32
+#define init_elf_binfmt init_elf32_binfmt
+#undef CONFIG_BINFMT_ELF
+#ifdef CONFIG_BINFMT_ELF32
+#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32
+#endif
+#undef CONFIG_BINFMT_ELF_MODULE
+#ifdef CONFIG_BINFMT_ELF32_MODULE
+#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
+#endif
+#define ELF_FLAGS_INIT current->thread.flags |= SPARC_FLAG_32BIT
+
+MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux/MIPS binaries");
+MODULE_AUTHOR("Ralf Baechle (ralf@oss.sgi.com)");
+
+#undef MODULE_DESCRIPTION
+#undef MODULE_AUTHOR
+
+#include "../../../fs/binfmt_elf.c"
diff --git a/arch/mips64/kernel/branch.c b/arch/mips64/kernel/branch.c
new file mode 100644
index 000000000..0b2f51c7f
--- /dev/null
+++ b/arch/mips64/kernel/branch.c
@@ -0,0 +1,194 @@
+/* $Id: branch.c,v 1.1 1999/10/09 20:55:05 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.
+ *
+ * Branch and jump emulation.
+ *
+ * Copyright (C) 1996, 1997 by Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/branch.h>
+#include <asm/inst.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * Compute the return address and do emulate branch simulation, if required.
+ */
+int __compute_return_epc(struct pt_regs *regs)
+{
+ unsigned int *addr, bit, fcr31;
+ long epc;
+ union mips_instruction insn;
+
+ epc = regs->cp0_epc;
+ if (epc & 3) {
+ printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
+ force_sig(SIGBUS, current);
+ return -EFAULT;
+ }
+
+ /*
+ * Read the instruction
+ */
+ addr = (unsigned int *) epc;
+ if (__get_user(insn.word, addr)) {
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
+ }
+
+ regs->regs[0] = 0;
+ switch (insn.i_format.opcode) {
+ /*
+ * jr and jalr are in r_format format.
+ */
+ case spec_op:
+ switch (insn.r_format.func) {
+ case jalr_op:
+ regs->regs[insn.r_format.rd] = epc + 8;
+ /* Fall through */
+ case jr_op:
+ regs->cp0_epc = regs->regs[insn.r_format.rs];
+ break;
+ }
+ break;
+
+ /*
+ * This group contains:
+ * bltz_op, bgez_op, bltzl_op, bgezl_op,
+ * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+ */
+ case bcond_op:
+ switch (insn.i_format.rt) {
+ case bltz_op:
+ case bltzl_op:
+ if (regs->regs[insn.i_format.rs] < 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bgez_op:
+ case bgezl_op:
+ if (regs->regs[insn.i_format.rs] >= 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bltzal_op:
+ case bltzall_op:
+ regs->regs[31] = epc + 8;
+ if (regs->regs[insn.i_format.rs] < 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bgezal_op:
+ case bgezall_op:
+ regs->regs[31] = epc + 8;
+ if (regs->regs[insn.i_format.rs] >= 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+ }
+ break;
+
+ /*
+ * These are unconditional and in j_format.
+ */
+ case jal_op:
+ regs->regs[31] = regs->cp0_epc + 8;
+ case j_op:
+ epc += 4;
+ epc >>= 28;
+ epc <<= 28;
+ epc |= (insn.j_format.target << 2);
+ regs->cp0_epc = epc;
+ break;
+
+ /*
+ * These are conditional and in i_format.
+ */
+ case beq_op:
+ case beql_op:
+ if (regs->regs[insn.i_format.rs] ==
+ regs->regs[insn.i_format.rt])
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bne_op:
+ case bnel_op:
+ if (regs->regs[insn.i_format.rs] !=
+ regs->regs[insn.i_format.rt])
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case blez_op: /* not really i_format */
+ case blezl_op:
+ /* rt field assumed to be zero */
+ if (regs->regs[insn.i_format.rs] <= 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bgtz_op:
+ case bgtzl_op:
+ /* rt field assumed to be zero */
+ if (regs->regs[insn.i_format.rs] > 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ /*
+ * And now the FPA/cp1 branch instructions.
+ */
+ case cop1_op:
+ asm ("cfc1\t%0,$31":"=r" (fcr31));
+ bit = (insn.i_format.rt >> 2);
+ bit += (bit != 0);
+ bit += 23;
+ switch (insn.i_format.rt) {
+ case 0: /* bc1f */
+ case 2: /* bc1fl */
+ if (~fcr31 & (1 << bit))
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case 1: /* bc1t */
+ case 3: /* bc1tl */
+ if (fcr31 & (1 << bit))
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
diff --git a/arch/mips64/kernel/entry.S b/arch/mips64/kernel/entry.S
index 297c41840..05bbee928 100644
--- a/arch/mips64/kernel/entry.S
+++ b/arch/mips64/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: entry.S,v 1.6 1999/11/23 17:12:49 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
@@ -9,20 +9,10 @@
* Copyright (C) 1994 - 1999 by Ralf Baechle
* Copyright (C) 1999 Silicon Graphics
*/
-#include <linux/config.h>
-#include <linux/sys.h>
-
#include <asm/asm.h>
-#include <asm/current.h>
-#include <asm/errno.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/regdef.h>
+#include <asm/mipsregs.h>
#include <asm/stackframe.h>
-#include <asm/processor.h>
-#include <asm/fpregdef.h>
-#include <asm/unistd.h>
/*
* Heia ... The %lo, %hi and %HI stuff is too strong for the ELF assembler
@@ -30,9 +20,14 @@
*/
.text
.set noreorder
- .set mips3
.align 4
+EXPORT(ret_from_fork)
+ jal schedule_tail
+ move a0, v0 # prev
+ j ret_from_sys_call
+ nop
EXPORT(handle_bottom_half)
+ .type handle_bottom_half,@function
jal do_bottom_half
nop
b 9f
@@ -42,16 +37,18 @@ reschedule: jal schedule
nop
EXPORT(ret_from_sys_call)
+ .type ret_from_sys_call,@function
EXPORT(ret_from_irq)
- lw t0,bh_mask
- lw t1,bh_active # unused delay slot
- and t0,t1
- bnez t0,handle_bottom_half
-9: lw t0,PT_STATUS(sp) # returning to kernel mode?
+ .type ret_from_irq,@function
+ ld t0, bh_mask
+ ld t1, bh_active # unused delay slot
+ and t0, t1
+ bnez t0, handle_bottom_half
+9: ld t0, PT_STATUS(sp) # returning to kernel mode?
andi t1, t0, 0x10
beqz t1, return # -> yes
- lw t1, TASK_NEED_RESCHED($28)
+ ld t1, TASK_NEED_RESCHED($28)
bnez t1, reschedule
lw v0, TASK_SIGPENDING($28)
move a0, zero
@@ -61,6 +58,7 @@ EXPORT(ret_from_irq)
move a1, sp
EXPORT(return) .set noat
+ .type return,@function
RESTORE_ALL
eret
.set at
@@ -81,82 +79,3 @@ LEAF(spurious_interrupt)
j ret_from_irq
sw t0,%lo(spurious_count)(t1)
END(spurious_interrupt)
-
-/*
- * Build a default exception handler for the exceptions that don't need
- * special handlers. If you didn't know yet - I *like* playing games with
- * the C preprocessor ...
- */
- .macro __build_clear_none
- .endm
-
- .macro __build_clear_sti
- STI
- .endm
-
- .macro __build_clear_cli
- CLI
- .endm
-
- .macro __build_clear_fpe
- cfc1 a1, fcr31
- li a2, ~(0x3f << 13)
- and a2, a1
- ctc1 a2, fcr31
- STI
- .endm
-
- .macro __build_clear_ade
- mfc0 t0, CP0_BADVADDR
- sd t0, PT_BVADDR(sp)
- KMODE
- .endm
-
- .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/head.S b/arch/mips64/kernel/head.S
index c5cf9d987..daa0e3ad1 100644
--- a/arch/mips64/kernel/head.S
+++ b/arch/mips64/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: head.S,v 1.4 1999/11/23 17:12:49 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
@@ -11,6 +11,8 @@
* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
+#define __ASSEMBLY__
+#include <linux/init.h>
#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/processor.h>
@@ -22,9 +24,25 @@
EXPORT(stext) # used for profiling
EXPORT(_stext)
+ __INIT
+
NESTED(kernel_entry, 16, sp) # kernel entry point
+
+ ori sp, 0xf # align stack on 16 byte.
+ xori sp, 0xf
+
+ /* Note that all firmware passed argument registers still
+ have their values. */
+ jal prom_init # initialize firmware
+
CLI # disable interrupts
+ mfc0 t0, CP0_STATUS
+ li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX)
+ and t0, t1
+ or t0, ST0_CU0
+ mtc0 t0, CP0_STATUS
+
la $28, init_task_union # init current pointer
daddiu t0, $28, KERNEL_STACK_SIZE-32
sd t0, kernelsp
@@ -34,22 +52,27 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
1: b 1b # just in case ...
END(kernel_entry)
+ __FINIT
+
.comm kernelsp, 8, 8 # current stackpointer
+ .comm current_pgd, 8, 8 # current page tables
#define PAGE_SIZE 0x1000
- .macro page name
+ .macro page name, order=0
.globl \name
- .org . + PAGE_SIZE
-\name: .size \name, PAGE_SIZE
+ .org . + (PAGE_SIZE << \order)
+\name: .size \name, (PAGE_SIZE << \order)
.type \name, @object
.endm
+ .align 12
.data
- page swapper_pg_dir
+ page swapper_pg_dir, 1
+ page invalid_pte_table, 1
+ page invalid_pmd_table, 1
page empty_bad_page
page empty_bad_page_table
- page invalid_pte_table
.align 13
diff --git a/arch/mips64/kernel/init_task.c b/arch/mips64/kernel/init_task.c
index fbf5bf9f0..1e68e96d2 100644
--- a/arch/mips64/kernel/init_task.c
+++ b/arch/mips64/kernel/init_task.c
@@ -21,5 +21,5 @@ struct mm_struct init_mm = INIT_MM(init_mm);
* The things we do for performance..
*/
union task_union init_task_union
- __attribute__((__section__(".text"))) =
+ __attribute__((__section__(".data.init_task"))) =
{ INIT_TASK(init_task_union.task) };
diff --git a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c
index 355f34115..d6fa01d8a 100644
--- a/arch/mips64/kernel/mips64_ksyms.c
+++ b/arch/mips64/kernel/mips64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: mips64_ksyms.c,v 1.4 1999/11/19 20:35:22 ralf Exp $
*
* Export MIPS64-specific functions needed for loadable modules.
*
@@ -34,6 +34,8 @@ extern long __strncpy_from_user_asm(char *__to, const char *__from,
long __len);
extern long __strlen_user_nocheck_asm(const char *s);
extern long __strlen_user_asm(const char *s);
+extern long __strnlen_user_nocheck_asm(const char *s);
+extern long __strnlen_user_asm(const char *s);
EXPORT_SYMBOL(EISA_bus);
@@ -54,7 +56,6 @@ EXPORT_SYMBOL_NOVERS(strtok);
EXPORT_SYMBOL_NOVERS(strpbrk);
EXPORT_SYMBOL(clear_page);
-EXPORT_SYMBOL(__mips_bh_counter);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(enable_irq);
@@ -70,6 +71,8 @@ EXPORT_SYMBOL_NOVERS(__strncpy_from_user_nocheck_asm);
EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm);
EXPORT_SYMBOL_NOVERS(__strlen_user_nocheck_asm);
EXPORT_SYMBOL_NOVERS(__strlen_user_asm);
+EXPORT_SYMBOL_NOVERS(__strnlen_user_nocheck_asm);
+EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
/* Networking helper routines. */
diff --git a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c
index 88091d324..670747b81 100644
--- a/arch/mips64/kernel/process.c
+++ b/arch/mips64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.1 1999/09/27 16:01:37 ralf Exp $
+/* $Id: process.c,v 1.7 1999/12/03 17:51:49 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
@@ -30,9 +30,23 @@
#include <asm/io.h>
#include <asm/elf.h>
+asmlinkage int cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ current->priority = 0;
+ current->counter = -100;
+ while (1) {
+ while (!current->need_resched)
+ if (wait_available)
+ __asm__("wait");
+ schedule();
+ check_pgt_cache();
+ }
+}
+
struct task_struct *last_task_used_math = NULL;
-asmlinkage void ret_from_sys_call(void);
+asmlinkage void ret_from_fork(void);
void exit_thread(void)
{
@@ -64,13 +78,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
if (last_task_used_math == current) {
set_cp0_status(ST0_CU1, ST0_CU1);
- r4xx0_save_fp(p);
+ 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) {
+ if (current->personality == PER_LINUX) {
childregs->regs[2] = 0; /* Child gets zero as return value */
regs->regs[2] = p->pid;
} else {
@@ -89,7 +103,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
p->thread.current_ds = USER_DS;
}
p->thread.reg29 = (unsigned long) childregs;
- p->thread.reg31 = (unsigned long) ret_from_sys_call;
+ p->thread.reg31 = (unsigned long) ret_from_fork;
/*
* New tasks loose permission to use the fpu. This accelerates context
@@ -98,7 +112,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
p->thread.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;
}
@@ -123,12 +136,15 @@ void dump_thread(struct pt_regs *regs, struct user *dump)
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;
+ 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->thread.fpu, sizeof(current->thread.fpu));
+ memcpy(&dump->regs[EF_SIZE/4], &current->thread.fpu,
+ sizeof(current->thread.fpu));
}
/*
@@ -136,24 +152,20 @@ void dump_thread(struct pt_regs *regs, struct user *dump)
*/
int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
- long retval;
+ int 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"
+ "move\t$4, %3\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"
+ "1:\tmove\t%0, $2"
:"=r" (retval)
:"i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn),
"r" (flags | CLONE_VM)
diff --git a/arch/mips64/kernel/ptrace.c b/arch/mips64/kernel/ptrace.c
new file mode 100644
index 000000000..fb687f496
--- /dev/null
+++ b/arch/mips64/kernel/ptrace.c
@@ -0,0 +1,37 @@
+/* $Id: ptrace.c,v 1.1 1999/10/11 14:19:58 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) 1992 Ross Biro
+ * Copyright (C) Linus Torvalds
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1996 David S. Miller
+ *
+ * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
+ * binaries.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+
+asmlinkage void syscall_trace(void)
+{
+ if ((current->flags & (PF_PTRACED|PF_TRACESYS))
+ != (PF_PTRACED|PF_TRACESYS))
+ return;
+ current->exit_code = SIGTRAP;
+ current->state = TASK_STOPPED;
+ notify_parent(current, SIGCHLD);
+ schedule();
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/mips64/kernel/r4k_cache.S b/arch/mips64/kernel/r4k_cache.S
new file mode 100644
index 000000000..87c496af8
--- /dev/null
+++ b/arch/mips64/kernel/r4k_cache.S
@@ -0,0 +1,28 @@
+/* $Id: r4k_cache.S,v 1.1 1999/10/10 18:49:17 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 - 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Cache error handler
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+
+/*
+ * Game over. Go to the button. Press gently. Swear where allowed by
+ * legislation.
+ */
+ LEAF(except_vec2_generic)
+ /* Famous last words: unreached */
+ mfc0 a1,CP0_ERROREPC
+ PRINT("Cache error exception: c0_errorepc == %08x\n")
+1:
+ j 1b
+ nop
+ END(except_vec2_generic)
diff --git a/arch/mips64/kernel/r4k_genex.S b/arch/mips64/kernel/r4k_genex.S
new file mode 100644
index 000000000..bfe00ae7d
--- /dev/null
+++ b/arch/mips64/kernel/r4k_genex.S
@@ -0,0 +1,167 @@
+/* $Id: r4k_genex.S,v 1.3 1999/11/23 17:12:49 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) 1999 Silicon Graphics
+ *
+ * Low level exception handling
+ */
+#define __ASSEMBLY__
+#include <linux/init.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/cacheops.h>
+
+ .macro __build_clear_none
+ .endm
+
+ .macro __build_clear_sti
+ STI
+ .endm
+
+ .macro __build_clear_cli
+ CLI
+ .endm
+
+ .macro __build_clear_fpe
+ cfc1 a1, fcr31
+ li a2, ~(0x3f << 13)
+ and a2, a1
+ ctc1 a2, fcr31
+ STI
+ .endm
+
+ .macro __build_clear_ade
+ dmfc0 t0, CP0_BADVADDR
+ sd t0, PT_BVADDR(sp)
+ KMODE
+ .endm
+
+ .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 */
+
+ __INIT
+
+ /* General exception handler for CPUs with virtual coherency
+ exception. version. */
+ NESTED(except_vec3_r4000, 0, sp)
+ .set noat
+ mfc0 k1, CP0_CAUSE
+ andi k1, k1, 0x7c
+ li k0, 31<<2
+ beq k1, k0, handle_vced
+ li k0, 14<<2
+ beq k1, k0, handle_vcei
+ dsll k1, k1, 1
+ daddu k0, k0, k1
+ ld k0, exception_handlers(k0)
+ jr k0
+ nop
+
+/*
+ * Big shit, we now may have two dirty primary cache lines for the same
+ * physical address. We can savely invalidate the line pointed to by
+ * c0_badvaddr because after return from this exception handler the load /
+ * store will be re-executed.
+ */
+handle_vced:
+ mfc0 k0, CP0_BADVADDR
+ li k1, -4 # Is this ...
+ and k0, k1 # ... really needed?
+ mtc0 zero, CP0_TAGLO
+ cache Index_Store_Tag_D,(k0)
+ cache Hit_Writeback_Inv_SD,(k0)
+ lui k0, %hi(vced_count)
+ lw k1, %lo(vced_count)(k0)
+ addiu k1, 1
+ sw k1, %lo(vced_count)(k0)
+ eret
+
+handle_vcei:
+ mfc0 k0, CP0_BADVADDR
+ cache Hit_Writeback_Inv_SD,(k0) # also cleans pi
+ lui k0, %hi(vcei_count)
+ lw k1, %lo(vcei_count)(k0)
+ addiu k1, 1
+ sw k1, %lo(vcei_count)(k0)
+ eret
+
+ END(except_vec3_r4000)
+ .set at
+
+ /* General exception vector for all other CPUs. */
+ NESTED(except_vec3_generic, 0, sp)
+ .set noat
+ mfc0 k1, CP0_CAUSE
+ andi k1, k1, 0x7c
+ dsll k1, k1, 1
+ ld k0, exception_handlers(k1)
+ jr k0
+ nop
+ END(except_vec3_generic)
+ .set at
+
+/*
+ * Special interrupt vector for embedded MIPS. This is a dedicated interrupt
+ * vector which reduces interrupt processing overhead. The jump instruction
+ * will be inserted here at initialization time. This handler may only be 8
+ * bytes in size!
+ */
+NESTED(except_vec4, 0, sp)
+1: j 1b /* Dummy, will be replaced */
+ nop
+ END(except_vec4)
+
+ __FINIT
diff --git a/arch/mips64/kernel/r4k_switch.S b/arch/mips64/kernel/r4k_switch.S
new file mode 100644
index 000000000..1c8ab8431
--- /dev/null
+++ b/arch/mips64/kernel/r4k_switch.S
@@ -0,0 +1,170 @@
+/* $Id: r4k_switch.S,v 1.2 1999/10/19 20:51: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
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995, 1996, 1998, 1999 by Ralf Baechle
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1994, 1995, 1996, by Andreas Busse
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/current.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/asmmacro.h>
+
+ .set mips3
+
+/*
+ * task_struct *resume(task_struct *prev, task_struct *next)
+ */
+ .set noreorder
+ .align 5
+ LEAF(resume)
+ mfc0 t1, CP0_STATUS
+ sd t1, THREAD_STATUS(a0)
+ cpu_save_nonscratch a0
+ sd ra, THREAD_REG31(a0)
+
+ /*
+ * The order of restoring the registers takes care of the race
+ * updating $28, $29 and kernelsp without disabling ints.
+ */
+ move $28, a1
+ cpu_restore_nonscratch $28
+ daddiu t0, $28, KERNEL_STACK_SIZE-32
+ sd t0, kernelsp
+ mfc0 t1, CP0_STATUS /* Do we really need this? */
+ li a3, 0xff00
+ and t1, a3
+ ld a2, THREAD_STATUS($28)
+ nor a3, $0, a3
+ and a2, a3
+ or a2, t1
+ mtc0 a2, CP0_STATUS
+ jr ra
+ move v0, a0
+ END(resume)
+
+/*
+ * Do lazy fpu context switch. Saves FPU context to the process in a0
+ * and loads the new context of the current process.
+ */
+
+#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS)
+
+LEAF(lazy_fpu_switch)
+ mfc0 t0, CP0_STATUS # enable cp1
+ li t3, 0x20000000
+ or t0, t3
+ mtc0 t0, CP0_STATUS
+
+ beqz a0, 2f # Save floating point state
+ nor t3, zero, t3
+
+ lw t1, ST_OFF(a0) # last thread looses fpu
+ and t1, t3
+ sd t1, ST_OFF(a0)
+ sll t2, t1, 5
+ bgez t2, 1f
+ sdc1 $f0, (THREAD_FPU + 0x00)(a0)
+ fpu_save_16odd a0
+1:
+ fpu_save_16even a0 t1 # clobbers t1
+2:
+
+ sll t0, t0, 5 # load new fp state
+ bgez t0, 1f
+ ldc1 $f0, (THREAD_FPU + 0x00)($28)
+ fpu_restore_16odd $28
+1:
+ .set reorder
+ fpu_restore_16even $28, t0 # clobbers t0
+ jr ra
+ END(lazy_fpu_switch)
+
+/*
+ * Save a thread's fp context.
+ */
+ .set noreorder
+LEAF(save_fp)
+ mfc0 t0, CP0_STATUS
+ sll t1, t0, 5
+ bgez t1, 1f # 16 register mode?
+ nop
+ fpu_save_16odd a0
+1:
+ fpu_save_16even a0 t1 # clobbers t1
+ jr ra
+ sdc1 $f0, (THREAD_FPU + 0x00)(a0)
+ END(save_fp)
+
+/*
+ * Load the FPU with signalling NANS. This bit pattern we're using has
+ * the property that no matter whether considered as single or as double
+ * precision represents signaling NANS.
+ *
+ * We initialize fcr31 to rounding to nearest, no exceptions.
+ */
+
+#define FPU_DEFAULT 0x00000000
+
+LEAF(init_fpu)
+ mfc0 t0, CP0_STATUS
+ li t1, 0x20000000
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+ sll t0, t0, 5
+
+ li t1, FPU_DEFAULT
+ ctc1 t1, fcr31
+
+ bgez t0, 1f # 16 / 32 register mode?
+ li t0, -1
+
+ dmtc1 t0, $f1
+ dmtc1 t0, $f3
+ dmtc1 t0, $f5
+ dmtc1 t0, $f7
+ dmtc1 t0, $f9
+ dmtc1 t0, $f11
+ dmtc1 t0, $f13
+ dmtc1 t0, $f15
+ dmtc1 t0, $f17
+ dmtc1 t0, $f19
+ dmtc1 t0, $f21
+ dmtc1 t0, $f23
+ dmtc1 t0, $f25
+ dmtc1 t0, $f27
+ dmtc1 t0, $f29
+ dmtc1 t0, $f31
+
+1: dmtc1 t0, $f0
+ dmtc1 t0, $f2
+ dmtc1 t0, $f4
+ dmtc1 t0, $f6
+ dmtc1 t0, $f8
+ dmtc1 t0, $f10
+ dmtc1 t0, $f12
+ dmtc1 t0, $f14
+ dmtc1 t0, $f16
+ dmtc1 t0, $f18
+ dmtc1 t0, $f20
+ dmtc1 t0, $f22
+ dmtc1 t0, $f24
+ dmtc1 t0, $f26
+ dmtc1 t0, $f28
+ jr ra
+ dmtc1 t0, $f30
+ END(init_fpu)
diff --git a/arch/mips64/kernel/r4k_tlb_debug.c b/arch/mips64/kernel/r4k_tlb_debug.c
new file mode 100644
index 000000000..f14725189
--- /dev/null
+++ b/arch/mips64/kernel/r4k_tlb_debug.c
@@ -0,0 +1,90 @@
+/* $Id: r4k_tlb_debug.c,v 1.6 1999/11/23 17:12:49 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) 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+asmlinkage void tlb_refill_debug(struct pt_regs regs)
+{
+ show_regs(&regs);
+ panic(__FUNCTION__ " called. This Does Not Happen (TM).");
+}
+
+asmlinkage void xtlb_refill_debug(struct pt_regs *regs)
+{
+ unsigned long addr;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ addr = regs->cp0_badvaddr & ~((PAGE_SIZE << 1) - 1);
+ pgd = pgd_offset(current->active_mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ pte = pte_offset(pmd, addr);
+
+ set_entrylo0(pte_val(pte[0]) >> 6);
+ set_entrylo1(pte_val(pte[1]) >> 6);
+ __asm__ __volatile__("nop;nop;nop");
+
+ tlb_write_random();
+}
+
+asmlinkage void xtlb_mod_debug(struct pt_regs *regs)
+{
+ show_regs(regs);
+ panic(__FUNCTION__ " called.");
+}
+
+asmlinkage void xtlb_tlbl_debug(struct pt_regs *regs)
+{
+ unsigned long addr;
+
+ addr = regs->cp0_badvaddr;
+#if 0
+ printk(__FUNCTION__ " called.\n");
+ show_regs(regs);
+ printk("TLB Dump:\n");
+ dump_tlb_all();
+ printk("c0_badvaddr = %08lx\n", addr);
+#endif
+ do_page_fault(regs, 0, addr);
+
+#if 0
+ printk("TLB Dump:\n");
+ dump_tlb_all();
+ printk("\n");
+#endif
+}
+
+asmlinkage void xtlb_tlbs_debug(struct pt_regs *regs)
+{
+ unsigned long addr;
+
+ addr = regs->cp0_badvaddr;
+#if 0
+ printk(__FUNCTION__ " called.\n");
+ show_regs(regs);
+ printk("TLB Dump:\n");
+ dump_tlb_all();
+ printk("c0_badvaddr = %08lx\n", addr);
+#endif
+ do_page_fault(regs, 1, addr);
+
+#if 0
+ printk("TLB Dump:\n");
+ dump_tlb_all();
+ printk("\n");
+#endif
+}
diff --git a/arch/mips64/kernel/r4k_tlb_glue.S b/arch/mips64/kernel/r4k_tlb_glue.S
new file mode 100644
index 000000000..767ecb76f
--- /dev/null
+++ b/arch/mips64/kernel/r4k_tlb_glue.S
@@ -0,0 +1,41 @@
+/* $Id: r4k_tlb_glue.S,v 1.5 1999/11/23 17:12:49 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) 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#define __ASSEMBLY__
+#include <linux/init.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ __INIT
+NESTED(__xtlb_refill_debug_tramp, PT_SIZE, sp)
+ j __xtlb_refill_debug
+ END(__xtlb_refill_debug_tramp)
+
+NESTED(__tlb_refill_debug_tramp, PT_SIZE, sp)
+ j __tlb_refill_debug
+ END(__tlb_refill_debug_tramp)
+ __FINIT
+
+ .macro tlb_handler name
+ NESTED(__\name, PT_SIZE, sp)
+ SAVE_ALL
+ dmfc0 t0, CP0_BADVADDR
+ sd t0, PT_BVADDR(sp)
+ move a0, sp
+ jal \name
+ j return
+ END(__\name)
+ .endm
+
+ tlb_handler tlb_refill_debug
+ tlb_handler xtlb_refill_debug
+ tlb_handler xtlb_mod_debug
+ tlb_handler xtlb_tlbl_debug
+ tlb_handler xtlb_tlbs_debug
diff --git a/arch/mips64/kernel/scall_64.S b/arch/mips64/kernel/scall_64.S
new file mode 100644
index 000000000..5167c344d
--- /dev/null
+++ b/arch/mips64/kernel/scall_64.S
@@ -0,0 +1,342 @@
+/* $Id: scall_64.S,v 1.1 1999/11/24 13:14:34 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, 1997, 1998, 1999 by Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <linux/errno.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/unistd.h>
+
+/* This duplicates the definition from <linux/sched.h> */
+#define PF_TRACESYS 0x00000020 /* tracing system calls */
+
+/* This duplicates the definition from <asm/signal.h> */
+#define SIGILL 4 /* Illegal instruction (ANSI). */
+
+/* Highest syscall handled here. */
+#define MAX_SYSCALL_NO __NR_Linux + __NR_Linux_syscalls
+
+ .align 5
+NESTED(handle_sys64, PT_SIZE, sp)
+ .set noat
+ SAVE_SOME
+ STI
+ .set at
+
+ ld t1, PT_EPC(sp) # skip syscall on return
+
+ sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
+ daddiu t1, 4 # skip to next instruction
+ beqz t0, illegal_syscall
+ sd t1, PT_EPC(sp)
+
+ /* XXX Put both in one cacheline, should save a bit. */
+ dsll t0, v0, 3
+ ld t2, (sys_call_table - (__NR_Linux * 8))(t0) # syscall routine
+ beqz t2, illegal_syscall;
+
+ sd a3, PT_R26(sp) # save a3 for syscall restarting
+
+ ld t0, TASK_FLAGS($28) # syscall tracing enabled?
+ andi t0, PF_TRACESYS
+ bnez t0, trace_a_syscall
+
+ jalr t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+EXPORT(ret_from_sys_call_64)
+ .type ret_from_sys_call_64,@function
+ ld t0, bh_mask
+ ld t1, bh_active # unused delay slot
+ and t0, t1
+ bnez t0, handle_bottom_half_64
+
+9: ld t0, PT_STATUS(sp) # returning to kernel mode?
+ andi t1, t0, 0x10
+ ld t2, TASK_NEED_RESCHED($28)
+ beqz t1, return_64 # -> yes
+ bnez t2, reschedule_64
+ lw v0, TASK_SIGPENDING($28)
+ move a0, zero
+ beqz v0, return_64
+ move a1, sp
+ SAVE_STATIC
+ jal do_signal
+
+return_64:
+ RESTORE_SOME
+ RESTORE_SP
+ .set mips3
+ eret
+ .set mips0
+
+handle_bottom_half_64:
+ jal do_bottom_half
+ b 9b
+reschedule_64:
+ SAVE_STATIC
+ jal schedule
+ b ret_from_sys_call_64
+
+/* ------------------------------------------------------------------------ */
+
+trace_a_syscall:
+ SAVE_STATIC
+ sd t2,PT_R1(sp)
+ jal syscall_trace
+ ld t2,PT_R1(sp)
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+ ld a2, PT_R6(sp)
+ ld a3, PT_R7(sp)
+ jalr t2
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+ jal syscall_trace
+ j ret_from_sys_call
+
+illegal_syscall:
+ /* This also isn't a 64-bit syscall, throw an error. */
+ li v0, ENOSYS # error
+ sd v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sd t0, PT_R7(sp)
+ j ret_from_sys_call
+ END(handle_sys64)
+
+sys_call_table:
+ PTR sys_syscall /* 4000 */
+ PTR sys_exit
+ PTR sys_fork
+ PTR sys_read
+ PTR sys_write
+ PTR sys_open /* 4005 */
+ PTR sys_close
+ PTR sys_waitpid
+ PTR sys_creat
+ PTR sys_link
+ PTR sys_unlink /* 4010 */
+ PTR sys_execve
+ PTR sys_chdir
+ PTR sys_time
+ PTR sys_mknod
+ PTR sys_chmod /* 4015 */
+ PTR sys_lchown
+ PTR sys_ni_syscall
+ PTR sys_stat
+ PTR sys_lseek
+ PTR sys_getpid /* 4020 */
+ PTR sys_mount
+ PTR sys_oldumount
+ PTR sys_setuid
+ PTR sys_getuid
+ PTR sys_stime /* 4025 */
+ PTR sys_ni_syscall /* ptrace */
+ PTR sys_alarm
+ PTR sys_fstat
+ PTR sys_ni_syscall
+ PTR sys_utime /* 4030 */
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+ PTR sys_access
+ PTR sys_nice
+ PTR sys_ni_syscall /* 4035 */
+ PTR sys_sync
+ PTR sys_kill
+ PTR sys_rename
+ PTR sys_mkdir
+ PTR sys_rmdir /* 4040 */
+ PTR sys_dup
+ PTR sys_pipe
+ PTR sys_times
+ PTR sys_ni_syscall
+ PTR sys_brk /* 4045 */
+ PTR sys_setgid
+ PTR sys_getgid
+ PTR sys_ni_syscall /* was signal 2 */
+ PTR sys_geteuid
+ PTR sys_getegid /* 4050 */
+ PTR sys_acct
+ PTR sys_umount
+ PTR sys_ni_syscall
+ PTR sys_ioctl
+ PTR sys_fcntl /* 4055 */
+ PTR sys_ni_syscall
+ PTR sys_setpgid
+ PTR sys_ni_syscall
+ PTR sys_olduname
+ PTR sys_umask /* 4060 */
+ PTR sys_chroot
+ PTR sys_ustat
+ PTR sys_dup2
+ PTR sys_getppid
+ PTR sys_getpgrp /* 4065 */
+ PTR sys_setsid
+ PTR sys_sigaction
+ PTR sys_sgetmask
+ PTR sys_ssetmask
+ PTR sys_setreuid /* 4070 */
+ PTR sys_setregid
+ PTR sys_sigsuspend
+ PTR sys_sigpending
+ PTR sys_sethostname
+ PTR sys_setrlimit /* 4075 */
+ PTR sys_getrlimit
+ PTR sys_getrusage
+ PTR sys_gettimeofday
+ PTR sys_settimeofday
+ PTR sys_getgroups /* 4080 */
+ PTR sys_setgroups
+ PTR sys_ni_syscall /* old_select */
+ PTR sys_symlink
+ PTR sys_lstat
+ PTR sys_readlink /* 4085 */
+ PTR sys_uselib
+ PTR sys_swapon
+ PTR sys_reboot
+ PTR old_readdir
+ PTR sys_mmap /* 4090 */
+ PTR sys_munmap
+ PTR sys_truncate
+ PTR sys_ftruncate
+ PTR sys_fchmod
+ PTR sys_fchown /* 4095 */
+ PTR sys_getpriority
+ PTR sys_setpriority
+ PTR sys_ni_syscall
+ PTR sys_statfs
+ PTR sys_fstatfs /* 4100 */
+ PTR sys_ni_syscall /* sys_ioperm */
+ PTR sys_socketcall
+ PTR sys_syslog
+ PTR sys_setitimer
+ PTR sys_getitimer /* 4105 */
+ PTR sys_newstat
+ PTR sys_newlstat
+ PTR sys_newfstat
+ PTR sys_uname
+ PTR sys_ni_syscall /* sys_ioperm *//* 4110 */
+ PTR sys_vhangup
+ PTR sys_ni_syscall /* was sys_idle */
+ PTR sys_ni_syscall /* sys_vm86 */
+ PTR sys_wait4
+ PTR sys_swapoff /* 4115 */
+ PTR sys_sysinfo
+ PTR sys_ipc
+ PTR sys_fsync
+ PTR sys_sigreturn
+ PTR sys_clone /* 4120 */
+ PTR sys_setdomainname
+ PTR sys_newuname
+ PTR sys_ni_syscall /* sys_modify_ldt */
+ PTR sys_adjtimex
+ PTR sys_mprotect /* 4125 */
+ PTR sys_sigprocmask
+ PTR sys_create_module
+ PTR sys_init_module
+ PTR sys_delete_module
+ PTR sys_get_kernel_syms /* 4130 */
+ PTR sys_quotactl
+ PTR sys_getpgid
+ PTR sys_fchdir
+ PTR sys_bdflush
+ PTR sys_sysfs /* 4135 */
+ PTR sys_personality
+ PTR sys_ni_syscall /* for afs_syscall */
+ PTR sys_setfsuid
+ PTR sys_setfsgid
+ PTR sys_llseek /* 4140 */
+ PTR sys_getdents
+ PTR sys_select
+ PTR sys_flock
+ PTR sys_msync
+ PTR sys_readv /* 4145 */
+ PTR sys_writev
+ PTR sys_cacheflush
+ PTR sys_cachectl
+ PTR sys_sysmips
+ PTR sys_ni_syscall /* 4150 */
+ PTR sys_getsid
+ PTR sys_fdatasync
+ PTR sys_sysctl
+ PTR sys_mlock
+ PTR sys_munlock /* 4155 */
+ PTR sys_mlockall
+ PTR sys_munlockall
+ PTR sys_sched_setparam
+ PTR sys_sched_getparam
+ PTR sys_sched_setscheduler /* 4160 */
+ PTR sys_sched_getscheduler
+ PTR sys_sched_yield
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+ PTR sys_sched_rr_get_interval /* 4165 */
+ PTR sys_nanosleep
+ PTR sys_mremap
+ PTR sys_accept
+ PTR sys_bind
+ PTR sys_connect /* 4170 */
+ PTR sys_getpeername
+ PTR sys_getsockname
+ PTR sys_getsockopt
+ PTR sys_listen
+ PTR sys_recv /* 4175 */
+ PTR sys_recvfrom
+ PTR sys_recvmsg
+ PTR sys_send
+ PTR sys_sendmsg
+ PTR sys_sendto /* 4180 */
+ PTR sys_setsockopt
+ PTR sys_shutdown
+ PTR sys_socket
+ PTR sys_socketpair
+ PTR sys_setresuid /* 4185 */
+ PTR sys_getresuid
+ PTR sys_query_module
+ PTR sys_poll
+ PTR sys_nfsservctl
+ PTR sys_setresgid /* 4190 */
+ PTR sys_getresgid
+ PTR sys_prctl
+ PTR sys_rt_sigreturn
+ PTR sys_rt_sigaction
+ PTR sys_rt_sigprocmask /* 4195 */
+ PTR sys_rt_sigpending
+ PTR sys_rt_sigtimedwait
+ PTR sys_rt_sigqueueinfo
+ PTR sys_rt_sigsuspend
+ PTR sys_pread /* 4200 */
+ PTR sys_pwrite
+ PTR sys_chown
+ PTR sys_getcwd
+ PTR sys_capget
+ PTR sys_capset /* 4205 */
+ PTR sys_sigaltstack
+ PTR sys_sendfile
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
diff --git a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S
new file mode 100644
index 000000000..b417303c6
--- /dev/null
+++ b/arch/mips64/kernel/scall_o32.S
@@ -0,0 +1,415 @@
+/* $Id$
+ *
+ * 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, 1997, 1998, 1999 by Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Hairy, the userspace application uses a different argument passing
+ * convention than the kernel, so we have to translate things from o32
+ * to ABI64 calling convention. 64-bit syscalls are also processed
+ * here for now.
+ */
+#include <asm/asm.h>
+#include <linux/errno.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/unistd.h>
+
+/* This duplicates the definition from <linux/sched.h> */
+#define PF_TRACESYS 0x00000020 /* tracing system calls */
+
+/* This duplicates the definition from <asm/signal.h> */
+#define SIGILL 4 /* Illegal instruction (ANSI). */
+
+/* Highest syscall used of any syscall flavour */
+#define MAX_SYSCALL_NO __NR_Linux32 + __NR_Linux_syscalls
+
+ .align 5
+NESTED(handle_sys, PT_SIZE, sp)
+ .set noat
+ SAVE_SOME
+ STI
+ .set at
+
+ ld t1, PT_EPC(sp) # skip syscall on return
+
+ sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
+ daddiu t1, 4 # skip to next instruction
+ beqz t0, not_o32_scall
+ sd t1, PT_EPC(sp)
+
+ /* XXX Put both in one cacheline, should save a bit. */
+ dsll t0, v0, 3
+ ld t2, (sys_call_table - (__NR_Linux * 8))(t0) # syscall routine
+ lbu t3, (sys_narg_table - __NR_Linux)(v0) # number of arguments
+ beqz t2, illegal_syscall;
+
+ subu t0, t3, 5 # 5 or more arguments?
+ sd a3, PT_R26(sp) # save a3 for syscall restarting
+ bgez t0, stackargs
+
+stack_done:
+ ld t0, TASK_FLAGS($28) # syscall tracing enabled?
+ andi t0, PF_TRACESYS
+ bnez t0, trace_a_syscall
+
+ jalr t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+EXPORT(o32_ret_from_sys_call)
+ .type o32_ret_from_sys_call,@function
+ ld t0,bh_mask
+ ld t1,bh_active # unused delay slot
+ and t0,t1
+ bnez t0,o32_handle_bottom_half
+
+9: ld t0,PT_STATUS(sp) # returning to kernel mode?
+ andi t1, t0, 0x10
+ ld t2, TASK_NEED_RESCHED($28)
+ beqz t1, o32_return # -> yes
+ bnez t2, o32_reschedule
+ lw v0, TASK_SIGPENDING($28)
+ move a0, zero
+ beqz v0, o32_return
+ move a1, sp
+ SAVE_STATIC
+ jal do_signal
+
+o32_return:
+ RESTORE_SOME
+ RESTORE_SP
+ .set mips3
+ eret
+ .set mips0
+
+o32_handle_bottom_half:
+ jal do_bottom_half
+ b 9b
+o32_reschedule:
+ SAVE_STATIC
+ jal schedule
+ b o32_ret_from_sys_call
+
+/* ------------------------------------------------------------------------ */
+
+trace_a_syscall:
+ SAVE_STATIC
+ sd t2,PT_R1(sp)
+ jal syscall_trace
+ ld t2,PT_R1(sp)
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+ ld a2, PT_R6(sp)
+ ld a3, PT_R7(sp)
+ jalr t2
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+ jal syscall_trace
+ j ret_from_sys_call
+
+/* ------------------------------------------------------------------------ */
+
+ /*
+ * More than four arguments. Try to deal with it by copying the
+ * stack arguments from the user stack to the kernel stack.
+ * This Sucks (TM).
+ */
+stackargs:
+ ld t0, PT_R29(sp) # get old user stack pointer
+ subu t3, 4
+ sll t1, t3, 2 # stack valid?
+
+ addu t1, t0 # end address
+ or t0, t1
+ bltz t0, bad_stack # -> sp is bad
+
+ ld t0, PT_R29(sp) # get old user stack pointer
+ la t1, 3f # copy 1 to 2 arguments
+ sll t3, t3, 2
+ subu t1, t3
+ jr t1
+
+ /* Ok, copy the args from the luser stack to the kernel stack */
+1: lw a5, 20(t0) # argument #6 from usp
+2: lw a4, 16(t0) # argument #5 from usp
+
+3: j stack_done # go back
+
+ .section __ex_table,"a"
+ PTR 1b, bad_stack
+ PTR 2b, bad_stack
+ .previous
+
+ /*
+ * The stackpointer for a call with more than 4 arguments is bad.
+ */
+bad_stack:
+ negu v0 # error
+ sd v0, PT_R0(sp)
+ sd v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sd t0, PT_R7(sp)
+ j ret_from_sys_call
+
+not_o32_scall:
+ /* This is not an 32-bit compatibility syscall, pass it on to
+ the 64-bit syscall handlers. */
+ j handle_sys64
+
+illegal_syscall:
+ /* This also isn't a 64-bit syscall, throw an error. */
+ li v0, ENOSYS # error
+ sd v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sd t0, PT_R7(sp)
+ j ret_from_sys_call
+ END(handle_sys)
+
+ .macro syscalltable
+ sys sys_syscall 0 /* 4000 */
+ sys sys_exit 1
+ sys sys_fork 0
+ sys sys_read 3
+ sys sys_write 3
+ sys sys_open 3 /* 4005 */
+ sys sys_close 3
+ sys sys_waitpid 3
+ sys sys_creat 2
+ sys sys_link 2
+ sys sys_unlink 1 /* 4010 */
+ sys sys_execve 0
+ sys sys_chdir 1
+ sys sys_time 1
+ sys sys_mknod 3
+ sys sys_chmod 2 /* 4015 */
+ sys sys_lchown 3
+ sys sys_ni_syscall 0
+ sys sys_stat 2
+ sys sys_lseek 3
+ sys sys_getpid 0 /* 4020 */
+ sys sys_mount 5
+ sys sys_oldumount 1
+ sys sys_setuid 1
+ sys sys_getuid 0
+ sys sys_stime 1 /* 4025 */
+ sys sys_ni_syscall 0 /* ptrace */
+ sys sys_alarm 1
+ sys sys_fstat 2
+ sys sys_ni_syscall 0
+ sys sys_utime 2 /* 4030 */
+ sys sys_ni_syscall 0
+ sys sys_ni_syscall 0
+ sys sys_access 2
+ sys sys_nice 1
+ sys sys_ni_syscall 0 /* 4035 */
+ sys sys_sync 0
+ sys sys_kill 2
+ sys sys_rename 2
+ sys sys_mkdir 2
+ sys sys_rmdir 1 /* 4040 */
+ sys sys_dup 1
+ sys sys_pipe 0
+ sys sys_times 1
+ sys sys_ni_syscall 0
+ sys sys_brk 1 /* 4045 */
+ sys sys_setgid 1
+ sys sys_getgid 0
+ sys sys_ni_syscall 0 /* was signal 2 */
+ sys sys_geteuid 0
+ sys sys_getegid 0 /* 4050 */
+ sys sys_acct 0
+ sys sys_umount 2
+ sys sys_ni_syscall 0
+ sys sys_ioctl 3
+ sys sys_fcntl 3 /* 4055 */
+ sys sys_ni_syscall 2
+ sys sys_setpgid 2
+ sys sys_ni_syscall, 0
+ sys sys_olduname 1
+ sys sys_umask 1 /* 4060 */
+ sys sys_chroot 1
+ sys sys_ustat 2
+ sys sys_dup2 2
+ sys sys_getppid 0
+ sys sys_getpgrp 0 /* 4065 */
+ sys sys_setsid 0
+ sys sys_sigaction 3
+ sys sys_sgetmask 0
+ sys sys_ssetmask 1
+ sys sys_setreuid 2 /* 4070 */
+ sys sys_setregid 2
+ sys sys_sigsuspend 0
+ sys sys_sigpending 1
+ sys sys_sethostname 2
+ sys sys_setrlimit 2 /* 4075 */
+ sys sys_getrlimit 2
+ sys sys_getrusage 2
+ sys sys_gettimeofday 2
+ sys sys_settimeofday 2
+ sys sys_getgroups 2 /* 4080 */
+ sys sys_setgroups 2
+ sys sys_ni_syscall 0 /* old_select */
+ sys sys_symlink 2
+ sys sys_lstat 2
+ sys sys_readlink 3 /* 4085 */
+ sys sys_uselib 1
+ sys sys_swapon 2
+ sys sys_reboot 3
+ sys old_readdir 3
+ sys sys_mmap 6 /* 4090 */
+ sys sys_munmap 2
+ sys sys_truncate 2
+ sys sys_ftruncate 2
+ sys sys_fchmod 2
+ sys sys_fchown 3 /* 4095 */
+ sys sys_getpriority 2
+ sys sys_setpriority 3
+ sys sys_ni_syscall 0
+ sys sys_statfs 2
+ sys sys_fstatfs 2 /* 4100 */
+ sys sys_ni_syscall 0 /* sys_ioperm */
+ sys sys_socketcall 2
+ sys sys_syslog 3
+ sys sys_setitimer 3
+ sys sys_getitimer 2 /* 4105 */
+ sys sys_newstat 2
+ sys sys_newlstat 2
+ sys sys_newfstat 2
+ sys sys_uname 1
+ sys sys_ni_syscall 0 /* sys_ioperm *//* 4110 */
+ sys sys_vhangup 0
+ sys sys_ni_syscall 0 /* was sys_idle */
+ sys sys_ni_syscall 0 /* sys_vm86 */
+ sys sys_wait4 4
+ sys sys_swapoff 1 /* 4115 */
+ sys sys_sysinfo 1
+ sys sys_ipc 6
+ sys sys_fsync 1
+ sys sys_sigreturn 0
+ sys sys_clone 0 /* 4120 */
+ sys sys_setdomainname 2
+ sys sys_newuname 1
+ sys sys_ni_syscall 0 /* sys_modify_ldt */
+ sys sys_adjtimex 1
+ sys sys_mprotect 3 /* 4125 */
+ sys sys_sigprocmask 3
+ sys sys_create_module 2
+ sys sys_init_module 5
+ sys sys_delete_module 1
+ sys sys_get_kernel_syms 1 /* 4130 */
+ sys sys_quotactl 0
+ sys sys_getpgid 1
+ sys sys_fchdir 1
+ sys sys_bdflush 2
+ sys sys_sysfs 3 /* 4135 */
+ sys sys_personality 1
+ sys sys_ni_syscall 0 /* for afs_syscall */
+ sys sys_setfsuid 1
+ sys sys_setfsgid 1
+ sys sys_llseek 5 /* 4140 */
+ sys sys_getdents 3
+ sys sys_select 5
+ sys sys_flock 2
+ sys sys_msync 3
+ sys sys_readv 3 /* 4145 */
+ sys sys_writev 3
+ sys sys_cacheflush 3
+ sys sys_cachectl 3
+ sys sys_sysmips 4
+ sys sys_ni_syscall 0 /* 4150 */
+ sys sys_getsid 1
+ sys sys_fdatasync 0
+ sys sys_sysctl 1
+ sys sys_mlock 2
+ sys sys_munlock 2 /* 4155 */
+ sys sys_mlockall 1
+ sys sys_munlockall 0
+ sys sys_sched_setparam 2
+ sys sys_sched_getparam 2
+ sys sys_sched_setscheduler 3 /* 4160 */
+ sys sys_sched_getscheduler 1
+ sys sys_sched_yield 0
+ sys sys_sched_get_priority_max 1
+ sys sys_sched_get_priority_min 1
+ sys sys_sched_rr_get_interval 2 /* 4165 */
+ sys sys_nanosleep 2
+ sys sys_mremap 4
+ sys sys_accept 3
+ sys sys_bind 3
+ sys sys_connect 3 /* 4170 */
+ sys sys_getpeername 3
+ sys sys_getsockname 3
+ sys sys_getsockopt 5
+ sys sys_listen 2
+ sys sys_recv 4 /* 4175 */
+ sys sys_recvfrom 6
+ sys sys_recvmsg 3
+ sys sys_send 4
+ sys sys_sendmsg 3
+ sys sys_sendto 6 /* 4180 */
+ sys sys_setsockopt 5
+ sys sys_shutdown 2
+ sys sys_socket 3
+ sys sys_socketpair 4
+ sys sys_setresuid 3 /* 4185 */
+ sys sys_getresuid 3
+ sys sys_query_module 5
+ sys sys_poll 3
+ sys sys_nfsservctl 3
+ sys sys_setresgid 3 /* 4190 */
+ sys sys_getresgid 3
+ sys sys_prctl 5
+ sys sys_rt_sigreturn 0
+ sys sys_rt_sigaction 4
+ 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 0
+ sys sys_pread 4 /* 4200 */
+ sys sys_pwrite 4
+ sys sys_chown 3
+ sys sys_getcwd 2
+ sys sys_capget 2
+ sys sys_capset 2 /* 4205 */
+ sys sys_sigaltstack 0
+ sys sys_sendfile 3
+ sys sys_ni_syscall 0
+ sys sys_ni_syscall 0
+ .endm
+
+ .macro sys function, nargs
+ PTR \function
+ .endm
+
+sys_call_table:
+ syscalltable
+
+ .macro sys function, nargs
+ .byte \nargs
+ .endm
+
+sys_narg_table:
+ syscalltable
diff --git a/arch/mips64/kernel/semaphore.c b/arch/mips64/kernel/semaphore.c
new file mode 100644
index 000000000..d62b355e1
--- /dev/null
+++ b/arch/mips64/kernel/semaphore.c
@@ -0,0 +1,129 @@
+/*
+ * Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR \
+ struct task_struct *tsk = current; \
+ wait_queue_t wait; \
+ init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ tsk->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ tsk->state = (task_state); \
+ } \
+ tsk->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+ DOWN_VAR
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ int ret = 0;
+ DOWN_VAR
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, tsk);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
diff --git a/arch/mips64/kernel/setup.c b/arch/mips64/kernel/setup.c
index f7904551e..347266fd2 100644
--- a/arch/mips64/kernel/setup.c
+++ b/arch/mips64/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: setup.c,v 1.3 1999/10/19 20:51:46 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
@@ -31,6 +31,7 @@
#include <asm/asm.h>
#include <asm/bootinfo.h>
#include <asm/cachectl.h>
+#include <asm/cpu.h>
#include <asm/io.h>
#include <asm/stackframe.h>
#include <asm/system.h>
@@ -79,7 +80,7 @@ struct kbd_ops *kbd_ops;
*
* These are initialized so they are in the .data section
*/
-unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */
+unsigned long mips_memory_upper = KSEG0;
unsigned long mips_cputype = CPU_UNKNOWN;
unsigned long mips_machtype = MACH_UNKNOWN;
unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
@@ -87,6 +88,7 @@ unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
unsigned char aux_device_present;
extern int _end;
+extern void load_mmu(void);
extern char empty_zero_page[PAGE_SIZE];
static char command_line[CL_SIZE] = { 0, };
@@ -95,6 +97,40 @@ extern char arcs_cmdline[CL_SIZE];
extern void ip22_setup(void);
+static inline void cpu_probe(void)
+{
+ unsigned int prid = read_32bit_cp0_register(CP0_PRID);
+
+ switch(prid & 0xff00) {
+ case PRID_IMP_R4000:
+ if((prid & 0xff) == PRID_REV_R4400)
+ mips_cputype = CPU_R4400SC;
+ else
+ mips_cputype = CPU_R4000SC;
+ break;
+ case PRID_IMP_R4600:
+ mips_cputype = CPU_R4600;
+ break;
+ case PRID_IMP_R4700:
+ mips_cputype = CPU_R4700;
+ break;
+ case PRID_IMP_R5000:
+ mips_cputype = CPU_R5000;
+ break;
+ case PRID_IMP_NEVADA:
+ mips_cputype = CPU_NEVADA;
+ break;
+ case PRID_IMP_R8000:
+ mips_cputype = CPU_R8000;
+ break;
+ case PRID_IMP_R10000:
+ mips_cputype = CPU_R10000;
+ break;
+ default:
+ mips_cputype = CPU_UNKNOWN;
+ }
+}
+
void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p,
unsigned long * memory_end_p)
{
@@ -104,6 +140,9 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p,
unsigned long *initrd_header;
#endif
+ cpu_probe();
+ load_mmu();
+
#ifdef CONFIG_SGI_IP22
ip22_setup();
#endif
diff --git a/arch/mips64/kernel/signal.c b/arch/mips64/kernel/signal.c
index 482ddd894..712459430 100644
--- a/arch/mips64/kernel/signal.c
+++ b/arch/mips64/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.1 1999/09/27 16:01:38 ralf Exp $
+/* $Id: signal.c,v 1.5 1999/10/19 20:51:46 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
@@ -34,14 +34,14 @@
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);
+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)
+sys_sigsuspend(abi64_no_regargs, struct pt_regs regs)
{
sigset_t *uset, saveset, newset;
@@ -68,7 +68,7 @@ sys_sigsuspend(struct pt_regs regs)
}
asmlinkage int
-sys_rt_sigsuspend(struct pt_regs regs)
+sys_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
{
sigset_t *unewset, saveset, newset;
size_t sigsetsize;
@@ -143,7 +143,7 @@ sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
}
asmlinkage int
-sys_sigaltstack(struct pt_regs regs)
+sys_sigaltstack(abi64_no_regargs, struct pt_regs regs)
{
const stack_t *uss = (const stack_t *) regs.regs[4];
stack_t *uoss = (stack_t *) regs.regs[5];
@@ -202,7 +202,7 @@ struct rt_sigframe {
};
asmlinkage void
-sys_sigreturn(struct pt_regs regs)
+sys_sigreturn(abi64_no_regargs, struct pt_regs regs)
{
struct sigframe *frame;
sigset_t blocked;
@@ -237,7 +237,7 @@ badframe:
}
asmlinkage void
-sys_rt_sigreturn(struct pt_regs regs)
+sys_rt_sigreturn(abi64_no_regargs, struct pt_regs regs)
{
struct rt_sigframe *frame;
sigset_t set;
@@ -612,7 +612,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS:
- if (do_cordump(signr, regs))
+ if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
diff --git a/arch/mips64/kernel/softfp.S b/arch/mips64/kernel/softfp.S
new file mode 100644
index 000000000..d042ca2d1
--- /dev/null
+++ b/arch/mips64/kernel/softfp.S
@@ -0,0 +1,668 @@
+/* $Id: softfp.S,v 1.1 1999/10/10 18:49:17 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) 1998, 1999 by Ralf Baechle
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ *
+ * For now it's just a crude hack good enough to run certain fp programs like
+ * Mozilla.
+ * XXX: Handle MIPS II/III/IV/V enhancements, exceptions, ...
+ */
+#include <asm/regdef.h>
+#include <asm/asm.h>
+
+#ifndef __KERNEL__
+#define printk printf
+#endif
+
+#define LOCK_KERNEL
+#define UNLOCK_KERNEL
+
+/*
+ * This duplicates definitions from <linux/kernel.h>.
+ */
+#define KERN_EMERG "<0>" /* system is unusable */
+#define KERN_ALERT "<1>" /* action must be taken immediately */
+#define KERN_CRIT "<2>" /* critical conditions */
+#define KERN_ERR "<3>" /* error conditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normal but significant condition */
+#define KERN_INFO "<6>" /* informational */
+#define KERN_DEBUG "<7>" /* debug-level messages */
+
+/*
+ * This duplicates definitions from <asm/signal.h>
+ */
+#define SIGILL 4 /* Illegal instruction (ANSI). */
+
+/*
+ * Definitions about the instruction format
+ */
+#define fd_shift 6
+#define fr_shift 21
+#define fs_shift 11
+#define ft_shift 16
+
+/*
+ * NaNs as use by the MIPS architecture
+ */
+#define S_QNaN 0x7fbfffff
+#define D_QNaN 0x7ff7ffffffffffff
+#define W_QNaN 0x7fffffff
+#define L_QNaN 0x7fffffffffffffff
+
+/*
+ * Checking for NaNs
+ */
+#define S_is_QNaN(reg,res) \
+ sll res, reg, S_F_size - S_F_bits
+#define D_is_QNaN(reg1,reg2,res) \
+ sll res, reg1, (D_F_size - 32) - (D_F_bits - 32); \
+ or res, reg2
+
+/*
+ * Checking for Denorms
+ */
+#define S_is_Denorm(reg,res) \
+ li res, 1 << (S_F_bits - 1); \
+ and reg, res
+
+/*
+ * Some constants that define the properties of single precission numbers.
+ */
+#define S_M_prec 24
+#define S_E_max 127
+#define S_E_min -126
+#define S_E_bias 127
+#define S_E_bits 8
+#define S_F_bits 23
+#define S_F_size 32
+
+/* Set temp0, if exponent of reg is S_E_max + 1. */
+#define S_is_E_max(reg,temp0,temp1) \
+ li temp0, (S_E_max + 1 + S_E_bias) << S_F_bits; \
+ and temp1, temp0, reg; \
+ seq temp0, temp1 /* temp0 != 0 if NaN */
+
+/* Clear temp0, if exponent of reg is S_E_min - 1. */
+#define S_is_E_min(reg,temp0) \
+ li temp0, (S_E_min - 1 + S_E_bias) << S_F_bits; \
+ and temp0, reg /* temp0 == 0 if denorm or zero */
+
+/* Set temp0 if reg is a NaN assuming S_is_E_max is true */
+#define S_get_F(reg,temp0) \
+ li temp0, (1 << S_F_bits) - 1; \
+ and temp0, reg /* temp0 != 0 if NaN */
+
+/* Set res if fraction of reg is != 0. */
+#define S_is_Inf(reg,res) \
+ li res, (1 << S_F_bits) - 1; \
+ and res, reg /* temp0 == 0 if Inf */
+
+
+/*
+ * Some constants that define the properties of double precission numbers.
+ */
+#define D_M_prec 53
+#define D_E_max 1023
+#define D_E_min -1022
+#define D_E_bias 1023
+#define D_E_bits 8
+#define D_F_bits 52
+#define D_F_size 64
+
+/* Set temp0, if exponent of reg1/reg2 is D_E_max. */
+#define D_is_E_max(reg1,reg2,temp0,temp1) \
+ li temp0, (D_E_max + 1 + D_E_bias) << (D_F_bits - 32); \
+ and temp1, temp0, reg1; \
+ seq temp0, temp1 /* temp0 != 0 if NaN */
+
+/* Clear temp0, if exponent of reg is D_E_min. */
+#define D_is_E_min(reg1,reg2,res) \
+ li res, (D_E_min + 1 + D_E_bias) << (D_F_bits - 32); \
+ and res, reg1 /* temp0 == 0 if NaN or zero */
+
+/* Set res if reg is a NaN assuming S_is_E_max is true */
+#define D_get_F(reg1,reg2,res) \
+ li res, (1 << (D_F_bits - 32)) - 1; \
+ and res, reg1 /* temp0 != 0 if NaN */
+
+/* Set temp0 if reg1/reg2 is a NaN */
+#define D_is_NAN(reg1,reg2,temp0,temp1) \
+ li temp0, (1 << (D_F_bits - 32) - 1; \
+ and temp0, reg1; \
+ or temp0, reg2; \
+ sne temp0, zero, temp0 /* temp0 != 0 if NaN */
+
+/* Set res if fraction of reg1/reg2 is != 0. */
+#define D_is_Inf(reg1,reg2,res) \
+ li res, (1 << (D_F_bits - 32)) - 1; \
+ and res, reg1; \
+ or res, reg2 /* temp0 == 0 if Inf */
+
+/* Complain about yet unhandled instruction. */
+#define BITCH(insn) \
+insn: LOCK_KERNEL; \
+ la a1, 8f; \
+ TEXT(#insn); \
+ la a1, nosim; \
+ UNLOCK_KERNEL; \
+ j done
+
+ .data
+nosim: .asciz KERN_DEBUG "Don't know how to simulate %s instruction\n"
+ .previous
+
+/*
+ * When we come here, we've saved some of the integer registers and
+ * reenabled interrupts.
+ */
+LEAF(simfp)
+ .set noreorder
+ .cpload $25
+ .set reorder
+
+ subu sp, 16
+ .cprestore 20
+ sw ra, 16(sp)
+
+ /* For now we assume that we get the opcode to simulate passed in as
+ an argument. */
+ move ta0, a0
+
+ /*
+ * First table lookup using insn[5:0]
+ */
+ la ta1, lowtab
+ andi ta2, ta0, 0x3f
+ sll ta2, ta2, 2
+ addu ta1, ta2
+ lw ta1, (ta1)
+ jr ta1
+ END(simfp)
+
+/*
+ * We only decode the lower 3 of the 5 bit in the fmt field. That way we
+ * can keep the jump table significantly shorter.
+ */
+#define FMT_switch(insn,opc,temp0,temp1) \
+insn: srl temp0, opc, 19; \
+ andi temp0, 0x1c; \
+ la temp1, insn ## .tab; \
+ addu temp0, temp1; \
+ lw temp0, (temp0); \
+ jr temp0; \
+ \
+ .data; \
+insn ## .tab: \
+ .word insn ## .s, insn ## .d, unimp, unimp; \
+ .word insn ## .w, insn ## .l, unimp, unimp; \
+ .previous
+
+ BITCH(add)
+ BITCH(sub)
+ BITCH(mul)
+ BITCH(div)
+ BITCH(sqrt)
+ BITCH(abs)
+ BITCH(mov)
+ BITCH(neg)
+ BITCH(round.l)
+ BITCH(trunc.l)
+ BITCH(ceil.l)
+ BITCH(floor.l)
+ BITCH(round.w)
+ BITCH(trunc.w)
+ BITCH(ceil.w)
+ BITCH(floor.w)
+ BITCH(cvt.s)
+ BITCH(cvt.d)
+
+/* ------------------------------------------------------------------------ */
+
+FMT_switch(cvt.w,ta0,ta1,ta2)
+
+/* Convert a single fp to a fixed point integer. */
+cvt.w.s:
+ srl ta1, ta0, fs_shift # Get source register
+ andi ta1, 31
+ jal s_get_fpreg
+
+ S_is_E_max(ta1,ta2,ta3)
+ beqz ta2, 3f
+ /* Might be a NaN or Inf. */
+ S_get_F(ta1,ta2)
+ beqz ta2, 2f
+
+ /* It's a NaN. IEEE says undefined. */
+ /* Is it a QNaN? Then the result is a QNaN as well. */
+ S_is_QNaN(ta1,ta2)
+ bltz ta2, 1f
+
+ /* XXX Ok, it's a SNaN. Signal invalid exception, if enabled.
+ For now we don't signal and supply a QNaN for result. */
+
+1: li ta2, W_QNaN
+ srl ta1, ta0, fd_shift # Put result register
+ andi ta1, 31
+ jal s_put_fpreg
+ j done
+2:
+
+ S_is_Inf(ta1,ta2)
+ bnez ta2, 2f
+
+ /* It's +/- Inf. Set register to +/- max. integer. */
+ /* XXX Send invalid operation exception instead, if enabled. */
+ srl ta1, ta1, 31 # Extract sign bit
+ li ta2, 0x7fffffff
+ addu ta2, ta1
+
+ srl ta1, ta0, fd_shift # Put result register
+ andi ta1, 31
+ jal s_put_fpreg
+ j done
+2:
+3:
+
+ /* But then it might be a denorm or zero? */
+ S_is_E_min(ta1,ta2)
+ bnez ta2, 2f
+
+ /* Ok, it's a denorm or zero. */
+ S_get_F(ta1,ta2)
+ beqz ta2, 1f
+
+ /* It's a denorm. */
+ /* XXX Should be signaling inexact exception, if enabled. */
+ /* Fall through. */
+1:
+ /* Yes, it is a denorm or zero. Supply a zero as result. */
+ move ta2, zero
+ srl ta1, ta0, fd_shift # Put result register
+ andi ta1, 31
+ jal s_put_fpreg
+ j done
+2:
+
+ /* XXX Ok, it's a normal number. We don't handle that case yet.
+ If we have fp hardware this case is unreached. Add this for
+ full fp simulation. */
+
+ /* Done, return. */
+ lw ra, 16(sp)
+ addu sp, 16
+ jr ra
+
+/* Convert a double fp to a fixed point integer. */
+cvt.w.d:
+ srl ta1, ta0, fs_shift # Get source register
+ andi ta1, 31
+ jal d_get_fpreg
+
+ D_is_E_max(ta1,ta2,ta3,t0)
+ beqz ta3, 3f
+
+ /* Might be a NaN or Inf. */
+ D_get_F(ta1,ta2,ta3)
+ or ta3, ta2
+ beqz ta3, 2f
+
+ /* It's a NaN. IEEE says undefined. */
+ /* Is it a QNaN? Then the result is a QNaN as well. */
+ D_is_QNaN(ta1,ta2,ta3)
+ bltz ta3, 1f
+
+ /* XXX Ok, it's a SNaN. Signal invalid exception, if enabled.
+ For now we don't signal and supply a QNaN for result. */
+
+1: li ta2, W_QNaN
+ srl ta1, ta0, fd_shift # Put result register
+ andi ta1, 31
+ jal s_put_fpreg
+ j done
+2:
+
+ D_is_Inf(ta1,ta2,ta3)
+ bnez ta3, 2f
+
+ /* It's +/- Inf. Set register to +/- max. integer. */
+ /* XXX Send invalid operation exception instead, if enabled. */
+ srl ta1, ta1, 31 # Extract sign bit
+ li ta2, 0x7fffffff
+ addu ta2, ta1
+
+ srl ta1, ta0, fd_shift # Put result register
+ andi ta1, 31
+ jal s_put_fpreg
+ j done
+2:
+3:
+
+ /* But then it might be a denorm or zero? */
+ D_is_E_min(ta1,ta2,ta3)
+ bnez ta3, 2f
+
+ /* Ok, it's a denorm or zero. */
+ D_get_F(ta1,ta2,ta3)
+ or ta3, ta2
+ beqz ta3, 1f
+
+ /* It's a denorm. */
+ /* XXX Should be signaling inexact exception, if enabled. */
+ /* Fall through. */
+1:
+ /* Yes, it is a denorm or zero. Supply a zero as result. */
+ move ta2, zero
+ srl ta1, ta0, fd_shift # Put result register
+ andi ta1, 31
+ jal s_put_fpreg
+ j done
+2:
+
+ /* XXX Ok, it's a normal number. We don't handle that case yet.
+ If we have fp hardware this case is only reached if the value
+ of the source register exceeds the range which is representable
+ in a single precission register. For now we kludge by returning
+ +/- maxint and don't signal overflow. */
+
+ srl ta1, ta1, 31 # Extract sign bit
+ li ta2, 0x7fffffff
+ addu ta2, ta1
+
+ srl ta1, ta0, fd_shift # Put result register
+ andi ta1, 31
+ jal s_put_fpreg
+
+ /* Done, return. */
+ lw ra, 16(sp)
+ addu sp, 16
+ jr ra
+
+cvt.w.w = unimp # undefined result
+cvt.w.l = unimp # undefined result
+
+/* MIPS III extension, no need to handle for 32bit OS. */
+cvt.l = unimp
+
+/* ------------------------------------------------------------------------ */
+
+ BITCH(c.f)
+ BITCH(c.un)
+ BITCH(c.eq)
+ BITCH(c.ueq)
+ BITCH(c.olt)
+ BITCH(c.ult)
+ BITCH(c.ole)
+ BITCH(c.ule)
+ BITCH(c.sf)
+ BITCH(c.ngle)
+ BITCH(c.seq)
+ BITCH(c.ngl)
+ BITCH(c.lt)
+ BITCH(c.nge)
+ BITCH(c.le)
+ BITCH(c.ngt)
+
+/* Get the single precission register which's number is in ta1. */
+s_get_fpreg:
+ .set noat
+ sll AT, ta1, 2
+ sll ta1, 3
+ addu ta1, AT
+ la AT, 1f
+ addu AT, ta1
+ jr AT
+ .set at
+
+1: mfc1 ta1, $0
+ jr ra
+ mfc1 ta1, $1
+ jr ra
+ mfc1 ta1, $2
+ jr ra
+ mfc1 ta1, $3
+ jr ra
+ mfc1 ta1, $4
+ jr ra
+ mfc1 ta1, $5
+ jr ra
+ mfc1 ta1, $6
+ jr ra
+ mfc1 ta1, $7
+ jr ra
+ mfc1 ta1, $8
+ jr ra
+ mfc1 ta1, $9
+ jr ra
+ mfc1 ta1, $10
+ jr ra
+ mfc1 ta1, $11
+ jr ra
+ mfc1 ta1, $12
+ jr ra
+ mfc1 ta1, $13
+ jr ra
+ mfc1 ta1, $14
+ jr ra
+ mfc1 ta1, $15
+ jr ra
+ mfc1 ta1, $16
+ jr ra
+ mfc1 ta1, $17
+ jr ra
+ mfc1 ta1, $18
+ jr ra
+ mfc1 ta1, $19
+ jr ra
+ mfc1 ta1, $20
+ jr ra
+ mfc1 ta1, $21
+ jr ra
+ mfc1 ta1, $22
+ jr ra
+ mfc1 ta1, $23
+ jr ra
+ mfc1 ta1, $24
+ jr ra
+ mfc1 ta1, $25
+ jr ra
+ mfc1 ta1, $26
+ jr ra
+ mfc1 ta1, $27
+ jr ra
+ mfc1 ta1, $28
+ jr ra
+ mfc1 ta1, $29
+ jr ra
+ mfc1 ta1, $30
+ jr ra
+ mfc1 ta1, $31
+ jr ra
+
+/*
+ * Put the value in ta2 into the single precission register which's number
+ * is in ta1.
+ */
+s_put_fpreg:
+ .set noat
+ sll AT, ta1, 2
+ sll ta1, 3
+ addu ta1, AT
+ la AT, 1f
+ addu AT, ta1
+ jr AT
+ .set at
+
+1: mtc1 ta2, $0
+ jr ra
+ mtc1 ta2, $1
+ jr ra
+ mtc1 ta2, $2
+ jr ra
+ mtc1 ta2, $3
+ jr ra
+ mtc1 ta2, $4
+ jr ra
+ mtc1 ta2, $5
+ jr ra
+ mtc1 ta2, $6
+ jr ra
+ mtc1 ta2, $7
+ jr ra
+ mtc1 ta2, $8
+ jr ra
+ mtc1 ta2, $9
+ jr ra
+ mtc1 ta2, $10
+ jr ra
+ mtc1 ta2, $11
+ jr ra
+ mtc1 ta2, $12
+ jr ra
+ mtc1 ta2, $13
+ jr ra
+ mtc1 ta2, $14
+ jr ra
+ mtc1 ta2, $15
+ jr ra
+ mtc1 ta2, $16
+ jr ra
+ mtc1 ta2, $17
+ jr ra
+ mtc1 ta2, $18
+ jr ra
+ mtc1 ta2, $19
+ jr ra
+ mtc1 ta2, $20
+ jr ra
+ mtc1 ta2, $21
+ jr ra
+ mtc1 ta2, $22
+ jr ra
+ mtc1 ta2, $23
+ jr ra
+ mtc1 ta2, $24
+ jr ra
+ mtc1 ta2, $25
+ jr ra
+ mtc1 ta2, $26
+ jr ra
+ mtc1 ta2, $27
+ jr ra
+ mtc1 ta2, $28
+ jr ra
+ mtc1 ta2, $29
+ jr ra
+ mtc1 ta2, $30
+ jr ra
+ mtc1 ta2, $31
+ jr ra
+
+/* Get the double precission register which's number is in ta1 into ta1/ta2. */
+d_get_fpreg:
+ .set noat
+ sll ta1, 3
+ la AT, 1f
+ addu AT, ta1
+ jr AT
+ .set at
+
+1: mfc1 ta1, $0
+ mfc1 ta2, $1
+ jr ra
+ mfc1 ta1, $2
+ mfc1 ta2, $3
+ jr ra
+ mfc1 ta1, $4
+ mfc1 ta2, $5
+ jr ra
+ mfc1 ta1, $6
+ mfc1 ta2, $7
+ jr ra
+ mfc1 ta1, $8
+ mfc1 ta2, $9
+ jr ra
+ mfc1 ta1, $10
+ mfc1 ta2, $11
+ jr ra
+ mfc1 ta1, $12
+ mfc1 ta2, $13
+ jr ra
+ mfc1 ta1, $14
+ mfc1 ta2, $15
+ jr ra
+ mfc1 ta1, $16
+ mfc1 ta2, $17
+ jr ra
+ mfc1 ta1, $18
+ mfc1 ta2, $19
+ jr ra
+ mfc1 ta1, $20
+ mfc1 ta2, $21
+ jr ra
+ mfc1 ta1, $22
+ mfc1 ta2, $23
+ jr ra
+ mfc1 ta1, $24
+ mfc1 ta2, $25
+ jr ra
+ mfc1 ta1, $26
+ mfc1 ta2, $27
+ jr ra
+ mfc1 ta1, $28
+ mfc1 ta2, $29
+ jr ra
+ mfc1 ta1, $30
+ mfc1 ta2, $31
+ jr ra
+
+/*
+ * Send an invalid operation exception.
+ */
+invalid:
+ lw ra, 16(sp)
+ addu sp, 16
+ jr ra
+
+/*
+ * Done, just skip over the current instruction
+ */
+done:
+ lw ra, 16(sp)
+ addu sp, 16
+ jr ra
+
+unimp:
+ /* We've run into an yet unknown instruction. This happens either
+ on new, yet unsupported CPU types or when the faulting instruction
+ is being executed for cache but has been overwritten in memory. */
+ LOCK_KERNEL
+ move a0, ta0
+ PRINT(KERN_DEBUG "FP support: unknown fp op %08lx, ")
+ PRINT("please mail to ralf@gnu.org.\n")
+ UNLOCK_KERNEL
+
+ li a0, SIGILL # Die, sucker ...
+ move a1, $28
+ jal force_sig
+
+ lw ra, 16(sp)
+ addu sp, 16
+ jr ra
+
+/*
+ * Jump table for the lowest 6 bits of a cp1 instruction.
+ */
+ .data
+lowtab: .word add, sub, mul, div, sqrt, abs, mov, neg
+ .word round.l,trunc.l,ceil.l,floor.l,round.w,trunc.w,ceil.w,floor.w
+ .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
+ .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
+ .word cvt.s, cvt.d, unimp, unimp, cvt.w, cvt.l, unimp, unimp
+ .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
+ .word c.f, c.un, c.eq, c.ueq, c.olt, c.ult, c.ole, c.ule
+ .word c.sf, c.ngle,c.seq, c.ngl, c.lt, c.nge, c.le, c.ngt
diff --git a/arch/mips64/kernel/syscall.c b/arch/mips64/kernel/syscall.c
new file mode 100644
index 000000000..31273522c
--- /dev/null
+++ b/arch/mips64/kernel/syscall.c
@@ -0,0 +1,341 @@
+/* $Id: syscall.c,v 1.3 1999/10/19 20:51:46 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 - 1999 by Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+#include <linux/unistd.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <asm/ipc.h>
+#include <asm/cachectl.h>
+#include <asm/offset.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/stackframe.h>
+#include <asm/sysmips.h>
+#include <asm/uaccess.h>
+
+asmlinkage int sys_pipe(abi64_no_regargs, struct pt_regs regs)
+{
+ int fd[2];
+ int error, res;
+
+ lock_kernel();
+ error = do_pipe(fd);
+ if (error) {
+ res = error;
+ goto out;
+ }
+ regs.regs[3] = fd[1];
+ res = fd[0];
+out:
+ unlock_kernel();
+ return res;
+}
+
+asmlinkage unsigned long
+sys_mmap(unsigned long addr, size_t len, unsigned long prot,
+ unsigned long flags, unsigned long fd, off_t offset)
+{
+ struct file * file = NULL;
+ unsigned long error = -EFAULT;
+
+ down(&current->mm->mmap_sem);
+ lock_kernel();
+ if (!(flags & MAP_ANONYMOUS)) {
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ error = do_mmap(file, addr, len, prot, flags, offset);
+ if (file)
+ fput(file);
+out:
+ unlock_kernel();
+ up(&current->mm->mmap_sem);
+
+ return error;
+}
+
+asmlinkage int sys_fork(abi64_no_regargs, struct pt_regs regs)
+{
+ int res;
+
+ save_static(&regs);
+ res = do_fork(SIGCHLD, regs.regs[29], &regs);
+ return res;
+}
+
+asmlinkage int sys_clone(abi64_no_regargs, struct pt_regs regs)
+{
+ unsigned long clone_flags;
+ unsigned long newsp;
+ int res;
+
+ save_static(&regs);
+ clone_flags = regs.regs[4];
+ newsp = regs.regs[5];
+ if (!newsp)
+ newsp = regs.regs[29];
+ res = do_fork(clone_flags, newsp, &regs);
+ return res;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs)
+{
+ int error;
+ char * filename;
+
+ lock_kernel();
+ filename = getname((char *) (long)regs.regs[4]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, (char **) (long)regs.regs[5],
+ (char **) (long)regs.regs[6], &regs);
+ putname(filename);
+
+out:
+ unlock_kernel();
+ return error;
+}
+
+/*
+ * Compacrapability ...
+ */
+asmlinkage int sys_uname(struct old_utsname * name)
+{
+ if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+ return 0;
+ return -EFAULT;
+}
+
+/*
+ * Compacrapability ...
+ */
+asmlinkage int sys_olduname(struct oldold_utsname * name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+ return -EFAULT;
+
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+ error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+ error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+ error -= __put_user(0,name->release+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+ error -= __put_user(0,name->version+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+ error = __put_user(0,name->machine+__OLD_UTS_LEN);
+ error = error ? -EFAULT : 0;
+
+ return error;
+}
+
+/*
+ * Do the indirect syscall syscall.
+ *
+ * XXX This is borken.
+ */
+asmlinkage int sys_syscall(abi64_no_regargs, struct pt_regs regs)
+{
+ return -ENOSYS;
+}
+
+asmlinkage int
+sys_sysmips(int cmd, long arg1, int arg2, int arg3)
+{
+ int *p;
+ char *name;
+ int flags, tmp, len, errno;
+
+ switch(cmd)
+ {
+ case SETNAME:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ name = (char *) arg1;
+ len = strlen_user(name);
+
+ if (len == 0 || len > __NEW_UTS_LEN)
+ return -EINVAL;
+ down(&uts_sem);
+ errno = -EFAULT;
+ if (!copy_from_user(system_utsname.nodename, name, len)) {
+ system_utsname.nodename[len] = '\0';
+ errno = 0;
+ }
+ up(&uts_sem);
+ return errno;
+
+ case MIPS_ATOMIC_SET:
+ /* This is broken in case of page faults and SMP ...
+ Risc/OS fauls after maximum 20 tries with EAGAIN. */
+ p = (int *) arg1;
+ errno = verify_area(VERIFY_WRITE, p, sizeof(*p));
+ if (errno)
+ return errno;
+ save_and_cli(flags);
+ errno = *p;
+ *p = arg2;
+ restore_flags(flags);
+
+ return errno; /* This is broken ... */
+
+ case MIPS_FIXADE:
+ tmp = current->thread.mflags & ~3;
+ current->thread.mflags = tmp | (arg1 & 3);
+ return 0;
+
+ case FLUSH_CACHE:
+ flush_cache_all();
+ return 0;
+
+ case MIPS_RDNVRAM:
+ return -EIO;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second,
+ int third, void *ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ if (call <= SEMCTL)
+ switch (call) {
+ case SEMOP:
+ return sys_semop (first, (struct sembuf *)ptr, second);
+ case SEMGET:
+ return sys_semget (first, second, third);
+ case SEMCTL: {
+ union semun fourth;
+ if (!ptr)
+ return -EINVAL;
+ if (get_user(fourth.__pad, (void **) ptr))
+ return -EFAULT;
+ return sys_semctl (first, second, third, fourth);
+ }
+ default:
+ return -EINVAL;
+ }
+
+ if (call <= MSGCTL)
+ switch (call) {
+ case MSGSND:
+ return sys_msgsnd (first, (struct msgbuf *) ptr,
+ second, third);
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+ if (!ptr)
+ return -EINVAL;
+
+ if (copy_from_user(&tmp,
+ (struct ipc_kludge *) ptr,
+ sizeof (tmp)))
+ return -EFAULT;
+ return sys_msgrcv (first, tmp.msgp, second,
+ tmp.msgtyp, third);
+ }
+ default:
+ return sys_msgrcv (first,
+ (struct msgbuf *) ptr,
+ second, fifth, third);
+ }
+ case MSGGET:
+ return sys_msgget ((key_t) first, second);
+ case MSGCTL:
+ return sys_msgctl (first, second,
+ (struct msqid_ds *) ptr);
+ default:
+ return -EINVAL;
+ }
+ if (call <= SHMCTL)
+ switch (call) {
+ case SHMAT:
+ switch (version) {
+ default: {
+ ulong raddr;
+ ret = sys_shmat (first, (char *) ptr,
+ second, &raddr);
+ if (ret)
+ return ret;
+ return put_user (raddr, (ulong *) third);
+ }
+ case 1: /* iBCS2 emulator entry point */
+ if (!segment_eq(get_fs(), get_ds()))
+ return -EINVAL;
+ return sys_shmat (first, (char *) ptr,
+ second, (ulong *) third);
+ }
+ case SHMDT:
+ return sys_shmdt ((char *)ptr);
+ case SHMGET:
+ return sys_shmget (first, second, third);
+ case SHMCTL:
+ return sys_shmctl (first, second,
+ (struct shmid_ds *) ptr);
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * No implemented yet ...
+ */
+asmlinkage int
+sys_cachectl(char *addr, int nbytes, int op)
+{
+ return -ENOSYS;
+}
+
+/*
+ * If we ever come here the user sp is bad. Zap the process right away.
+ * Due to the bad stack signaling wouldn't work.
+ */
+asmlinkage void bad_stack(void)
+{
+ do_exit(SIGSEGV);
+}
diff --git a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c
index ea700e5ef..38f67b59b 100644
--- a/arch/mips64/kernel/traps.c
+++ b/arch/mips64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.1 1999/09/27 16:01:38 ralf Exp $
+/* $Id: traps.c,v 1.10 1999/11/23 17:12:49 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
@@ -15,6 +15,7 @@
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
#include <asm/branch.h>
#include <asm/cachectl.h>
@@ -25,15 +26,22 @@
#include <asm/system.h>
#include <asm/uaccess.h>
+extern int console_loglevel;
+
+static inline void console_silent(void)
+{
+ console_loglevel = 0;
+}
+
static inline void console_verbose(void)
{
- extern int console_loglevel;
- console_loglevel = 15;
+ if (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 __xtlb_mod_debug(void);
+extern asmlinkage void __xtlb_tlbl_debug(void);
+extern asmlinkage void __xtlb_tlbs_debug(void);
extern asmlinkage void handle_adel(void);
extern asmlinkage void handle_ades(void);
extern asmlinkage void handle_ibe(void);
@@ -53,6 +61,7 @@ static char *cpu_names[] = CPU_NAMES;
char watch_available = 0;
char dedicated_iv_available = 0;
char vce_available = 0;
+char mips4_available = 0;
void (*ibe_board_handler)(struct pt_regs *regs);
void (*dbe_board_handler)(struct pt_regs *regs);
@@ -161,12 +170,15 @@ void show_code(unsigned int *pc)
}
}
+spinlock_t die_lock;
+
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();
+ spin_lock_irq(&die_lock);
printk("%s: %04lx\n", str, err & 0xffff);
show_regs(regs);
printk("Process %s (pid: %ld, stackpage=%08lx)\n",
@@ -175,6 +187,7 @@ void die(const char * str, struct pt_regs * regs, unsigned long err)
show_trace((unsigned int *) regs->regs[29]);
show_code((unsigned int *) regs->cp0_epc);
printk("\n");
+ spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
@@ -357,10 +370,9 @@ void do_cpu(struct pt_regs *regs)
return;
if (current->used_math) { /* Using the FPU again. */
- r4xx0_lazy_fpu_switch(last_task_used_math);
+ lazy_fpu_switch(last_task_used_math);
} else { /* First time FPU user. */
-
- r4xx0_init_fpu();
+ init_fpu();
current->used_math = 1;
}
last_task_used_math = current;
@@ -416,6 +428,7 @@ static inline void watch_init(unsigned long cputype)
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);
@@ -433,7 +446,7 @@ unsigned long exception_handlers[32];
*/
void set_except_vector(int n, void *addr)
{
- unsigned handler = (unsigned long) addr;
+ unsigned long handler = (unsigned long) addr;
exception_handlers[n] = handler;
if (n == 0 && dedicated_iv_available) {
*(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
@@ -442,24 +455,38 @@ void set_except_vector(int n, void *addr)
}
}
-asmlinkage void (*save_fp_context)(struct sigcontext *sc);
-extern asmlinkage void r4k_save_fp_context(struct sigcontext *sc);
+static inline void mips4_setup(void)
+{
+ switch (mips_cputype) {
+ case CPU_R5000:
+ case CPU_R5000A:
+ case CPU_NEVADA:
+ case CPU_R8000:
+ case CPU_R10000:
+ mips4_available = 1;
+ set_cp0_status(ST0_XX, ST0_XX);
+ }
+ mips4_available = 0;
+}
-asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
-extern asmlinkage void r4k_restore_fp_context(struct sigcontext *sc);
+static inline void go_64(void)
+{
+ unsigned int bits;
-extern asmlinkage void *r4xx0_resume(void *last, void *next);
+ bits = ST0_KX|ST0_SX|ST0_UX;
+ set_cp0_status(bits, bits);
+ printk("Entering 64-bit mode.\n");
+}
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 __tlb_refill_debug_tramp;
+ extern char __xtlb_refill_debug_tramp;
+ extern char 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);
@@ -475,6 +502,8 @@ void __init trap_init(void)
*/
watch_init(mips_cputype);
setup_dedicated_int();
+ mips4_setup();
+ go_64(); /* In memoriam C128 ;-) */
/*
* Handling the following exceptions depends mostly of the cpu type
@@ -504,14 +533,11 @@ void __init trap_init(void)
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);
+ case CPU_R5000:
+ case CPU_NEVADA:
+ /* Debug TLB refill handler. */
+ memcpy((void *)KSEG0, &__tlb_refill_debug_tramp, 0x80);
+ memcpy((void *)KSEG0 + 0x080, &__xtlb_refill_debug_tramp, 0x80);
/* Cache error vector */
memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
@@ -524,12 +550,9 @@ void __init trap_init(void)
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(1, __xtlb_mod_debug);
+ set_except_vector(2, __xtlb_tlbl_debug);
+ set_except_vector(3, __xtlb_tlbs_debug);
set_except_vector(4, handle_adel);
set_except_vector(5, handle_ades);
@@ -559,4 +582,7 @@ void __init trap_init(void)
panic("Unknown CPU type");
}
flush_icache_range(KSEG0, KSEG0 + 0x200);
+
+ atomic_inc(&init_mm.mm_count); /* XXX UP? */
+ current->active_mm = &init_mm;
}
diff --git a/arch/mips64/kernel/unaligned.c b/arch/mips64/kernel/unaligned.c
new file mode 100644
index 000000000..22c1819eb
--- /dev/null
+++ b/arch/mips64/kernel/unaligned.c
@@ -0,0 +1,405 @@
+/* $Id: unaligned.c,v 1.2 1999/11/23 17:12:50 ralf Exp $
+ *
+ * Handle unaligned accesses by emulation.
+ *
+ * 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) 1996, 1998, 1999 by Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * This file contains exception handler for address error exception with the
+ * special capability to execute faulting instructions in software. The
+ * handler does not try to handle the case when the program counter points
+ * to an address not aligned to a word boundary.
+ *
+ * Putting data to unaligned addresses is a bad practice even on Intel where
+ * only the performance is affected. Much worse is that such code is non-
+ * portable. Due to several programs that die on MIPS due to alignment
+ * problems I decided to implement this handler anyway though I originally
+ * didn't intend to do this at all for user code.
+ *
+ * For now I enable fixing of address errors by default to make life easier.
+ * I however intend to disable this somewhen in the future when the alignment
+ * problems with user programs have been fixed. For programmers this is the
+ * right way to go.
+ *
+ * Fixing address errors is a per process option. The option is inherited
+ * across fork(2) and execve(2) calls. If you really want to use the
+ * option in your user programs - I discourage the use of the software
+ * emulation strongly - use the following code in your userland stuff:
+ *
+ * #include <sys/sysmips.h>
+ *
+ * ...
+ * sysmips(MIPS_FIXADE, x);
+ * ...
+ *
+ * The argument x is 0 for disabling software emulation, enabled otherwise.
+ *
+ * Below a little program to play around with this feature.
+ *
+ * #include <stdio.h>
+ * #include <asm/sysmips.h>
+ *
+ * struct foo {
+ * unsigned char bar[8];
+ * };
+ *
+ * main(int argc, char *argv[])
+ * {
+ * struct foo x = {0, 1, 2, 3, 4, 5, 6, 7};
+ * unsigned int *p = (unsigned int *) (x.bar + 3);
+ * int i;
+ *
+ * if (argc > 1)
+ * sysmips(MIPS_FIXADE, atoi(argv[1]));
+ *
+ * printf("*p = %08lx\n", *p);
+ *
+ * *p = 0xdeadface;
+ *
+ * for(i = 0; i <= 7; i++)
+ * printf("%02x ", x.bar[i]);
+ * printf("\n");
+ * }
+ *
+ * Coprocessor loads are not supported; I think this case is unimportant
+ * in the practice.
+ *
+ * TODO: Handle ndc (attempted store to doubleword in uncached memory)
+ * exception for the R6000.
+ * A store crossing a page boundary might be executed only partially.
+ * Undo the partial store in this case.
+ */
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+
+#define STR(x) __STR(x)
+#define __STR(x) #x
+
+/*
+ * User code may only access USEG; kernel code may access the
+ * entire address space.
+ */
+#define check_axs(p,a,s) \
+ if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \
+ goto sigbus;
+
+static inline void
+emulate_load_store_insn(struct pt_regs *regs,
+ unsigned long addr,
+ unsigned long pc)
+{
+ union mips_instruction insn;
+ unsigned long value, fixup;
+
+ regs->regs[0] = 0;
+ /*
+ * This load never faults.
+ */
+ __get_user(insn.word, (unsigned int *)pc);
+
+ switch (insn.i_format.opcode) {
+ /*
+ * These are instructions that a compiler doesn't generate. We
+ * can assume therefore that the code is MIPS-aware and
+ * really buggy. Emulating these instructions would break the
+ * semantics anyway.
+ */
+ case ll_op:
+ case lld_op:
+ case sc_op:
+ case scd_op:
+
+ /*
+ * For these instructions the only way to create an address
+ * error is an attempted access to kernel/supervisor address
+ * space.
+ */
+ case ldl_op:
+ case ldr_op:
+ case lwl_op:
+ case lwr_op:
+ case sdl_op:
+ case sdr_op:
+ case swl_op:
+ case swr_op:
+ case lb_op:
+ case lbu_op:
+ case sb_op:
+ goto sigbus;
+
+ /*
+ * The remaining opcodes are the ones that are really of interest.
+ */
+ case lh_op:
+ check_axs(pc, addr, 2);
+ __asm__(
+ ".set\tnoat\n"
+#ifdef __BIG_ENDIAN
+ "1:\tlb\t%0,0(%1)\n"
+ "2:\tlbu\t$1,1(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlb\t%0,1(%1)\n"
+ "2:\tlbu\t$1,0(%1)\n\t"
+#endif
+ "sll\t%0,0x8\n\t"
+ "or\t%0,$1\n\t"
+ ".set\tat\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ :"=&r" (value)
+ :"r" (addr), "i" (&&fault)
+ :"$1");
+ regs->regs[insn.i_format.rt] = value;
+ return;
+
+ case lw_op:
+ check_axs(pc, addr, 4);
+ __asm__(
+#ifdef __BIG_ENDIAN
+ "1:\tlwl\t%0,(%1)\n"
+ "2:\tlwr\t%0,3(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlwl\t%0,3(%1)\n"
+ "2:\tlwr\t%0,(%1)\n\t"
+#endif
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ :"=&r" (value)
+ :"r" (addr), "i" (&&fault));
+ regs->regs[insn.i_format.rt] = value;
+ return;
+
+ case lhu_op:
+ check_axs(pc, addr, 2);
+ __asm__(
+ ".set\tnoat\n"
+#ifdef __BIG_ENDIAN
+ "1:\tlbu\t%0,0(%1)\n"
+ "2:\tlbu\t$1,1(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlbu\t%0,1(%1)\n"
+ "2:\tlbu\t$1,0(%1)\n\t"
+#endif
+ "sll\t%0,0x8\n\t"
+ "or\t%0,$1\n\t"
+ ".set\tat\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ :"=&r" (value)
+ :"r" (addr), "i" (&&fault)
+ :"$1");
+ regs->regs[insn.i_format.rt] = value;
+ return;
+
+ case lwu_op:
+ check_axs(pc, addr, 4);
+ __asm__(
+#ifdef __BIG_ENDIAN
+ "1:\tlwl\t%0,(%1)\n"
+ "2:\tlwr\t%0,3(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlwl\t%0,3(%1)\n"
+ "2:\tlwr\t%0,(%1)\n\t"
+#endif
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ :"=&r" (value)
+ :"r" (addr), "i" (&&fault));
+ value &= 0xffffffff;
+ regs->regs[insn.i_format.rt] = value;
+ return;
+
+ case ld_op:
+ check_axs(pc, addr, 8);
+ __asm__(
+ ".set\tmips3\n"
+#ifdef __BIG_ENDIAN
+ "1:\tldl\t%0,(%1)\n"
+ "2:\tldr\t%0,7(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tldl\t%0,7(%1)\n"
+ "2:\tldr\t%0,(%1)\n\t"
+#endif
+ ".set\tmips0\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ :"=&r" (value)
+ :"r" (addr), "i" (&&fault));
+ regs->regs[insn.i_format.rt] = value;
+ return;
+
+ case sh_op:
+ check_axs(pc, addr, 2);
+ value = regs->regs[insn.i_format.rt];
+ __asm__(
+#ifdef __BIG_ENDIAN
+ ".set\tnoat\n"
+ "1:\tsb\t%0,1(%1)\n\t"
+ "srl\t$1,%0,0x8\n"
+ "2:\tsb\t$1,0(%1)\n\t"
+ ".set\tat\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ ".set\tnoat\n"
+ "1:\tsb\t%0,0(%1)\n\t"
+ "srl\t$1,%0,0x8\n"
+ "2:\tsb\t$1,1(%1)\n\t"
+ ".set\tat\n\t"
+#endif
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ : /* no outputs */
+ :"r" (value), "r" (addr), "i" (&&fault)
+ :"$1");
+ return;
+
+ case sw_op:
+ check_axs(pc, addr, 4);
+ value = regs->regs[insn.i_format.rt];
+ __asm__(
+#ifdef __BIG_ENDIAN
+ "1:\tswl\t%0,(%1)\n"
+ "2:\tswr\t%0,3(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tswl\t%0,3(%1)\n"
+ "2:\tswr\t%0,(%1)\n\t"
+#endif
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ : /* no outputs */
+ :"r" (value), "r" (addr), "i" (&&fault));
+ return;
+
+ case sd_op:
+ check_axs(pc, addr, 8);
+ value = regs->regs[insn.i_format.rt];
+ __asm__(
+ ".set\tmips3\n"
+#ifdef __BIG_ENDIAN
+ "1:\tsdl\t%0,(%1)\n"
+ "2:\tsdr\t%0,7(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tsdl\t%0,7(%1)\n"
+ "2:\tsdr\t%0,(%1)\n\t"
+#endif
+ ".set\tmips0\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b,%2\n\t"
+ STR(PTR)"\t2b,%2\n\t"
+ ".previous"
+ : /* no outputs */
+ :"r" (value), "r" (addr), "i" (&&fault));
+ return;
+
+ case lwc1_op:
+ case ldc1_op:
+ case swc1_op:
+ case sdc1_op:
+ /*
+ * I herewith declare: this does not happen. So send SIGBUS.
+ */
+ goto sigbus;
+
+ case lwc2_op:
+ case ldc2_op:
+ case swc2_op:
+ case sdc2_op:
+ /*
+ * These are the coprocessor 2 load/stores. The current
+ * implementations don't use cp2 and cp2 should always be
+ * disabled in c0_status. So send SIGILL.
+ * (No longer true: The Sony Praystation uses cp2 for
+ * 3D matrix operations. Dunno if that thingy has a MMU ...)
+ */
+ default:
+ /*
+ * Pheeee... We encountered an yet unknown instruction or
+ * cache coherence problem. Die sucker, die ...
+ */
+ goto sigill;
+ }
+ return;
+
+fault:
+ /* Did we have an exception handler installed? */
+ fixup = search_exception_table(regs->cp0_epc);
+ if (fixup) {
+ long new_epc;
+ new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
+ printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)\n",
+ current->comm, regs->cp0_epc, new_epc);
+ regs->cp0_epc = new_epc;
+ return;
+ }
+
+ send_sig(SIGSEGV, current, 1);
+ return;
+sigbus:
+ send_sig(SIGBUS, current, 1);
+ return;
+sigill:
+ send_sig(SIGILL, current, 1);
+ return;
+}
+
+unsigned long unaligned_instructions;
+
+asmlinkage void do_ade(abi64_no_regargs, struct pt_regs regs)
+{
+ unsigned long pc;
+
+ /*
+ * Did we catch a fault trying to load an instruction?
+ * This also catches attempts to activate MIPS16 code on
+ * CPUs which don't support it.
+ */
+ if (regs.cp0_badvaddr == regs.cp0_epc)
+ goto sigbus;
+
+ pc = regs.cp0_epc + ((regs.cp0_cause & CAUSEF_BD) ? 4 : 0);
+ if (compute_return_epc(&regs))
+ return;
+ if ((current->thread.mflags & MF_FIXADE) == 0)
+ goto sigbus;
+
+ emulate_load_store_insn(&regs, regs.cp0_badvaddr, pc);
+ unaligned_instructions++;
+
+ return;
+
+sigbus:
+ force_sig(SIGBUS, current);
+}
diff --git a/arch/mips64/ld.script.elf32 b/arch/mips64/ld.script.elf32
index f5878cb35..2ae26c104 100644
--- a/arch/mips64/ld.script.elf32
+++ b/arch/mips64/ld.script.elf32
@@ -37,14 +37,30 @@ SECTIONS
_etext = .;
PROVIDE (etext = .);
+ . = ALIGN(16384);
+ .data.init_task : { *(.data.init_task) }
+
/* Startup code */
. = ALIGN(4096);
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { *(.setup.init) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
. = ALIGN(4096); /* Align double page for init_task_union */
__init_end = .;
+ . = ALIGN(4096);
+ .data.page_aligned : { *(.data.idt) }
+
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
.fini : { *(.fini) } =0
.reginfo : { *(.reginfo) }
/* Adjust the address for the data segment. We want to adjust up to
diff --git a/arch/mips64/lib/Makefile b/arch/mips64/lib/Makefile
index f916d7263..3e61ae79e 100644
--- a/arch/mips64/lib/Makefile
+++ b/arch/mips64/lib/Makefile
@@ -1,4 +1,4 @@
-# $Id$
+# $Id: Makefile,v 1.2 1999/11/19 20:35:22 ralf Exp $
#
# Makefile for MIPS-specific library files..
#
@@ -11,6 +11,7 @@
L_TARGET = lib.a
L_OBJS = csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \
- rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o watch.o
+ rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o \
+ strnlen_user.o watch.o
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/lib/csum_partial.S b/arch/mips64/lib/csum_partial.S
index 9d31bba49..27147065a 100644
--- a/arch/mips64/lib/csum_partial.S
+++ b/arch/mips64/lib/csum_partial.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: csum_partial.S,v 1.1 1999/08/21 21:43:00 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
diff --git a/arch/mips64/lib/csum_partial_copy.c b/arch/mips64/lib/csum_partial_copy.c
index 235bdbfaa..9f08f405a 100644
--- a/arch/mips64/lib/csum_partial_copy.c
+++ b/arch/mips64/lib/csum_partial_copy.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: csum_partial_copy.c,v 1.1 1999/08/21 21:43:00 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
diff --git a/arch/mips64/lib/dump_tlb.c b/arch/mips64/lib/dump_tlb.c
index 0d563cbb6..27d5bd45d 100644
--- a/arch/mips64/lib/dump_tlb.c
+++ b/arch/mips64/lib/dump_tlb.c
@@ -1,8 +1,8 @@
/*
* Dump R4x00 TLB for debugging purposes.
*
- * Copyright (C) 1994, 1995 by Waldorf Electronics,
- * written by Ralf Baechle.
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
*/
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -15,22 +15,18 @@
#include <asm/page.h>
#include <asm/pgtable.h>
-static char *region_map [] = {
- "u", "s", "k", "!"
-};
+#define mips_tlb_entries 48
void
dump_tlb(int first, int last)
{
int i;
- int wired;
- unsigned int pagemask, c0, c1, r;
- unsigned long long entryhi, entrylo0, entrylo1;
+ unsigned int pagemask, c0, c1, asid;
+ unsigned long entryhi, entrylo0, entrylo1;
- wired = read_32bit_cp0_register(CP0_WIRED);
- printk("Wired: %d", wired);
-
- for(i=first;i<last;i++)
+ asid = get_entryhi() & 0xff;
+
+ for(i=first;i<=last;i++)
{
write_32bit_cp0_register(CP0_INDEX, i);
__asm__ __volatile__(
@@ -42,30 +38,31 @@ dump_tlb(int first, int last)
".set\treorder\n\t"
".set\tmips0\n\t");
pagemask = read_32bit_cp0_register(CP0_PAGEMASK);
- entryhi = read_64bit_cp0_register(CP0_ENTRYHI);
- entrylo0 = read_64bit_cp0_register(CP0_ENTRYLO0);
- entrylo1 = read_64bit_cp0_register(CP0_ENTRYLO1);
+ entryhi = read_32bit_cp0_register(CP0_ENTRYHI);
+ entrylo0 = read_32bit_cp0_register(CP0_ENTRYLO0);
+ entrylo1 = read_32bit_cp0_register(CP0_ENTRYLO1);
- if((entrylo0|entrylo1) & 2)
- {
+ /* Unused entries have a virtual address of KSEG0. */
+ if ((entryhi & 0xffffe000) != 0x80000000
+ && (entryhi & 0xff) == asid) {
/*
* Only print entries in use
*/
- printk("\nIndex: %2d pgmask=%08x ", i, pagemask);
+ printk("Index: %2d pgmask=%08x ", i, pagemask);
- r = entryhi >> 62;
c0 = (entrylo0 >> 3) & 7;
c1 = (entrylo1 >> 3) & 7;
- printk("%s vpn2=%08Lx "
- "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]"
- "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]",
- region_map [r], (entryhi >> 13) & 0xffffffff,
- (entrylo0 >> 6) & 0xffffff, c0,
+ printk("va=%08lx asid=%08lx"
+ " [pa=%06lx c=%d d=%d v=%d g=%ld]"
+ " [pa=%06lx c=%d d=%d v=%d g=%ld]",
+ (entryhi & 0xffffe000),
+ entryhi & 0xff,
+ entrylo0 & PAGE_MASK, c0,
(entrylo0 & 4) ? 1 : 0,
(entrylo0 & 2) ? 1 : 0,
(entrylo0 & 1),
- (entrylo1 >> 6) & 0xffffff, c1,
+ entrylo1 & PAGE_MASK, c1,
(entrylo1 & 4) ? 1 : 0,
(entrylo1 & 2) ? 1 : 0,
(entrylo1 & 1));
@@ -73,6 +70,8 @@ dump_tlb(int first, int last)
}
}
printk("\n");
+
+ set_entryhi(asid);
}
void
@@ -84,9 +83,45 @@ dump_tlb_all(void)
void
dump_tlb_wired(void)
{
+ int wired;
+
+ wired = read_32bit_cp0_register(CP0_WIRED);
+ printk("Wired: %d", wired);
dump_tlb(0, read_32bit_cp0_register(CP0_WIRED));
}
+#define BARRIER \
+ __asm__ __volatile__( \
+ ".set\tnoreorder\n\t" \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ ".set\treorder");
+
+void
+dump_tlb_addr(unsigned long addr)
+{
+ unsigned int flags, oldpid;
+ int index;
+
+ __save_and_cli(flags);
+ oldpid = get_entryhi() & 0xff;
+ BARRIER;
+ set_entryhi((addr & PAGE_MASK) | oldpid);
+ BARRIER;
+ tlb_probe();
+ BARRIER;
+ index = get_index();
+ set_entryhi(oldpid);
+ __restore_flags(flags);
+
+ if (index < 0) {
+ printk("No entry for address 0x%08lx in TLB\n", addr);
+ return;
+ }
+
+ printk("Entry %d maps address 0x%08lx\n", index, addr);
+ dump_tlb(index, index);
+}
+
void
dump_tlb_nonwired(void)
{
@@ -99,30 +134,39 @@ dump_list_process(struct task_struct *t, void *address)
pgd_t *page_dir, *pgd;
pmd_t *pmd;
pte_t *pte, page;
- unsigned long addr;
+ unsigned int addr;
+ unsigned long val;
- addr = (unsigned long) address;
+ addr = (unsigned int) address;
- printk("Addr == %08lx\n", addr);
- printk("tasks->thread.pg_dir == %08lx\n",
- (unsigned long) t->thread.pg_dir);
- printk("tasks->mm.pgd == %08lx\n",
- (unsigned long) t->mm->pgd);
+ printk("Addr == %08x\n", addr);
+ printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
page_dir = pgd_offset(t->mm, 0);
- printk("page_dir == %08lx\n", (unsigned long) page_dir);
+ printk("page_dir == %08x\n", (unsigned int) page_dir);
pgd = pgd_offset(t->mm, addr);
- printk("pgd == %08lx, ", (unsigned long) pgd);
+ printk("pgd == %08x, ", (unsigned int) pgd);
pmd = pmd_offset(pgd, addr);
- printk("pmd == %08lx, ", (unsigned long) pmd);
+ printk("pmd == %08x, ", (unsigned int) pmd);
pte = pte_offset(pmd, addr);
- printk("pte == %08lx, ", (unsigned long) pte);
+ printk("pte == %08x, ", (unsigned int) pte);
page = *pte;
- printk("page == %08lx\n", (unsigned long) pte_val(page));
+ printk("page == %08x\n", (unsigned int) pte_val(page));
+
+ val = pte_val(page);
+ if (val & _PAGE_PRESENT) printk("present ");
+ if (val & _PAGE_READ) printk("read ");
+ if (val & _PAGE_WRITE) printk("write ");
+ if (val & _PAGE_ACCESSED) printk("accessed ");
+ if (val & _PAGE_MODIFIED) printk("modified ");
+ if (val & _PAGE_R4KBUG) printk("r4kbug ");
+ if (val & _PAGE_GLOBAL) printk("global ");
+ if (val & _PAGE_VALID) printk("valid ");
+ printk("\n");
}
void
@@ -131,13 +175,13 @@ dump_list_current(void *address)
dump_list_process(current, address);
}
-unsigned long
+unsigned int
vtop(void *address)
{
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- unsigned long addr, paddr;
+ unsigned int addr, paddr;
addr = (unsigned long) address;
pgd = pgd_offset(current->mm, addr);
@@ -154,7 +198,8 @@ dump16(unsigned long *p)
{
int i;
- for(i=0; i<8; i++) {
+ for(i=0;i<8;i++)
+ {
printk("*%08lx == %08lx, ",
(unsigned long)p, (unsigned long)*p++);
printk("*%08lx == %08lx\n",
diff --git a/arch/mips64/lib/floppy-no.c b/arch/mips64/lib/floppy-no.c
index 45b174a03..f0cd72d28 100644
--- a/arch/mips64/lib/floppy-no.c
+++ b/arch/mips64/lib/floppy-no.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: floppy-no.c,v 1.1 1999/08/21 21:43:00 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
diff --git a/arch/mips64/lib/floppy-std.c b/arch/mips64/lib/floppy-std.c
index 77d7298ae..88dbfdbc1 100644
--- a/arch/mips64/lib/floppy-std.c
+++ b/arch/mips64/lib/floppy-std.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: floppy-std.c,v 1.1 1999/08/21 21:43:00 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
diff --git a/arch/mips64/lib/ide-no.c b/arch/mips64/lib/ide-no.c
index 6fdadc7df..7a7833db7 100644
--- a/arch/mips64/lib/ide-no.c
+++ b/arch/mips64/lib/ide-no.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ide-no.c,v 1.1 1999/08/21 21:43:00 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
diff --git a/arch/mips64/lib/ide-std.c b/arch/mips64/lib/ide-std.c
index 1538ffde9..f80f7d5ea 100644
--- a/arch/mips64/lib/ide-std.c
+++ b/arch/mips64/lib/ide-std.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ide-std.c,v 1.1 1999/08/21 21:43:00 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
diff --git a/arch/mips64/lib/kbd-no.c b/arch/mips64/lib/kbd-no.c
index 5da1be2b7..0120e9ba4 100644
--- a/arch/mips64/lib/kbd-no.c
+++ b/arch/mips64/lib/kbd-no.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: kbd-no.c,v 1.1 1999/08/21 21:43:00 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
diff --git a/arch/mips64/lib/kbd-std.c b/arch/mips64/lib/kbd-std.c
index 1a1bbcbf7..a35a0c5c8 100644
--- a/arch/mips64/lib/kbd-std.c
+++ b/arch/mips64/lib/kbd-std.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: kbd-std.c,v 1.1 1999/08/21 21:43: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
diff --git a/arch/mips64/lib/memcpy.S b/arch/mips64/lib/memcpy.S
index 8efad1581..9f44b4b8b 100644
--- a/arch/mips64/lib/memcpy.S
+++ b/arch/mips64/lib/memcpy.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: memcpy.S,v 1.2 1999/10/19 20:51:51 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
@@ -93,7 +93,7 @@
.set noat
.align 5
-LEAF(memcpy) /* a0=dst a1=src a2=len */
+LEAF(xxmemcpy) /* a0=dst a1=src a2=len */
move v0, a0 /* return value */
__memcpy:
EXPORT(__copy_user)
@@ -365,7 +365,7 @@ u_end_bytes:
jr ra
move a2, zero
- END(memcpy)
+ END(xxmemcpy)
/* descending order, destination aligned */
#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \
@@ -406,14 +406,14 @@ u_end_bytes:
usw t3, (offset + 0x0c)(dst)
.align 5
-LEAF(memmove)
+LEAF(xxmemmove)
sltu ta0, a0, a1 # dst < src -> memcpy
- bnez ta0, memcpy
+ bnez ta0, xxmemcpy
daddu v0, a0, a2
sltu ta0, v0, a1 # dst + len < src -> non-
bnez ta0, __memcpy # overlapping, can use memcpy
move v0, a0 /* return value */
- END(memmove)
+ END(xxmemmove)
LEAF(__rmemcpy) /* a0=dst a1=src a2=len */
daddu a0, a2 # dst = dst + len
diff --git a/arch/mips64/lib/memset.S b/arch/mips64/lib/memset.S
index 25afb2c89..56dc72160 100644
--- a/arch/mips64/lib/memset.S
+++ b/arch/mips64/lib/memset.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: memset.S,v 1.2 1999/10/19 20:51:51 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
@@ -36,7 +36,7 @@
*/
.set noreorder
.align 5
-LEAF(memset)
+LEAF(xxmemset)
beqz a1, 1f
move v0, a0 /* result */
@@ -109,7 +109,7 @@ small_memset:
2: jr ra /* done */
move a2, zero
- END(memset)
+ END(xxmemset)
first_fixup:
jr ra
diff --git a/arch/mips64/lib/rtc-no.c b/arch/mips64/lib/rtc-no.c
index c471da824..808033648 100644
--- a/arch/mips64/lib/rtc-no.c
+++ b/arch/mips64/lib/rtc-no.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: rtc-no.c,v 1.1 1999/08/21 21:43: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
diff --git a/arch/mips64/lib/rtc-std.c b/arch/mips64/lib/rtc-std.c
index 7369db07d..a4a6ead81 100644
--- a/arch/mips64/lib/rtc-std.c
+++ b/arch/mips64/lib/rtc-std.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: rtc-std.c,v 1.1 1999/08/21 21:43: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
diff --git a/arch/mips64/lib/strlen_user.S b/arch/mips64/lib/strlen_user.S
index da37c0c2a..bb4347c02 100644
--- a/arch/mips64/lib/strlen_user.S
+++ b/arch/mips64/lib/strlen_user.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: strlen_user.S,v 1.2 1999/11/19 20:35:22 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
@@ -23,24 +23,23 @@
*
* Return 0 for error
*/
-LEAF(__strlen_user_nocheck_asm)
- LONG_L v0, THREAD_CURDS($28) # pointer ok?
- LONG_SUBU v0, zero, v0
- and v0, a0
- not v0
- beqz v0, fault
-EXPORT(__strlen_user_asm)
- move v0, a0
-1: EX(lb, t0, (v0), fault)
- LONG_ADDIU v0, 1
- bnez t0, 1b
- LONG_SUBU v0, a0
- jr ra
- END(__strlen_user_nocheck_asm)
+LEAF(__strlen_user_asm)
+ ld v0, THREAD_CURDS($28) # pointer ok?
+ and v0, a0
+ bltz v0, fault
+
+EXPORT(__strlen_user_nocheck_asm)
+ move v0, a0
+1: EX(lb, ta0, (v0), fault)
+ daddiu v0, 1
+ bnez ta0, 1b
+ dsubu v0, a0
+ jr ra
+ END(__strlen_user_asm)
.section __ex_table,"a"
PTR 1b, fault
.previous
-fault: move v0, zero
- jr ra
+fault: move v0, zero
+ jr ra
diff --git a/arch/mips64/lib/strncpy_user.S b/arch/mips64/lib/strncpy_user.S
index aad14c263..d30046cae 100644
--- a/arch/mips64/lib/strncpy_user.S
+++ b/arch/mips64/lib/strncpy_user.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: strncpy_user.S,v 1.2 1999/11/19 20:35:23 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
@@ -29,32 +29,31 @@
*/
LEAF(__strncpy_from_user_asm)
- LONG_L v0, THREAD_CURDS($28) # pointer ok?
- LONG_SUBU v0, zero, v0
- and v0, a1
- not v0
- beqz v0, fault
+ ld v0, THREAD_CURDS($28) # pointer ok?
+ and v0, a1
+ bltz v0, fault
+
EXPORT(__strncpy_from_user_nocheck_asm)
- move v0,zero
- move v1,a1
- .set noreorder
-1: EX(lbu, t0, (v1), fault)
- LONG_ADDIU v1,1
- beqz t0,2f
- sb t0,(a0)
- LONG_ADDIU v0,1
- bne v0,a2,1b
- LONG_ADDIU a0,1
- .set reorder
-2: LONG_ADDU t0,a1,v0
- xor t0,a1
- bltz t0,fault
- jr ra # return n
+ move v0, zero
+ move v1, a1
+ .set noreorder
+1: EX(lbu, ta0, (v1), fault)
+ daddiu v1, 1
+ beqz ta0, 2f
+ sb ta0, (a0)
+ daddiu v0, 1
+ bne v0, a2, 1b
+ daddiu a0, 1
+ .set reorder
+2: daddu ta0, a1, v0
+ xor ta0, a1
+ bltz ta0, fault
+ jr ra # return n
END(__strncpy_from_user_asm)
-fault: li v0, -EFAULT
- jr ra
+fault: li v0, -EFAULT
+ jr ra
.section __ex_table,"a"
- PTR 1b, fault
+ PTR 1b, fault
.previous
diff --git a/arch/mips64/lib/strnlen_user.S b/arch/mips64/lib/strnlen_user.S
new file mode 100644
index 000000000..9df7e5e87
--- /dev/null
+++ b/arch/mips64/lib/strnlen_user.S
@@ -0,0 +1,47 @@
+/* $Id: strnlen_user.S,v 1.1 1999/11/19 20:35:23 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) 1996, 1998, 1999 by Ralf Baechle
+ * Copyright (c) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+#include <asm/sgidefs.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error, len on string but at max a1 otherwise
+ */
+LEAF(__strnlen_user_asm)
+ ld v0, THREAD_CURDS($28) # pointer ok?
+ and v0, ta0
+ bltz v0, fault
+
+EXPORT(__strnlen_user_nocheck_asm)
+ move v0, a0
+ daddu a1, a0 # stop pointer
+1: beq v0, a1, 1f # limit reached?
+ EX(lb, ta0, (v0), fault)
+ daddiu v0, 1
+ bnez ta0, 1b
+1: dsubu v0, a0
+ jr ra
+ END(__strnlen_user_asm)
+
+ .section __ex_table,"a"
+ PTR 1b, fault
+ .previous
+
+fault: move v0, zero
+ jr ra
diff --git a/arch/mips64/lib/watch.S b/arch/mips64/lib/watch.S
index ee9559522..3f3d18c6e 100644
--- a/arch/mips64/lib/watch.S
+++ b/arch/mips64/lib/watch.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: watch.S,v 1.1 1999/08/21 21:43: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
diff --git a/arch/mips64/mm/Makefile b/arch/mips64/mm/Makefile
index dc9459a41..17100d9f6 100644
--- a/arch/mips64/mm/Makefile
+++ b/arch/mips64/mm/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 1999/08/18 23:37:47 ralf Exp $
+# $Id: Makefile,v 1.2 1999/08/20 21:13:33 ralf Exp $
#
# Makefile for the Linux/MIPS-specific parts of the memory manager.
#
diff --git a/arch/mips64/mm/andes.c b/arch/mips64/mm/andes.c
index e048a1203..dec5940c8 100644
--- a/arch/mips64/mm/andes.c
+++ b/arch/mips64/mm/andes.c
@@ -1,4 +1,4 @@
-/* $Id: andes.c,v 1.1 1999/08/18 23:37:47 ralf Exp $
+/* $Id: andes.c,v 1.3 1999/11/23 17:12:50 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
@@ -89,11 +89,6 @@ andes_load_pgd(unsigned long pg_dir)
{
}
-static void
-andes_pgd_init(unsigned long page)
-{
-}
-
static int
andes_user_mode(struct pt_regs *regs)
{
@@ -117,7 +112,6 @@ void __init ld_mmu_andes(void)
user_mode = andes_user_mode;
load_pgd = andes_load_pgd;
- pgd_init = andes_pgd_init;
flush_cache_all();
flush_tlb_all();
diff --git a/arch/mips64/mm/extable.c b/arch/mips64/mm/extable.c
index 7a7ab27ea..f9ae91ae0 100644
--- a/arch/mips64/mm/extable.c
+++ b/arch/mips64/mm/extable.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: extable.c,v 1.2 1999/11/23 17:12:50 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
@@ -14,7 +14,7 @@
extern const struct exception_table_entry __start___ex_table[];
extern const struct exception_table_entry __stop___ex_table[];
-static inline unsigned
+static inline unsigned long
search_one_table(const struct exception_table_entry *first,
const struct exception_table_entry *last,
unsigned long value)
diff --git a/arch/mips64/mm/fault.c b/arch/mips64/mm/fault.c
index 09fbedbff..b7091a83d 100644
--- a/arch/mips64/mm/fault.c
+++ b/arch/mips64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.2 1999/09/28 22:25:52 ralf Exp $
+/* $Id: fault.c,v 1.5 1999/11/23 17:12:50 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,8 +45,7 @@ unsigned long asid_cache;
* routines.
*/
asmlinkage void
-do_page_fault(struct pt_regs *regs, unsigned long write,
- unsigned long address)
+do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address)
{
struct vm_area_struct * vma;
struct task_struct *tsk = current;
@@ -147,6 +146,7 @@ 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]);
+while(1);
die("Oops", regs, write);
do_exit(SIGKILL);
diff --git a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c
index 6a0e3c195..2b889669c 100644
--- a/arch/mips64/mm/init.c
+++ b/arch/mips64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.3 1999/08/20 21:59:05 ralf Exp $
+/* $Id: init.c,v 1.5 1999/11/23 17:12:50 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
@@ -49,11 +49,92 @@ void __bad_pte(pmd_t *pmd)
pmd_set(pmd, BAD_PAGETABLE);
}
+/* Fixme, we need something like BAD_PMDTABLE ... */
+void __bad_pmd(pgd_t *pgd)
+{
+ printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
+ pgd_set(pgd, (pmd_t *) BAD_PAGETABLE);
+}
+
+extern inline void pgd_init(unsigned long page)
+{
+ unsigned long *p, *end;
+
+ p = (unsigned long *) page;
+ end = p + PTRS_PER_PGD;
+
+ while (p < end) {
+ p[0] = (unsigned long) invalid_pmd_table;
+ p[1] = (unsigned long) invalid_pmd_table;
+ p[2] = (unsigned long) invalid_pmd_table;
+ p[3] = (unsigned long) invalid_pmd_table;
+ p[4] = (unsigned long) invalid_pmd_table;
+ p[5] = (unsigned long) invalid_pmd_table;
+ p[6] = (unsigned long) invalid_pmd_table;
+ p[7] = (unsigned long) invalid_pmd_table;
+ p += 8;
+ }
+}
+
+pgd_t *get_pgd_slow(void)
+{
+ pgd_t *ret, *init;
+
+ ret = (pgd_t *) __get_free_pages(GFP_KERNEL, 1);
+ if (ret) {
+ init = pgd_offset(&init_mm, 0);
+ pgd_init((unsigned long)ret);
+ }
+ return ret;
+}
+
+extern inline void pmd_init(unsigned long addr)
+{
+ unsigned long *p, *end;
+
+ p = (unsigned long *) addr;
+ end = p + PTRS_PER_PMD;
+
+ while (p < end) {
+ p[0] = (unsigned long) invalid_pte_table;
+ p[1] = (unsigned long) invalid_pte_table;
+ p[2] = (unsigned long) invalid_pte_table;
+ p[3] = (unsigned long) invalid_pte_table;
+ p[4] = (unsigned long) invalid_pte_table;
+ p[5] = (unsigned long) invalid_pte_table;
+ p[6] = (unsigned long) invalid_pte_table;
+ p[7] = (unsigned long) invalid_pte_table;
+ p += 8;
+ }
+}
+
+pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
+{
+ pmd_t *pmd;
+
+ pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 1);
+ if (pgd_none(*pgd)) {
+ if (pmd) {
+ pmd_init((unsigned long)pmd);
+ pgd_set(pgd, pmd);
+ return pmd + offset;
+ }
+ pgd_set(pgd, BAD_PMDTABLE);
+ return NULL;
+ }
+ free_page((unsigned long)pmd);
+ if (pgd_bad(*pgd)) {
+ __bad_pmd(pgd);
+ return NULL;
+ }
+ return (pmd_t *) pgd_page(*pgd) + offset;
+}
+
pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
{
pte_t *page;
- page = (pte_t *) __get_free_page(GFP_USER);
+ page = (pte_t *) __get_free_pages(GFP_USER, 1);
if (pmd_none(*pmd)) {
if (page) {
clear_page((unsigned long)page);
@@ -75,7 +156,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
{
pte_t *page;
- page = (pte_t *) __get_free_page(GFP_KERNEL);
+ page = (pte_t *) __get_free_pages(GFP_KERNEL, 1);
if (pmd_none(*pmd)) {
if (page) {
clear_page((unsigned long)page);
@@ -85,7 +166,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
pmd_set(pmd, BAD_PAGETABLE);
return NULL;
}
- free_page((unsigned long)page);
+ free_pages((unsigned long)page, 1);
if (pmd_bad(*pmd)) {
__bad_pte(pmd);
return NULL;
@@ -93,6 +174,23 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
return (pte_t *) pmd_page(*pmd) + offset;
}
+int do_check_pgt_cache(int low, int high)
+{
+ int freed = 0;
+
+ if (pgtable_cache_size > high) {
+ do {
+ if (pgd_quicklist)
+ free_pgd_slow(get_pgd_fast()), freed++;
+ if (pmd_quicklist)
+ free_pmd_slow(get_pmd_fast()), freed++;
+ if (pte_quicklist)
+ free_pte_slow(get_pte_fast()), freed++;
+ } while (pgtable_cache_size > low);
+ }
+ return freed;
+}
+
asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
{
@@ -143,21 +241,19 @@ static inline unsigned long setup_zero_pages(void)
return size;
}
-int do_check_pgt_cache(int low, int high)
+extern inline void pte_init(unsigned long page)
{
- int freed = 0;
+ unsigned long *p, *end, bp;
- if(pgtable_cache_size > high) {
- do {
- if(pgd_quicklist)
- free_pgd_slow(get_pgd_fast()), freed++;
- if(pmd_quicklist)
- free_pmd_slow(get_pmd_fast()), freed++;
- if(pte_quicklist)
- free_pte_slow(get_pte_fast()), freed++;
- } while(pgtable_cache_size > low);
+ bp = pte_val(BAD_PAGE);
+ p = (unsigned long *) page;
+ end = p + PTRS_PER_PTE;
+
+ while (p < end) {
+ p[0] = p[1] = p[2] = p[3] =
+ p[4] = p[5] = p[6] = p[7] = bp;
+ p += 8;
}
- return freed;
}
/*
@@ -173,27 +269,24 @@ int do_check_pgt_cache(int low, int high)
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
+pmd_t * __bad_pmd_table(void)
+{
+ extern pmd_t invalid_pmd_table[PTRS_PER_PMD];
+ unsigned long page;
+
+ page = (unsigned long) invalid_pmd_table;
+ pte_init(page);
+
+ return (pmd_t *) page;
+}
+
pte_t * __bad_pagetable(void)
{
extern char empty_bad_page_table[PAGE_SIZE];
- unsigned long dummy1, dummy2, page;
+ unsigned long page;
page = (unsigned long) empty_bad_page_table;
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "dsll\t$1, %1, 32\n\t"
- "dsrl\t%1, $1, 32\n\t"
- "or\t%1, $1\n\t"
- "daddiu\t$1, %0, %4\n"
- "1:\tdaddiu\t%0, 8\n\t"
- "bne\t$1, %0, 1b\n\t"
- " sd\t%1, -8(%0)\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1), "=r" (dummy2)
- :"0" (page), "1" (pte_val(BAD_PAGE)), "i" (PAGE_SIZE)
- :"$1");
+ pte_init(page);
return (pte_t *) page;
}
@@ -231,7 +324,7 @@ void show_mem(void)
printk("%d reserved pages\n", reserved);
printk("%d pages shared\n", shared);
printk("%d pages swap cached\n",cached);
- printk("%ld pages in page table cache\n",pgtable_cache_size);
+ printk("%ld pages in page table cache\n", pgtable_cache_size);
printk("%d free pages\n", free);
#ifdef CONFIG_NET
show_net_buffers();
@@ -246,6 +339,7 @@ paging_init(unsigned long start_mem, unsigned long end_mem)
/* Initialize the entire pgd. */
pgd_init((unsigned long)swapper_pg_dir);
pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2);
+ pmd_init((unsigned long)invalid_pmd_table);
return free_area_init(start_mem, end_mem);
}
diff --git a/arch/mips64/mm/loadmmu.c b/arch/mips64/mm/loadmmu.c
index 0c9be7291..3053b9dbd 100644
--- a/arch/mips64/mm/loadmmu.c
+++ b/arch/mips64/mm/loadmmu.c
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.1 1999/08/18 23:37:48 ralf Exp $
+/* $Id: loadmmu.c,v 1.6 1999/11/23 17:12:50 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
@@ -46,7 +46,6 @@ void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page);
/* Miscellaneous. */
void (*load_pgd)(unsigned long pg_dir);
-void (*pgd_init)(unsigned long page);
void (*update_mmu_cache)(struct vm_area_struct * vma,
unsigned long address, pte_t pte);
@@ -54,15 +53,11 @@ void (*show_regs)(struct pt_regs *);
int (*user_mode)(struct pt_regs *);
-asmlinkage void *(*resume)(void *last, void *next);
-
-extern void ld_mmu_r2300(void);
extern void ld_mmu_r4xx0(void);
-extern void ld_mmu_r6000(void);
extern void ld_mmu_tfp(void);
extern void ld_mmu_andes(void);
-void __init loadmmu(void)
+void __init load_mmu(void)
{
switch(mips_cputype) {
case CPU_R4000PC:
diff --git a/arch/mips64/mm/r4xx0.c b/arch/mips64/mm/r4xx0.c
index b026dc4a6..4cd61e19b 100644
--- a/arch/mips64/mm/r4xx0.c
+++ b/arch/mips64/mm/r4xx0.c
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.3 1999/09/28 22:25:52 ralf Exp $
+/* $Id: r4xx0.c,v 1.6 1999/11/23 17:12:50 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
@@ -21,6 +21,7 @@
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
#include <asm/mmu_context.h>
/* CP0 hazard avoidance. */
@@ -798,10 +799,8 @@ r4k_flush_cache_range_s16d16i16(struct mm_struct *mm, unsigned long start,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int text;
__save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
pmd = pmd_offset(pgd, start);
@@ -838,10 +837,8 @@ r4k_flush_cache_range_s32d16i16(struct mm_struct *mm, unsigned long start,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int text;
save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
pmd = pmd_offset(pgd, start);
@@ -878,10 +875,8 @@ r4k_flush_cache_range_s64d16i16(struct mm_struct *mm, unsigned long start,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int text;
save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
pmd = pmd_offset(pgd, start);
@@ -918,10 +913,8 @@ r4k_flush_cache_range_s128d16i16(struct mm_struct *mm, unsigned long start,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int text;
save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
pmd = pmd_offset(pgd, start);
@@ -958,10 +951,8 @@ r4k_flush_cache_range_s32d32i32(struct mm_struct *mm, unsigned long start,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int text;
save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
pmd = pmd_offset(pgd, start);
@@ -998,10 +989,8 @@ r4k_flush_cache_range_s64d32i32(struct mm_struct *mm, unsigned long start,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int text;
save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
pmd = pmd_offset(pgd, start);
@@ -1038,10 +1027,8 @@ r4k_flush_cache_range_s128d32i32(struct mm_struct *mm, unsigned long start,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int text;
save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
while(start < end) {
pgd = pgd_offset(mm, start);
pmd = pmd_offset(pgd, start);
@@ -2142,23 +2129,6 @@ static void r4k_load_pgd(unsigned long pg_dir)
{
}
-static void r4k_pgd_init(unsigned long page)
-{
- unsigned long *p = (unsigned long *) page;
- int i;
-
- for(i = 0; i < USER_PTRS_PER_PGD; i+=8) {
- p[i + 0] = (unsigned long) invalid_pte_table;
- p[i + 1] = (unsigned long) invalid_pte_table;
- p[i + 2] = (unsigned long) invalid_pte_table;
- p[i + 3] = (unsigned long) invalid_pte_table;
- p[i + 4] = (unsigned long) invalid_pte_table;
- p[i + 5] = (unsigned long) invalid_pte_table;
- p[i + 6] = (unsigned long) invalid_pte_table;
- p[i + 7] = (unsigned long) invalid_pte_table;
- }
-}
-
#ifdef DEBUG_TLBUPDATE
static unsigned long ehi_debug[NTLB_ENTRIES];
static unsigned long el0_debug[NTLB_ENTRIES];
@@ -2243,29 +2213,34 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
}
#endif
-static void r4k_show_regs(struct pt_regs * regs)
+static void r4k_show_regs(struct pt_regs *regs)
{
/* Saved main processor registers. */
- printk("$0 : %08lx %08lx %08lx %08lx\n",
+ printk("$0 : %016lx %016lx %016lx %016lx\n",
0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
- printk("$4 : %08lx %08lx %08lx %08lx\n",
+ printk("$4 : %016lx %016lx %016lx %016lx\n",
regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
- printk("$8 : %08lx %08lx %08lx %08lx\n",
+ printk("$8 : %016lx %016lx %016lx %016lx\n",
regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
- printk("$12: %08lx %08lx %08lx %08lx\n",
+ printk("$12 : %016lx %016lx %016lx %016lx\n",
regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
- printk("$16: %08lx %08lx %08lx %08lx\n",
+ printk("$16 : %016lx %016lx %016lx %016lx\n",
regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
- printk("$20: %08lx %08lx %08lx %08lx\n",
+ printk("$20 : %016lx %016lx %016lx %016lx\n",
regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
- printk("$24: %08lx %08lx\n",
+ printk("$24 : %016lx %016lx\n",
regs->regs[24], regs->regs[25]);
- printk("$28: %08lx %08lx %08lx %08lx\n",
+ printk("$28 : %016lx %016lx %016lx %016lx\n",
regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
+ printk("Hi : %016lx\n", regs->hi);
+ printk("Lo : %016lx\n", regs->lo);
/* Saved cp0 registers. */
- printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n",
- regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
+ printk("epc : %016lx\nbadvaddr: %016lx\n",
+ regs->cp0_epc, regs->cp0_badvaddr);
+ printk("Status : %08x\nCause : %08x\n",
+ (unsigned int) regs->cp0_status, (unsigned int) regs->cp0_cause);
+//{static int x = 3; x--; if(!x) while(1);}
}
/* Detect and size the various r4k caches. */
@@ -2546,7 +2521,6 @@ void __init ld_mmu_r4xx0(void)
flush_tlb_page = r4k_flush_tlb_page;
load_pgd = r4k_load_pgd;
- pgd_init = r4k_pgd_init;
update_mmu_cache = r4k_update_mmu_cache;
show_regs = r4k_show_regs;
diff --git a/arch/mips64/mm/tfp.c b/arch/mips64/mm/tfp.c
index 46345a40e..517a617b0 100644
--- a/arch/mips64/mm/tfp.c
+++ b/arch/mips64/mm/tfp.c
@@ -1,4 +1,4 @@
-/* $Id: tfp.c,v 1.2 1999/08/21 22:19:16 ralf Exp $
+/* $Id: tfp.c,v 1.4 1999/11/23 17:12:50 ralf Exp $
*
* tfp.c: MMU and cache routines specific to the r8000 (TFP).
*
@@ -78,10 +78,6 @@ static void tfp_load_pgd(unsigned long pg_dir)
{
}
-static void tfp_pgd_init(unsigned long page)
-{
-}
-
static int tfp_user_mode(struct pt_regs *regs)
{
return (regs->cp0_status & ST0_KSU) == KSU_USER;
@@ -104,7 +100,6 @@ void __init ld_mmu_tfp(void)
user_mode = tfp_user_mode;
load_pgd = tfp_load_pgd;
- pgd_init = tfp_pgd_init;
flush_cache_all();
flush_tlb_all();
diff --git a/arch/mips64/mm/umap.c b/arch/mips64/mm/umap.c
index 90d6f19fd..847cc8cb3 100644
--- a/arch/mips64/mm/umap.c
+++ b/arch/mips64/mm/umap.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: umap.c,v 1.1 1999/08/18 21:46:52 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
diff --git a/arch/mips64/sgi-ip22/Makefile b/arch/mips64/sgi-ip22/Makefile
index 476432a99..8e03f3d9a 100644
--- a/arch/mips64/sgi-ip22/Makefile
+++ b/arch/mips64/sgi-ip22/Makefile
@@ -1,4 +1,4 @@
-# $Id$
+# $Id: Makefile,v 1.1 1999/08/20 21:13:33 ralf Exp $
#
# Makefile for the SGI specific kernel interface routines
# under Linux.
diff --git a/arch/mips64/sgi-ip22/ip22-hpc.c b/arch/mips64/sgi-ip22/ip22-hpc.c
index c3019e8bf..5e42803c1 100644
--- a/arch/mips64/sgi-ip22/ip22-hpc.c
+++ b/arch/mips64/sgi-ip22/ip22-hpc.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-hpc.c,v 1.2 1999/10/19 20:51:52 ralf Exp $
*
* ip22-hpc.c: Routines for generic manipulation of the HPC controllers.
*
@@ -6,6 +6,7 @@
* Copyright (C) 1998, 1999 Ralf Baechle
*/
#include <linux/init.h>
+#include <linux/types.h>
#include <asm/addrspace.h>
#include <asm/sgi/sgihpc.h>
@@ -18,7 +19,7 @@ struct hpc3_regs *hpc3c0, *hpc3c1;
struct hpc3_miscregs *hpc3mregs;
/* We need software copies of these because they are write only. */
-unsigned long sgi_hpc_write1, sgi_hpc_write2;
+unsigned int sgi_hpc_write1, sgi_hpc_write2;
/* Machine specific identifier knobs. */
int sgi_has_ioc2 = 0;
diff --git a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c
index e6fe49354..765c90da1 100644
--- a/arch/mips64/sgi-ip22/ip22-int.c
+++ b/arch/mips64/sgi-ip22/ip22-int.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-int.c,v 1.4 1999/11/19 20:35:23 ralf Exp $
*
* indy_int.c: Routines for generic manipulation of the INT[23] ASIC
* found on INDY workstations..
@@ -259,8 +259,6 @@ int get_irq_list(char *buf)
return len;
}
-atomic_t __mips_bh_counter;
-
/*
* do_IRQ handles IRQ's that have been installed without the
* SA_INTERRUPT flag: it uses the full signal-handling return
@@ -279,7 +277,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
printk("Got irq %d, press a key.", irq);
prom_getchar();
- romvec->imode();
+ ArcEnterInteractiveMode();
/*
* mask and ack quickly, we don't want the irq controller
diff --git a/arch/mips64/sgi-ip22/ip22-irq.S b/arch/mips64/sgi-ip22/ip22-irq.S
index 9f4234598..e943d3e30 100644
--- a/arch/mips64/sgi-ip22/ip22-irq.S
+++ b/arch/mips64/sgi-ip22/ip22-irq.S
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-irq.S,v 1.1 1999/08/20 21:13:33 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
diff --git a/arch/mips64/sgi-ip22/ip22-mc.c b/arch/mips64/sgi-ip22/ip22-mc.c
index aa43afe28..be8a91a0a 100644
--- a/arch/mips64/sgi-ip22/ip22-mc.c
+++ b/arch/mips64/sgi-ip22/ip22-mc.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-mc.c,v 1.2 1999/10/19 20:51:52 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
@@ -20,7 +20,7 @@
/* #define DEBUG_SGIMC */
struct sgimc_misc_ctrl *mcmisc_regs;
-unsigned long *rpsscounter;
+u32 *rpsscounter;
struct sgimc_dma_ctrl *dmactrlregs;
static inline char *mconfig_string(unsigned long val)
@@ -54,7 +54,7 @@ void __init sgimc_init(void)
unsigned long tmpreg;
mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000);
- rpsscounter = (unsigned long *) (KSEG1 + 0x1fa01004);
+ rpsscounter = (u32 *) (KSEG1 + 0x1fa01004);
dmactrlregs = (struct sgimc_dma_ctrl *) (KSEG1+0x1fa02000);
printk("MC: SGI memory controller Revision %d\n",
diff --git a/arch/mips64/sgi-ip22/ip22-reset.c b/arch/mips64/sgi-ip22/ip22-reset.c
index cd521291f..7146076d1 100644
--- a/arch/mips64/sgi-ip22/ip22-reset.c
+++ b/arch/mips64/sgi-ip22/ip22-reset.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-reset.c,v 1.3 1999/10/08 21:07:51 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
@@ -15,7 +15,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/reboot.h>
#include <asm/sgialib.h>
#include <asm/sgi/sgihpc.h>
#include <asm/sgi/sgint23.h>
@@ -38,26 +37,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 ip22_machine_restart(char *command) __attribute__((noreturn));
-static void ip22_machine_halt(void) __attribute__((noreturn));
-static void ip22_machine_power_off(void) __attribute__((noreturn));
+void machine_restart(char *command) __attribute__((noreturn));
+void machine_halt(void) __attribute__((noreturn));
+void machine_power_off(void) __attribute__((noreturn));
/* XXX How to pass the reboot command to the firmware??? */
-static void ip22_machine_restart(char *command)
+void machine_restart(char *command)
{
if (shuting_down)
- ip22_machine_power_off();
+ machine_power_off();
ArcReboot();
}
-static void ip22_machine_halt(void)
+void machine_halt(void)
{
if (shuting_down)
- ip22_machine_power_off();
+ machine_power_off();
ArcEnterInteractiveMode();
}
-static void ip22_machine_power_off(void)
+void machine_power_off(void)
{
struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS;
@@ -79,7 +78,7 @@ static void ip22_machine_power_off(void)
static void power_timeout(unsigned long data)
{
- ip22_machine_power_off();
+ machine_power_off();
}
static void blink_timeout(unsigned long data)
@@ -118,7 +117,7 @@ static inline void power_button(void)
if (shuting_down || kill_proc(1, SIGINT, 1)) {
/* No init process or button pressed twice. */
- ip22_machine_power_off();
+ machine_power_off();
}
shuting_down = 1;
@@ -235,10 +234,6 @@ void ip22_reboot_setup(void)
return;
setup_done = 1;
- _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);
blink_timer.function = blink_timeout;
diff --git a/arch/mips64/sgi-ip22/ip22-rtc.c b/arch/mips64/sgi-ip22/ip22-rtc.c
index f138ff27f..eca3bcaab 100644
--- a/arch/mips64/sgi-ip22/ip22-rtc.c
+++ b/arch/mips64/sgi-ip22/ip22-rtc.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-rtc.c,v 1.1 1999/08/20 21:13:34 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
diff --git a/arch/mips64/sgi-ip22/ip22-sc.c b/arch/mips64/sgi-ip22/ip22-sc.c
index 6c48e5611..92e6bf4d3 100644
--- a/arch/mips64/sgi-ip22/ip22-sc.c
+++ b/arch/mips64/sgi-ip22/ip22-sc.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-sc.c,v 1.3 1999/10/20 18:10:24 ralf Exp $
*
* indy_sc.c: Indy cache managment functions.
*
@@ -33,31 +33,16 @@ static unsigned long scache_size;
static inline void indy_sc_wipe(unsigned long first, unsigned long last)
{
- unsigned long tmp;
-
__asm__ __volatile__("
.set noreorder
- .set mips3
- .set noat
- mfc0 %2, $12
- li $1, 0x80 # Go 64 bit
- mtc0 $1, $12
-
- dli $1, 0x9000000080000000
- or %0, $1 # first line to flush
- or %1, $1 # last line to flush
- .set at
-
+ or %0, %4 # first line to flush
+ or %1, %4 # last line to flush
1: sw $0, 0(%0)
bne %0, %1, 1b
daddu %0, 32
-
- mtc0 %2, $12 # Back to 32 bit
- nop; nop; nop; nop;
- .set mips0
.set reorder"
- : "=r" (first), "=r" (last), "=&r" (tmp)
- : "0" (first), "1" (last)
+ : "=r" (first), "=r" (last)
+ : "0" (first), "1" (last), "r" (0x9000000080000000)
: "$1");
}
@@ -88,78 +73,33 @@ out:
__restore_flags(flags);
}
-static void indy_sc_enable(void)
+static void inline indy_sc_enable(void)
{
- unsigned long tmp1, tmp2, tmp3;
-
- /* This is really cool... */
#ifdef DEBUG_CACHE
printk("Enabling R4600 SCACHE\n");
#endif
- __asm__ __volatile__("
- .set push
- .set noreorder
- .set mips3
- mfc0 %2, $12
- nop; nop; nop; nop;
- li %1, 0x80
- mtc0 %1, $12
- nop; nop; nop; nop;
- li %0, 0x1
- dsll %0, 31
- lui %1, 0x9000
- dsll32 %1, 0
- or %0, %1, %0
- sb $0, 0(%0)
- mtc0 $0, $12
- nop; nop; nop; nop;
- mtc0 %2, $12
- nop; nop; nop; nop;
- .set pop"
- : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
+ *(volatile unsigned char *) 0x9000000080000000 = 0;
}
static void indy_sc_disable(void)
{
- unsigned long tmp1, tmp2, tmp3;
-
#ifdef DEBUG_CACHE
printk("Disabling R4600 SCACHE\n");
#endif
- __asm__ __volatile__("
- .set push
- .set noreorder
- .set mips3
- li %0, 0x1
- dsll %0, 31
- lui %1, 0x9000
- dsll32 %1, 0
- or %0, %1, %0
- mfc0 %2, $12
- nop; nop; nop; nop;
- li %1, 0x80
- mtc0 %1, $12
- nop; nop; nop; nop;
- sh $0, 0(%0)
- mtc0 $0, $12
- nop; nop; nop; nop;
- mtc0 %2, $12
- nop; nop; nop; nop;
- .set pop"
- : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
+ *(volatile unsigned short *) 0x9000000080000000 = 0;
}
static inline __init int indy_sc_probe(void)
{
- volatile unsigned int *cpu_control;
+ volatile u32 *cpu_control;
unsigned short cmd = 0xc220;
unsigned long data = 0;
int i, n;
#ifdef __MIPSEB__
- cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034);
+ cpu_control = (volatile u32 *) KSEG1ADDR(0x1fa00034);
#else
- cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030);
+ cpu_control = (volatile u32 *) KSEG1ADDR(0x1fa00030);
#endif
#define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
#define ASSERT(bit) (*(cpu_control) |= (bit))
@@ -211,7 +151,7 @@ static inline __init int indy_sc_probe(void)
/* XXX Check with wje if the Indy caches can differenciate between
writeback + invalidate and just invalidate. */
-struct bcache_ops indy_sc_ops = {
+static struct bcache_ops indy_sc_ops = {
indy_sc_enable,
indy_sc_disable,
indy_sc_wback_invalidate,
@@ -220,6 +160,7 @@ struct bcache_ops indy_sc_ops = {
void __init indy_sc_init(void)
{
+return; /* Not for now, debugging ... */
if (indy_sc_probe()) {
indy_sc_enable();
bcops = &indy_sc_ops;
diff --git a/arch/mips64/sgi-ip22/ip22-setup.c b/arch/mips64/sgi-ip22/ip22-setup.c
index c3c41c387..a1ae065d8 100644
--- a/arch/mips64/sgi-ip22/ip22-setup.c
+++ b/arch/mips64/sgi-ip22/ip22-setup.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-setup.c,v 1.4 1999/10/08 21:07:51 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
@@ -26,7 +26,6 @@
#include <asm/bcache.h>
#include <asm/keyboard.h>
#include <asm/irq.h>
-#include <asm/reboot.h>
#include <asm/sgialib.h>
#include <asm/sgi/sgi.h>
#include <asm/sgi/sgimc.h>
diff --git a/arch/mips64/sgi-ip22/ip22-timer.c b/arch/mips64/sgi-ip22/ip22-timer.c
index 3302ba1a7..633bf0ef8 100644
--- a/arch/mips64/sgi-ip22/ip22-timer.c
+++ b/arch/mips64/sgi-ip22/ip22-timer.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: ip22-timer.c,v 1.3 1999/10/19 20:51:52 ralf Exp $
*
* indy_timer.c: Setting up the clock on the INDY 8254 controller.
*
@@ -228,15 +228,13 @@ void __init indy_timer_init(void)
struct sgi_ioc_timers *p;
volatile unsigned char *tcwp, *tc2p;
- /* Figure out the r4k offset, the algorithm is very simple
- * and works in _all_ cases as long as the 8254 counter
- * register itself works ok (as an interrupt driving timer
- * it does not because of bug, this is why we are using
- * the onchip r4k counter/compare register to serve this
- * purpose, but for r4k_offset calculation it will work
- * ok for us). There are other very complicated ways
- * of performing this calculation but this one works just
- * fine so I am not going to futz around. ;-)
+ /* Figure out the r4k offset, the algorithm is very simple and works
+ * in _all_ cases as long as the 8254 counter register itself works ok
+ * (as an interrupt driving timer it does not because of bug, this is
+ * why we are using the onchip r4k counter/compare register to serve
+ * this purpose, but for r4k_offset calculation it will work ok for us).
+ * There are other very complicated ways of performing this calculation
+ * but this one works just fine so I am not going to futz around. ;-)
*/
p = ioc_timers;
tcwp = &p->tcword;
diff --git a/arch/mips64/sgi-ip22/system.c b/arch/mips64/sgi-ip22/system.c
index bd2a313f0..ce8b81085 100644
--- a/arch/mips64/sgi-ip22/system.c
+++ b/arch/mips64/sgi-ip22/system.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: system.c,v 1.3 1999/10/19 20:51:52 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
@@ -49,7 +49,7 @@ static int __init string_to_cpu(char *s)
prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s);
prom_printf("press a key to reboot\n");
prom_getchar();
- romvec->imode();
+ ArcEnterInteractiveMode();
return 0;
}
@@ -78,7 +78,7 @@ void __init sgi_sysinit(void)
prom_printf("\nYeee, SGI MP not ready yet\n");
prom_printf("press a key to reboot\n");
prom_getchar();
- romvec->imode();
+ ArcEnterInteractiveMode();
}
printk("CPU: %s ", p->iname);
cpup = p;
@@ -90,7 +90,7 @@ void __init sgi_sysinit(void)
prom_printf("\nYeee, could not find cpu ARCS component\n");
prom_printf("press a key to reboot\n");
prom_getchar();
- romvec->imode();
+ ArcEnterInteractiveMode();
}
p = ArcGetChild(cpup);
while(p) {
diff --git a/arch/mips64/sgi-ip22/time.c b/arch/mips64/sgi-ip22/time.c
index 5d1d907de..27a104d00 100644
--- a/arch/mips64/sgi-ip22/time.c
+++ b/arch/mips64/sgi-ip22/time.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: time.c,v 1.1 1999/08/20 21:13:34 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
diff --git a/arch/mips64/tools/Makefile b/arch/mips64/tools/Makefile
index 6e82a2dcc..6a7d7de6b 100644
--- a/arch/mips64/tools/Makefile
+++ b/arch/mips64/tools/Makefile
@@ -1,4 +1,4 @@
-# $Id$
+# $Id: Makefile,v 1.1 1999/08/18 21:46:53 ralf Exp $
#
# Makefile for MIPS kernel build tools.
#
diff --git a/arch/mips64/tools/offset.c b/arch/mips64/tools/offset.c
index 2d5eae28f..4f8e28d09 100644
--- a/arch/mips64/tools/offset.c
+++ b/arch/mips64/tools/offset.c
@@ -1,9 +1,8 @@
-/* $Id: offset.c,v 1.2 1999/09/28 22:25:54 ralf Exp $
+/* $Id: offset.c,v 1.5 1999/10/08 21:07:52 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.
*/
@@ -111,7 +110,6 @@ void output_thread_defines(void)
offset("#define THREAD_ECODE ", struct task_struct, \
thread.error_code);
offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no);
- offset("#define THREAD_PGDIR ", struct task_struct, thread.pg_dir);
offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags);
offset("#define THREAD_CURDS ", struct task_struct, \
thread.current_ds);
@@ -125,7 +123,7 @@ void output_thread_defines(void)
void output_mm_defines(void)
{
text("/* Linux mm_struct offsets. */");
- offset("#define MM_USERS ", struct mm_struct, users);
+ offset("#define MM_USERS ", struct mm_struct, mm_users);
offset("#define MM_PGD ", struct mm_struct, pgd);
offset("#define MM_CONTEXT ", struct mm_struct, context);
linefeed;