diff options
Diffstat (limited to 'arch/mips64')
41 files changed, 2087 insertions, 199 deletions
diff --git a/arch/mips64/Makefile b/arch/mips64/Makefile index 20685e5e3..6879aca98 100644 --- a/arch/mips64/Makefile +++ b/arch/mips64/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.3 1999/10/19 20:51:44 ralf Exp $ +# $Id: Makefile,v 1.3 1999/12/04 03:59: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 @@ -77,6 +77,18 @@ SUBDIRS += arch/mips64/sgi-ip22 arch/mips64/arc LOADADDR += 0x88004000 endif +ifdef CONFIG_SGI_IP27 +LIBS += arch/mips64/sgi-ip27/ip27.a arch/mips64/arc/arclib.a +SUBDIRS += arch/mips64/sgi-ip27 arch/mips64/arc +# +# Set LOADADDR to >= 0xc000000000300000 if you want to leave space for +# symmon, 0xc00000000001c000 for production kernels. Note that the value +# must be 16kb aligned or the handling of the current variable will break. +# +#LOADADDR += 0xa80000000001c000 +LOADADDR += 0x8001c000 +endif + # # Some machines like the Indy need 32-bit ELF binaries for booting purposes. # Other need ECOFF, so we build a 32-bit ELF binary for them which we then @@ -86,6 +98,17 @@ ifdef CONFIG_BOOT_ELF32 CFLAGS += -Wa,-32 LINKFLAGS += -T arch/mips64/ld.script.elf32 endif +# +# The 64-bit ELF tools are pretty broken so at this time we generate 64-bit +# ELF files from 32-bit files by conversion. +# +ifdef CONFIG_BOOT_ELF64 +CFLAGS += -Wa,-32 +LINKFLAGS += -T arch/mips64/ld.script.elf32 +#AS += -64 +#LD += -m elf64bmip +#LINKFLAGS += -T arch/mips64/ld.script.elf64 +endif LINKFLAGS += -Ttext $(LOADADDR) @@ -97,6 +120,15 @@ LIBS := arch/mips64/lib/lib.a $(LIBS) MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +ifdef CONFIG_CPU_LITTLE_ENDIAN +64bit-bfd = elf64-littlemips +else +64bit-bfd = elf64-bigmips +endif + +vmlinux.64: vmlinux + $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@ + zImage: vmlinux @$(MAKEBOOT) zImage diff --git a/arch/mips64/arc/Makefile b/arch/mips64/arc/Makefile index 471ff92a1..039caf88d 100644 --- a/arch/mips64/arc/Makefile +++ b/arch/mips64/arc/Makefile @@ -1,23 +1,14 @@ # $Id: Makefile,v 1.1 1999/08/20 21:13:32 ralf Exp $ -# Makefile for the SGI arcs prom monitor library routines -# under Linux. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). +# Makefile for the ARC prom monitor library routines under Linux. # -# Note 2! The CFLAGS definitions are now in the main makefile... -OBJS = console.o init.o printf.o memory.o tree.o env.o \ - cmdline.o misc.o time.o file.o identify.o +L_TARGET = arclib.a +L_OBJS = console.o init.o printf.o tree.o env.o cmdline.o misc.o time.o \ + file.o identify.o -all: arclib.a - -arclib.a: $(OBJS) - $(AR) rcs arclib.a $(OBJS) - sync - -dep: - $(CPP) -M *.c > .depend +ifdef CONFIG_ARC_MEMORY +L_OBJS += memory.o +endif include $(TOPDIR)/Rules.make diff --git a/arch/mips64/arc/identify.c b/arch/mips64/arc/identify.c index 2103dd427..ab2d553ad 100644 --- a/arch/mips64/arc/identify.c +++ b/arch/mips64/arc/identify.c @@ -13,6 +13,7 @@ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ #include <linux/init.h> +#include <linux/config.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/string.h> @@ -29,6 +30,7 @@ struct smatch { static struct smatch mach_table[] = { { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS }, + { "SGI-IP27", MACH_GROUP_SGI, MACH_SGI_IP27, PROM_FLAG_ARCS }, { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 }, { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 }, { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 } @@ -58,12 +60,22 @@ prom_identify_arch(void) { pcomponent *p; struct smatch *mach; + const char *iname; /* The root component tells us what machine architecture we have here. */ p = ArcGetChild(PROM_NULL_COMPONENT); - printk("ARCH: %s\n", (char *) (long) p->iname); - mach = string_to_mach((char *) (long) p->iname); + if (p == NULL) { +#ifdef CONFIG_SGI_IP27 + /* IP27 PROM bisbehaves, seems to not implement ARC + GetChild(). So we just assume it's an IP27. */ + iname = "SGI-IP27"; +#endif + } else + iname = (char *) (long) p->iname; + + printk("ARCH: %s\n", iname); + mach = string_to_mach(iname); mips_machgroup = mach->group; mips_machtype = mach->type; diff --git a/arch/mips64/arc/memory.c b/arch/mips64/arc/memory.c index 85129ee99..a63d8d631 100644 --- a/arch/mips64/arc/memory.c +++ b/arch/mips64/arc/memory.c @@ -4,12 +4,14 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * memory.c: PROM library functions for acquiring/using memory descriptors - * given to us from the ARCS firmware. + * Copyright (C) 1996 by David S. Miller + * Copyright (C) 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 by Silicon Graphics, Inc. * - * Copyright (C) 1996 by David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1999 by Ralf Baechle - * Copyright (C) 1999 by Silicon Graphics, Inc. + * PROM library functions for acquiring/using memory descriptors given to us + * from the ARCS firmware. This is only used when CONFIG_ARC_MEMORY is set + * because on some machines like SGI IP27 the ARC memory configuration data + * completly bogus and alternate easier to use mechanisms are available. */ #include <linux/config.h> #include <linux/init.h> @@ -133,11 +135,12 @@ void __init prom_meminit(void) { struct linux_mdesc *p; - int totram; - int i = 0; + unsigned long totram; + int i; - p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); #ifdef DEBUG + i = 0; + p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); while(p) { prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", @@ -151,21 +154,22 @@ prom_meminit(void) i = 0; while(p) { prom_pblocks[i].type = prom_memtype_classify (p->type); - prom_pblocks[i].base = ((p->base<<PAGE_SHIFT) + 0x80000000); + prom_pblocks[i].base = PAGE_OFFSET + (p->base << PAGE_SHIFT); prom_pblocks[i].size = p->pages << PAGE_SHIFT; switch (prom_pblocks[i].type) { case MEMTYPE_FREE: totram += prom_pblocks[i].size; #ifdef DEBUG - prom_printf("free_chunk[%d]: base=%08lx size=%d\n", + prom_printf("free_chunk[%d]: base=%08lx size=%x" + " total=%x\n", i, prom_pblocks[i].base, - prom_pblocks[i].size); + prom_pblocks[i].size, totram); #endif i++; break; case MEMTYPE_PROM: #ifdef DEBUG - prom_printf("prom_chunk[%d]: base=%08lx size=%d\n", + prom_printf("prom_chunk[%d]: base=%08lx size=%x\n", i, prom_pblocks[i].base, prom_pblocks[i].size); #endif @@ -178,7 +182,7 @@ prom_meminit(void) } prom_pblocks[i].base = 0xdeadbeef; prom_pblocks[i].size = 0; /* indicates last elem. of array */ - printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", + printk("PROMLIB: Total free ram %ld bytes (%ldK,%ldMB)\n", totram, (totram/1024), (totram/1024/1024)); /* Setup upper physical memory bound. */ @@ -217,7 +221,7 @@ restart: } } -void +void __init prom_free_prom_memory (void) { struct prom_pmemblock *p; diff --git a/arch/mips64/arc/misc.c b/arch/mips64/arc/misc.c index 220c3cc71..703305c20 100644 --- a/arch/mips64/arc/misc.c +++ b/arch/mips64/arc/misc.c @@ -28,7 +28,7 @@ extern void reset_wd33c93(void *instance); VOID ArcHalt(VOID) { - bcops->bc_disable(); + bc_disable(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -40,7 +40,7 @@ never: goto never; VOID ArcPowerDown(VOID) { - bcops->bc_disable(); + bc_disable(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -53,7 +53,7 @@ never: goto never; VOID ArcRestart(VOID) { - bcops->bc_disable(); + bc_disable(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -65,7 +65,7 @@ never: goto never; VOID ArcReboot(VOID) { - bcops->bc_disable(); + bc_disable(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -77,7 +77,7 @@ never: goto never; VOID ArcEnterInteractiveMode(VOID) { - bcops->bc_disable(); + bc_disable(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); diff --git a/arch/mips64/config.in b/arch/mips64/config.in index 7ee2b2a42..85f28ad6e 100644 --- a/arch/mips64/config.in +++ b/arch/mips64/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.8 1999/11/23 17:12:49 ralf Exp $ +# $Id: config.in,v 1.5 1999/12/04 03:59:00 ralf Exp $ # # For a description of the syntax of this configuration file, # see the Configure script. @@ -13,18 +13,35 @@ endmenu mainmenu_option next_comment comment 'Machine selection' bool 'Support for SGI IP22' CONFIG_SGI_IP22 +bool 'Support for SGI IP27' CONFIG_SGI_IP27 +if [ "$CONFIG_SGI_IP27" = "y" ]; then + bool ' IP27 N-Mode' CONFIG_SGI_SN0_N_MODE + #bool ' IP27 XXL' CONFIG_SGI_SN0_XXL +fi endmenu # # Select some configuration options automatically based on user selections # unset CONFIG_BOOT_ELF32 +unset CONFIG_BOOT_ELF64 unset CONFIG_ARC32 unset CONFIG_ARC64 +unset CONFIG_BOARD_SCACHE +unset CONFIG_COHERENT_IO +unset CONFIG_BINFMT_ELF32 if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_BOOT_ELF32 y define_bool CONFIG_ARC32 y + define_bool CONFIG_BOARD_SCACHE y + define_bool CONFIG_ARC_MEMORY y +fi + +if [ "$CONFIG_SGI_IP27" = "y" ]; then + define_bool CONFIG_BOOT_ELF64 y + define_bool CONFIG_ARC64 y + define_bool CONFIG_COHERENT_IO y fi mainmenu_option next_comment @@ -47,14 +64,16 @@ if [ "$CONFIG_CPU_R10000" = "y" ]; then fi bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN -define_bool CONFIG_BINFMT_AOUT n -define_bool CONFIG_BINFMT_ELF y -tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC - bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL +tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for Linux/MIPS 32-bit binary compatibility' CONFIG_MIPS32_COMPAT +if [ "$CONFIG_MIPS32_COMPAT" = "y" ]; then + define_bool CONFIG_BINFMT_ELF32 y +fi +tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC mainmenu_option next_comment comment 'Loadable module support' diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig index 71fac0fc9..22060ed89 100644 --- a/arch/mips64/defconfig +++ b/arch/mips64/defconfig @@ -10,31 +10,36 @@ # # Machine selection # -CONFIG_SGI_IP22=y -CONFIG_BOOT_ELF32=y -CONFIG_ARC32=y +# CONFIG_SGI_IP22 is not set +CONFIG_SGI_IP27=y +# CONFIG_SGI_SN0_N_MODE is not set +CONFIG_BOOT_ELF64=y +CONFIG_ARC64=y +CONFIG_COHERENT_IO=y # # CPU selection # # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set -CONFIG_CPU_R5000=y +# CONFIG_CPU_R5000 is not set # CONFIG_CPU_NEVADA is not set # CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set +CONFIG_CPU_R10000=y # # General setup # +# CONFIG_MIPS_INSANE_LARGE is not set # CONFIG_CPU_LITTLE_ENDIAN is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set +# CONFIG_BINFMT_ELF is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_BINFMT_ELF32=y +# CONFIG_BINFMT_MISC is not set # # Loadable module support @@ -116,7 +121,16 @@ CONFIG_NETDEVICES=y # # Ethernet (10 or 100Mbit) # -# CONFIG_NET_ETHERNET is not set +CONFIG_NET_ETHERNET=y +CONFIG_SGI_IOC3_ETH=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_DEPCA is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_PLIP is not set # CONFIG_PPP is not set @@ -144,7 +158,6 @@ CONFIG_NETDEVICES=y # CONFIG_PCMCIA_PCNET is not set # CONFIG_PCMCIA_3C589 is not set # CONFIG_PCMCIA_RAYCS is not set -CONFIG_SGISEEQ=y # # Amateur Radio support @@ -169,9 +182,9 @@ CONFIG_SGISEEQ=y # # Character devices # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_UNIX98_PTYS is not set @@ -260,24 +273,13 @@ CONFIG_SGI_PARTITION=y # CONFIG_NLS is not set # -# Console drivers -# -CONFIG_SGI_NEWPORT_CONSOLE=y - -# # Sound # # CONFIG_SOUND is not set # -# SGI devices -# -# CONFIG_SGI_SERIAL is not set -CONFIG_SGI_DS1286=y - -# # Kernel hacking # CONFIG_CROSSCOMPILE=y # CONFIG_REMOTE_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set +CONFIG_MAGIC_SYSRQ=y diff --git a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22 new file mode 100644 index 000000000..71fac0fc9 --- /dev/null +++ b/arch/mips64/defconfig-ip22 @@ -0,0 +1,283 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set + +# +# Machine selection +# +CONFIG_SGI_IP22=y +CONFIG_BOOT_ELF32=y +CONFIG_ARC32=y + +# +# CPU selection +# +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set + +# +# General setup +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_ONLY is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=m +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=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 + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Network device support +# +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 +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_PRINTER is not set +# CONFIG_PPDEV is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# USB drivers - not for the faint of heart +# +# CONFIG_USB is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_UDF_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_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 +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_SGI_NEWPORT_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# SGI devices +# +# CONFIG_SGI_SERIAL is not set +CONFIG_SGI_DS1286=y + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_MAGIC_SYSRQ is not set diff --git a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27 new file mode 100644 index 000000000..22060ed89 --- /dev/null +++ b/arch/mips64/defconfig-ip27 @@ -0,0 +1,285 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set + +# +# Machine selection +# +# CONFIG_SGI_IP22 is not set +CONFIG_SGI_IP27=y +# CONFIG_SGI_SN0_N_MODE is not set +CONFIG_BOOT_ELF64=y +CONFIG_ARC64=y +CONFIG_COHERENT_IO=y + +# +# CPU selection +# +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +CONFIG_CPU_R10000=y + +# +# General setup +# +# CONFIG_MIPS_INSANE_LARGE is not set +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +# CONFIG_BINFMT_ELF is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_BINFMT_ELF32=y +# CONFIG_BINFMT_MISC is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_ONLY is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=m +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=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 + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Network device support +# +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=y +CONFIG_SGI_IOC3_ETH=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_DEPCA is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET 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 + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_PRINTER is not set +# CONFIG_PPDEV is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# USB drivers - not for the faint of heart +# +# CONFIG_USB is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_UDF_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_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 +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +CONFIG_MAGIC_SYSRQ=y diff --git a/arch/mips64/kernel/Makefile b/arch/mips64/kernel/Makefile index 9856524c3..0f70cba13 100644 --- a/arch/mips64/kernel/Makefile +++ b/arch/mips64/kernel/Makefile @@ -12,12 +12,19 @@ all: kernel.o head.o init_task.o O_TARGET := kernel.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 +O_OBJS := 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 \ + semaphore.o setup.o signal.o softfp.o syscall.o traps.o unaligned.o OX_OBJS := mips64_ksyms.o +ifdef CONFIG_MIPS32_COMPAT +O_OBJS += linux32.o scall_o32.o signal32.o +endif + +ifdef CONFIG_BINFMT_ELF32 +O_OBJS += binfmt_elf32.o +endif + clean: include $(TOPDIR)/Rules.make diff --git a/arch/mips64/kernel/binfmt_elf32.c b/arch/mips64/kernel/binfmt_elf32.c index 3494f4cf0..a199839a6 100644 --- a/arch/mips64/kernel/binfmt_elf32.c +++ b/arch/mips64/kernel/binfmt_elf32.c @@ -90,7 +90,6 @@ struct elf_prpsinfo32 #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)"); diff --git a/arch/mips64/kernel/entry.S b/arch/mips64/kernel/entry.S index 05bbee928..1206a68c3 100644 --- a/arch/mips64/kernel/entry.S +++ b/arch/mips64/kernel/entry.S @@ -21,13 +21,12 @@ .text .set noreorder .align 4 -EXPORT(ret_from_fork) +FEXPORT(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 +FEXPORT(handle_bottom_half) jal do_bottom_half nop b 9f @@ -36,10 +35,8 @@ EXPORT(handle_bottom_half) reschedule: jal schedule nop -EXPORT(ret_from_sys_call) - .type ret_from_sys_call,@function -EXPORT(ret_from_irq) - .type ret_from_irq,@function +FEXPORT(ret_from_sys_call) +FEXPORT(ret_from_irq) ld t0, bh_mask ld t1, bh_active # unused delay slot and t0, t1 @@ -57,8 +54,7 @@ EXPORT(ret_from_irq) jal do_signal move a1, sp -EXPORT(return) .set noat - .type return,@function +FEXPORT(return) .set noat RESTORE_ALL eret .set at diff --git a/arch/mips64/kernel/head.S b/arch/mips64/kernel/head.S index daa0e3ad1..98718e93c 100644 --- a/arch/mips64/kernel/head.S +++ b/arch/mips64/kernel/head.S @@ -12,6 +12,7 @@ * Copyright (C) 1999 Silicon Graphics, Inc. */ #define __ASSEMBLY__ +#include <linux/config.h> #include <linux/init.h> #include <asm/asm.h> #include <asm/regdef.h> @@ -28,6 +29,14 @@ EXPORT(_stext) NESTED(kernel_entry, 16, sp) # kernel entry point +#ifdef CONFIG_ARC64 + /* We get launched at a XKPHYS address but the kernel is linked to + run at a KSEG0 address, so jump there. */ + la t0, 1f + jr t0 +1: +#endif + ori sp, 0xf # align stack on 16 byte. xori sp, 0xf @@ -38,9 +47,9 @@ NESTED(kernel_entry, 16, sp) # kernel entry point CLI # disable interrupts mfc0 t0, CP0_STATUS - li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX) + li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3) and t0, t1 - or t0, ST0_CU0 + or t0, (ST0_CU0|ST0_KX|ST0_SX) mtc0 t0, CP0_STATUS la $28, init_task_union # init current pointer diff --git a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c index d6fa01d8a..cc077a486 100644 --- a/arch/mips64/kernel/mips64_ksyms.c +++ b/arch/mips64/kernel/mips64_ksyms.c @@ -89,6 +89,11 @@ EXPORT_SYMBOL(dma_cache_inv); EXPORT_SYMBOL(invalid_pte_table); /* + * Base address of ports for Intel style I/O. + */ +EXPORT_SYMBOL(mips_io_port_base); + +/* * Kernel hacking ... */ #include <asm/branch.h> diff --git a/arch/mips64/kernel/r4k_tlb_debug.c b/arch/mips64/kernel/r4k_tlb_debug.c index f14725189..a9d41cb46 100644 --- a/arch/mips64/kernel/r4k_tlb_debug.c +++ b/arch/mips64/kernel/r4k_tlb_debug.c @@ -6,6 +6,9 @@ * * Copyright (C) 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. + * + * TLB debugging routines. These perform horribly slow but can easily be + * modified for debugging purposes. */ #include <linux/linkage.h> #include <linux/kernel.h> @@ -43,8 +46,10 @@ asmlinkage void xtlb_refill_debug(struct pt_regs *regs) asmlinkage void xtlb_mod_debug(struct pt_regs *regs) { - show_regs(regs); - panic(__FUNCTION__ " called."); + unsigned long addr; + + addr = regs->cp0_badvaddr; + do_page_fault(regs, 1, addr); } asmlinkage void xtlb_tlbl_debug(struct pt_regs *regs) @@ -52,20 +57,7 @@ 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) @@ -73,18 +65,5 @@ 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 index 767ecb76f..81d457fda 100644 --- a/arch/mips64/kernel/r4k_tlb_glue.S +++ b/arch/mips64/kernel/r4k_tlb_glue.S @@ -26,6 +26,7 @@ NESTED(__tlb_refill_debug_tramp, PT_SIZE, sp) .macro tlb_handler name NESTED(__\name, PT_SIZE, sp) SAVE_ALL + CLI dmfc0 t0, CP0_BADVADDR sd t0, PT_BVADDR(sp) move a0, sp diff --git a/arch/mips64/kernel/scall_64.S b/arch/mips64/kernel/scall_64.S index 27ce842e9..3d49cbe07 100644 --- a/arch/mips64/kernel/scall_64.S +++ b/arch/mips64/kernel/scall_64.S @@ -7,6 +7,7 @@ * Copyright (C) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include <linux/config.h> #include <asm/asm.h> #include <linux/errno.h> #include <asm/current.h> @@ -24,6 +25,10 @@ /* Highest syscall handled here. */ #define MAX_SYSCALL_NO __NR_Linux + __NR_Linux_syscalls +#ifndef CONFIG_MIPS32_COMPAT +#define handle_sys64 handle_sys +#endif + .align 5 NESTED(handle_sys64, PT_SIZE, sp) @@ -55,8 +60,7 @@ NESTED(handle_sys64, PT_SIZE, sp) 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 +FEXPORT(ret_from_sys_call_64) ld t0, bh_mask ld t1, bh_active # unused delay slot and t0, t1 diff --git a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S index 2899405f0..56b087a7b 100644 --- a/arch/mips64/kernel/scall_o32.S +++ b/arch/mips64/kernel/scall_o32.S @@ -258,13 +258,13 @@ illegal_syscall: sys sys_getppid 0 sys sys_getpgrp 0 /* 4065 */ sys sys_setsid 0 - sys sys_sigaction 3 + sys sys32_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 sys32_sigsuspend 0 + sys sys32_sigpending 1 sys sys_sethostname 2 sys sys_setrlimit 2 /* 4075 */ sys sys_getrlimit 2 @@ -297,9 +297,9 @@ illegal_syscall: 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 sys32_newstat 2 + sys sys32_newlstat 2 + sys sys32_newfstat 2 sys sys_uname 1 sys sys_ni_syscall 0 /* sys_ioperm *//* 4110 */ sys sys_vhangup 0 @@ -310,7 +310,7 @@ illegal_syscall: sys sys_sysinfo 1 sys sys_ipc 6 sys sys_fsync 1 - sys sys_sigreturn 0 + sys sys32_sigreturn 0 sys sys_clone 0 /* 4120 */ sys sys_setdomainname 2 sys sys_newuname 1 @@ -384,20 +384,20 @@ illegal_syscall: 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 sys32_rt_sigreturn 0 + sys sys32_rt_sigaction 4 + sys sys32_rt_sigprocmask 4 /* 4195 */ + sys sys32_rt_sigpending 2 + sys sys32_rt_sigtimedwait 4 + sys sys32_rt_sigqueueinfo 3 + sys sys32_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 sys32_sigaltstack 0 sys sys_sendfile 3 sys sys_ni_syscall 0 sys sys_ni_syscall 0 diff --git a/arch/mips64/kernel/setup.c b/arch/mips64/kernel/setup.c index 347266fd2..37b4f33e9 100644 --- a/arch/mips64/kernel/setup.c +++ b/arch/mips64/kernel/setup.c @@ -95,7 +95,14 @@ static char command_line[CL_SIZE] = { 0, }; char saved_command_line[CL_SIZE]; extern char arcs_cmdline[CL_SIZE]; +/* + * mips_io_port_base is the begin of the address space to which x86 style + * I/O ports are mapped. + */ +unsigned long mips_io_port_base; + extern void ip22_setup(void); +extern void ip27_setup(void); static inline void cpu_probe(void) { @@ -146,6 +153,9 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, #ifdef CONFIG_SGI_IP22 ip22_setup(); #endif +#ifdef CONFIG_SGI_IP27 + ip27_setup(); +#endif memory_end = mips_memory_upper; @@ -164,6 +174,12 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, *cmdline_p = command_line; *memory_start_p = (unsigned long) &_end; +#ifdef CONFIG_BOOT_ELF64 + /* memory_end is a XKPHYS address but memory_start is in CKSEG. + All memory handling is done using XKPHYS addresses, so convert. */ + *memory_start_p = (*memory_start_p & 0x1ffffffUL) + | 0xa800000000000000UL; +#endif *memory_end_p = memory_end; #ifdef CONFIG_BLK_DEV_INITRD diff --git a/arch/mips64/kernel/signal.c b/arch/mips64/kernel/signal.c index 712459430..bc21e4d4c 100644 --- a/arch/mips64/kernel/signal.c +++ b/arch/mips64/kernel/signal.c @@ -519,12 +519,19 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) } extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); +extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { struct k_sigaction *ka; siginfo_t info; +#ifdef CONFIG_BINFMT_ELF32 + if (current->thread.mflags & MF_32BIT) { + return do_signal32(oldset, regs); + } +#endif + #ifdef CONFIG_BINFMT_IRIX if (current->personality != PER_LINUX) return do_irix_signal(oldset, regs); diff --git a/arch/mips64/kernel/unaligned.c b/arch/mips64/kernel/unaligned.c index 22c1819eb..5381642f1 100644 --- a/arch/mips64/kernel/unaligned.c +++ b/arch/mips64/kernel/unaligned.c @@ -377,7 +377,7 @@ sigill: unsigned long unaligned_instructions; -asmlinkage void do_ade(abi64_no_regargs, struct pt_regs regs) +asmlinkage void do_ade(struct pt_regs *regs) { unsigned long pc; @@ -386,16 +386,16 @@ asmlinkage void do_ade(abi64_no_regargs, struct pt_regs regs) * This also catches attempts to activate MIPS16 code on * CPUs which don't support it. */ - if (regs.cp0_badvaddr == regs.cp0_epc) + 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)) + pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); + if (compute_return_epc(regs)) return; if ((current->thread.mflags & MF_FIXADE) == 0) goto sigbus; - emulate_load_store_insn(®s, regs.cp0_badvaddr, pc); + emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); unaligned_instructions++; return; diff --git a/arch/mips64/ld.script.elf64 b/arch/mips64/ld.script.elf64 new file mode 100644 index 000000000..abfdf5422 --- /dev/null +++ b/arch/mips64/ld.script.elf64 @@ -0,0 +1,119 @@ +OUTPUT_ARCH(mips) +ENTRY(kernel_entry) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + /* . = 0xc000000000000000; */ + + /* This is the value for an Origin kernel, taken from an IRIX kernel. */ + /* . = 0xc00000000001c000; */ + + /* Set the vaddr for the text segment to a value + >= 0xa800 0000 0001 9000 if no symmon is going to configured + >= 0xa800 0000 0030 0000 otherwise */ + + /* . = 0xa800000000300000; */ + /* . = 0xa800000000300000; */ + . = 0xffffffff80300000; + .text : { + _ftext = . ; + *(.text) + *(.rodata) + *(.rodata1) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } = 0 + _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 + the same address within the page on the next page up. It would + be more correct to do this: + . = .; + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = .; + .data : + { + _fdata = . ; + *(.data) + CONSTRUCTORS + } + .data1 : { *(.data1) } + _gp = . + 0x8000; + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + + __bss_start = .; + _fbss = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + _end = . ; + PROVIDE (end = .); + } + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + /* DWARF debug sections. + Symbols in the .debug DWARF section are relative to the beginning of the + section so we begin .debug at 0. It's not clear yet what needs to happen + for the others. */ + .debug 0 : { *(.debug) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .line 0 : { *(.line) } + /* These must appear regardless of . */ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } +} diff --git a/arch/mips64/lib/memcpy.S b/arch/mips64/lib/memcpy.S index 9f44b4b8b..d78327f11 100644 --- a/arch/mips64/lib/memcpy.S +++ b/arch/mips64/lib/memcpy.S @@ -96,7 +96,7 @@ LEAF(xxmemcpy) /* a0=dst a1=src a2=len */ move v0, a0 /* return value */ __memcpy: -EXPORT(__copy_user) +FEXPORT(__copy_user) xor ta0, a0, a1 andi ta0, ta0, 0x3 move t3, a0 diff --git a/arch/mips64/lib/strlen_user.S b/arch/mips64/lib/strlen_user.S index bb4347c02..38b7082d9 100644 --- a/arch/mips64/lib/strlen_user.S +++ b/arch/mips64/lib/strlen_user.S @@ -28,7 +28,7 @@ LEAF(__strlen_user_asm) and v0, a0 bltz v0, fault -EXPORT(__strlen_user_nocheck_asm) +FEXPORT(__strlen_user_nocheck_asm) move v0, a0 1: EX(lb, ta0, (v0), fault) daddiu v0, 1 diff --git a/arch/mips64/lib/strncpy_user.S b/arch/mips64/lib/strncpy_user.S index d30046cae..49ba07b05 100644 --- a/arch/mips64/lib/strncpy_user.S +++ b/arch/mips64/lib/strncpy_user.S @@ -33,7 +33,7 @@ LEAF(__strncpy_from_user_asm) and v0, a1 bltz v0, fault -EXPORT(__strncpy_from_user_nocheck_asm) +FEXPORT(__strncpy_from_user_nocheck_asm) move v0, zero move v1, a1 .set noreorder diff --git a/arch/mips64/mm/Makefile b/arch/mips64/mm/Makefile index 17100d9f6..db898cad4 100644 --- a/arch/mips64/mm/Makefile +++ b/arch/mips64/mm/Makefile @@ -1,10 +1,29 @@ -# $Id: Makefile,v 1.2 1999/08/20 21:13:33 ralf Exp $ +# $Id: Makefile,v 1.3 1999/12/04 03:59:00 ralf Exp $ # # Makefile for the Linux/MIPS-specific parts of the memory manager. # O_TARGET := mm.o -O_OBJS := extable.o init.o fault.o r4xx0.o tfp.o andes.o loadmmu.o +O_OBJS := extable.o init.o fault.o loadmmu.o + +ifdef CONFIG_CPU_R4300 +O_OBJS += r4xx0.o +endif +ifdef CONFIG_CPU_R4X00 +O_OBJS += r4xx0.o +endif +ifdef CONFIG_CPU_R5000 +O_OBJS += r4xx0.o +endif +ifdef CONFIG_CPU_NEVADA +O_OBJS += r4xx0.o +endif +ifdef CONFIG_CPU_R8000 +O_OBJS += tfp.o +endif +ifdef CONFIG_CPU_R10000 +O_OBJS += andes.o +endif ifdef CONFIG_SGI_IP22 O_OBJS += umap.o diff --git a/arch/mips64/mm/andes.c b/arch/mips64/mm/andes.c index dec5940c8..0c80e0377 100644 --- a/arch/mips64/mm/andes.c +++ b/arch/mips64/mm/andes.c @@ -1,10 +1,9 @@ -/* $Id: andes.c,v 1.3 1999/11/23 17:12:50 ralf Exp $ +/* $Id: andes.c,v 1.3 1999/12/04 03:59: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 * for more details. * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999 Silicon Graphics, Inc. */ @@ -14,79 +13,380 @@ #include <linux/mm.h> #include <asm/page.h> #include <asm/pgtable.h> +#include <asm/r10kcache.h> #include <asm/system.h> #include <asm/sgialib.h> #include <asm/mmu_context.h> -extern unsigned long mips_tlb_entries; +/* CP0 hazard avoidance. I think we can drop this for the R10000. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") -/* Cache operations. XXX Write these dave... */ +/* R10000 has no Create_Dirty type cacheops. */ +static void andes_clear_page(unsigned long page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tsd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (page) + :"0" (page), "I" (PAGE_SIZE) + :"$1", "memory"); +} + +static void andes_copy_page(unsigned long to, unsigned long from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE)); +} + +/* Cache operations. These are only used with the virtual memory system, + not for non-coherent I/O so it's ok to ignore the secondary caches. */ static void andes_flush_cache_all(void) { - /* XXX */ + blast_dcache32(); blast_icache64(); } static void andes_flush_cache_mm(struct mm_struct *mm) { - /* XXX */ + if (mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + andes_flush_cache_all(); + } } static void andes_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - /* XXX */ + if (mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + save_and_cli(flags); + blast_dcache32(); blast_icache64(); + restore_flags(flags); + } } static void andes_flush_cache_page(struct vm_area_struct *vma, unsigned long page) { - /* XXX */ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if (mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_and_cli(flags); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_PRESENT)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if ((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { + blast_dcache32_page(page); + if(text) + blast_icache64_page(page); + } else { + /* + * Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (CKSEG0 + (page & (dcache_size - 1))); + blast_dcache32_page_indexed(page); + if(text) + blast_icache64_page_indexed(page); + } +out: + restore_flags(flags); } +/* Hoo hum... will this ever be called for an address that is not in CKSEG0 + and not cacheable? */ static void andes_flush_page_to_ram(unsigned long page) { - /* XXX */ + page &= PAGE_MASK; + if ((page >= K0BASE_NONCOH && page < (0xb0UL << 56)) + || (page >= KSEG0 && page < KSEG1) + || (page >= KSEG2)) { +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + blast_dcache32_page(page); + } } static void -andes_flush_cache_sigtramp(unsigned long page) +andes_flush_cache_sigtramp(unsigned long addr) { - /* XXX */ + unsigned long daddr, iaddr; + + daddr = addr & ~(dc_lsize - 1); + protected_writeback_dcache_line(daddr); + protected_writeback_dcache_line(daddr + dc_lsize); + iaddr = addr & ~(ic_lsize - 1); + protected_flush_icache_line(iaddr); + protected_flush_icache_line(iaddr + ic_lsize); } -/* TLB operations. XXX Write these dave... */ -static void +#define NTLB_ENTRIES 64 +#define NTLB_ENTRIES_HALF 32 + +/* TLB operations. + XXX These should work fine on R10k without the BARRIERs. */ +static inline void andes_flush_tlb_all(void) { - /* XXX */ + unsigned long flags; + unsigned long old_ctx; + unsigned long entry; + +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + + __save_and_cli(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = get_entryhi() & 0xff; + set_entryhi(CKSEG0); + set_entrylo0(0); + set_entrylo1(0); + BARRIER; + + entry = get_wired(); + + /* Blast 'em all away. */ + while(entry < NTLB_ENTRIES) { + set_index(entry); + BARRIER; + tlb_write_indexed(); + BARRIER; + entry++; + } + BARRIER; + set_entryhi(old_ctx); + __restore_flags(flags); } -static void -andes_flush_tlb_mm(struct mm_struct *mm) +static void andes_flush_tlb_mm(struct mm_struct *mm) { - /* XXX */ + if(mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_TLB + printk("[tlbmm<%d>]", mm->context); +#endif + save_and_cli(flags); + get_new_mmu_context(mm, asid_cache); + if(mm == current->mm) + set_entryhi(mm->context & 0xff); + restore_flags(flags); + } } static void andes_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - /* XXX */ + if(mm->context != 0) { + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), + start, end); +#endif + save_and_cli(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if(size <= NTLB_ENTRIES_HALF) { + int oldpid = (get_entryhi() & 0xff); + int newpid = (mm->context & 0xff); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + while(start < end) { + int idx; + + set_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + BARRIER; + tlb_probe(); + BARRIER; + idx = get_index(); + set_entrylo0(0); + set_entrylo1(0); + set_entryhi(KSEG0); + BARRIER; + if(idx < 0) + continue; + tlb_write_indexed(); + BARRIER; + } + set_entryhi(oldpid); + } else { + get_new_mmu_context(mm, asid_cache); + if(mm == current->mm) + set_entryhi(mm->context & 0xff); + } + __restore_flags(flags); + } } static void andes_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - /* XXX */ + if(vma->vm_mm->context != 0) { + unsigned long flags; + int oldpid, newpid, idx; + +#ifdef DEBUG_TLB + printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); +#endif + newpid = (vma->vm_mm->context & 0xff); + page &= (PAGE_MASK << 1); + save_and_cli(flags); + oldpid = (get_entryhi() & 0xff); + set_entryhi(page | newpid); + BARRIER; + tlb_probe(); + BARRIER; + idx = get_index(); + set_entrylo0(0); + set_entrylo1(0); + set_entryhi(KSEG0); + if(idx < 0) + goto finish; + BARRIER; + tlb_write_indexed(); + + finish: + BARRIER; + set_entryhi(oldpid); + restore_flags(flags); + } } -static void -andes_load_pgd(unsigned long pg_dir) +/* XXX Simplify this. On the R10000 writing a TLB entry for an virtual + address that already exists will overwrite the old entry and not result + in TLB malfunction or TLB shutdown. */ +static void andes_update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) { + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + pid = get_entryhi() & 0xff; + +#ifdef DEBUG_TLB + if((pid != (vma->vm_mm->context & 0xff)) || + (vma->vm_mm->context == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", + (int) (vma->vm_mm->context & 0xff), pid); + } +#endif + + __save_and_cli(flags); + address &= (PAGE_MASK << 1); + set_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + BARRIER; + tlb_probe(); + BARRIER; + pmdp = pmd_offset(pgdp, address); + idx = get_index(); + ptep = pte_offset(pmdp, address); + BARRIER; + set_entrylo0(pte_val(*ptep++) >> 6); + set_entrylo1(pte_val(*ptep) >> 6); + set_entryhi(address | (pid)); + BARRIER; + if(idx < 0) { + tlb_write_random(); + } else { + tlb_write_indexed(); + } + BARRIER; + set_entryhi(pid); + BARRIER; + __restore_flags(flags); } static int @@ -95,8 +395,49 @@ andes_user_mode(struct pt_regs *regs) return (regs->cp0_status & ST0_KSU) == KSU_USER; } +static void andes_show_regs(struct pt_regs *regs) +{ + /* Saved main processor registers. */ + printk("$0 : %016lx %016lx %016lx %016lx\n", + 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); + printk("$4 : %016lx %016lx %016lx %016lx\n", + regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); + printk("$8 : %016lx %016lx %016lx %016lx\n", + regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); + printk("$12 : %016lx %016lx %016lx %016lx\n", + regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); + printk("$16 : %016lx %016lx %016lx %016lx\n", + regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); + printk("$20 : %016lx %016lx %016lx %016lx\n", + regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); + printk("$24 : %016lx %016lx\n", + regs->regs[24], regs->regs[25]); + 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 : %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); +} + void __init ld_mmu_andes(void) { + printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); + + printk("Primary instruction cache %dkb, linesize %d bytes\n", + icache_size >> 10, ic_lsize); + printk("Primary data cache %dkb, linesize %d bytes\n", + dcache_size >> 10, dc_lsize); + printk("Secondary cache sized at %ldK, linesize %ld\n", + scache_size() >> 10, sc_lsize()); + + clear_page = andes_clear_page; + copy_page = andes_copy_page; + flush_cache_all = andes_flush_cache_all; flush_cache_mm = andes_flush_cache_mm; flush_cache_range = andes_flush_cache_range; @@ -109,10 +450,26 @@ void __init ld_mmu_andes(void) flush_tlb_range = andes_flush_tlb_range; flush_tlb_page = andes_flush_tlb_page; + update_mmu_cache = andes_update_mmu_cache; + show_regs = andes_show_regs; + user_mode = andes_user_mode; - load_pgd = andes_load_pgd; + flush_cache_all(); + write_32bit_cp0_register(CP0_WIRED, 0); + + /* + * You should never change this register: + * - On R4600 1.7 the tlbp never hits for pages smaller than + * the value in the c0_pagemask register. + * - The entire mm handling assumes the c0_pagemask register to + * be set for 4kb pages. + */ + write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); + + /* We can't flush the TLB at this time since the IP27 ARC firmware + depends on it. ARC go home. */ + /* flush_tlb_all(); */ - flush_cache_all(); - flush_tlb_all(); + /* Did I tell you that ARC SUCKS? */ } diff --git a/arch/mips64/mm/loadmmu.c b/arch/mips64/mm/loadmmu.c index 3053b9dbd..0359f92a1 100644 --- a/arch/mips64/mm/loadmmu.c +++ b/arch/mips64/mm/loadmmu.c @@ -1,4 +1,4 @@ -/* $Id: loadmmu.c,v 1.6 1999/11/23 17:12:50 ralf Exp $ +/* $Id: loadmmu.c,v 1.3 1999/12/04 03:59: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 @@ -8,6 +8,7 @@ * Copyright (C) 1997, 1999 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -45,7 +46,6 @@ void (*flush_tlb_range)(struct mm_struct *mm, unsigned long start, void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page); /* Miscellaneous. */ -void (*load_pgd)(unsigned long pg_dir); void (*update_mmu_cache)(struct vm_area_struct * vma, unsigned long address, pte_t pte); @@ -60,6 +60,10 @@ extern void ld_mmu_andes(void); void __init load_mmu(void) { switch(mips_cputype) { +#if defined (CONFIG_CPU_R4300) \ + || defined (CONFIG_CPU_R4X00) \ + || defined (CONFIG_CPU_R5000) \ + || defined (CONFIG_CPU_NEVADA) case CPU_R4000PC: case CPU_R4000SC: case CPU_R4000MC: @@ -78,16 +82,21 @@ void __init load_mmu(void) printk("Loading R4000 MMU routines.\n"); ld_mmu_r4xx0(); break; +#endif +#if defined (CONFIG_CPU_R8000) case CPU_R8000: printk("Loading TFP MMU routines.\n"); ld_mmu_tfp(); break; +#endif +#if defined (CONFIG_CPU_R10000) case CPU_R10000: printk("Loading R10000 MMU routines.\n"); ld_mmu_andes(); break; +#endif default: /* XXX We need an generic routine in the MIPS port @@ -96,6 +105,7 @@ void __init load_mmu(void) * XXX routines look good for this, but only the SGI * XXX code has a full library for that at this time. */ - panic("Yeee, unsupported mmu/cache architecture."); + panic("Yeee, unsupported mmu/cache architecture or " + "wrong compiletime kernel configuration."); } } diff --git a/arch/mips64/mm/r4xx0.c b/arch/mips64/mm/r4xx0.c index 4cd61e19b..ff239b38e 100644 --- a/arch/mips64/mm/r4xx0.c +++ b/arch/mips64/mm/r4xx0.c @@ -1,4 +1,4 @@ -/* $Id: r4xx0.c,v 1.6 1999/11/23 17:12:50 ralf Exp $ +/* $Id: r4xx0.c,v 1.5 1999/12/04 03:59: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 @@ -36,7 +36,7 @@ static int ic_lsize, dc_lsize; /* LineSize in bytes */ /* Secondary cache (if present) parameters. */ static unsigned int scache_size, sc_lsize; /* Again, in bytes */ -#include <asm/cacheops.h> +#include <asm/r4kcacheops.h> #include <asm/r4kcache.h> #undef DEBUG_CACHE @@ -1876,7 +1876,7 @@ r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) } __restore_flags(flags); } - bcops->bc_wback_inv(addr, size); + bc_wback_inv(addr, size); } static void @@ -1921,7 +1921,7 @@ r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size) __restore_flags(flags); } - bcops->bc_inv(addr, size); + bc_inv(addr, size); } static void @@ -2124,11 +2124,6 @@ static void r4k_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) } } -/* Load a new root pointer into the TLB. */ -static void r4k_load_pgd(unsigned long pg_dir) -{ -} - #ifdef DEBUG_TLBUPDATE static unsigned long ehi_debug[NTLB_ENTRIES]; static unsigned long el0_debug[NTLB_ENTRIES]; @@ -2520,7 +2515,6 @@ void __init ld_mmu_r4xx0(void) flush_tlb_range = r4k_flush_tlb_range; flush_tlb_page = r4k_flush_tlb_page; - load_pgd = r4k_load_pgd; 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 517a617b0..aca942a66 100644 --- a/arch/mips64/mm/tfp.c +++ b/arch/mips64/mm/tfp.c @@ -1,4 +1,4 @@ -/* $Id: tfp.c,v 1.4 1999/11/23 17:12:50 ralf Exp $ +/* $Id: tfp.c,v 1.4 1999/12/04 03:59:01 ralf Exp $ * * tfp.c: MMU and cache routines specific to the r8000 (TFP). * @@ -74,10 +74,6 @@ static void tfp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) /* XXX */ } -static void tfp_load_pgd(unsigned long pg_dir) -{ -} - static int tfp_user_mode(struct pt_regs *regs) { return (regs->cp0_status & ST0_KSU) == KSU_USER; @@ -99,8 +95,6 @@ void __init ld_mmu_tfp(void) user_mode = tfp_user_mode; - load_pgd = tfp_load_pgd; - flush_cache_all(); flush_tlb_all(); } diff --git a/arch/mips64/sgi-ip22/Makefile b/arch/mips64/sgi-ip22/Makefile index 8e03f3d9a..3265aab41 100644 --- a/arch/mips64/sgi-ip22/Makefile +++ b/arch/mips64/sgi-ip22/Makefile @@ -9,16 +9,8 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -OBJS = ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \ +L_TARGET = ip22.a +L_OBJS = ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \ ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o -all: sgikern.a - -sgikern.a: $(OBJS) - $(AR) rcs sgikern.a $(OBJS) - sync - -dep: - $(CPP) -M *.c > .depend - include $(TOPDIR)/Rules.make diff --git a/arch/mips64/sgi-ip22/ip22-timer.c b/arch/mips64/sgi-ip22/ip22-timer.c index 633bf0ef8..ff8ece37a 100644 --- a/arch/mips64/sgi-ip22/ip22-timer.c +++ b/arch/mips64/sgi-ip22/ip22-timer.c @@ -85,6 +85,7 @@ void indy_timer_interrupt(struct pt_regs *regs) unsigned long count; int irq = 7; + write_lock(&xtime_lock); /* Ack timer and compute new compare. */ count = read_32bit_cp0_register(CP0_COUNT); /* This has races. */ @@ -114,6 +115,7 @@ void indy_timer_interrupt(struct pt_regs *regs) /* do it again in 60s */ last_rtc_update = xtime.tv_sec - 600; } + write_unlock(&xtime_lock); } static unsigned long dosample(volatile unsigned char *tcwp, @@ -252,9 +254,10 @@ void __init indy_timer_init(void) set_cp0_status(ST0_IM, ALLINTS); sti(); - /* Read time from the dallas chipset. */ - xtime.tv_sec = get_indy_time(); + write_lock_irq(&xtime_lock); + xtime.tv_sec = get_indy_time(); /* Read time from RTC. */ xtime.tv_usec = 0; + write_unlock_irq(&xtime_lock); } void indy_8254timer_irq(void) @@ -274,17 +277,17 @@ void do_gettimeofday(struct timeval *tv) { unsigned long flags; - save_and_cli(flags); + read_lock_irqsave(&xtime_lock, flags); *tv = xtime; - restore_flags(flags); + read_unlock_irqrestore(&xtime_lock, flags); } void do_settimeofday(struct timeval *tv) { - cli(); + write_lock_irq(&xtime_lock); xtime = *tv; time_state = TIME_BAD; time_maxerror = MAXPHASE; time_esterror = MAXPHASE; - sti(); + write_unlock_irq(&xtime_lock); } diff --git a/arch/mips64/sgi-ip27/.cvsignore b/arch/mips64/sgi-ip27/.cvsignore new file mode 100644 index 000000000..857dd22e9 --- /dev/null +++ b/arch/mips64/sgi-ip27/.cvsignore @@ -0,0 +1,2 @@ +.depend +.*.flags diff --git a/arch/mips64/sgi-ip27/Makefile b/arch/mips64/sgi-ip27/Makefile new file mode 100644 index 000000000..46fbe0b5c --- /dev/null +++ b/arch/mips64/sgi-ip27/Makefile @@ -0,0 +1,15 @@ +# $Id$ +# +# Makefile for the IP27 specific kernel interface routines under Linux. +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +L_TARGET = ip27.a +L_OBJS = ip27-irq.o ip27-irq-glue.o ip27-klconfig.o ip27-memory.o \ + ip27-reset.o ip27-setup.o ip27-timer.o + +include $(TOPDIR)/Rules.make diff --git a/arch/mips64/sgi-ip27/ip27-irq-glue.S b/arch/mips64/sgi-ip27/ip27-irq-glue.S new file mode 100644 index 000000000..40517c2d4 --- /dev/null +++ b/arch/mips64/sgi-ip27/ip27-irq-glue.S @@ -0,0 +1,65 @@ +/* $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) 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#include <asm/asm.h> +#include <asm/mipsregs.h> +#include <asm/regdef.h> +#include <asm/stackframe.h> + + .text + .set noat + .align 5 +NESTED(ip27_irq, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + /* IP27 may signal interrupt which we're not interested in. + Mask them out. */ + mfc0 s0, CP0_CAUSE + mfc0 t0, CP0_STATUS + and s0, t0 + + /* First check for RT interrupt. */ + andi a0, s0, CAUSEF_IP4 + beqz a0, 1f + + /* Ok, a timer interrupt. */ + move a0, sp + jal rt_timer_interrupt + + j ret_from_irq + +1: andi a0, s0, (CAUSEF_IP2 | CAUSEF_IP3) + beqz a0, 1f + + /* ... a device interrupt ... */ + move a0, sp + jal ip27_do_irq + + j ret_from_irq + +1: +#if 1 + mfc0 a1, CP0_STATUS + srl a1, a1, 8 + andi a1, 0xff + + mfc0 a2, CP0_CAUSE + srl a2, a2, 8 + andi a2, 0xff + + move a3, s0 + PRINT("Spurious interrupt, c0_status = %02x, c0_cause = %02x, pending %02x.\n") + ld a1, PT_EPC(sp) +0: b 0b +#endif + + j ret_from_irq + END(ip27_irq) diff --git a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c new file mode 100644 index 000000000..8749652b6 --- /dev/null +++ b/arch/mips64/sgi-ip27/ip27-irq.c @@ -0,0 +1,321 @@ +/* $Id$ + * + * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. + * + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#include <linux/config.h> +#include <linux/init.h> + +#include <linux/errno.h> +#include <linux/kernel_stat.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/malloc.h> +#include <linux/random.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> + +#include <asm/bitops.h> +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/mipsregs.h> +#include <asm/system.h> + +#include <asm/ptrace.h> +#include <asm/processor.h> +#include <asm/pci/bridge.h> +#include <asm/sn/sn0/hub.h> +#include <asm/sn/sn0/ip27.h> +#include <asm/sn/arch.h> + +extern asmlinkage void ip27_irq(void); +int (*irq_cannonicalize)(int irq); + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +unsigned long spurious_count = 0; + +void disable_irq(unsigned int irq_nr) +{ + panic("disable_irq() called ..."); +} + +void enable_irq(unsigned int irq_nr) +{ + panic("enable_irq() called ..."); +} + +/* This is stupid for an Origin which can have thousands of IRQs ... */ +static struct irqaction *irq_action[NR_IRQS]; + +int get_irq_list(char *buf) +{ + int i, len = 0; + struct irqaction * action; + + for (i = 0 ; i < 32 ; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", i, kstat.irqs[0][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) + ? " +" : "", + action->name); + } + len += sprintf(buf+len, "\n"); + } + return len; +} + +/* + * do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts + * have their own specific handlers). + */ +asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + hardirq_enter(cpu); + kstat.irqs[cpu][irq]++; + + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + } + hardirq_exit(cpu); + + /* unmasking and bottom half handling is done magically for us. */ +} + +/* For now ... */ +void ip27_do_irq(struct pt_regs *regs) +{ + hubreg_t pend0, mask0; + + pend0 = LOCAL_HUB_L(PI_INT_PEND0); + mask0 = LOCAL_HUB_L(PI_INT_MASK0_A); + + if (pend0 & mask0 & (1 << 9)) { + LOCAL_HUB_S(PI_INT_MASK0_A, mask0 & ~(1 << 9)); + LOCAL_HUB_S(PI_INT_PEND_MOD, 9); + LOCAL_HUB_L(PI_INT_MASK0_A); /* Flush */ + do_IRQ(9, regs); + LOCAL_HUB_S(PI_INT_MASK0_A, mask0); + } +} + + +/* Startup one of the (PCI ...) IRQs routes over a bridge. */ +static unsigned int bridge_startup(unsigned int irq) +{ + bridge_t *bridge = (bridge_t *) 0x9200000008000000; + bridgereg_t br; + int pin; + + /* FIIIIIXME ... Temporary kludge. This knows how interrupts are + setup in _my_ Origin. */ + switch (irq) { + case IOC3_SERIAL_INT: pin = 3; break; + case IOC3_ETH_INT: pin = 2; break; + default: panic("bridge_startup: whoops?"); + } + + br = LOCAL_HUB_L(PI_INT_MASK0_A); + LOCAL_HUB_S(PI_INT_MASK0_A, br | (1 << irq)); + LOCAL_HUB_L(PI_INT_MASK0_A); /* Flush */ + + bridge->b_int_addr[pin].addr = 0x20000 | irq; + bridge->b_int_enable |= (1 << pin); + bridge->b_widget.w_tflush; /* Flush */ + + return 0; /* Never anything pending. */ +} + +/* Startup one of the (PCI ...) IRQs routes over a bridge. */ +static unsigned int bridge_shutdown(unsigned int irq) +{ + bridge_t *bridge = (bridge_t *) 0x9200000008000000; + bridgereg_t br; + int pin; + + /* FIIIIIXME ... Temporary kludge. This knows how interrupts are + setup in _my_ Origin. */ + switch (irq) { + case IOC3_SERIAL_INT: pin = 3; break; + case IOC3_ETH_INT: pin = 2; break; + default: panic("bridge_startup: whoops?"); + } + + br = LOCAL_HUB_L(PI_INT_MASK0_A); + LOCAL_HUB_S(PI_INT_MASK0_A, br & ~(1 << irq)); + LOCAL_HUB_L(PI_INT_MASK0_A); /* Flush */ + + bridge->b_int_enable &= ~(1 << pin); + bridge->b_widget.w_tflush; /* Flush */ + + return 0; /* Never anything pending. */ +} + +static void bridge_init(void) +{ + bridge_t *bridge = (bridge_t *) 0x9200000008000000; + + /* Hmm... IRIX sets additional bits in the address which are + documented as reserved in the bridge docs ... */ + bridge->b_int_mode = 0x0; /* Don't clear ints */ + bridge->b_wid_int_upper = 0x000a8000; /* Ints to node 0 */ + bridge->b_wid_int_lower = 0x01000090; + bridge->b_dir_map = 0xa00000; /* DMA */ + bridge->b_int_enable = 0; + bridge->b_widget.w_tflush; /* Flush */ + set_cp0_status(SRB_DEV0 | SRB_DEV1, SRB_DEV0 | SRB_DEV1); +} + +void irq_debug(void) +{ + bridge_t *bridge = (bridge_t *) 0x9200000008000000; + + printk("bridge->b_int_status = 0x%x\n", bridge->b_int_status); + printk("bridge->b_int_enable = 0x%x\n", bridge->b_int_enable); + printk("PI_INT_PEND0 = 0x%x\n", LOCAL_HUB_L(PI_INT_PEND0)); + printk("PI_INT_MASK0_A = 0x%x\n", LOCAL_HUB_L(PI_INT_MASK0_A)); +} + +int setup_irq(int irq, struct irqaction *new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_and_cli(flags); + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { + restore_flags(flags); + return -EBUSY; + } + + /* Add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + *p = new; + + if (!shared) { + bridge_startup(irq); + } + restore_flags(flags); + + return 0; +} + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char * devname, void *dev_id) +{ + int retval; + struct irqaction *action; + + if (irq < 8 > irq > 9) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *)kmalloc(sizeof(*action), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_irq(irq, action); + if (retval) + kfree(action); + + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction * action, **p; + unsigned long flags; + + if (irq < 8 > irq > 9) { + printk("Trying to free IRQ%d\n", irq); + return; + } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_and_cli(flags); + *p = action->next; + if (!irq[irq_action]) + bridge_shutdown(irq); + restore_flags(flags); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); +} + +/* Useless ISA nonsense. */ +unsigned long probe_irq_on (void) +{ + return 0; +} + +int probe_irq_off (unsigned long irqs) +{ + return 0; +} + +static int indy_irq_cannonicalize(int irq) +{ + return irq; /* Sane hardware, sane code ... */ +} + +void __init init_IRQ(void) +{ + irq_cannonicalize = indy_irq_cannonicalize; + + bridge_init(); + set_except_vector(0, ip27_irq); +} diff --git a/arch/mips64/sgi-ip27/ip27-klconfig.c b/arch/mips64/sgi-ip27/ip27-klconfig.c new file mode 100644 index 000000000..54073abfd --- /dev/null +++ b/arch/mips64/sgi-ip27/ip27-klconfig.c @@ -0,0 +1,33 @@ +/* $Id$ + * + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/kernel_stat.h> +#include <linux/param.h> +#include <linux/timex.h> +#include <linux/mm.h> + +#include <asm/sn/klconfig.h> + +lboard_t *find_lboard(unsigned int type) +{ + lboard_t *b; + + for ( +b = KL_CONFIG_INFO(get_nasid()); +b; +b = KLCF_NEXT(b)) { + if (KLCF_REMOTE(b)) + continue; /* Skip remote boards. */ + + if (b->brd_type == type) + return (lboard_t *) b; + } + + return NULL; +} diff --git a/arch/mips64/sgi-ip27/ip27-memory.c b/arch/mips64/sgi-ip27/ip27-memory.c new file mode 100644 index 000000000..a3110cc31 --- /dev/null +++ b/arch/mips64/sgi-ip27/ip27-memory.c @@ -0,0 +1,65 @@ +/* $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) 2000 by Ralf Baechle + * Copyright (C) 2000 by Silicon Graphics, Inc. + * + * On SGI IP27 the ARC memory configuration data is completly bogus but + * alternate easier to use mechanisms are available. + */ +#include <linux/init.h> +#include <linux/config.h> +#include <linux/kernel.h> + +#include <asm/page.h> +#include <asm/bootinfo.h> +#include <asm/sn/klconfig.h> + +void __init +prom_meminit(void) +{ + unsigned long mb; + int bank, size; + lboard_t *board; + klmembnk_t *mem; + + board = find_lboard(KLTYPE_IP27); + if (!board) + panic("Can't find memory info for myself."); + + mem = (klmembnk_t *) KLCF_COMP(board, IP27_MEM_INDEX); + if (!mem) + panic("I'm running but don't exist?"); + + mb = 0; + for (bank = 0; bank < MD_MEM_BANKS; bank++) { + size = KLCONFIG_MEMBNK_SIZE(mem, bank); + mb += size; + if (size != 512) { + break; + } + } + + if (bank != MD_MEM_BANKS && size != 0) + printk("Warning: noncontiguous memory configuration, " + "not using entire available memory."); + + printk("Found %ldmb of memory.\n", mb); + mips_memory_upper = PAGE_OFFSET + (mb << 20); +} + +/* Called from mem_init() to fixup the mem_map page settings. */ +void __init +prom_fixup_mem_map(unsigned long start, unsigned long end) +{ + /* mem_map is already completly setup. */ +} + +void __init +prom_free_prom_memory (void) +{ + /* We got nothing to free here ... */ +} diff --git a/arch/mips64/sgi-ip27/ip27-reset.c b/arch/mips64/sgi-ip27/ip27-reset.c new file mode 100644 index 000000000..fade7ed76 --- /dev/null +++ b/arch/mips64/sgi-ip27/ip27-reset.c @@ -0,0 +1,45 @@ +/* $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. + * + * Reset an IP27. + * + * Copyright (C) 1997, 1998, 1999 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/timer.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/system.h> +#include <asm/sgialib.h> +#include <asm/sgi/sgihpc.h> +#include <asm/sgi/sgint23.h> + +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??? */ +void machine_restart(char *command) +{ + ArcReboot(); +} + +void machine_halt(void) +{ + ArcEnterInteractiveMode(); +} + +void machine_power_off(void) +{ + /* To do ... */ +} + +void ip27_reboot_setup(void) +{ + /* Nothing to do on IP27. */ +} diff --git a/arch/mips64/sgi-ip27/ip27-setup.c b/arch/mips64/sgi-ip27/ip27-setup.c new file mode 100644 index 000000000..52e3782dd --- /dev/null +++ b/arch/mips64/sgi-ip27/ip27-setup.c @@ -0,0 +1,88 @@ +/* $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. + * + * SGI IP27 specific setup. + * + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Silcon Graphics, Inc. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/sn/types.h> +#include <asm/sn/sn0/addrs.h> +#include <asm/sn/sn0/hubni.h> +#include <asm/sn/sn0/hubio.h> +#include <asm/sn/klconfig.h> +#include <asm/ioc3.h> +#include <asm/mipsregs.h> +#include <asm/sn/klconfig.h> + +/* + * get_nasid() returns the physical node id number of the caller. + */ +nasid_t +get_nasid(void) +{ + return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) + >> NSRI_NODEID_SHFT); +} + +/* Extracted from the IOC3 meta driver. FIXME. */ +static inline void ioc3_sio_init(void) +{ + struct ioc3 *ioc3; + nasid_t nid; + long loops; + + nid = get_nasid(); + ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; + + ioc3->sscr_a = 0; /* PIO mode for uarta. */ + ioc3->sscr_b = 0; /* PIO mode for uartb. */ + ioc3->sio_iec = ~0; + ioc3->sio_ies = (SIO_IR_SA_INT | SIO_IR_SB_INT); + + loops=1000000; while(loops--); + ioc3->sregs.uarta.iu_fcr = 0; + ioc3->sregs.uartb.iu_fcr = 0; + loops=1000000; while(loops--); +} + +static inline void ioc3_eth_init(void) +{ + struct ioc3 *ioc3; + nasid_t nid; + + nid = get_nasid(); + ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; + + ioc3->eier = 0; +} + +void __init ip27_setup(void) +{ + nasid_t nid; + hubreg_t p, e; + + set_cp0_status(ST0_IM, 0); + nid = get_nasid(); + printk("IP27: Running on node %d.\n", nid); + + p = LOCAL_HUB_L(PI_CPU_PRESENT_A) & 1; + e = LOCAL_HUB_L(PI_CPU_ENABLE_A) & 1; + printk("Node %d has %s primary CPU%s.\n", nid, + p ? "a" : "no", + e ? ", CPU is running" : ""); + + p = LOCAL_HUB_L(PI_CPU_PRESENT_B) & 1; + e = LOCAL_HUB_L(PI_CPU_ENABLE_B) & 1; + printk("Node %d has %s secondary CPU%s.\n", nid, + p ? "a" : "no", + e ? ", CPU is running" : ""); + + ioc3_sio_init(); + ioc3_eth_init(); +} diff --git a/arch/mips64/sgi-ip27/ip27-timer.c b/arch/mips64/sgi-ip27/ip27-timer.c new file mode 100644 index 000000000..e5fd6c377 --- /dev/null +++ b/arch/mips64/sgi-ip27/ip27-timer.c @@ -0,0 +1,115 @@ +/* $Id$ + * + * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org) + * Copytight (C) 1999 Silicon Graphics, Inc. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/kernel_stat.h> +#include <linux/param.h> +#include <linux/timex.h> +#include <linux/mm.h> + +#include <asm/pgtable.h> +#include <asm/sgialib.h> +#include <asm/sn/arch.h> +#include <asm/sn/addrs.h> +#include <asm/sn/sn0/ip27.h> +#include <asm/sn/sn0/hub.h> + +/* This is a hack; we really need to figure these values out dynamically + * + * Since 800 ns works very well with various HUB frequencies, such as + * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. + * + * Ralf: which clock rate is used to feed the counter? + */ +#define NSEC_PER_CYCLE 800 +#define NSEC_PER_SEC 1000000000 +#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE) +#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ) + +static unsigned long ct_cur; /* What counter should be at next timer irq */ + +extern rwlock_t xtime_lock; + +void rt_timer_interrupt(struct pt_regs *regs) +{ + int irq = 7; /* XXX Assign number */ + + write_lock(&xtime_lock); + +again: + LOCAL_HUB_S(PI_RT_PEND_A, 0); /* Ack */ + ct_cur += CYCLES_PER_JIFFY; + LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur); + + if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur) + goto again; + + kstat.irqs[0][irq]++; + do_timer(regs); + + write_unlock(&xtime_lock); +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + read_lock_irqsave(&xtime_lock, flags); + *tv = xtime; + read_unlock_irqrestore(&xtime_lock, flags); +} + +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq(&xtime_lock); + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + write_unlock_irq(&xtime_lock); +} + +/* Includes for ioc3_init(). */ +#include <linux/init.h> +#include <asm/sn/types.h> +#include <asm/sn/sn0/addrs.h> +#include <asm/sn/sn0/hubni.h> +#include <asm/sn/sn0/hubio.h> +#include <asm/sn/klconfig.h> +#include <asm/ioc3.h> +#include <asm/pci/bridge.h> + +extern void ioc3_eth_init(void); + +void __init time_init(void) +{ + unsigned int cpufreq; + char *cpufreqstr; + + /* Is this timesource good enough? Ok to assume that all CPUs have + this clockrate? Are they 100% synchronously clocked? */ + cpufreqstr = ArcGetEnvironmentVariable("cpufreq"); + if (cpufreqstr == NULL) + panic("Cannot detect CPU clock rate"); + cpufreq = simple_strtoul(cpufreqstr, NULL, 10); + printk("PROM says CPU clock is %dMHz\n", cpufreq); + + /* We didn't flush the TLB earlier since the ARC firmware depends on + it. So do it now. */ + flush_tlb_all(); + + /* Don't worry about second CPU, it's disabled. */ + LOCAL_HUB_S(PI_RT_EN_A, 1); + LOCAL_HUB_S(PI_PROF_EN_A, 0); + ct_cur = CYCLES_PER_JIFFY; + LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur); + LOCAL_HUB_S(PI_RT_COUNT, 0); + LOCAL_HUB_S(PI_RT_PEND_A, 0); + + set_cp0_status(SRB_TIMOCLK, SRB_TIMOCLK); +} |