diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-12-04 03:58:56 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-12-04 03:58:56 +0000 |
commit | 1d67e90f19a7acfd9a05dc59678e7d0c5090bd0d (patch) | |
tree | 357efc7b93f8f5102110d20d293f41360ec212fc /arch/mips64 | |
parent | aea27b2e18d69af87e673972246e66657b4fa274 (diff) |
Merge with Linux 2.3.21.
Diffstat (limited to 'arch/mips64')
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], ¤t->thread.fpu, sizeof(current->thread.fpu)); + memcpy(&dump->regs[EF_SIZE/4], ¤t->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(®s); + 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(¤t->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(¤t->mm->mmap_sem); + + return error; +} + +asmlinkage int sys_fork(abi64_no_regargs, struct pt_regs regs) +{ + int res; + + save_static(®s); + res = do_fork(SIGCHLD, regs.regs[29], ®s); + return res; +} + +asmlinkage int sys_clone(abi64_no_regargs, struct pt_regs regs) +{ + unsigned long clone_flags; + unsigned long newsp; + int res; + + save_static(®s); + clone_flags = regs.regs[4]; + newsp = regs.regs[5]; + if (!newsp) + newsp = regs.regs[29]; + res = do_fork(clone_flags, newsp, ®s); + 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], ®s); + 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(®s)) + return; + if ((current->thread.mflags & MF_FIXADE) == 0) + goto sigbus; + + emulate_load_store_insn(®s, 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; |