diff options
Diffstat (limited to 'arch/sparc64')
139 files changed, 0 insertions, 51402 deletions
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig deleted file mode 100644 index ab733be9af0..00000000000 --- a/arch/sparc64/Kconfig +++ /dev/null @@ -1,400 +0,0 @@ -# $Id: config.in,v 1.158 2002/01/24 22:14:44 davem Exp $ -# For a description of the syntax of this configuration file, -# see the Configure script. -# - -mainmenu "Linux/UltraSPARC Kernel Configuration" - -config SPARC - bool - default y - -config SPARC64 - bool - default y - help - SPARC is a family of RISC microprocessors designed and marketed by - Sun Microsystems, incorporated. This port covers the newer 64-bit - UltraSPARC. The UltraLinux project maintains both the SPARC32 and - SPARC64 ports; its web page is available at - <http://www.ultralinux.org/>. - -config 64BIT - def_bool y - -config MMU - bool - default y - -config TIME_INTERPOLATION - bool - default y - -config ARCH_MAY_HAVE_PC_FDC - bool - default y - -choice - prompt "Kernel page size" - default SPARC64_PAGE_SIZE_8KB - -config SPARC64_PAGE_SIZE_8KB - bool "8KB" - help - This lets you select the page size of the kernel. - - 8KB and 64KB work quite well, since Sparc ELF sections - provide for up to 64KB alignment. - - Therefore, 512KB and 4MB are for expert hackers only. - - If you don't know what to do, choose 8KB. - -config SPARC64_PAGE_SIZE_64KB - bool "64KB" - -config SPARC64_PAGE_SIZE_512KB - bool "512KB" - -config SPARC64_PAGE_SIZE_4MB - bool "4MB" - -endchoice - -config SECCOMP - bool "Enable seccomp to safely compute untrusted bytecode" - depends on PROC_FS - default y - help - This kernel feature is useful for number crunching applications - that may need to compute untrusted bytecode during their - execution. By using pipes or other transports made available to - the process as file descriptors supporting the read/write - syscalls, it's possible to isolate those applications in - their own address space using seccomp. Once seccomp is - enabled via /proc/<pid>/seccomp, it cannot be disabled - and the task is only allowed to execute a few safe syscalls - defined by each seccomp mode. - - If unsure, say Y. Only embedded should say N here. - -source kernel/Kconfig.hz - -source "init/Kconfig" - -config SYSVIPC_COMPAT - bool - depends on COMPAT && SYSVIPC - default y - -menu "General machine setup" - -config SMP - bool "Symmetric multi-processing support" - ---help--- - This enables support for systems with more than one CPU. If you have - a system with only one CPU, say N. If you have a system with more than - one CPU, say Y. - - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on many, but not all, - singleprocessor machines. On a singleprocessor machine, the kernel - will run faster if you say N here. - - People using multiprocessor machines who say Y here should also say - Y to "Enhanced Real Time Clock Support", below. The "Advanced Power - Management" code will be disabled if you say Y here. - - See also the <file:Documentation/smp.txt>, - <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at - <http://www.tldp.org/docs.html#howto>. - - If you don't know what to do here, say N. - -config PREEMPT - bool "Preemptible Kernel" - help - This option reduces the latency of the kernel when reacting to - real-time or interactive events by allowing a low priority process to - be preempted even if it is in kernel mode executing a system call. - This allows applications to run more reliably even when the system is - under load. - - Say Y here if you are building a kernel for a desktop, embedded - or real-time system. Say N if you are unsure. - -config NR_CPUS - int "Maximum number of CPUs (2-64)" - range 2 64 - depends on SMP - default "32" - -source "drivers/cpufreq/Kconfig" - -config US3_FREQ - tristate "UltraSPARC-III CPU Frequency driver" - depends on CPU_FREQ - select CPU_FREQ_TABLE - help - This adds the CPUFreq driver for UltraSPARC-III processors. - - For details, take a look at <file:Documentation/cpu-freq>. - - If in doubt, say N. - -config US2E_FREQ - tristate "UltraSPARC-IIe CPU Frequency driver" - depends on CPU_FREQ - select CPU_FREQ_TABLE - help - This adds the CPUFreq driver for UltraSPARC-IIe processors. - - For details, take a look at <file:Documentation/cpu-freq>. - - If in doubt, say N. - -# Global things across all Sun machines. -config RWSEM_GENERIC_SPINLOCK - bool - -config RWSEM_XCHGADD_ALGORITHM - bool - default y - -config GENERIC_CALIBRATE_DELAY - bool - default y - -choice - prompt "SPARC64 Huge TLB Page Size" - depends on HUGETLB_PAGE - default HUGETLB_PAGE_SIZE_4MB - -config HUGETLB_PAGE_SIZE_4MB - bool "4MB" - -config HUGETLB_PAGE_SIZE_512K - depends on !SPARC64_PAGE_SIZE_4MB - bool "512K" - -config HUGETLB_PAGE_SIZE_64K - depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB - bool "64K" - -endchoice - -endmenu - -source "mm/Kconfig" - -config GENERIC_ISA_DMA - bool - default y - -config ISA - bool - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -config ISAPNP - bool - help - Say Y here if you would like support for ISA Plug and Play devices. - Some information is in <file:Documentation/isapnp.txt>. - - To compile this driver as a module, choose M here: the - module will be called isapnp. - - If unsure, say Y. - -config EISA - bool - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config MCA - bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - <file:Documentation/mca.txt> (and especially the web page given - there) before attempting to build an MCA bus kernel. - -config PCMCIA - tristate - ---help--- - Say Y here if you want to attach PCMCIA- or PC-cards to your Linux - computer. These are credit-card size devices such as network cards, - modems or hard drives often used with laptops computers. There are - actually two varieties of these cards: the older 16 bit PCMCIA cards - and the newer 32 bit CardBus cards. If you want to use CardBus - cards, you need to say Y here and also to "CardBus support" below. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file <file:Documentation/Changes> - for location). Please also read the PCMCIA-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - To compile this driver as modules, choose M here: the - modules will be called pcmcia_core and ds. - -config SBUS - bool - default y - -config SBUSCHAR - bool - default y - -config SUN_AUXIO - bool - default y - -config SUN_IO - bool - default y - -config PCI - bool "PCI support" - help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - - The PCI-HOWTO, available from - <http://www.tldp.org/docs.html#howto>, contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - -config PCI_DOMAINS - bool - default PCI - -source "drivers/pci/Kconfig" - -config SUN_OPENPROMFS - tristate "Openprom tree appears in /proc/openprom" - help - If you say Y, the OpenPROM device tree will be available as a - virtual file system, which you can mount to /proc/openprom by "mount - -t openpromfs none /proc/openprom". - - To compile the /proc/openprom support as a module, choose M here: the - module will be called openpromfs. If unsure, choose M. - -config SPARC32_COMPAT - bool "Kernel support for Linux/Sparc 32bit binary compatibility" - help - This allows you to run 32-bit binaries on your Ultra. - Everybody wants this; say Y. - -config COMPAT - bool - depends on SPARC32_COMPAT - default y - -config BINFMT_ELF32 - tristate "Kernel support for 32-bit ELF binaries" - depends on SPARC32_COMPAT - help - This allows you to run 32-bit Linux/ELF binaries on your Ultra. - Everybody wants this; say Y. - -config BINFMT_AOUT32 - bool "Kernel support for 32-bit (ie. SunOS) a.out binaries" - depends on SPARC32_COMPAT - help - This allows you to run 32-bit a.out format binaries on your Ultra. - If you want to run SunOS binaries (see SunOS binary emulation below) - or other a.out binaries, say Y. If unsure, say N. - -menu "Executable file formats" - -source "fs/Kconfig.binfmt" - -config SUNOS_EMUL - bool "SunOS binary emulation" - depends on BINFMT_AOUT32 - help - This allows you to run most SunOS binaries. If you want to do this, - say Y here and place appropriate files in /usr/gnemul/sunos. See - <http://www.ultralinux.org/faq.html> for more information. If you - want to run SunOS binaries on an Ultra you must also say Y to - "Kernel support for 32-bit a.out binaries" above. - -config SOLARIS_EMUL - tristate "Solaris binary emulation (EXPERIMENTAL)" - depends on SPARC32_COMPAT && EXPERIMENTAL - help - This is experimental code which will enable you to run (many) - Solaris binaries on your SPARC Linux machine. - - To compile this code as a module, choose M here: the - module will be called solaris. - -endmenu - -config CMDLINE_BOOL - bool "Default bootloader kernel arguments" - -config CMDLINE - string "Initial kernel command string" - depends on CMDLINE_BOOL - default "console=ttyS0,9600 root=/dev/sda1" - help - Say Y here if you want to be able to pass default arguments to - the kernel. This will be overridden by the bootloader, if you - use one (such as SILO). This is most useful if you want to boot - a kernel from TFTP, and want default options to be available - with having them passed on the command line. - - NOTE: This option WILL override the PROM bootargs setting! - -source "net/Kconfig" - -source "drivers/Kconfig" - -source "drivers/sbus/char/Kconfig" - -source "drivers/fc4/Kconfig" - -source "fs/Kconfig" - -menu "Instrumentation Support" - depends on EXPERIMENTAL - -source "arch/sparc64/oprofile/Kconfig" - -config KPROBES - bool "Kprobes (EXPERIMENTAL)" - help - Kprobes allows you to trap at almost any kernel address and - execute a callback function. register_kprobe() establishes - a probepoint and specifies the callback. Kprobes is useful - for kernel debugging, non-intrusive instrumentation and testing. - If in doubt, say "N". -endmenu - -source "arch/sparc64/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug deleted file mode 100644 index 3e31be494e5..00000000000 --- a/arch/sparc64/Kconfig.debug +++ /dev/null @@ -1,44 +0,0 @@ -menu "Kernel hacking" - -source "lib/Kconfig.debug" - -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_DCFLUSH - bool "D-cache flush debugging" - depends on DEBUG_KERNEL - -config STACK_DEBUG - depends on DEBUG_KERNEL - bool "Stack Overflow Detection Support" - -config DEBUG_BOOTMEM - depends on DEBUG_KERNEL - bool "Debug BOOTMEM initialization" - -config DEBUG_PAGEALLOC - bool "Page alloc debugging" - depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND - help - Unmap pages from the kernel linear mapping after free_pages(). - This results in a large slowdown, but helps to find certain types - of memory corruptions. - -config MCOUNT - bool - depends on STACK_DEBUG - default y - -config FRAME_POINTER - bool - depends on MCOUNT - default y - -endmenu diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile deleted file mode 100644 index cad10c5b83d..00000000000 --- a/arch/sparc64/Makefile +++ /dev/null @@ -1,78 +0,0 @@ -# $Id: Makefile,v 1.52 2002/02/09 19:49:31 davem Exp $ -# sparc64/Makefile -# -# Makefile for the architecture dependent flags and dependencies on the -# 64-bit Sparc. -# -# Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu) -# Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) -# - -CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -m64 - -CPPFLAGS_vmlinux.lds += -Usparc - -CC := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo $(CC); else echo sparc64-linux-gcc; fi ) - -NEW_GCC := $(call cc-option-yn, -m64 -mcmodel=medlow) -NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) -UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; ) - -export NEW_GCC - -ifneq ($(NEW_GAS),y) -AS = sparc64-linux-as -LD = sparc64-linux-ld -NM = sparc64-linux-nm -AR = sparc64-linux-ar -RANLIB = sparc64-linux-ranlib -else -AS := $(AS) -64 -LDFLAGS := -m elf64_sparc -endif - -ifneq ($(UNDECLARED_REGS),y) -CC_UNDECL = -else -CC_UNDECL = -Wa,--undeclared-regs -AS := $(AS) --undeclared-regs -endif - -ifneq ($(NEW_GCC),y) - CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \ - -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare -else - CFLAGS := $(CFLAGS) -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ - -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ - $(CC_UNDECL) - AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL) -endif - -ifeq ($(CONFIG_MCOUNT),y) - CFLAGS := $(CFLAGS) -pg -endif - -head-y := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o - -core-y += arch/sparc64/kernel/ arch/sparc64/mm/ -core-$(CONFIG_SOLARIS_EMUL) += arch/sparc64/solaris/ -core-y += arch/sparc64/math-emu/ -libs-y += arch/sparc64/prom/ arch/sparc64/lib/ - -# FIXME: is drivers- right? -drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/ - -boot := arch/sparc64/boot - -image tftpboot.img vmlinux.aout: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ - -archclean: - $(Q)$(MAKE) $(clean)=$(boot) - -define archhelp - echo '* vmlinux - Standard sparc64 kernel' - echo ' vmlinux.aout - a.out kernel for sparc64' - echo ' tftpboot.img - Image prepared for tftp' -endef - diff --git a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile deleted file mode 100644 index 6968a6da57d..00000000000 --- a/arch/sparc64/boot/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# $Id: Makefile,v 1.4 1997/12/15 20:08:56 ecd Exp $ -# Makefile for the Sparc64 boot stuff. -# -# Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) -# Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - -ROOT_IMG := /usr/src/root.img -ELFTOAOUT := elftoaout - -hostprogs-y := piggyback -targets := image tftpboot.img vmlinux.aout - -quiet_cmd_elftoaout = ELF2AOUT $@ - cmd_elftoaout = $(ELFTOAOUT) vmlinux -o $@ -quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback $@ System.map $(ROOT_IMG) -quiet_cmd_strip = STRIP $@ - cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@ - - -# Actual linking -$(obj)/image: vmlinux FORCE - $(call if_changed,strip) - @echo ' kernel: $@ is ready' - -$(obj)/tftpboot.img: vmlinux $(obj)/piggyback System.map $(ROOT_IMG) FORCE - $(call if_changed,elftoaout) - $(call if_changed,piggy) - @echo ' kernel: $@ is ready' - -$(obj)/vmlinux.aout: vmlinux FORCE - $(call if_changed,elftoaout) - @echo ' kernel: $@ is ready' - diff --git a/arch/sparc64/boot/piggyback.c b/arch/sparc64/boot/piggyback.c deleted file mode 100644 index 36f907408c6..00000000000 --- a/arch/sparc64/boot/piggyback.c +++ /dev/null @@ -1,109 +0,0 @@ -/* $Id: piggyback.c,v 1.2 2000/09/19 14:34:39 anton Exp $ - Simple utility to make a single-image install kernel with initial ramdisk - for Sparc64 tftpbooting without need to set up nfs. - - Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <dirent.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> - -/* Note: run this on an a.out kernel (use elftoaout for it), as PROM looks for a.out image onlly - usage: piggyback vmlinux System.map tail, where tail is gzipped fs of the initial ramdisk */ - -void die(char *str) -{ - perror (str); - exit(1); -} - -int main(int argc,char **argv) -{ - char buffer [1024], *q, *r; - unsigned int i, j, k, start, end, offset; - FILE *map; - struct stat s; - int image, tail; - - if (stat (argv[3], &s) < 0) die (argv[3]); - map = fopen (argv[2], "r"); - if (!map) die(argv[2]); - while (fgets (buffer, 1024, map)) { - if (!strcmp (buffer + 19, "_start\n")) - start = strtoul (buffer + 8, NULL, 16); - else if (!strcmp (buffer + 19, "_end\n")) - end = strtoul (buffer + 8, NULL, 16); - } - fclose (map); - if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]); - if (read(image,buffer,512) != 512) die(argv[1]); - if (!memcmp (buffer, "\177ELF", 4)) { - unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28)); - - i = p[1] + *(unsigned int *)(buffer + 24) - p[2]; - if (lseek(image,i,0) < 0) die("lseek"); - if (read(image,buffer,512) != 512) die(argv[1]); - j = 0; - } else if (*(unsigned int *)buffer == 0x01030107) { - i = j = 32; - } else { - fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n"); - exit(1); - } - k = i; - if (j == 32 && buffer[40] == 'H' && buffer[41] == 'd' && buffer[42] == 'r' && buffer[43] == 'S') { - offset = 40 + 10; - } else { - i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512; - if (lseek(image,i,0) < 0) die("lseek"); - if (read(image,buffer,1024) != 1024) die(argv[1]); - for (q = buffer, r = q + 512; q < r; q += 4) { - if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') - break; - } - if (q == r) { - fprintf (stderr, "Couldn't find headers signature in the kernel.\n"); - exit(1); - } - offset = i + (q - buffer) + 10; - } - if (lseek(image, offset, 0) < 0) die ("lseek"); - *(unsigned *)buffer = 0; - *(unsigned *)(buffer + 4) = 0x01000000; - *(unsigned *)(buffer + 8) = ((end + 32 + 8191) & ~8191); - *(unsigned *)(buffer + 12) = s.st_size; - if (write(image,buffer+2,14) != 14) die (argv[1]); - if (lseek(image, 4, 0) < 0) die ("lseek"); - *(unsigned *)buffer = ((end + 32 + 8191) & ~8191) - (start & ~0x3fffffUL) + s.st_size; - *(unsigned *)(buffer + 4) = 0; - *(unsigned *)(buffer + 8) = 0; - if (write(image,buffer,12) != 12) die (argv[1]); - if (lseek(image, k - start + ((end + 32 + 8191) & ~8191), 0) < 0) die ("lseek"); - if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); - while ((i = read (tail,buffer,1024)) > 0) - if (write(image,buffer,i) != i) die (argv[1]); - if (close(image) < 0) die("close"); - if (close(tail) < 0) die("close"); - return 0; -} diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig deleted file mode 100644 index 9ceddad0fb4..00000000000 --- a/arch/sparc64/defconfig +++ /dev/null @@ -1,1352 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc1 -# Wed Jan 18 13:41:02 2006 -# -CONFIG_SPARC=y -CONFIG_SPARC64=y -CONFIG_64BIT=y -CONFIG_MMU=y -CONFIG_TIME_INTERPOLATION=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_SPARC64_PAGE_SIZE_8KB=y -# CONFIG_SPARC64_PAGE_SIZE_64KB is not set -# CONFIG_SPARC64_PAGE_SIZE_512KB is not set -# CONFIG_SPARC64_PAGE_SIZE_4MB is not set -CONFIG_SECCOMP=y -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y -# CONFIG_HZ_1000 is not set -CONFIG_HZ=250 - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_UID16=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -CONFIG_SLAB=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y -CONFIG_KMOD=y - -# -# Block layer -# - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_SYSVIPC_COMPAT=y - -# -# General machine setup -# -# CONFIG_SMP is not set -# CONFIG_PREEMPT is not set -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=m -# CONFIG_CPU_FREQ_DEBUG is not set -CONFIG_CPU_FREQ_STAT=m -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_US3_FREQ=m -CONFIG_US2E_FREQ=m -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_HUGETLB_PAGE_SIZE_4MB=y -# CONFIG_HUGETLB_PAGE_SIZE_512K is not set -# CONFIG_HUGETLB_PAGE_SIZE_64K is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_GENERIC_ISA_DMA=y -CONFIG_SBUS=y -CONFIG_SBUSCHAR=y -CONFIG_SUN_AUXIO=y -CONFIG_SUN_IO=y -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -# CONFIG_PCI_LEGACY_PROC is not set -# CONFIG_PCI_DEBUG is not set -CONFIG_SUN_OPENPROMFS=m -CONFIG_SPARC32_COMPAT=y -CONFIG_COMPAT=y -CONFIG_BINFMT_ELF32=y -# CONFIG_BINFMT_AOUT32 is not set - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -# CONFIG_SOLARIS_EMUL is not set -# CONFIG_CMDLINE_BOOL is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=m -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -CONFIG_ARPD=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_INET_TUNNEL=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -CONFIG_TCP_CONG_ADVANCED=y - -# -# TCP congestion control -# -CONFIG_TCP_CONG_BIC=y -CONFIG_TCP_CONG_CUBIC=m -CONFIG_TCP_CONG_WESTWOOD=m -CONFIG_TCP_CONG_HTCP=m -CONFIG_TCP_CONG_HSTCP=m -CONFIG_TCP_CONG_HYBLA=m -CONFIG_TCP_CONG_VEGAS=m -CONFIG_TCP_CONG_SCALABLE=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_INET6_TUNNEL=m -CONFIG_IPV6_TUNNEL=m -# CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# -CONFIG_IP_DCCP=m -CONFIG_INET_DCCP_DIAG=m - -# -# DCCP CCIDs Configuration (EXPERIMENTAL) -# -CONFIG_IP_DCCP_CCID3=m -CONFIG_IP_DCCP_TFRC_LIB=m - -# -# DCCP Kernel Hacking -# -# CONFIG_IP_DCCP_DEBUG is not set -# CONFIG_IP_DCCP_UNLOAD_HACK is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -CONFIG_VLAN_8021Q=m -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# -# CONFIG_TIPC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_IEEE80211 is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -CONFIG_FW_LOADER=y -# CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# -CONFIG_CONNECTOR=m - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_SX8 is not set -CONFIG_BLK_DEV_UB=m -# CONFIG_BLK_DEV_RAM is not set -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_CDROM_PKTCDVD=m -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -CONFIG_CDROM_PKTCDVD_WCACHE=y -CONFIG_ATA_OVER_ETH=m - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_IDEPCI_SHARE_IRQ is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -CONFIG_IDEDMA_ONLYDISK=y -# CONFIG_BLK_DEV_AEC62XX is not set -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_ARM is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -CONFIG_RAID_ATTRS=m -CONFIG_SCSI=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=m -# CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -CONFIG_SCSI_SPI_ATTRS=y -CONFIG_SCSI_FC_ATTRS=y -CONFIG_SCSI_ISCSI_ATTRS=m -# CONFIG_SCSI_SAS_ATTRS is not set - -# -# SCSI low-level drivers -# -CONFIG_ISCSI_TCP=m -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLOGICPTI is not set -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_LPFC is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_SUNESP is not set - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=m -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID10=m -CONFIG_MD_RAID5=m -CONFIG_MD_RAID6=m -CONFIG_MD_MULTIPATH=m -# CONFIG_MD_FAULTY is not set -CONFIG_BLK_DEV_DM=m -CONFIG_DM_CRYPT=m -CONFIG_DM_SNAPSHOT=m -CONFIG_DM_MIRROR=m -CONFIG_DM_ZERO=m -# CONFIG_DM_MULTIPATH is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# PHY device support -# -# CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=m -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -CONFIG_CASSINI=m -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set -# CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set -# CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_VIA_RHINE is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -CONFIG_E1000=m -CONFIG_E1000_NAPI=y -# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set -CONFIG_TIGON3=m -CONFIG_BNX2=m - -# -# Ethernet (10000 Mbit) -# -# CONFIG_CHELSIO_T1 is not set -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -CONFIG_KEYBOARD_SUNKBD=y -CONFIG_KEYBOARD_LKKBD=m -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_SERIAL=y -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -CONFIG_INPUT_MISC=y -CONFIG_INPUT_SPARCSPKR=y -# CONFIG_INPUT_UINPUT is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -# CONFIG_SERIO_SERPORT is not set -CONFIG_SERIO_PCIPS2=m -CONFIG_SERIO_LIBPS2=y -CONFIG_SERIO_RAW=m -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_SUNCORE=y -# CONFIG_SERIAL_SUNZILOG is not set -CONFIG_SERIAL_SUNSU=y -CONFIG_SERIAL_SUNSU_CONSOLE=y -CONFIG_SERIAL_SUNSAB=m -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -CONFIG_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# -CONFIG_I2C=y -# CONFIG_I2C_CHARDEV is not set - -# -# I2C Algorithms -# -CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set -# CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -# CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set -# CONFIG_I2C_VOODOO3 is not set -# CONFIG_I2C_PCA_ISA is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Hardware Monitoring support -# -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_FSCPOS is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SIS5595 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_VT8231 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Misc devices -# - -# -# Multimedia Capabilities Port drivers -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -CONFIG_FB=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_MACMODES is not set -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_SBUS is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set -CONFIG_FB_RADEON=y -CONFIG_FB_RADEON_I2C=y -# CONFIG_FB_RADEON_DEBUG is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_PCI is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_PROM_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -CONFIG_FONT_SUN8x16=y -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_LOGO_SUN_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# -CONFIG_SOUND=m - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_RAWMIDI=m -CONFIG_SND_SEQUENCER=m -CONFIG_SND_SEQ_DUMMY=m -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_SEQUENCER_OSS=y -# CONFIG_SND_RTCTIMER is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -CONFIG_SND_MPU401_UART=m -CONFIG_SND_AC97_CODEC=m -CONFIG_SND_AC97_BUS=m -CONFIG_SND_DUMMY=m -CONFIG_SND_VIRMIDI=m -CONFIG_SND_MTPAV=m -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# PCI devices -# -# CONFIG_SND_AD1889 is not set -CONFIG_SND_ALI5451=m -# CONFIG_SND_ATIIXP is not set -# CONFIG_SND_ATIIXP_MODEM is not set -# CONFIG_SND_AU8810 is not set -# CONFIG_SND_AU8820 is not set -# CONFIG_SND_AU8830 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_FM801 is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_PCXHR is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VIA82XX_MODEM is not set -# CONFIG_SND_VX222 is not set -# CONFIG_SND_YMFPCI is not set - -# -# USB devices -# -# CONFIG_SND_USB_AUDIO is not set - -# -# ALSA Sparc devices -# -# CONFIG_SND_SUN_AMD7930 is not set -CONFIG_SND_SUN_CS4231=m -# CONFIG_SND_SUN_DBRI is not set - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=m -# CONFIG_USB_EHCI_SPLIT_ISO is not set -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set -# CONFIG_USB_ISP116X_HCD is not set -CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_BIG_ENDIAN is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y -CONFIG_USB_UHCI_HCD=m -# CONFIG_USB_SL811_HCD is not set - -# -# USB Device Class drivers -# -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# may also be needed; see USB_STORAGE Help for more information -# -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=y -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -CONFIG_USB_HIDDEV=y -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_MON is not set - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TEST is not set - -# -# USB DSL modem support -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# InfiniBand support -# -# CONFIG_INFINIBAND is not set - -# -# SN Devices -# - -# -# Misc Linux/SPARC drivers -# -CONFIG_SUN_OPENPROMIO=m -CONFIG_SUN_MOSTEK_RTC=y -# CONFIG_OBP_FLASH is not set -# CONFIG_SUN_BPP is not set -# CONFIG_BBC_I2C is not set -# CONFIG_ENVCTRL is not set -# CONFIG_DISPLAY7SEG is not set - -# -# Fibre Channel support -# -# CONFIG_FC4 is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_RAMFS=y -CONFIG_RELAYFS_FS=m -# CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SUN_PARTITION=y - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Instrumentation Support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -CONFIG_KPROBES=y - -# -# Kernel hacking -# -CONFIG_PRINTK_TIME=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=18 -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_SCHEDSTATS=y -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_FS=y -# CONFIG_DEBUG_VM is not set -CONFIG_FORCED_INLINING=y -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_DCFLUSH is not set -# CONFIG_STACK_DEBUG is not set -# CONFIG_DEBUG_BOOTMEM is not set -# CONFIG_DEBUG_PAGEALLOC is not set - -# -# Security options -# -CONFIG_KEYS=y -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_TEST=m - -# -# Hardware crypto devices -# - -# -# Library routines -# -CONFIG_CRC_CCITT=m -CONFIG_CRC16=m -CONFIG_CRC32=y -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile deleted file mode 100644 index 83d67eb1889..00000000000 --- a/arch/sparc64/kernel/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# $Id: Makefile,v 1.70 2002/02/09 19:49:30 davem Exp $ -# Makefile for the linux kernel. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -extra-y := head.o init_task.o vmlinux.lds - -obj-y := process.o setup.o cpu.o idprom.o \ - traps.o devices.o auxio.o una_asm.o \ - irq.o ptrace.o time.o sys_sparc.o signal.o \ - unaligned.o central.o pci.o starfire.o semaphore.o \ - power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o - -obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ - pci_psycho.o pci_sabre.o pci_schizo.o -obj-$(CONFIG_SMP) += smp.o trampoline.o -obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o -obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o -obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o -obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o -obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o -obj-$(CONFIG_KPROBES) += kprobes.o - -ifdef CONFIG_SUNOS_EMUL - obj-y += sys_sunos32.o sunos_ioctl32.o -else - ifdef CONFIG_SOLARIS_EMUL - obj-y += sys_sunos32.o sunos_ioctl32.o - endif -endif - -ifneq ($(NEW_GCC),y) - CMODEL_CFLAG := -mmedlow -else - CMODEL_CFLAG := -m64 -mcmodel=medlow -endif - -head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \ - etrap.S rtrap.S winfixup.S entry.S diff --git a/arch/sparc64/kernel/asm-offsets.c b/arch/sparc64/kernel/asm-offsets.c deleted file mode 100644 index 9e263112a6e..00000000000 --- a/arch/sparc64/kernel/asm-offsets.c +++ /dev/null @@ -1 +0,0 @@ -/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */ diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c deleted file mode 100644 index 8852c20c8d9..00000000000 --- a/arch/sparc64/kernel/auxio.c +++ /dev/null @@ -1,152 +0,0 @@ -/* auxio.c: Probing for the Sparc AUXIO register at boot time. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * - * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net) - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/ioport.h> - -#include <asm/oplib.h> -#include <asm/io.h> -#include <asm/sbus.h> -#include <asm/ebus.h> -#include <asm/auxio.h> - -/* This cannot be static, as it is referenced in irq.c */ -void __iomem *auxio_register = NULL; - -enum auxio_type { - AUXIO_TYPE_NODEV, - AUXIO_TYPE_SBUS, - AUXIO_TYPE_EBUS -}; - -static enum auxio_type auxio_devtype = AUXIO_TYPE_NODEV; -static DEFINE_SPINLOCK(auxio_lock); - -static void __auxio_sbus_set(u8 bits_on, u8 bits_off) -{ - if (auxio_register) { - unsigned char regval; - unsigned long flags; - unsigned char newval; - - spin_lock_irqsave(&auxio_lock, flags); - - regval = sbus_readb(auxio_register); - newval = regval | bits_on; - newval &= ~bits_off; - newval &= ~AUXIO_AUX1_MASK; - sbus_writeb(newval, auxio_register); - - spin_unlock_irqrestore(&auxio_lock, flags); - } -} - -static void __auxio_ebus_set(u8 bits_on, u8 bits_off) -{ - if (auxio_register) { - unsigned char regval; - unsigned long flags; - unsigned char newval; - - spin_lock_irqsave(&auxio_lock, flags); - - regval = (u8)readl(auxio_register); - newval = regval | bits_on; - newval &= ~bits_off; - writel((u32)newval, auxio_register); - - spin_unlock_irqrestore(&auxio_lock, flags); - } -} - -static inline void __auxio_ebus_set_led(int on) -{ - (on) ? __auxio_ebus_set(AUXIO_PCIO_LED, 0) : - __auxio_ebus_set(0, AUXIO_PCIO_LED) ; -} - -static inline void __auxio_sbus_set_led(int on) -{ - (on) ? __auxio_sbus_set(AUXIO_AUX1_LED, 0) : - __auxio_sbus_set(0, AUXIO_AUX1_LED) ; -} - -void auxio_set_led(int on) -{ - switch(auxio_devtype) { - case AUXIO_TYPE_SBUS: - __auxio_sbus_set_led(on); - break; - case AUXIO_TYPE_EBUS: - __auxio_ebus_set_led(on); - break; - default: - break; - } -} - -static inline void __auxio_sbus_set_lte(int on) -{ - (on) ? __auxio_sbus_set(AUXIO_AUX1_LTE, 0) : - __auxio_sbus_set(0, AUXIO_AUX1_LTE) ; -} - -void auxio_set_lte(int on) -{ - switch(auxio_devtype) { - case AUXIO_TYPE_SBUS: - __auxio_sbus_set_lte(on); - break; - case AUXIO_TYPE_EBUS: - /* FALL-THROUGH */ - default: - break; - } -} - -void __init auxio_probe(void) -{ - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if(!strcmp(sdev->prom_name, "auxio")) - goto found_sdev; - } - } - -found_sdev: - if (sdev) { - auxio_devtype = AUXIO_TYPE_SBUS; - auxio_register = sbus_ioremap(&sdev->resource[0], 0, - sdev->reg_addrs[0].reg_size, - "auxiliaryIO"); - } -#ifdef CONFIG_PCI - else { - struct linux_ebus *ebus; - struct linux_ebus_device *edev = NULL; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "auxio")) - goto ebus_done; - } - } - ebus_done: - if (edev) { - auxio_devtype = AUXIO_TYPE_EBUS; - auxio_register = - ioremap(edev->resource[0].start, sizeof(u32)); - } - } - auxio_set_led(AUXIO_LED_ON); -#endif -} diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c deleted file mode 100644 index 202a80c24b6..00000000000 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * linux/fs/binfmt_aout.c - * - * Copyright (C) 1991, 1992, 1996 Linus Torvalds - * - * Hacked a bit by DaveM to make it work with 32-bit SunOS - * binaries on the sparc64 port. - */ - -#include <linux/module.h> - -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/mman.h> -#include <linux/a.out.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/string.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/stat.h> -#include <linux/fcntl.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/slab.h> -#include <linux/binfmts.h> -#include <linux/personality.h> -#include <linux/init.h> - -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/pgalloc.h> - -static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs); -static int load_aout32_library(struct file*); -static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file); - -static struct linux_binfmt aout32_format = { - NULL, THIS_MODULE, load_aout32_binary, load_aout32_library, aout32_core_dump, - PAGE_SIZE -}; - -static void set_brk(unsigned long start, unsigned long end) -{ - start = PAGE_ALIGN(start); - end = PAGE_ALIGN(end); - if (end <= start) - return; - down_write(¤t->mm->mmap_sem); - do_brk(start, end - start); - up_write(¤t->mm->mmap_sem); -} - -/* - * These are the only things you should do on a core-file: use only these - * macros to write out all the necessary info. - */ - -static int dump_write(struct file *file, const void *addr, int nr) -{ - return file->f_op->write(file, addr, nr, &file->f_pos) == nr; -} - -#define DUMP_WRITE(addr, nr) \ - if (!dump_write(file, (void *)(addr), (nr))) \ - goto end_coredump; - -#define DUMP_SEEK(offset) \ -if (file->f_op->llseek) { \ - if (file->f_op->llseek(file,(offset),0) != (offset)) \ - goto end_coredump; \ -} else file->f_pos = (offset) - -/* - * Routine writes a core dump image in the current directory. - * Currently only a stub-function. - * - * Note that setuid/setgid files won't make a core-dump if the uid/gid - * changed due to the set[u|g]id. It's enforced by the "current->mm->dumpable" - * field, which also makes sure the core-dumps won't be recursive if the - * dumping of the process results in another error.. - */ - -static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file) -{ - mm_segment_t fs; - int has_dumped = 0; - unsigned long dump_start, dump_size; - struct user dump; -# define START_DATA(u) (u.u_tsize) -# define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1)) - - fs = get_fs(); - set_fs(KERNEL_DS); - has_dumped = 1; - current->flags |= PF_DUMPCORE; - strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm)); - dump.signal = signr; - dump_thread(regs, &dump); - -/* If the size of the dump file exceeds the rlimit, then see what would happen - if we wrote the stack, but not the data area. */ - if ((dump.u_dsize+dump.u_ssize) > - current->signal->rlim[RLIMIT_CORE].rlim_cur) - dump.u_dsize = 0; - -/* Make sure we have enough room to write the stack and data areas. */ - if ((dump.u_ssize) > - current->signal->rlim[RLIMIT_CORE].rlim_cur) - dump.u_ssize = 0; - -/* make sure we actually have a data and stack area to dump */ - set_fs(USER_DS); - if (!access_ok(VERIFY_READ, (void __user *) START_DATA(dump), dump.u_dsize)) - dump.u_dsize = 0; - if (!access_ok(VERIFY_READ, (void __user *) START_STACK(dump), dump.u_ssize)) - dump.u_ssize = 0; - - set_fs(KERNEL_DS); -/* struct user */ - DUMP_WRITE(&dump,sizeof(dump)); -/* now we start writing out the user space info */ - set_fs(USER_DS); -/* Dump the data area */ - if (dump.u_dsize != 0) { - dump_start = START_DATA(dump); - dump_size = dump.u_dsize; - DUMP_WRITE(dump_start,dump_size); - } -/* Now prepare to dump the stack area */ - if (dump.u_ssize != 0) { - dump_start = START_STACK(dump); - dump_size = dump.u_ssize; - DUMP_WRITE(dump_start,dump_size); - } -/* Finally dump the task struct. Not be used by gdb, but could be useful */ - set_fs(KERNEL_DS); - DUMP_WRITE(current,sizeof(*current)); -end_coredump: - set_fs(fs); - return has_dumped; -} - -/* - * create_aout32_tables() parses the env- and arg-strings in new user - * memory and creates the pointer tables from them, and puts their - * addresses on the "stack", returning the new stack pointer value. - */ - -static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bprm) -{ - u32 __user *argv; - u32 __user *envp; - u32 __user *sp; - int argc = bprm->argc; - int envc = bprm->envc; - - sp = (u32 __user *)((-(unsigned long)sizeof(char *))&(unsigned long)p); - - /* This imposes the proper stack alignment for a new process. */ - sp = (u32 __user *) (((unsigned long) sp) & ~7); - if ((envc+argc+3)&1) - --sp; - - sp -= envc+1; - envp = sp; - sp -= argc+1; - argv = sp; - put_user(argc,--sp); - current->mm->arg_start = (unsigned long) p; - while (argc-->0) { - char c; - put_user(((u32)(unsigned long)(p)),argv++); - do { - get_user(c,p++); - } while (c); - } - put_user(NULL,argv); - current->mm->arg_end = current->mm->env_start = (unsigned long) p; - while (envc-->0) { - char c; - put_user(((u32)(unsigned long)(p)),envp++); - do { - get_user(c,p++); - } while (c); - } - put_user(NULL,envp); - current->mm->env_end = (unsigned long) p; - return sp; -} - -/* - * These are the functions used to load a.out style executables and shared - * libraries. There is no binary dependent code anywhere else. - */ - -static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) -{ - struct exec ex; - unsigned long error; - unsigned long fd_offset; - unsigned long rlim; - unsigned long orig_thr_flags; - int retval; - - ex = *((struct exec *) bprm->buf); /* exec-header */ - if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && - N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || - N_TRSIZE(ex) || N_DRSIZE(ex) || - bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { - return -ENOEXEC; - } - - fd_offset = N_TXTOFF(ex); - - /* Check initial limits. This avoids letting people circumvent - * size limits imposed on them by creating programs with large - * arrays in the data or bss. - */ - rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; - if (rlim >= RLIM_INFINITY) - rlim = ~0; - if (ex.a_data + ex.a_bss > rlim) - return -ENOMEM; - - /* Flush all traces of the currently running executable */ - retval = flush_old_exec(bprm); - if (retval) - return retval; - - /* OK, This is the point of no return */ - set_personality(PER_SUNOS); - - current->mm->end_code = ex.a_text + - (current->mm->start_code = N_TXTADDR(ex)); - current->mm->end_data = ex.a_data + - (current->mm->start_data = N_DATADDR(ex)); - current->mm->brk = ex.a_bss + - (current->mm->start_brk = N_BSSADDR(ex)); - - current->mm->mmap = NULL; - compute_creds(bprm); - current->flags &= ~PF_FORKNOEXEC; - if (N_MAGIC(ex) == NMAGIC) { - loff_t pos = fd_offset; - /* Fuck me plenty... */ - down_write(¤t->mm->mmap_sem); - error = do_brk(N_TXTADDR(ex), ex.a_text); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), - ex.a_text, &pos); - down_write(¤t->mm->mmap_sem); - error = do_brk(N_DATADDR(ex), ex.a_data); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex), - ex.a_data, &pos); - goto beyond_if; - } - - if (N_MAGIC(ex) == OMAGIC) { - loff_t pos = fd_offset; - down_write(¤t->mm->mmap_sem); - do_brk(N_TXTADDR(ex) & PAGE_MASK, - ex.a_text+ex.a_data + PAGE_SIZE - 1); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), - ex.a_text+ex.a_data, &pos); - } else { - static unsigned long error_time; - if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && - (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time) > 5*HZ) - { - printk(KERN_NOTICE "executable not page aligned\n"); - error_time = jiffies; - } - - if (!bprm->file->f_op->mmap) { - loff_t pos = fd_offset; - down_write(¤t->mm->mmap_sem); - do_brk(0, ex.a_text+ex.a_data); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, - (char __user *)N_TXTADDR(ex), - ex.a_text+ex.a_data, &pos); - goto beyond_if; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, - PROT_READ | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, - fd_offset); - up_write(¤t->mm->mmap_sem); - - if (error != N_TXTADDR(ex)) { - send_sig(SIGKILL, current, 0); - return error; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, - fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); - if (error != N_DATADDR(ex)) { - send_sig(SIGKILL, current, 0); - return error; - } - } -beyond_if: - set_binfmt(&aout32_format); - - set_brk(current->mm->start_brk, current->mm->brk); - - /* Make sure STACK_TOP returns the right thing. */ - orig_thr_flags = current_thread_info()->flags; - current_thread_info()->flags |= _TIF_32BIT; - - retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); - if (retval < 0) { - current_thread_info()->flags = orig_thr_flags; - - /* Someone check-me: is this error path enough? */ - send_sig(SIGKILL, current, 0); - return retval; - } - - current->mm->start_stack = - (unsigned long) create_aout32_tables((char __user *)bprm->p, bprm); - if (!(orig_thr_flags & _TIF_32BIT)) { - unsigned long pgd_cache = get_pgd_cache(current->mm->pgd); - - __asm__ __volatile__("stxa\t%0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (pgd_cache), - "r" (TSB_REG), "i" (ASI_DMMU)); - } - start_thread32(regs, ex.a_entry, current->mm->start_stack); - if (current->ptrace & PT_PTRACED) - send_sig(SIGTRAP, current, 0); - return 0; -} - -/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */ -static int load_aout32_library(struct file *file) -{ - struct inode * inode; - unsigned long bss, start_addr, len; - unsigned long error; - int retval; - struct exec ex; - - inode = file->f_dentry->d_inode; - - retval = -ENOEXEC; - error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); - if (error != sizeof(ex)) - goto out; - - /* We come in here for the regular a.out style of shared libraries */ - if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || - N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || - inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { - goto out; - } - - if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) && - (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) { - printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n"); - goto out; - } - - if (N_FLAGS(ex)) - goto out; - - /* For QMAGIC, the starting address is 0x20 into the page. We mask - this off to get the starting address for the page */ - - start_addr = ex.a_entry & 0xfffff000; - - /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); - error = do_mmap(file, start_addr, ex.a_text + ex.a_data, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, - N_TXTOFF(ex)); - up_write(¤t->mm->mmap_sem); - retval = error; - if (error != start_addr) - goto out; - - len = PAGE_ALIGN(ex.a_text + ex.a_data); - bss = ex.a_text + ex.a_data + ex.a_bss; - if (bss > len) { - down_write(¤t->mm->mmap_sem); - error = do_brk(start_addr + len, bss - len); - up_write(¤t->mm->mmap_sem); - retval = error; - if (error != start_addr + len) - goto out; - } - retval = 0; -out: - return retval; -} - -static int __init init_aout32_binfmt(void) -{ - return register_binfmt(&aout32_format); -} - -static void __exit exit_aout32_binfmt(void) -{ - unregister_binfmt(&aout32_format); -} - -module_init(init_aout32_binfmt); -module_exit(exit_aout32_binfmt); diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c deleted file mode 100644 index a1a12d2aa35..00000000000 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra. - * - * 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_SPARC -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2MSB; - -/* For the most part we present code dumps in the format - * Solaris does. - */ -typedef unsigned int elf_greg_t; -#define ELF_NGREG 38 -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -/* Format is: - * G0 --> G7 - * O0 --> O7 - * L0 --> L7 - * I0 --> I7 - * PSR, PC, nPC, Y, WIM, TBR - */ -#include <asm/psrcompat.h> -#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ -do { unsigned int *dest = &(__elf_regs[0]); \ - struct pt_regs *src = (__pt_regs); \ - unsigned int __user *sp; \ - int i; \ - for(i = 0; i < 16; i++) \ - dest[i] = (unsigned int) src->u_regs[i];\ - /* Don't try this at home kids... */ \ - sp = (unsigned int __user *) (src->u_regs[14] & \ - 0x00000000fffffffc); \ - for(i = 0; i < 16; i++) \ - __get_user(dest[i+16], &sp[i]); \ - dest[32] = tstate_to_psr(src->tstate); \ - dest[33] = (unsigned int) src->tpc; \ - dest[34] = (unsigned int) src->tnpc; \ - dest[35] = src->y; \ - dest[36] = dest[37] = 0; /* XXX */ \ -} while(0); - -typedef struct { - union { - unsigned int pr_regs[32]; - unsigned long pr_dregs[16]; - } pr_fr; - unsigned int __unused; - unsigned int pr_fsr; - unsigned char pr_qcnt; - unsigned char pr_q_entrysize; - unsigned char pr_en; - unsigned int pr_q[64]; -} elf_fpregset_t; - -/* UltraSparc extensions. Still unused, but will be eventually. */ -typedef struct { - unsigned int pr_type; - unsigned int pr_align; - union { - struct { - union { - unsigned int pr_regs[32]; - unsigned long pr_dregs[16]; - long double pr_qregs[8]; - } pr_xfr; - } pr_v8p; - unsigned int pr_xfsr; - unsigned int pr_fprs; - unsigned int pr_xg[8]; - unsigned int pr_xo[8]; - unsigned long pr_tstate; - unsigned int pr_filler[8]; - } pr_un; -} elf_xregset_t; - -#define elf_check_arch(x) (((x)->e_machine == EM_SPARC) || ((x)->e_machine == EM_SPARC32PLUS)) - -#define ELF_ET_DYN_BASE 0x70000000 - - -#include <asm/processor.h> -#include <linux/module.h> -#include <linux/config.h> -#include <linux/elfcore.h> -#include <linux/compat.h> - -#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 compat_timeval pr_utime; /* User time */ - struct compat_timeval pr_stime; /* System time */ - struct compat_timeval pr_cutime; /* Cumulative user time */ - struct compat_timeval 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 */ -}; - -#include <linux/highuid.h> - -#undef NEW_TO_OLD_UID -#undef NEW_TO_OLD_GID -#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) -#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) - -#include <linux/time.h> - -#undef cputime_to_timeval -#define cputime_to_timeval cputime_to_compat_timeval -static __inline__ void -cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) -{ - unsigned long jiffies = cputime_to_jiffies(cputime); - value->tv_usec = (jiffies % HZ) * (1000000L / HZ); - value->tv_sec = jiffies / HZ; -} - -#define elf_addr_t u32 -#undef start_thread -#define start_thread start_thread32 -#define init_elf_binfmt init_elf32_binfmt - -MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra"); -MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek"); - -#undef MODULE_DESCRIPTION -#undef MODULE_AUTHOR - -#undef TASK_SIZE -#define TASK_SIZE 0xf0000000 - -#include "../../../fs/binfmt_elf.c" diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c deleted file mode 100644 index 3d184a78496..00000000000 --- a/arch/sparc64/kernel/central.c +++ /dev/null @@ -1,457 +0,0 @@ -/* $Id: central.c,v 1.15 2001/12/19 00:29:51 davem Exp $ - * central.c: Central FHC driver for Sunfire/Starfire/Wildfire. - * - * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/bootmem.h> - -#include <asm/page.h> -#include <asm/fhc.h> -#include <asm/starfire.h> - -struct linux_central *central_bus = NULL; -struct linux_fhc *fhc_list = NULL; - -#define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child) - -static void central_probe_failure(int line) -{ - prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n", - line); - prom_halt(); -} - -static void central_ranges_init(int cnode, struct linux_central *central) -{ - int success; - - central->num_central_ranges = 0; - success = prom_getproperty(central->prom_node, "ranges", - (char *) central->central_ranges, - sizeof (central->central_ranges)); - if (success != -1) - central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); -} - -static void fhc_ranges_init(int fnode, struct linux_fhc *fhc) -{ - int success; - - fhc->num_fhc_ranges = 0; - success = prom_getproperty(fhc->prom_node, "ranges", - (char *) fhc->fhc_ranges, - sizeof (fhc->fhc_ranges)); - if (success != -1) - fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); -} - -/* Range application routines are exported to various drivers, - * so do not __init this. - */ -static void adjust_regs(struct linux_prom_registers *regp, int nregs, - struct linux_prom_ranges *rangep, int nranges) -{ - int regc, rngc; - - for (regc = 0; regc < nregs; regc++) { - for (rngc = 0; rngc < nranges; rngc++) - if (regp[regc].which_io == rangep[rngc].ot_child_space) - break; /* Fount it */ - if (rngc == nranges) /* oops */ - central_probe_failure(__LINE__); - regp[regc].which_io = rangep[rngc].ot_parent_space; - regp[regc].phys_addr -= rangep[rngc].ot_child_base; - regp[regc].phys_addr += rangep[rngc].ot_parent_base; - } -} - -/* Apply probed fhc ranges to registers passed, if no ranges return. */ -void apply_fhc_ranges(struct linux_fhc *fhc, - struct linux_prom_registers *regs, - int nregs) -{ - if (fhc->num_fhc_ranges) - adjust_regs(regs, nregs, fhc->fhc_ranges, - fhc->num_fhc_ranges); -} - -/* Apply probed central ranges to registers passed, if no ranges return. */ -void apply_central_ranges(struct linux_central *central, - struct linux_prom_registers *regs, int nregs) -{ - if (central->num_central_ranges) - adjust_regs(regs, nregs, central->central_ranges, - central->num_central_ranges); -} - -void * __init central_alloc_bootmem(unsigned long size) -{ - void *ret; - - ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); - if (ret != NULL) - memset(ret, 0, size); - - return ret; -} - -static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) -{ - unsigned long ret = ((unsigned long) r->which_io) << 32; - - return ret | (unsigned long) r->phys_addr; -} - -static void probe_other_fhcs(void) -{ - struct linux_prom64_registers fpregs[6]; - char namebuf[128]; - int node; - - node = prom_getchild(prom_root_node); - node = prom_searchsiblings(node, "fhc"); - if (node == 0) - central_probe_failure(__LINE__); - while (node) { - struct linux_fhc *fhc; - int board; - u32 tmp; - - fhc = (struct linux_fhc *) - central_alloc_bootmem(sizeof(struct linux_fhc)); - if (fhc == NULL) - central_probe_failure(__LINE__); - - /* Link it into the FHC chain. */ - fhc->next = fhc_list; - fhc_list = fhc; - - /* Toplevel FHCs have no parent. */ - fhc->parent = NULL; - - fhc->prom_node = node; - prom_getstring(node, "name", namebuf, sizeof(namebuf)); - strcpy(fhc->prom_name, namebuf); - fhc_ranges_init(node, fhc); - - /* Non-central FHC's have 64-bit OBP format registers. */ - if (prom_getproperty(node, "reg", - (char *)&fpregs[0], sizeof(fpregs)) == -1) - central_probe_failure(__LINE__); - - /* Only central FHC needs special ranges applied. */ - fhc->fhc_regs.pregs = fpregs[0].phys_addr; - fhc->fhc_regs.ireg = fpregs[1].phys_addr; - fhc->fhc_regs.ffregs = fpregs[2].phys_addr; - fhc->fhc_regs.sregs = fpregs[3].phys_addr; - fhc->fhc_regs.uregs = fpregs[4].phys_addr; - fhc->fhc_regs.tregs = fpregs[5].phys_addr; - - board = prom_getintdefault(node, "board#", -1); - fhc->board = board; - - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); - if ((tmp & FHC_JTAG_CTRL_MENAB) != 0) - fhc->jtag_master = 1; - else - fhc->jtag_master = 0; - - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n", - board, - (tmp & FHC_ID_VERS) >> 28, - (tmp & FHC_ID_PARTID) >> 12, - (tmp & FHC_ID_MANUF) >> 1, - (fhc->jtag_master ? "(JTAG Master)" : "")); - - /* This bit must be set in all non-central FHC's in - * the system. When it is clear, this identifies - * the central board. - */ - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - tmp |= FHC_CONTROL_IXIST; - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - - /* Look for the next FHC. */ - node = prom_getsibling(node); - if (node == 0) - break; - node = prom_searchsiblings(node, "fhc"); - if (node == 0) - break; - } -} - -static void probe_clock_board(struct linux_central *central, - struct linux_fhc *fhc, - int cnode, int fnode) -{ - struct linux_prom_registers cregs[3]; - int clknode, nslots, tmp, nregs; - - clknode = prom_searchsiblings(prom_getchild(fnode), "clock-board"); - if (clknode == 0 || clknode == -1) - central_probe_failure(__LINE__); - - nregs = prom_getproperty(clknode, "reg", (char *)&cregs[0], sizeof(cregs)); - if (nregs == -1) - central_probe_failure(__LINE__); - - nregs /= sizeof(struct linux_prom_registers); - apply_fhc_ranges(fhc, &cregs[0], nregs); - apply_central_ranges(central, &cregs[0], nregs); - central->cfreg = prom_reg_to_paddr(&cregs[0]); - central->clkregs = prom_reg_to_paddr(&cregs[1]); - - if (nregs == 2) - central->clkver = 0UL; - else - central->clkver = prom_reg_to_paddr(&cregs[2]); - - tmp = upa_readb(central->clkregs + CLOCK_STAT1); - tmp &= 0xc0; - switch(tmp) { - case 0x40: - nslots = 16; - break; - case 0xc0: - nslots = 8; - break; - case 0x80: - if (central->clkver != 0UL && - upa_readb(central->clkver) != 0) { - if ((upa_readb(central->clkver) & 0x80) != 0) - nslots = 4; - else - nslots = 5; - break; - } - default: - nslots = 4; - break; - }; - central->slots = nslots; - printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n", - central->slots, upa_readb(central->cfreg), - (central->clkver ? upa_readb(central->clkver) : 0x00)); -} - -static void ZAP(unsigned long iclr, unsigned long imap) -{ - u32 imap_tmp; - - upa_writel(0, iclr); - upa_readl(iclr); - imap_tmp = upa_readl(imap); - imap_tmp &= ~(0x80000000); - upa_writel(imap_tmp, imap); - upa_readl(imap); -} - -static void init_all_fhc_hw(void) -{ - struct linux_fhc *fhc; - - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) { - u32 tmp; - - /* Clear all of the interrupt mapping registers - * just in case OBP left them in a foul state. - */ - ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR, - fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP); - ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR, - fhc->fhc_regs.sregs + FHC_SREGS_IMAP); - ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR, - fhc->fhc_regs.uregs + FHC_UREGS_IMAP); - ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR, - fhc->fhc_regs.tregs + FHC_TREGS_IMAP); - - /* Setup FHC control register. */ - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - - /* All non-central boards have this bit set. */ - if (! IS_CENTRAL_FHC(fhc)) - tmp |= FHC_CONTROL_IXIST; - - /* For all FHCs, clear the firmware synchronization - * line and both low power mode enables. - */ - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | - FHC_CONTROL_SLINE); - - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - } - -} - -void central_probe(void) -{ - struct linux_prom_registers fpregs[6]; - struct linux_fhc *fhc; - char namebuf[128]; - int cnode, fnode, err; - - cnode = prom_finddevice("/central"); - if (cnode == 0 || cnode == -1) { - if (this_is_starfire) - starfire_cpu_setup(); - return; - } - - /* Ok we got one, grab some memory for software state. */ - central_bus = (struct linux_central *) - central_alloc_bootmem(sizeof(struct linux_central)); - if (central_bus == NULL) - central_probe_failure(__LINE__); - - fhc = (struct linux_fhc *) - central_alloc_bootmem(sizeof(struct linux_fhc)); - if (fhc == NULL) - central_probe_failure(__LINE__); - - /* First init central. */ - central_bus->child = fhc; - central_bus->prom_node = cnode; - - prom_getstring(cnode, "name", namebuf, sizeof(namebuf)); - strcpy(central_bus->prom_name, namebuf); - - central_ranges_init(cnode, central_bus); - - /* And then central's FHC. */ - fhc->next = fhc_list; - fhc_list = fhc; - - fhc->parent = central_bus; - fnode = prom_searchsiblings(prom_getchild(cnode), "fhc"); - if (fnode == 0 || fnode == -1) - central_probe_failure(__LINE__); - - fhc->prom_node = fnode; - prom_getstring(fnode, "name", namebuf, sizeof(namebuf)); - strcpy(fhc->prom_name, namebuf); - - fhc_ranges_init(fnode, fhc); - - /* Now, map in FHC register set. */ - if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) - central_probe_failure(__LINE__); - - apply_central_ranges(central_bus, &fpregs[0], 6); - - fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]); - fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]); - fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]); - fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]); - fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]); - fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]); - - /* Obtain board number from board status register, Central's - * FHC lacks "board#" property. - */ - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR); - fhc->board = (((err >> 16) & 0x01) | - ((err >> 12) & 0x0e)); - - fhc->jtag_master = 0; - - /* Attach the clock board registers for CENTRAL. */ - probe_clock_board(central_bus, fhc, cnode, fnode); - - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", - fhc->board, - ((err & FHC_ID_VERS) >> 28), - ((err & FHC_ID_PARTID) >> 12), - ((err & FHC_ID_MANUF) >> 1)); - - probe_other_fhcs(); - - init_all_fhc_hw(); -} - -static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on) -{ - u32 tmp; - - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - - /* NOTE: reverse logic on this bit */ - if (on) - tmp &= ~(FHC_CONTROL_RLED); - else - tmp |= FHC_CONTROL_RLED; - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); - - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); -} - -static __inline__ void central_ledblink(struct linux_central *central, int on) -{ - u8 tmp; - - tmp = upa_readb(central->clkregs + CLOCK_CTRL); - - /* NOTE: reverse logic on this bit */ - if (on) - tmp &= ~(CLOCK_CTRL_RLED); - else - tmp |= CLOCK_CTRL_RLED; - - upa_writeb(tmp, central->clkregs + CLOCK_CTRL); - upa_readb(central->clkregs + CLOCK_CTRL); -} - -static struct timer_list sftimer; -static int led_state; - -static void sunfire_timer(unsigned long __ignored) -{ - struct linux_fhc *fhc; - - central_ledblink(central_bus, led_state); - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) - if (! IS_CENTRAL_FHC(fhc)) - fhc_ledblink(fhc, led_state); - led_state = ! led_state; - sftimer.expires = jiffies + (HZ >> 1); - add_timer(&sftimer); -} - -/* After PCI/SBUS busses have been probed, this is called to perform - * final initialization of all FireHose Controllers in the system. - */ -void firetruck_init(void) -{ - struct linux_central *central = central_bus; - u8 ctrl; - - /* No central bus, nothing to do. */ - if (central == NULL) - return; - - /* OBP leaves it on, turn it off so clock board timer LED - * is in sync with FHC ones. - */ - ctrl = upa_readb(central->clkregs + CLOCK_CTRL); - ctrl &= ~(CLOCK_CTRL_RLED); - upa_writeb(ctrl, central->clkregs + CLOCK_CTRL); - - led_state = 0; - init_timer(&sftimer); - sftimer.data = 0; - sftimer.function = &sunfire_timer; - sftimer.expires = jiffies + (HZ >> 1); - add_timer(&sftimer); -} diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c deleted file mode 100644 index 97cf912f085..00000000000 --- a/arch/sparc64/kernel/chmc.c +++ /dev/null @@ -1,458 +0,0 @@ -/* $Id: chmc.c,v 1.4 2002/01/08 16:00:14 davem Exp $ - * memctrlr.c: Driver for UltraSPARC-III memory controller. - * - * Copyright (C) 2001 David S. Miller (davem@redhat.com) - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <asm/spitfire.h> -#include <asm/chmctrl.h> -#include <asm/oplib.h> -#include <asm/io.h> - -#define CHMCTRL_NDGRPS 2 -#define CHMCTRL_NDIMMS 4 - -#define DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) - -/* OBP memory-layout property format. */ -struct obp_map { - unsigned char dimm_map[144]; - unsigned char pin_map[576]; -}; - -#define DIMM_LABEL_SZ 8 - -struct obp_mem_layout { - /* One max 8-byte string label per DIMM. Usually - * this matches the label on the motherboard where - * that DIMM resides. - */ - char dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ]; - - /* If symmetric use map[0], else it is - * asymmetric and map[1] should be used. - */ - char symmetric; - - struct obp_map map[2]; -}; - -#define CHMCTRL_NBANKS 4 - -struct bank_info { - struct mctrl_info *mp; - int bank_id; - - u64 raw_reg; - int valid; - int uk; - int um; - int lk; - int lm; - int interleave; - unsigned long base; - unsigned long size; -}; - -struct mctrl_info { - struct list_head list; - int portid; - int index; - - struct obp_mem_layout layout_prop; - int layout_size; - - void __iomem *regs; - - u64 timing_control1; - u64 timing_control2; - u64 timing_control3; - u64 timing_control4; - u64 memaddr_control; - - struct bank_info logical_banks[CHMCTRL_NBANKS]; -}; - -static LIST_HEAD(mctrl_list); - -/* Does BANK decode PHYS_ADDR? */ -static int bank_match(struct bank_info *bp, unsigned long phys_addr) -{ - unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; - unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; - - /* Bank must be enabled to match. */ - if (bp->valid == 0) - return 0; - - /* Would BANK match upper bits? */ - upper_bits ^= bp->um; /* What bits are different? */ - upper_bits = ~upper_bits; /* Invert. */ - upper_bits |= bp->uk; /* What bits don't matter for matching? */ - upper_bits = ~upper_bits; /* Invert. */ - - if (upper_bits) - return 0; - - /* Would BANK match lower bits? */ - lower_bits ^= bp->lm; /* What bits are different? */ - lower_bits = ~lower_bits; /* Invert. */ - lower_bits |= bp->lk; /* What bits don't matter for matching? */ - lower_bits = ~lower_bits; /* Invert. */ - - if (lower_bits) - return 0; - - /* I always knew you'd be the one. */ - return 1; -} - -/* Given PHYS_ADDR, search memory controller banks for a match. */ -static struct bank_info *find_bank(unsigned long phys_addr) -{ - struct list_head *mctrl_head = &mctrl_list; - struct list_head *mctrl_entry = mctrl_head->next; - - for (;;) { - struct mctrl_info *mp = - list_entry(mctrl_entry, struct mctrl_info, list); - int bank_no; - - if (mctrl_entry == mctrl_head) - break; - mctrl_entry = mctrl_entry->next; - - for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { - struct bank_info *bp; - - bp = &mp->logical_banks[bank_no]; - if (bank_match(bp, phys_addr)) - return bp; - } - } - - return NULL; -} - -/* This is the main purpose of this driver. */ -#define SYNDROME_MIN -1 -#define SYNDROME_MAX 144 -int chmc_getunumber(int syndrome_code, - unsigned long phys_addr, - char *buf, int buflen) -{ - struct bank_info *bp; - struct obp_mem_layout *prop; - int bank_in_controller, first_dimm; - - bp = find_bank(phys_addr); - if (bp == NULL || - syndrome_code < SYNDROME_MIN || - syndrome_code > SYNDROME_MAX) { - buf[0] = '?'; - buf[1] = '?'; - buf[2] = '?'; - buf[3] = '\0'; - return 0; - } - - prop = &bp->mp->layout_prop; - bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); - first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); - first_dimm *= CHMCTRL_NDIMMS; - - if (syndrome_code != SYNDROME_MIN) { - struct obp_map *map; - int qword, where_in_line, where, map_index, map_offset; - unsigned int map_val; - - /* Yaay, single bit error so we can figure out - * the exact dimm. - */ - if (prop->symmetric) - map = &prop->map[0]; - else - map = &prop->map[1]; - - /* Covert syndrome code into the way the bits are - * positioned on the bus. - */ - if (syndrome_code < 144 - 16) - syndrome_code += 16; - else if (syndrome_code < 144) - syndrome_code -= (144 - 7); - else if (syndrome_code < (144 + 3)) - syndrome_code -= (144 + 3 - 4); - else - syndrome_code -= 144 + 3; - - /* All this magic has to do with how a cache line - * comes over the wire on Safari. A 64-bit line - * comes over in 4 quadword cycles, each of which - * transmit ECC/MTAG info as well as the actual - * data. 144 bits per quadword, 576 total. - */ -#define LINE_SIZE 64 -#define LINE_ADDR_MSK (LINE_SIZE - 1) -#define QW_PER_LINE 4 -#define QW_BYTES (LINE_SIZE / QW_PER_LINE) -#define QW_BITS 144 -#define LAST_BIT (576 - 1) - - qword = (phys_addr & LINE_ADDR_MSK) / QW_BYTES; - where_in_line = ((3 - qword) * QW_BITS) + syndrome_code; - where = (LAST_BIT - where_in_line); - map_index = where >> 2; - map_offset = where & 0x3; - map_val = map->dimm_map[map_index]; - map_val = ((map_val >> ((3 - map_offset) << 1)) & (2 - 1)); - - sprintf(buf, "%s, pin %3d", - prop->dimm_labels[first_dimm + map_val], - map->pin_map[where_in_line]); - } else { - int dimm; - - /* Multi-bit error, we just dump out all the - * dimm labels associated with this bank. - */ - for (dimm = 0; dimm < CHMCTRL_NDIMMS; dimm++) { - sprintf(buf, "%s ", - prop->dimm_labels[first_dimm + dimm]); - buf += strlen(buf); - } - } - return 0; -} - -/* Accessing the registers is slightly complicated. If you want - * to get at the memory controller which is on the same processor - * the code is executing, you must use special ASI load/store else - * you go through the global mapping. - */ -static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) -{ - unsigned long ret; - int this_cpu = get_cpu(); - - if (mp->portid == this_cpu) { - __asm__ __volatile__("ldxa [%1] %2, %0" - : "=r" (ret) - : "r" (offset), "i" (ASI_MCU_CTRL_REG)); - } else { - __asm__ __volatile__("ldxa [%1] %2, %0" - : "=r" (ret) - : "r" (mp->regs + offset), - "i" (ASI_PHYS_BYPASS_EC_E)); - } - put_cpu(); - - return ret; -} - -#if 0 /* currently unused */ -static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val) -{ - if (mp->portid == smp_processor_id()) { - __asm__ __volatile__("stxa %0, [%1] %2" - : : "r" (val), - "r" (offset), "i" (ASI_MCU_CTRL_REG)); - } else { - __asm__ __volatile__("ldxa %0, [%1] %2" - : : "r" (val), - "r" (mp->regs + offset), - "i" (ASI_PHYS_BYPASS_EC_E)); - } -} -#endif - -static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val) -{ - struct bank_info *p = &mp->logical_banks[which_bank]; - - p->mp = mp; - p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank; - p->raw_reg = val; - p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; - p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; - p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; - p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; - p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; - - p->base = (p->um); - p->base &= ~(p->uk); - p->base <<= PA_UPPER_BITS_SHIFT; - - switch(p->lk) { - case 0xf: - default: - p->interleave = 1; - break; - - case 0xe: - p->interleave = 2; - break; - - case 0xc: - p->interleave = 4; - break; - - case 0x8: - p->interleave = 8; - break; - - case 0x0: - p->interleave = 16; - break; - }; - - /* UK[10] is reserved, and UK[11] is not set for the SDRAM - * bank size definition. - */ - p->size = (((unsigned long)p->uk & - ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; - p->size /= p->interleave; -} - -static void fetch_decode_regs(struct mctrl_info *mp) -{ - if (mp->layout_size == 0) - return; - - interpret_one_decode_reg(mp, 0, - read_mcreg(mp, CHMCTRL_DECODE1)); - interpret_one_decode_reg(mp, 1, - read_mcreg(mp, CHMCTRL_DECODE2)); - interpret_one_decode_reg(mp, 2, - read_mcreg(mp, CHMCTRL_DECODE3)); - interpret_one_decode_reg(mp, 3, - read_mcreg(mp, CHMCTRL_DECODE4)); -} - -static int init_one_mctrl(int node, int index) -{ - struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL); - int portid = prom_getintdefault(node, "portid", -1); - struct linux_prom64_registers p_reg_prop; - int t; - - if (!mp) - return -1; - memset(mp, 0, sizeof(*mp)); - if (portid == -1) - goto fail; - - mp->portid = portid; - mp->layout_size = prom_getproplen(node, "memory-layout"); - if (mp->layout_size < 0) - mp->layout_size = 0; - if (mp->layout_size > sizeof(mp->layout_prop)) - goto fail; - - if (mp->layout_size > 0) - prom_getproperty(node, "memory-layout", - (char *) &mp->layout_prop, - mp->layout_size); - - t = prom_getproperty(node, "reg", - (char *) &p_reg_prop, - sizeof(p_reg_prop)); - if (t < 0 || p_reg_prop.reg_size != 0x48) - goto fail; - - mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size); - if (mp->regs == NULL) - goto fail; - - if (mp->layout_size != 0UL) { - mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); - mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2); - mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3); - mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4); - mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL); - } - - fetch_decode_regs(mp); - - mp->index = index; - - list_add(&mp->list, &mctrl_list); - - /* Report the device. */ - printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n", - mp->index, - mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); - - return 0; - -fail: - if (mp) { - if (mp->regs != NULL) - iounmap(mp->regs); - kfree(mp); - } - return -1; -} - -static int __init probe_for_string(char *name, int index) -{ - int node = prom_getchild(prom_root_node); - - while ((node = prom_searchsiblings(node, name)) != 0) { - int ret = init_one_mctrl(node, index); - - if (!ret) - index++; - - node = prom_getsibling(node); - if (!node) - break; - } - - return index; -} - -static int __init chmc_init(void) -{ - int index; - - /* This driver is only for cheetah platforms. */ - if (tlb_type != cheetah && tlb_type != cheetah_plus) - return -ENODEV; - - index = probe_for_string("memory-controller", 0); - index = probe_for_string("mc-us3", index); - - return 0; -} - -static void __exit chmc_cleanup(void) -{ - struct list_head *head = &mctrl_list; - struct list_head *tmp = head->next; - - for (;;) { - struct mctrl_info *p = - list_entry(tmp, struct mctrl_info, list); - if (tmp == head) - break; - tmp = tmp->next; - - list_del(&p->list); - iounmap(p->regs); - kfree(p); - } -} - -module_init(chmc_init); -module_exit(chmc_cleanup); diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c deleted file mode 100644 index 00eed88ef2e..00000000000 --- a/arch/sparc64/kernel/cpu.c +++ /dev/null @@ -1,128 +0,0 @@ -/* cpu.c: Dinky routines to look for the kind of Sparc cpu - * we are on. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <asm/asi.h> -#include <asm/system.h> -#include <asm/fpumacro.h> -#include <asm/cpudata.h> - -DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; - -struct cpu_iu_info { - short manuf; - short impl; - char* cpu_name; /* should be enough I hope... */ -}; - -struct cpu_fp_info { - short manuf; - short impl; - char fpu_vers; - char* fp_name; -}; - -struct cpu_fp_info linux_sparc_fpu[] = { - { 0x17, 0x10, 0, "UltraSparc I integrated FPU"}, - { 0x22, 0x10, 0, "UltraSparc I integrated FPU"}, - { 0x17, 0x11, 0, "UltraSparc II integrated FPU"}, - { 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"}, - { 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"}, - { 0x3e, 0x14, 0, "UltraSparc III integrated FPU"}, - { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"}, - { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"}, - { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"}, - { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"}, - { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"}, -}; - -#define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) - -struct cpu_iu_info linux_sparc_chips[] = { - { 0x17, 0x10, "TI UltraSparc I (SpitFire)"}, - { 0x22, 0x10, "TI UltraSparc I (SpitFire)"}, - { 0x17, 0x11, "TI UltraSparc II (BlackBird)"}, - { 0x17, 0x12, "TI UltraSparc IIi (Sabre)"}, - { 0x17, 0x13, "TI UltraSparc IIe (Hummingbird)"}, - { 0x3e, 0x14, "TI UltraSparc III (Cheetah)"}, - { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"}, - { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"}, - { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"}, - { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"}, - { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"}, -}; - -#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) - -char *sparc_cpu_type = "cpu-oops"; -char *sparc_fpu_type = "fpu-oops"; - -unsigned int fsr_storage; - -void __init cpu_probe(void) -{ - unsigned long ver, fpu_vers, manuf, impl, fprs; - int i; - - fprs = fprs_read(); - fprs_write(FPRS_FEF); - __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" - : "=&r" (ver) - : "r" (&fpu_vers)); - fprs_write(fprs); - - manuf = ((ver >> 48) & 0xffff); - impl = ((ver >> 32) & 0xffff); - - fpu_vers = ((fpu_vers >> 17) & 0x7); - -retry: - for (i = 0; i < NSPARCCHIPS; i++) { - if (linux_sparc_chips[i].manuf == manuf) { - if (linux_sparc_chips[i].impl == impl) { - sparc_cpu_type = - linux_sparc_chips[i].cpu_name; - break; - } - } - } - - if (i == NSPARCCHIPS) { - /* Maybe it is a cheetah+ derivative, report it as cheetah+ - * in that case until we learn the real names. - */ - if (manuf == 0x3e && - impl > 0x15) { - impl = 0x15; - goto retry; - } else { - printk("DEBUG: manuf[%lx] impl[%lx]\n", - manuf, impl); - } - sparc_cpu_type = "Unknown CPU"; - } - - for (i = 0; i < NSPARCFPU; i++) { - if (linux_sparc_fpu[i].manuf == manuf && - linux_sparc_fpu[i].impl == impl) { - if (linux_sparc_fpu[i].fpu_vers == fpu_vers) { - sparc_fpu_type = - linux_sparc_fpu[i].fp_name; - break; - } - } - } - - if (i == NSPARCFPU) { - printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n", - manuf, impl, fpu_vers); - sparc_fpu_type = "Unknown FPU"; - } -} diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c deleted file mode 100644 index df9a1ca8fd7..00000000000 --- a/arch/sparc64/kernel/devices.c +++ /dev/null @@ -1,166 +0,0 @@ -/* devices.c: Initial scan of the prom device tree for important - * Sparc device nodes which we need to find. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/threads.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/string.h> -#include <linux/spinlock.h> -#include <linux/errno.h> - -#include <asm/page.h> -#include <asm/oplib.h> -#include <asm/system.h> -#include <asm/smp.h> -#include <asm/spitfire.h> -#include <asm/timer.h> -#include <asm/cpudata.h> - -/* Used to synchronize acceses to NatSemi SUPER I/O chip configure - * operations in asm/ns87303.h - */ -DEFINE_SPINLOCK(ns87303_lock); - -extern void cpu_probe(void); -extern void central_probe(void); - -static char *cpu_mid_prop(void) -{ - if (tlb_type == spitfire) - return "upa-portid"; - return "portid"; -} - -static int check_cpu_node(int nd, int *cur_inst, - int (*compare)(int, int, void *), void *compare_arg, - int *prom_node, int *mid) -{ - char node_str[128]; - - prom_getstring(nd, "device_type", node_str, sizeof(node_str)); - if (strcmp(node_str, "cpu")) - return -ENODEV; - - if (!compare(nd, *cur_inst, compare_arg)) { - if (prom_node) - *prom_node = nd; - if (mid) - *mid = prom_getintdefault(nd, cpu_mid_prop(), 0); - return 0; - } - - (*cur_inst)++; - - return -ENODEV; -} - -static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, - int *prom_node, int *mid) -{ - int nd, cur_inst, err; - - nd = prom_root_node; - cur_inst = 0; - - err = check_cpu_node(nd, &cur_inst, - compare, compare_arg, - prom_node, mid); - if (err == 0) - return 0; - - nd = prom_getchild(nd); - while ((nd = prom_getsibling(nd)) != 0) { - err = check_cpu_node(nd, &cur_inst, - compare, compare_arg, - prom_node, mid); - if (err == 0) - return 0; - } - - return -ENODEV; -} - -static int cpu_instance_compare(int nd, int instance, void *_arg) -{ - int desired_instance = (int) (long) _arg; - - if (instance == desired_instance) - return 0; - return -ENODEV; -} - -int cpu_find_by_instance(int instance, int *prom_node, int *mid) -{ - return __cpu_find_by(cpu_instance_compare, (void *)(long)instance, - prom_node, mid); -} - -static int cpu_mid_compare(int nd, int instance, void *_arg) -{ - int desired_mid = (int) (long) _arg; - int this_mid; - - this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0); - if (this_mid == desired_mid) - return 0; - return -ENODEV; -} - -int cpu_find_by_mid(int mid, int *prom_node) -{ - return __cpu_find_by(cpu_mid_compare, (void *)(long)mid, - prom_node, NULL); -} - -void __init device_scan(void) -{ - /* FIX ME FAST... -DaveM */ - ioport_resource.end = 0xffffffffffffffffUL; - - prom_printf("Booting Linux...\n"); - -#ifndef CONFIG_SMP - { - int err, cpu_node; - err = cpu_find_by_instance(0, &cpu_node, NULL); - if (err) { - prom_printf("No cpu nodes, cannot continue\n"); - prom_halt(); - } - cpu_data(0).clock_tick = prom_getintdefault(cpu_node, - "clock-frequency", - 0); - cpu_data(0).dcache_size = prom_getintdefault(cpu_node, - "dcache-size", - 16 * 1024); - cpu_data(0).dcache_line_size = - prom_getintdefault(cpu_node, "dcache-line-size", 32); - cpu_data(0).icache_size = prom_getintdefault(cpu_node, - "icache-size", - 16 * 1024); - cpu_data(0).icache_line_size = - prom_getintdefault(cpu_node, "icache-line-size", 32); - cpu_data(0).ecache_size = prom_getintdefault(cpu_node, - "ecache-size", - 4 * 1024 * 1024); - cpu_data(0).ecache_line_size = - prom_getintdefault(cpu_node, "ecache-line-size", 64); - printk("CPU[0]: Caches " - "D[sz(%d):line_sz(%d)] " - "I[sz(%d):line_sz(%d)] " - "E[sz(%d):line_sz(%d)]\n", - cpu_data(0).dcache_size, cpu_data(0).dcache_line_size, - cpu_data(0).icache_size, cpu_data(0).icache_line_size, - cpu_data(0).ecache_size, cpu_data(0).ecache_line_size); - } -#endif - - central_probe(); - - cpu_probe(); -} diff --git a/arch/sparc64/kernel/dtlb_backend.S b/arch/sparc64/kernel/dtlb_backend.S deleted file mode 100644 index acc889a7f9c..00000000000 --- a/arch/sparc64/kernel/dtlb_backend.S +++ /dev/null @@ -1,170 +0,0 @@ -/* $Id: dtlb_backend.S,v 1.16 2001/10/09 04:02:11 davem Exp $ - * dtlb_backend.S: Back end to DTLB miss replacement strategy. - * This is included directly into the trap table. - * - * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <asm/pgtable.h> -#include <asm/mmu.h> - -#define VALID_SZ_BITS (_PAGE_VALID | _PAGE_SZBITS) - -#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P ) -#define VPTE_SHIFT (PAGE_SHIFT - 3) - -/* Ways we can get here: - * - * 1) Nucleus loads and stores to/from PA-->VA direct mappings at tl>1. - * 2) Nucleus loads and stores to/from user/kernel window save areas. - * 3) VPTE misses from dtlb_base and itlb_base. - * - * We need to extract out the PMD and PGDIR indexes from the - * linear virtual page table access address. The PTE index - * is at the bottom, but we are not concerned with it. Bits - * 0 to 2 are clear since each PTE is 8 bytes in size. Each - * PMD and PGDIR entry are 4 bytes in size. Thus, this - * address looks something like: - * - * |---------------------------------------------------------------| - * | ... | PGDIR index | PMD index | PTE index | | - * |---------------------------------------------------------------| - * 63 F E D C B A 3 2 0 <- bit nr - * - * The variable bits above are defined as: - * A --> 3 + (PAGE_SHIFT - log2(8)) - * --> 3 + (PAGE_SHIFT - 3) - 1 - * (ie. this is "bit 3" + PAGE_SIZE - size of PTE entry in bits - 1) - * B --> A + 1 - * C --> B + (PAGE_SHIFT - log2(4)) - * --> B + (PAGE_SHIFT - 2) - 1 - * (ie. this is "bit B" + PAGE_SIZE - size of PMD entry in bits - 1) - * D --> C + 1 - * E --> D + (PAGE_SHIFT - log2(4)) - * --> D + (PAGE_SHIFT - 2) - 1 - * (ie. this is "bit D" + PAGE_SIZE - size of PGDIR entry in bits - 1) - * F --> E + 1 - * - * (Note how "B" always evalutes to PAGE_SHIFT, all the other constants - * cancel out.) - * - * For 8K PAGE_SIZE (thus, PAGE_SHIFT of 13) the bit numbers are: - * A --> 12 - * B --> 13 - * C --> 23 - * D --> 24 - * E --> 34 - * F --> 35 - * - * For 64K PAGE_SIZE (thus, PAGE_SHIFT of 16) the bit numbers are: - * A --> 15 - * B --> 16 - * C --> 29 - * D --> 30 - * E --> 43 - * F --> 44 - * - * Because bits both above and below each PGDIR and PMD index need to - * be masked out, and the index can be as long as 14 bits (when using a - * 64K PAGE_SIZE, and thus a PAGE_SHIFT of 16), we need 3 instructions - * to extract each index out. - * - * Shifts do not pair very well on UltraSPARC-I, II, IIi, and IIe, so - * we try to avoid using them for the entire operation. We could setup - * a mask anywhere from bit 31 down to bit 10 using the sethi instruction. - * - * We need a mask covering bits B --> C and one covering D --> E. - * For 8K PAGE_SIZE these masks are 0x00ffe000 and 0x7ff000000. - * For 64K PAGE_SIZE these masks are 0x3fff0000 and 0xfffc0000000. - * The second in each set cannot be loaded with a single sethi - * instruction, because the upper bits are past bit 32. We would - * need to use a sethi + a shift. - * - * For the time being, we use 2 shifts and a simple "and" mask. - * We shift left to clear the bits above the index, we shift down - * to clear the bits below the index (sans the log2(4 or 8) bits) - * and a mask to clear the log2(4 or 8) bits. We need therefore - * define 4 shift counts, all of which are relative to PAGE_SHIFT. - * - * Although unsupportable for other reasons, this does mean that - * 512K and 4MB page sizes would be generaally supported by the - * kernel. (ELF binaries would break with > 64K PAGE_SIZE since - * the sections are only aligned that strongly). - * - * The operations performed for extraction are thus: - * - * ((X << FOO_SHIFT_LEFT) >> FOO_SHIFT_RIGHT) & ~0x3 - * - */ - -#define A (3 + (PAGE_SHIFT - 3) - 1) -#define B (A + 1) -#define C (B + (PAGE_SHIFT - 2) - 1) -#define D (C + 1) -#define E (D + (PAGE_SHIFT - 2) - 1) -#define F (E + 1) - -#define PMD_SHIFT_LEFT (64 - D) -#define PMD_SHIFT_RIGHT (64 - (D - B) - 2) -#define PGDIR_SHIFT_LEFT (64 - F) -#define PGDIR_SHIFT_RIGHT (64 - (F - D) - 2) -#define LOW_MASK_BITS 0x3 - -/* TLB1 ** ICACHE line 1: tl1 DTLB and quick VPTE miss */ - ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS - add %g3, %g3, %g5 ! Compute VPTE base - cmp %g4, %g5 ! VPTE miss? - bgeu,pt %xcc, 1f ! Continue here - andcc %g4, TAG_CONTEXT_BITS, %g5 ! tl0 miss Nucleus test - ba,a,pt %xcc, from_tl1_trap ! Fall to tl0 miss -1: sllx %g6, VPTE_SHIFT, %g4 ! Position TAG_ACCESS - or %g4, %g5, %g4 ! Prepare TAG_ACCESS - -/* TLB1 ** ICACHE line 2: Quick VPTE miss */ - mov TSB_REG, %g1 ! Grab TSB reg - ldxa [%g1] ASI_DMMU, %g5 ! Doing PGD caching? - sllx %g6, PMD_SHIFT_LEFT, %g1 ! Position PMD offset - be,pn %xcc, sparc64_vpte_nucleus ! Is it from Nucleus? - srlx %g1, PMD_SHIFT_RIGHT, %g1 ! Mask PMD offset bits - brnz,pt %g5, sparc64_vpte_continue ! Yep, go like smoke - andn %g1, LOW_MASK_BITS, %g1 ! Final PMD mask - sllx %g6, PGDIR_SHIFT_LEFT, %g5 ! Position PGD offset - -/* TLB1 ** ICACHE line 3: Quick VPTE miss */ - srlx %g5, PGDIR_SHIFT_RIGHT, %g5 ! Mask PGD offset bits - andn %g5, LOW_MASK_BITS, %g5 ! Final PGD mask - lduwa [%g7 + %g5] ASI_PHYS_USE_EC, %g5! Load PGD - brz,pn %g5, vpte_noent ! Valid? -sparc64_kpte_continue: - sllx %g5, 11, %g5 ! Shift into place -sparc64_vpte_continue: - lduwa [%g5 + %g1] ASI_PHYS_USE_EC, %g5! Load PMD - sllx %g5, 11, %g5 ! Shift into place - brz,pn %g5, vpte_noent ! Valid? - -/* TLB1 ** ICACHE line 4: Quick VPTE miss */ - mov (VALID_SZ_BITS >> 61), %g1 ! upper vpte into %g1 - sllx %g1, 61, %g1 ! finish calc - or %g5, VPTE_BITS, %g5 ! Prepare VPTE data - or %g5, %g1, %g5 ! ... - mov TLB_SFSR, %g1 ! Restore %g1 value - stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Load VPTE into TLB - stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS - retry ! Load PTE once again - -#undef VALID_SZ_BITS -#undef VPTE_SHIFT -#undef VPTE_BITS -#undef A -#undef B -#undef C -#undef D -#undef E -#undef F -#undef PMD_SHIFT_LEFT -#undef PMD_SHIFT_RIGHT -#undef PGDIR_SHIFT_LEFT -#undef PGDIR_SHIFT_RIGHT -#undef LOW_MASK_BITS - diff --git a/arch/sparc64/kernel/dtlb_base.S b/arch/sparc64/kernel/dtlb_base.S deleted file mode 100644 index 6528786840c..00000000000 --- a/arch/sparc64/kernel/dtlb_base.S +++ /dev/null @@ -1,109 +0,0 @@ -/* $Id: dtlb_base.S,v 1.17 2001/10/11 22:33:52 davem Exp $ - * dtlb_base.S: Front end to DTLB miss replacement strategy. - * This is included directly into the trap table. - * - * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <asm/pgtable.h> -#include <asm/mmu.h> - -/* %g1 TLB_SFSR (%g1 + %g1 == TLB_TAG_ACCESS) - * %g2 (KERN_HIGHBITS | KERN_LOWBITS) - * %g3 VPTE base (0xfffffffe00000000) Spitfire/Blackbird (44-bit VA space) - * (0xffe0000000000000) Cheetah (64-bit VA space) - * %g7 __pa(current->mm->pgd) - * - * The VPTE base value is completely magic, but note that - * few places in the kernel other than these TLB miss - * handlers know anything about the VPTE mechanism or - * how it works (see VPTE_SIZE, TASK_SIZE and PTRS_PER_PGD). - * Consider the 44-bit VADDR Ultra-I/II case as an example: - * - * VA[0 : (1<<43)] produce VPTE index [%g3 : 0] - * VA[0 : -(1<<43)] produce VPTE index [%g3-(1<<(43-PAGE_SHIFT+3)) : %g3] - * - * For Cheetah's 64-bit VADDR space this is: - * - * VA[0 : (1<<63)] produce VPTE index [%g3 : 0] - * VA[0 : -(1<<63)] produce VPTE index [%g3-(1<<(63-PAGE_SHIFT+3)) : %g3] - * - * If you're paying attention you'll notice that this means half of - * the VPTE table is above %g3 and half is below, low VA addresses - * map progressively upwards from %g3, and high VA addresses map - * progressively upwards towards %g3. This trick was needed to make - * the same 8 instruction handler work both for Spitfire/Blackbird's - * peculiar VA space hole configuration and the full 64-bit VA space - * one of Cheetah at the same time. - */ - -/* Ways we can get here: - * - * 1) Nucleus loads and stores to/from PA-->VA direct mappings. - * 2) Nucleus loads and stores to/from vmalloc() areas. - * 3) User loads and stores. - * 4) User space accesses by nucleus at tl0 - */ - -#if PAGE_SHIFT == 13 -/* - * To compute vpte offset, we need to do ((addr >> 13) << 3), - * which can be optimized to (addr >> 10) if bits 10/11/12 can - * be guaranteed to be 0 ... mmu_context.h does guarantee this - * by only using 10 bits in the hwcontext value. - */ -#define CREATE_VPTE_OFFSET1(r1, r2) nop -#define CREATE_VPTE_OFFSET2(r1, r2) \ - srax r1, 10, r2 -#else -#define CREATE_VPTE_OFFSET1(r1, r2) \ - srax r1, PAGE_SHIFT, r2 -#define CREATE_VPTE_OFFSET2(r1, r2) \ - sllx r2, 3, r2 -#endif - -/* DTLB ** ICACHE line 1: Quick user TLB misses */ - mov TLB_SFSR, %g1 - ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS - andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus? -from_tl1_trap: - rdpr %tl, %g5 ! For TL==3 test - CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset - be,pn %xcc, kvmap ! Yep, special processing - CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset - cmp %g5, 4 ! Last trap level? - -/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */ - be,pn %xcc, longpath ! Yep, cannot risk VPTE miss - nop ! delay slot - ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE -1: brgez,pn %g5, longpath ! Invalid, branch out - nop ! Delay-slot -9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB - retry ! Trap return - nop - -/* DTLB ** ICACHE line 3: winfixups+real_faults */ -longpath: - rdpr %pstate, %g5 ! Move into alternate globals - wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tl, %g4 ! See where we came from. - cmp %g4, 1 ! Is etrap/rtrap window fault? - mov TLB_TAG_ACCESS, %g4 ! Prepare for fault processing - ldxa [%g4] ASI_DMMU, %g5 ! Load faulting VA page - be,pt %xcc, sparc64_realfault_common ! Jump to normal fault handling - mov FAULT_CODE_DTLB, %g4 ! It was read from DTLB - -/* DTLB ** ICACHE line 4: Unused... */ - ba,a,pt %xcc, winfix_trampoline ! Call window fixup code - nop - nop - nop - nop - nop - nop - nop - -#undef CREATE_VPTE_OFFSET1 -#undef CREATE_VPTE_OFFSET2 diff --git a/arch/sparc64/kernel/dtlb_prot.S b/arch/sparc64/kernel/dtlb_prot.S deleted file mode 100644 index e0a92016260..00000000000 --- a/arch/sparc64/kernel/dtlb_prot.S +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: dtlb_prot.S,v 1.22 2001/04/11 23:40:32 davem Exp $ - * dtlb_prot.S: DTLB protection trap strategy. - * This is included directly into the trap table. - * - * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -/* Ways we can get here: - * - * [TL == 0] 1) User stores to readonly pages. - * [TL == 0] 2) Nucleus stores to user readonly pages. - * [TL > 0] 3) Nucleus stores to user readonly stack frame. - */ - -/* PROT ** ICACHE line 1: User DTLB protection trap */ - mov TLB_SFSR, %g1 - stxa %g0, [%g1] ASI_DMMU ! Clear FaultValid bit - membar #Sync ! Synchronize stores - rdpr %pstate, %g5 ! Move into alt-globals - wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tl, %g1 ! Need a winfixup? - cmp %g1, 1 ! Trap level >1? - mov TLB_TAG_ACCESS, %g4 ! For reload of vaddr - -/* PROT ** ICACHE line 2: More real fault processing */ - bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup - ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 - ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault - mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4 - nop - nop - nop - nop - -/* PROT ** ICACHE line 3: Unused... */ - nop - nop - nop - nop - nop - nop - nop - nop - -/* PROT ** ICACHE line 4: Unused... */ - nop - nop - nop - nop - nop - nop - nop - nop diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c deleted file mode 100644 index 7991e919d8a..00000000000 --- a/arch/sparc64/kernel/ebus.c +++ /dev/null @@ -1,639 +0,0 @@ -/* $Id: ebus.c,v 1.64 2001/11/08 04:41:33 davem Exp $ - * ebus.c: PCI to EBus bridge device. - * - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/delay.h> - -#include <asm/system.h> -#include <asm/page.h> -#include <asm/pbm.h> -#include <asm/ebus.h> -#include <asm/oplib.h> -#include <asm/bpp.h> -#include <asm/irq.h> - -/* EBUS dma library. */ - -#define EBDMA_CSR 0x00UL /* Control/Status */ -#define EBDMA_ADDR 0x04UL /* DMA Address */ -#define EBDMA_COUNT 0x08UL /* DMA Count */ - -#define EBDMA_CSR_INT_PEND 0x00000001 -#define EBDMA_CSR_ERR_PEND 0x00000002 -#define EBDMA_CSR_DRAIN 0x00000004 -#define EBDMA_CSR_INT_EN 0x00000010 -#define EBDMA_CSR_RESET 0x00000080 -#define EBDMA_CSR_WRITE 0x00000100 -#define EBDMA_CSR_EN_DMA 0x00000200 -#define EBDMA_CSR_CYC_PEND 0x00000400 -#define EBDMA_CSR_DIAG_RD_DONE 0x00000800 -#define EBDMA_CSR_DIAG_WR_DONE 0x00001000 -#define EBDMA_CSR_EN_CNT 0x00002000 -#define EBDMA_CSR_TC 0x00004000 -#define EBDMA_CSR_DIS_CSR_DRN 0x00010000 -#define EBDMA_CSR_BURST_SZ_MASK 0x000c0000 -#define EBDMA_CSR_BURST_SZ_1 0x00080000 -#define EBDMA_CSR_BURST_SZ_4 0x00000000 -#define EBDMA_CSR_BURST_SZ_8 0x00040000 -#define EBDMA_CSR_BURST_SZ_16 0x000c0000 -#define EBDMA_CSR_DIAG_EN 0x00100000 -#define EBDMA_CSR_DIS_ERR_PEND 0x00400000 -#define EBDMA_CSR_TCI_DIS 0x00800000 -#define EBDMA_CSR_EN_NEXT 0x01000000 -#define EBDMA_CSR_DMA_ON 0x02000000 -#define EBDMA_CSR_A_LOADED 0x04000000 -#define EBDMA_CSR_NA_LOADED 0x08000000 -#define EBDMA_CSR_DEV_ID_MASK 0xf0000000 - -#define EBUS_DMA_RESET_TIMEOUT 10000 - -static void __ebus_dma_reset(struct ebus_dma_info *p, int no_drain) -{ - int i; - u32 val = 0; - - writel(EBDMA_CSR_RESET, p->regs + EBDMA_CSR); - udelay(1); - - if (no_drain) - return; - - for (i = EBUS_DMA_RESET_TIMEOUT; i > 0; i--) { - val = readl(p->regs + EBDMA_CSR); - - if (!(val & (EBDMA_CSR_DRAIN | EBDMA_CSR_CYC_PEND))) - break; - udelay(10); - } -} - -static irqreturn_t ebus_dma_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - struct ebus_dma_info *p = dev_id; - unsigned long flags; - u32 csr = 0; - - spin_lock_irqsave(&p->lock, flags); - csr = readl(p->regs + EBDMA_CSR); - writel(csr, p->regs + EBDMA_CSR); - spin_unlock_irqrestore(&p->lock, flags); - - if (csr & EBDMA_CSR_ERR_PEND) { - printk(KERN_CRIT "ebus_dma(%s): DMA error!\n", p->name); - p->callback(p, EBUS_DMA_EVENT_ERROR, p->client_cookie); - return IRQ_HANDLED; - } else if (csr & EBDMA_CSR_INT_PEND) { - p->callback(p, - (csr & EBDMA_CSR_TC) ? - EBUS_DMA_EVENT_DMA : EBUS_DMA_EVENT_DEVICE, - p->client_cookie); - return IRQ_HANDLED; - } - - return IRQ_NONE; - -} - -int ebus_dma_register(struct ebus_dma_info *p) -{ - u32 csr; - - if (!p->regs) - return -EINVAL; - if (p->flags & ~(EBUS_DMA_FLAG_USE_EBDMA_HANDLER | - EBUS_DMA_FLAG_TCI_DISABLE)) - return -EINVAL; - if ((p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) && !p->callback) - return -EINVAL; - if (!strlen(p->name)) - return -EINVAL; - - __ebus_dma_reset(p, 1); - - csr = EBDMA_CSR_BURST_SZ_16 | EBDMA_CSR_EN_CNT; - - if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE) - csr |= EBDMA_CSR_TCI_DIS; - - writel(csr, p->regs + EBDMA_CSR); - - return 0; -} -EXPORT_SYMBOL(ebus_dma_register); - -int ebus_dma_irq_enable(struct ebus_dma_info *p, int on) -{ - unsigned long flags; - u32 csr; - - if (on) { - if (p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) { - if (request_irq(p->irq, ebus_dma_irq, SA_SHIRQ, p->name, p)) - return -EBUSY; - } - - spin_lock_irqsave(&p->lock, flags); - csr = readl(p->regs + EBDMA_CSR); - csr |= EBDMA_CSR_INT_EN; - writel(csr, p->regs + EBDMA_CSR); - spin_unlock_irqrestore(&p->lock, flags); - } else { - spin_lock_irqsave(&p->lock, flags); - csr = readl(p->regs + EBDMA_CSR); - csr &= ~EBDMA_CSR_INT_EN; - writel(csr, p->regs + EBDMA_CSR); - spin_unlock_irqrestore(&p->lock, flags); - - if (p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) { - free_irq(p->irq, p); - } - } - - return 0; -} -EXPORT_SYMBOL(ebus_dma_irq_enable); - -void ebus_dma_unregister(struct ebus_dma_info *p) -{ - unsigned long flags; - u32 csr; - int irq_on = 0; - - spin_lock_irqsave(&p->lock, flags); - csr = readl(p->regs + EBDMA_CSR); - if (csr & EBDMA_CSR_INT_EN) { - csr &= ~EBDMA_CSR_INT_EN; - writel(csr, p->regs + EBDMA_CSR); - irq_on = 1; - } - spin_unlock_irqrestore(&p->lock, flags); - - if (irq_on) - free_irq(p->irq, p); -} -EXPORT_SYMBOL(ebus_dma_unregister); - -int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, size_t len) -{ - unsigned long flags; - u32 csr; - int err; - - if (len >= (1 << 24)) - return -EINVAL; - - spin_lock_irqsave(&p->lock, flags); - csr = readl(p->regs + EBDMA_CSR); - err = -EINVAL; - if (!(csr & EBDMA_CSR_EN_DMA)) - goto out; - err = -EBUSY; - if (csr & EBDMA_CSR_NA_LOADED) - goto out; - - writel(len, p->regs + EBDMA_COUNT); - writel(bus_addr, p->regs + EBDMA_ADDR); - err = 0; - -out: - spin_unlock_irqrestore(&p->lock, flags); - - return err; -} -EXPORT_SYMBOL(ebus_dma_request); - -void ebus_dma_prepare(struct ebus_dma_info *p, int write) -{ - unsigned long flags; - u32 csr; - - spin_lock_irqsave(&p->lock, flags); - __ebus_dma_reset(p, 0); - - csr = (EBDMA_CSR_INT_EN | - EBDMA_CSR_EN_CNT | - EBDMA_CSR_BURST_SZ_16 | - EBDMA_CSR_EN_NEXT); - - if (write) - csr |= EBDMA_CSR_WRITE; - if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE) - csr |= EBDMA_CSR_TCI_DIS; - - writel(csr, p->regs + EBDMA_CSR); - - spin_unlock_irqrestore(&p->lock, flags); -} -EXPORT_SYMBOL(ebus_dma_prepare); - -unsigned int ebus_dma_residue(struct ebus_dma_info *p) -{ - return readl(p->regs + EBDMA_COUNT); -} -EXPORT_SYMBOL(ebus_dma_residue); - -unsigned int ebus_dma_addr(struct ebus_dma_info *p) -{ - return readl(p->regs + EBDMA_ADDR); -} -EXPORT_SYMBOL(ebus_dma_addr); - -void ebus_dma_enable(struct ebus_dma_info *p, int on) -{ - unsigned long flags; - u32 orig_csr, csr; - - spin_lock_irqsave(&p->lock, flags); - orig_csr = csr = readl(p->regs + EBDMA_CSR); - if (on) - csr |= EBDMA_CSR_EN_DMA; - else - csr &= ~EBDMA_CSR_EN_DMA; - if ((orig_csr & EBDMA_CSR_EN_DMA) != - (csr & EBDMA_CSR_EN_DMA)) - writel(csr, p->regs + EBDMA_CSR); - spin_unlock_irqrestore(&p->lock, flags); -} -EXPORT_SYMBOL(ebus_dma_enable); - -struct linux_ebus *ebus_chain = NULL; - -#ifdef CONFIG_SUN_AUXIO -extern void auxio_probe(void); -#endif - -static inline void *ebus_alloc(size_t size) -{ - void *mem; - - mem = kmalloc(size, GFP_ATOMIC); - if (!mem) - panic("ebus_alloc: out of memory"); - memset((char *)mem, 0, size); - return mem; -} - -static void __init ebus_ranges_init(struct linux_ebus *ebus) -{ - int success; - - ebus->num_ebus_ranges = 0; - success = prom_getproperty(ebus->prom_node, "ranges", - (char *)ebus->ebus_ranges, - sizeof(ebus->ebus_ranges)); - if (success != -1) - ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges)); -} - -static void __init ebus_intmap_init(struct linux_ebus *ebus) -{ - int success; - - ebus->num_ebus_intmap = 0; - success = prom_getproperty(ebus->prom_node, "interrupt-map", - (char *)ebus->ebus_intmap, - sizeof(ebus->ebus_intmap)); - if (success == -1) - return; - - ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap)); - - success = prom_getproperty(ebus->prom_node, "interrupt-map-mask", - (char *)&ebus->ebus_intmask, - sizeof(ebus->ebus_intmask)); - if (success == -1) { - prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__); - prom_halt(); - } -} - -int __init ebus_intmap_match(struct linux_ebus *ebus, - struct linux_prom_registers *reg, - int *interrupt) -{ - unsigned int hi, lo, irq; - int i; - - if (!ebus->num_ebus_intmap) - return 0; - - hi = reg->which_io & ebus->ebus_intmask.phys_hi; - lo = reg->phys_addr & ebus->ebus_intmask.phys_lo; - irq = *interrupt & ebus->ebus_intmask.interrupt; - for (i = 0; i < ebus->num_ebus_intmap; i++) { - if ((ebus->ebus_intmap[i].phys_hi == hi) && - (ebus->ebus_intmap[i].phys_lo == lo) && - (ebus->ebus_intmap[i].interrupt == irq)) { - *interrupt = ebus->ebus_intmap[i].cinterrupt; - return 0; - } - } - return -1; -} - -void __init fill_ebus_child(int node, struct linux_prom_registers *preg, - struct linux_ebus_child *dev, int non_standard_regs) -{ - int regs[PROMREG_MAX]; - int irqs[PROMREG_MAX]; - int i, len; - - dev->prom_node = node; - prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); - printk(" (%s)", dev->prom_name); - - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); - dev->num_addrs = len / sizeof(regs[0]); - - if (non_standard_regs) { - /* This is to handle reg properties which are not - * in the parent relative format. One example are - * children of the i2c device on CompactPCI systems. - * - * So, for such devices we just record the property - * raw in the child resources. - */ - for (i = 0; i < dev->num_addrs; i++) - dev->resource[i].start = regs[i]; - } else { - for (i = 0; i < dev->num_addrs; i++) { - int rnum = regs[i]; - if (rnum >= dev->parent->num_addrs) { - prom_printf("UGH: property for %s was %d, need < %d\n", - dev->prom_name, len, dev->parent->num_addrs); - panic(__FUNCTION__); - } - dev->resource[i].start = dev->parent->resource[i].start; - dev->resource[i].end = dev->parent->resource[i].end; - dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dev->prom_name; - } - } - - for (i = 0; i < PROMINTR_MAX; i++) - dev->irqs[i] = PCI_IRQ_NONE; - - len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); - if ((len == -1) || (len == 0)) { - dev->num_irqs = 0; - /* - * Oh, well, some PROMs don't export interrupts - * property to children of EBus devices... - * - * Be smart about PS/2 keyboard and mouse. - */ - if (!strcmp(dev->parent->prom_name, "8042")) { - if (!strcmp(dev->prom_name, "kb_ps2")) { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[0]; - } else { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[1]; - } - } - } else { - dev->num_irqs = len / sizeof(irqs[0]); - for (i = 0; i < dev->num_irqs; i++) { - struct pci_pbm_info *pbm = dev->bus->parent; - struct pci_controller_info *p = pbm->parent; - - if (ebus_intmap_match(dev->bus, preg, &irqs[i]) != -1) { - dev->irqs[i] = p->irq_build(pbm, - dev->bus->self, - irqs[i]); - } else { - /* If we get a bogus interrupt property, just - * record the raw value instead of punting. - */ - dev->irqs[i] = irqs[i]; - } - } - } -} - -static int __init child_regs_nonstandard(struct linux_ebus_device *dev) -{ - if (!strcmp(dev->prom_name, "i2c") || - !strcmp(dev->prom_name, "SUNW,lombus")) - return 1; - return 0; -} - -void __init fill_ebus_device(int node, struct linux_ebus_device *dev) -{ - struct linux_prom_registers regs[PROMREG_MAX]; - struct linux_ebus_child *child; - int irqs[PROMINTR_MAX]; - int i, n, len; - - dev->prom_node = node; - prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); - printk(" [%s", dev->prom_name); - - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); - if (len == -1) { - dev->num_addrs = 0; - goto probe_interrupts; - } - - if (len % sizeof(struct linux_prom_registers)) { - prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_name, len, - (int)sizeof(struct linux_prom_registers)); - prom_halt(); - } - dev->num_addrs = len / sizeof(struct linux_prom_registers); - - for (i = 0; i < dev->num_addrs; i++) { - /* XXX Learn how to interpret ebus ranges... -DaveM */ - if (regs[i].which_io >= 0x10) - n = (regs[i].which_io - 0x10) >> 2; - else - n = regs[i].which_io; - - dev->resource[i].start = dev->bus->self->resource[n].start; - dev->resource[i].start += (unsigned long)regs[i].phys_addr; - dev->resource[i].end = - (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); - dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dev->prom_name; - request_resource(&dev->bus->self->resource[n], - &dev->resource[i]); - } - -probe_interrupts: - for (i = 0; i < PROMINTR_MAX; i++) - dev->irqs[i] = PCI_IRQ_NONE; - - len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); - if ((len == -1) || (len == 0)) { - dev->num_irqs = 0; - } else { - dev->num_irqs = len / sizeof(irqs[0]); - for (i = 0; i < dev->num_irqs; i++) { - struct pci_pbm_info *pbm = dev->bus->parent; - struct pci_controller_info *p = pbm->parent; - - if (ebus_intmap_match(dev->bus, ®s[0], &irqs[i]) != -1) { - dev->irqs[i] = p->irq_build(pbm, - dev->bus->self, - irqs[i]); - } else { - /* If we get a bogus interrupt property, just - * record the raw value instead of punting. - */ - dev->irqs[i] = irqs[i]; - } - } - } - - if ((node = prom_getchild(node))) { - printk(" ->"); - dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); - - child = dev->children; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(node, ®s[0], - child, child_regs_nonstandard(dev)); - - while ((node = prom_getsibling(node)) != 0) { - child->next = ebus_alloc(sizeof(struct linux_ebus_child)); - - child = child->next; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(node, ®s[0], - child, child_regs_nonstandard(dev)); - } - } - printk("]"); -} - -static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) -{ - struct pci_dev *pdev = start; - - while ((pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev))) - if (pdev->device == PCI_DEVICE_ID_SUN_EBUS || - pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS) - break; - - *is_rio_p = !!(pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS)); - - return pdev; -} - -void __init ebus_init(void) -{ - struct pci_pbm_info *pbm; - struct linux_ebus_device *dev; - struct linux_ebus *ebus; - struct pci_dev *pdev; - struct pcidev_cookie *cookie; - int nd, ebusnd, is_rio; - int num_ebus = 0; - - pdev = find_next_ebus(NULL, &is_rio); - if (!pdev) { - printk("ebus: No EBus's found.\n"); - return; - } - - cookie = pdev->sysdata; - ebusnd = cookie->prom_node; - - ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); - ebus->next = NULL; - ebus->is_rio = is_rio; - - while (ebusnd) { - /* SUNW,pci-qfe uses four empty ebuses on it. - I think we should not consider them here, - as they have half of the properties this - code expects and once we do PCI hot-plug, - we'd have to tweak with the ebus_chain - in the runtime after initialization. -jj */ - if (!prom_getchild (ebusnd)) { - pdev = find_next_ebus(pdev, &is_rio); - if (!pdev) { - if (ebus == ebus_chain) { - ebus_chain = NULL; - printk("ebus: No EBus's found.\n"); - return; - } - break; - } - ebus->is_rio = is_rio; - cookie = pdev->sysdata; - ebusnd = cookie->prom_node; - continue; - } - printk("ebus%d:", num_ebus); - - prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name)); - ebus->index = num_ebus; - ebus->prom_node = ebusnd; - ebus->self = pdev; - ebus->parent = pbm = cookie->pbm; - - ebus_ranges_init(ebus); - ebus_intmap_init(ebus); - - nd = prom_getchild(ebusnd); - if (!nd) - goto next_ebus; - - ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = ebus->devices; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(nd, dev); - - while ((nd = prom_getsibling(nd)) != 0) { - dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = dev->next; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(nd, dev); - } - - next_ebus: - printk("\n"); - - pdev = find_next_ebus(pdev, &is_rio); - if (!pdev) - break; - - cookie = pdev->sysdata; - ebusnd = cookie->prom_node; - - ebus->next = ebus_alloc(sizeof(struct linux_ebus)); - ebus = ebus->next; - ebus->next = NULL; - ebus->is_rio = is_rio; - ++num_ebus; - } - pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ - -#ifdef CONFIG_SUN_AUXIO - auxio_probe(); -#endif -} diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S deleted file mode 100644 index e50e56e4ab6..00000000000 --- a/arch/sparc64/kernel/entry.S +++ /dev/null @@ -1,1692 +0,0 @@ -/* $Id: entry.S,v 1.144 2002/02/09 19:49:30 davem Exp $ - * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. - * - * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1996,98,99 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/config.h> -#include <linux/errno.h> - -#include <asm/head.h> -#include <asm/asi.h> -#include <asm/smp.h> -#include <asm/ptrace.h> -#include <asm/page.h> -#include <asm/signal.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/visasm.h> -#include <asm/estate.h> -#include <asm/auxio.h> -#include <asm/sfafsr.h> - -#define curptr g6 - -#define NR_SYSCALLS 284 /* Each OS is different... */ - - .text - .align 32 - - /* This is trivial with the new code... */ - .globl do_fpdis -do_fpdis: - sethi %hi(TSTATE_PEF), %g4 - rdpr %tstate, %g5 - andcc %g5, %g4, %g0 - be,pt %xcc, 1f - nop - rd %fprs, %g5 - andcc %g5, FPRS_FEF, %g0 - be,pt %xcc, 1f - nop - - /* Legal state when DCR_IFPOE is set in Cheetah %dcr. */ - sethi %hi(109f), %g7 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - add %g0, %g0, %g0 - ba,a,pt %xcc, rtrap_clr_l6 - -1: ldub [%g6 + TI_FPSAVED], %g5 - wr %g0, FPRS_FEF, %fprs - andcc %g5, FPRS_FEF, %g0 - be,a,pt %icc, 1f - clr %g7 - ldx [%g6 + TI_GSR], %g7 -1: andcc %g5, FPRS_DL, %g0 - bne,pn %icc, 2f - fzero %f0 - andcc %g5, FPRS_DU, %g0 - bne,pn %icc, 1f - fzero %f2 - faddd %f0, %f2, %f4 - fmuld %f0, %f2, %f6 - faddd %f0, %f2, %f8 - fmuld %f0, %f2, %f10 - faddd %f0, %f2, %f12 - fmuld %f0, %f2, %f14 - faddd %f0, %f2, %f16 - fmuld %f0, %f2, %f18 - faddd %f0, %f2, %f20 - fmuld %f0, %f2, %f22 - faddd %f0, %f2, %f24 - fmuld %f0, %f2, %f26 - faddd %f0, %f2, %f28 - fmuld %f0, %f2, %f30 - faddd %f0, %f2, %f32 - fmuld %f0, %f2, %f34 - faddd %f0, %f2, %f36 - fmuld %f0, %f2, %f38 - faddd %f0, %f2, %f40 - fmuld %f0, %f2, %f42 - faddd %f0, %f2, %f44 - fmuld %f0, %f2, %f46 - faddd %f0, %f2, %f48 - fmuld %f0, %f2, %f50 - faddd %f0, %f2, %f52 - fmuld %f0, %f2, %f54 - faddd %f0, %f2, %f56 - fmuld %f0, %f2, %f58 - b,pt %xcc, fpdis_exit2 - faddd %f0, %f2, %f60 -1: mov SECONDARY_CONTEXT, %g3 - add %g6, TI_FPREGS + 0x80, %g1 - faddd %f0, %f2, %f4 - fmuld %f0, %f2, %f6 - ldxa [%g3] ASI_DMMU, %g5 - sethi %hi(sparc64_kern_sec_context), %g2 - ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 - stxa %g2, [%g3] ASI_DMMU - membar #Sync - add %g6, TI_FPREGS + 0xc0, %g2 - faddd %f0, %f2, %f8 - fmuld %f0, %f2, %f10 - membar #Sync - ldda [%g1] ASI_BLK_S, %f32 - ldda [%g2] ASI_BLK_S, %f48 - membar #Sync - faddd %f0, %f2, %f12 - fmuld %f0, %f2, %f14 - faddd %f0, %f2, %f16 - fmuld %f0, %f2, %f18 - faddd %f0, %f2, %f20 - fmuld %f0, %f2, %f22 - faddd %f0, %f2, %f24 - fmuld %f0, %f2, %f26 - faddd %f0, %f2, %f28 - fmuld %f0, %f2, %f30 - b,pt %xcc, fpdis_exit - nop -2: andcc %g5, FPRS_DU, %g0 - bne,pt %icc, 3f - fzero %f32 - mov SECONDARY_CONTEXT, %g3 - fzero %f34 - ldxa [%g3] ASI_DMMU, %g5 - add %g6, TI_FPREGS, %g1 - sethi %hi(sparc64_kern_sec_context), %g2 - ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 - stxa %g2, [%g3] ASI_DMMU - membar #Sync - add %g6, TI_FPREGS + 0x40, %g2 - faddd %f32, %f34, %f36 - fmuld %f32, %f34, %f38 - membar #Sync - ldda [%g1] ASI_BLK_S, %f0 - ldda [%g2] ASI_BLK_S, %f16 - membar #Sync - faddd %f32, %f34, %f40 - fmuld %f32, %f34, %f42 - faddd %f32, %f34, %f44 - fmuld %f32, %f34, %f46 - faddd %f32, %f34, %f48 - fmuld %f32, %f34, %f50 - faddd %f32, %f34, %f52 - fmuld %f32, %f34, %f54 - faddd %f32, %f34, %f56 - fmuld %f32, %f34, %f58 - faddd %f32, %f34, %f60 - fmuld %f32, %f34, %f62 - ba,pt %xcc, fpdis_exit - nop -3: mov SECONDARY_CONTEXT, %g3 - add %g6, TI_FPREGS, %g1 - ldxa [%g3] ASI_DMMU, %g5 - sethi %hi(sparc64_kern_sec_context), %g2 - ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 - stxa %g2, [%g3] ASI_DMMU - membar #Sync - mov 0x40, %g2 - membar #Sync - ldda [%g1] ASI_BLK_S, %f0 - ldda [%g1 + %g2] ASI_BLK_S, %f16 - add %g1, 0x80, %g1 - ldda [%g1] ASI_BLK_S, %f32 - ldda [%g1 + %g2] ASI_BLK_S, %f48 - membar #Sync -fpdis_exit: - stxa %g5, [%g3] ASI_DMMU - membar #Sync -fpdis_exit2: - wr %g7, 0, %gsr - ldx [%g6 + TI_XFSR], %fsr - rdpr %tstate, %g3 - or %g3, %g4, %g3 ! anal... - wrpr %g3, %tstate - wr %g0, FPRS_FEF, %fprs ! clean DU/DL bits - retry - - .align 32 -fp_other_bounce: - call do_fpother - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - .globl do_fpother_check_fitos - .align 32 -do_fpother_check_fitos: - sethi %hi(fp_other_bounce - 4), %g7 - or %g7, %lo(fp_other_bounce - 4), %g7 - - /* NOTE: Need to preserve %g7 until we fully commit - * to the fitos fixup. - */ - stx %fsr, [%g6 + TI_XFSR] - rdpr %tstate, %g3 - andcc %g3, TSTATE_PRIV, %g0 - bne,pn %xcc, do_fptrap_after_fsr - nop - ldx [%g6 + TI_XFSR], %g3 - srlx %g3, 14, %g1 - and %g1, 7, %g1 - cmp %g1, 2 ! Unfinished FP-OP - bne,pn %xcc, do_fptrap_after_fsr - sethi %hi(1 << 23), %g1 ! Inexact - andcc %g3, %g1, %g0 - bne,pn %xcc, do_fptrap_after_fsr - rdpr %tpc, %g1 - lduwa [%g1] ASI_AIUP, %g3 ! This cannot ever fail -#define FITOS_MASK 0xc1f83fe0 -#define FITOS_COMPARE 0x81a01880 - sethi %hi(FITOS_MASK), %g1 - or %g1, %lo(FITOS_MASK), %g1 - and %g3, %g1, %g1 - sethi %hi(FITOS_COMPARE), %g2 - or %g2, %lo(FITOS_COMPARE), %g2 - cmp %g1, %g2 - bne,pn %xcc, do_fptrap_after_fsr - nop - std %f62, [%g6 + TI_FPREGS + (62 * 4)] - sethi %hi(fitos_table_1), %g1 - and %g3, 0x1f, %g2 - or %g1, %lo(fitos_table_1), %g1 - sllx %g2, 2, %g2 - jmpl %g1 + %g2, %g0 - ba,pt %xcc, fitos_emul_continue - -fitos_table_1: - fitod %f0, %f62 - fitod %f1, %f62 - fitod %f2, %f62 - fitod %f3, %f62 - fitod %f4, %f62 - fitod %f5, %f62 - fitod %f6, %f62 - fitod %f7, %f62 - fitod %f8, %f62 - fitod %f9, %f62 - fitod %f10, %f62 - fitod %f11, %f62 - fitod %f12, %f62 - fitod %f13, %f62 - fitod %f14, %f62 - fitod %f15, %f62 - fitod %f16, %f62 - fitod %f17, %f62 - fitod %f18, %f62 - fitod %f19, %f62 - fitod %f20, %f62 - fitod %f21, %f62 - fitod %f22, %f62 - fitod %f23, %f62 - fitod %f24, %f62 - fitod %f25, %f62 - fitod %f26, %f62 - fitod %f27, %f62 - fitod %f28, %f62 - fitod %f29, %f62 - fitod %f30, %f62 - fitod %f31, %f62 - -fitos_emul_continue: - sethi %hi(fitos_table_2), %g1 - srl %g3, 25, %g2 - or %g1, %lo(fitos_table_2), %g1 - and %g2, 0x1f, %g2 - sllx %g2, 2, %g2 - jmpl %g1 + %g2, %g0 - ba,pt %xcc, fitos_emul_fini - -fitos_table_2: - fdtos %f62, %f0 - fdtos %f62, %f1 - fdtos %f62, %f2 - fdtos %f62, %f3 - fdtos %f62, %f4 - fdtos %f62, %f5 - fdtos %f62, %f6 - fdtos %f62, %f7 - fdtos %f62, %f8 - fdtos %f62, %f9 - fdtos %f62, %f10 - fdtos %f62, %f11 - fdtos %f62, %f12 - fdtos %f62, %f13 - fdtos %f62, %f14 - fdtos %f62, %f15 - fdtos %f62, %f16 - fdtos %f62, %f17 - fdtos %f62, %f18 - fdtos %f62, %f19 - fdtos %f62, %f20 - fdtos %f62, %f21 - fdtos %f62, %f22 - fdtos %f62, %f23 - fdtos %f62, %f24 - fdtos %f62, %f25 - fdtos %f62, %f26 - fdtos %f62, %f27 - fdtos %f62, %f28 - fdtos %f62, %f29 - fdtos %f62, %f30 - fdtos %f62, %f31 - -fitos_emul_fini: - ldd [%g6 + TI_FPREGS + (62 * 4)], %f62 - done - - .globl do_fptrap - .align 32 -do_fptrap: - stx %fsr, [%g6 + TI_XFSR] -do_fptrap_after_fsr: - ldub [%g6 + TI_FPSAVED], %g3 - rd %fprs, %g1 - or %g3, %g1, %g3 - stb %g3, [%g6 + TI_FPSAVED] - rd %gsr, %g3 - stx %g3, [%g6 + TI_GSR] - mov SECONDARY_CONTEXT, %g3 - ldxa [%g3] ASI_DMMU, %g5 - sethi %hi(sparc64_kern_sec_context), %g2 - ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 - stxa %g2, [%g3] ASI_DMMU - membar #Sync - add %g6, TI_FPREGS, %g2 - andcc %g1, FPRS_DL, %g0 - be,pn %icc, 4f - mov 0x40, %g3 - stda %f0, [%g2] ASI_BLK_S - stda %f16, [%g2 + %g3] ASI_BLK_S - andcc %g1, FPRS_DU, %g0 - be,pn %icc, 5f -4: add %g2, 128, %g2 - stda %f32, [%g2] ASI_BLK_S - stda %f48, [%g2 + %g3] ASI_BLK_S -5: mov SECONDARY_CONTEXT, %g1 - membar #Sync - stxa %g5, [%g1] ASI_DMMU - membar #Sync - ba,pt %xcc, etrap - wr %g0, 0, %fprs - - /* The registers for cross calls will be: - * - * DATA 0: [low 32-bits] Address of function to call, jmp to this - * [high 32-bits] MMU Context Argument 0, place in %g5 - * DATA 1: Address Argument 1, place in %g1 - * DATA 2: Address Argument 2, place in %g7 - * - * With this method we can do most of the cross-call tlb/cache - * flushing very quickly. - * - * Current CPU's IRQ worklist table is locked into %g6, don't touch. - */ - .text - .align 32 - .globl do_ivec -do_ivec: - mov 0x40, %g3 - ldxa [%g3 + %g0] ASI_INTR_R, %g3 - sethi %hi(KERNBASE), %g4 - cmp %g3, %g4 - bgeu,pn %xcc, do_ivec_xcall - srlx %g3, 32, %g5 - stxa %g0, [%g0] ASI_INTR_RECEIVE - membar #Sync - - sethi %hi(ivector_table), %g2 - sllx %g3, 5, %g3 - or %g2, %lo(ivector_table), %g2 - add %g2, %g3, %g3 - ldub [%g3 + 0x04], %g4 /* pil */ - mov 1, %g2 - sllx %g2, %g4, %g2 - sllx %g4, 2, %g4 - - lduw [%g6 + %g4], %g5 /* g5 = irq_work(cpu, pil) */ - stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */ - stw %g3, [%g6 + %g4] /* irq_work(cpu, pil) = bucket */ - wr %g2, 0x0, %set_softint - retry -do_ivec_xcall: - mov 0x50, %g1 - ldxa [%g1 + %g0] ASI_INTR_R, %g1 - srl %g3, 0, %g3 - - mov 0x60, %g7 - ldxa [%g7 + %g0] ASI_INTR_R, %g7 - stxa %g0, [%g0] ASI_INTR_RECEIVE - membar #Sync - ba,pt %xcc, 1f - nop - - .align 32 -1: jmpl %g3, %g0 - nop - - .globl save_alternate_globals -save_alternate_globals: /* %o0 = save_area */ - rdpr %pstate, %o5 - andn %o5, PSTATE_IE, %o1 - wrpr %o1, PSTATE_AG, %pstate - stx %g0, [%o0 + 0x00] - stx %g1, [%o0 + 0x08] - stx %g2, [%o0 + 0x10] - stx %g3, [%o0 + 0x18] - stx %g4, [%o0 + 0x20] - stx %g5, [%o0 + 0x28] - stx %g6, [%o0 + 0x30] - stx %g7, [%o0 + 0x38] - wrpr %o1, PSTATE_IG, %pstate - stx %g0, [%o0 + 0x40] - stx %g1, [%o0 + 0x48] - stx %g2, [%o0 + 0x50] - stx %g3, [%o0 + 0x58] - stx %g4, [%o0 + 0x60] - stx %g5, [%o0 + 0x68] - stx %g6, [%o0 + 0x70] - stx %g7, [%o0 + 0x78] - wrpr %o1, PSTATE_MG, %pstate - stx %g0, [%o0 + 0x80] - stx %g1, [%o0 + 0x88] - stx %g2, [%o0 + 0x90] - stx %g3, [%o0 + 0x98] - stx %g4, [%o0 + 0xa0] - stx %g5, [%o0 + 0xa8] - stx %g6, [%o0 + 0xb0] - stx %g7, [%o0 + 0xb8] - wrpr %o5, 0x0, %pstate - retl - nop - - .globl restore_alternate_globals -restore_alternate_globals: /* %o0 = save_area */ - rdpr %pstate, %o5 - andn %o5, PSTATE_IE, %o1 - wrpr %o1, PSTATE_AG, %pstate - ldx [%o0 + 0x00], %g0 - ldx [%o0 + 0x08], %g1 - ldx [%o0 + 0x10], %g2 - ldx [%o0 + 0x18], %g3 - ldx [%o0 + 0x20], %g4 - ldx [%o0 + 0x28], %g5 - ldx [%o0 + 0x30], %g6 - ldx [%o0 + 0x38], %g7 - wrpr %o1, PSTATE_IG, %pstate - ldx [%o0 + 0x40], %g0 - ldx [%o0 + 0x48], %g1 - ldx [%o0 + 0x50], %g2 - ldx [%o0 + 0x58], %g3 - ldx [%o0 + 0x60], %g4 - ldx [%o0 + 0x68], %g5 - ldx [%o0 + 0x70], %g6 - ldx [%o0 + 0x78], %g7 - wrpr %o1, PSTATE_MG, %pstate - ldx [%o0 + 0x80], %g0 - ldx [%o0 + 0x88], %g1 - ldx [%o0 + 0x90], %g2 - ldx [%o0 + 0x98], %g3 - ldx [%o0 + 0xa0], %g4 - ldx [%o0 + 0xa8], %g5 - ldx [%o0 + 0xb0], %g6 - ldx [%o0 + 0xb8], %g7 - wrpr %o5, 0x0, %pstate - retl - nop - - .globl getcc, setcc -getcc: - ldx [%o0 + PT_V9_TSTATE], %o1 - srlx %o1, 32, %o1 - and %o1, 0xf, %o1 - retl - stx %o1, [%o0 + PT_V9_G1] -setcc: - ldx [%o0 + PT_V9_TSTATE], %o1 - ldx [%o0 + PT_V9_G1], %o2 - or %g0, %ulo(TSTATE_ICC), %o3 - sllx %o3, 32, %o3 - andn %o1, %o3, %o1 - sllx %o2, 32, %o2 - and %o2, %o3, %o2 - or %o1, %o2, %o1 - retl - stx %o1, [%o0 + PT_V9_TSTATE] - - .globl utrap, utrap_ill -utrap: brz,pn %g1, etrap - nop - save %sp, -128, %sp - rdpr %tstate, %l6 - rdpr %cwp, %l7 - andn %l6, TSTATE_CWP, %l6 - wrpr %l6, %l7, %tstate - rdpr %tpc, %l6 - rdpr %tnpc, %l7 - wrpr %g1, 0, %tnpc - done -utrap_ill: - call bad_trap - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - /* XXX Here is stuff we still need to write... -DaveM XXX */ - .globl netbsd_syscall -netbsd_syscall: - retl - nop - - /* We need to carefully read the error status, ACK - * the errors, prevent recursive traps, and pass the - * information on to C code for logging. - * - * We pass the AFAR in as-is, and we encode the status - * information as described in asm-sparc64/sfafsr.h - */ - .globl __spitfire_access_error -__spitfire_access_error: - /* Disable ESTATE error reporting so that we do not - * take recursive traps and RED state the processor. - */ - stxa %g0, [%g0] ASI_ESTATE_ERROR_EN - membar #Sync - - mov UDBE_UE, %g1 - ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR - - /* __spitfire_cee_trap branches here with AFSR in %g4 and - * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the - * ESTATE Error Enable register. - */ -__spitfire_cee_trap_continue: - ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR - - rdpr %tt, %g3 - and %g3, 0x1ff, %g3 ! Paranoia - sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3 - or %g4, %g3, %g4 - rdpr %tl, %g3 - cmp %g3, 1 - mov 1, %g3 - bleu %xcc, 1f - sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3 - - or %g4, %g3, %g4 - - /* Read in the UDB error register state, clearing the - * sticky error bits as-needed. We only clear them if - * the UE bit is set. Likewise, __spitfire_cee_trap - * below will only do so if the CE bit is set. - * - * NOTE: UltraSparc-I/II have high and low UDB error - * registers, corresponding to the two UDB units - * present on those chips. UltraSparc-IIi only - * has a single UDB, called "SDB" in the manual. - * For IIi the upper UDB register always reads - * as zero so for our purposes things will just - * work with the checks below. - */ -1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3 - and %g3, 0x3ff, %g7 ! Paranoia - sllx %g7, SFSTAT_UDBH_SHIFT, %g7 - or %g4, %g7, %g4 - andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE - be,pn %xcc, 1f - nop - stxa %g3, [%g0] ASI_UDB_ERROR_W - membar #Sync - -1: mov 0x18, %g3 - ldxa [%g3] ASI_UDBL_ERROR_R, %g3 - and %g3, 0x3ff, %g7 ! Paranoia - sllx %g7, SFSTAT_UDBL_SHIFT, %g7 - or %g4, %g7, %g4 - andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE - be,pn %xcc, 1f - nop - mov 0x18, %g7 - stxa %g3, [%g7] ASI_UDB_ERROR_W - membar #Sync - -1: /* Ok, now that we've latched the error state, - * clear the sticky bits in the AFSR. - */ - stxa %g4, [%g0] ASI_AFSR - membar #Sync - - rdpr %tl, %g2 - cmp %g2, 1 - rdpr %pil, %g2 - bleu,pt %xcc, 1f - wrpr %g0, 15, %pil - - ba,pt %xcc, etraptl1 - rd %pc, %g7 - - ba,pt %xcc, 2f - nop - -1: ba,pt %xcc, etrap_irq - rd %pc, %g7 - -2: mov %l4, %o1 - mov %l5, %o2 - call spitfire_access_error - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - /* This is the trap handler entry point for ECC correctable - * errors. They are corrected, but we listen for the trap - * so that the event can be logged. - * - * Disrupting errors are either: - * 1) single-bit ECC errors during UDB reads to system - * memory - * 2) data parity errors during write-back events - * - * As far as I can make out from the manual, the CEE trap - * is only for correctable errors during memory read - * accesses by the front-end of the processor. - * - * The code below is only for trap level 1 CEE events, - * as it is the only situation where we can safely record - * and log. For trap level >1 we just clear the CE bit - * in the AFSR and return. - * - * This is just like __spiftire_access_error above, but it - * specifically handles correctable errors. If an - * uncorrectable error is indicated in the AFSR we - * will branch directly above to __spitfire_access_error - * to handle it instead. Uncorrectable therefore takes - * priority over correctable, and the error logging - * C code will notice this case by inspecting the - * trap type. - */ - .globl __spitfire_cee_trap -__spitfire_cee_trap: - ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR - mov 1, %g3 - sllx %g3, SFAFSR_UE_SHIFT, %g3 - andcc %g4, %g3, %g0 ! Check for UE - bne,pn %xcc, __spitfire_access_error - nop - - /* Ok, in this case we only have a correctable error. - * Indicate we only wish to capture that state in register - * %g1, and we only disable CE error reporting unlike UE - * handling which disables all errors. - */ - ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3 - andn %g3, ESTATE_ERR_CE, %g3 - stxa %g3, [%g0] ASI_ESTATE_ERROR_EN - membar #Sync - - /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */ - ba,pt %xcc, __spitfire_cee_trap_continue - mov UDBE_CE, %g1 - - .globl __spitfire_data_access_exception - .globl __spitfire_data_access_exception_tl1 -__spitfire_data_access_exception_tl1: - rdpr %pstate, %g4 - wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate - mov TLB_SFSR, %g3 - mov DMMU_SFAR, %g5 - ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR - ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR - stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit - membar #Sync - rdpr %tt, %g3 - cmp %g3, 0x80 ! first win spill/fill trap - blu,pn %xcc, 1f - cmp %g3, 0xff ! last win spill/fill trap - bgu,pn %xcc, 1f - nop - ba,pt %xcc, winfix_dax - rdpr %tpc, %g3 -1: sethi %hi(109f), %g7 - ba,pt %xcc, etraptl1 -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call spitfire_data_access_exception_tl1 - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - -__spitfire_data_access_exception: - rdpr %pstate, %g4 - wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate - mov TLB_SFSR, %g3 - mov DMMU_SFAR, %g5 - ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR - ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR - stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit - membar #Sync - sethi %hi(109f), %g7 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call spitfire_data_access_exception - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - .globl __spitfire_insn_access_exception - .globl __spitfire_insn_access_exception_tl1 -__spitfire_insn_access_exception_tl1: - rdpr %pstate, %g4 - wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate - mov TLB_SFSR, %g3 - ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR - rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC - stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit - membar #Sync - sethi %hi(109f), %g7 - ba,pt %xcc, etraptl1 -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call spitfire_insn_access_exception_tl1 - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - -__spitfire_insn_access_exception: - rdpr %pstate, %g4 - wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate - mov TLB_SFSR, %g3 - ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR - rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC - stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit - membar #Sync - sethi %hi(109f), %g7 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call spitfire_insn_access_exception - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - /* These get patched into the trap table at boot time - * once we know we have a cheetah processor. - */ - .globl cheetah_fecc_trap_vector, cheetah_fecc_trap_vector_tl1 -cheetah_fecc_trap_vector: - membar #Sync - ldxa [%g0] ASI_DCU_CONTROL_REG, %g1 - andn %g1, DCU_DC | DCU_IC, %g1 - stxa %g1, [%g0] ASI_DCU_CONTROL_REG - membar #Sync - sethi %hi(cheetah_fast_ecc), %g2 - jmpl %g2 + %lo(cheetah_fast_ecc), %g0 - mov 0, %g1 -cheetah_fecc_trap_vector_tl1: - membar #Sync - ldxa [%g0] ASI_DCU_CONTROL_REG, %g1 - andn %g1, DCU_DC | DCU_IC, %g1 - stxa %g1, [%g0] ASI_DCU_CONTROL_REG - membar #Sync - sethi %hi(cheetah_fast_ecc), %g2 - jmpl %g2 + %lo(cheetah_fast_ecc), %g0 - mov 1, %g1 - .globl cheetah_cee_trap_vector, cheetah_cee_trap_vector_tl1 -cheetah_cee_trap_vector: - membar #Sync - ldxa [%g0] ASI_DCU_CONTROL_REG, %g1 - andn %g1, DCU_IC, %g1 - stxa %g1, [%g0] ASI_DCU_CONTROL_REG - membar #Sync - sethi %hi(cheetah_cee), %g2 - jmpl %g2 + %lo(cheetah_cee), %g0 - mov 0, %g1 -cheetah_cee_trap_vector_tl1: - membar #Sync - ldxa [%g0] ASI_DCU_CONTROL_REG, %g1 - andn %g1, DCU_IC, %g1 - stxa %g1, [%g0] ASI_DCU_CONTROL_REG - membar #Sync - sethi %hi(cheetah_cee), %g2 - jmpl %g2 + %lo(cheetah_cee), %g0 - mov 1, %g1 - .globl cheetah_deferred_trap_vector, cheetah_deferred_trap_vector_tl1 -cheetah_deferred_trap_vector: - membar #Sync - ldxa [%g0] ASI_DCU_CONTROL_REG, %g1; - andn %g1, DCU_DC | DCU_IC, %g1; - stxa %g1, [%g0] ASI_DCU_CONTROL_REG; - membar #Sync; - sethi %hi(cheetah_deferred_trap), %g2 - jmpl %g2 + %lo(cheetah_deferred_trap), %g0 - mov 0, %g1 -cheetah_deferred_trap_vector_tl1: - membar #Sync; - ldxa [%g0] ASI_DCU_CONTROL_REG, %g1; - andn %g1, DCU_DC | DCU_IC, %g1; - stxa %g1, [%g0] ASI_DCU_CONTROL_REG; - membar #Sync; - sethi %hi(cheetah_deferred_trap), %g2 - jmpl %g2 + %lo(cheetah_deferred_trap), %g0 - mov 1, %g1 - - /* Cheetah+ specific traps. These are for the new I/D cache parity - * error traps. The first argument to cheetah_plus_parity_handler - * is encoded as follows: - * - * Bit0: 0=dcache,1=icache - * Bit1: 0=recoverable,1=unrecoverable - */ - .globl cheetah_plus_dcpe_trap_vector, cheetah_plus_dcpe_trap_vector_tl1 -cheetah_plus_dcpe_trap_vector: - membar #Sync - sethi %hi(do_cheetah_plus_data_parity), %g7 - jmpl %g7 + %lo(do_cheetah_plus_data_parity), %g0 - nop - nop - nop - nop - nop - -do_cheetah_plus_data_parity: - rdpr %pil, %g2 - wrpr %g0, 15, %pil - ba,pt %xcc, etrap_irq - rd %pc, %g7 - mov 0x0, %o0 - call cheetah_plus_parity_error - add %sp, PTREGS_OFF, %o1 - ba,a,pt %xcc, rtrap_irq - -cheetah_plus_dcpe_trap_vector_tl1: - membar #Sync - wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate - sethi %hi(do_dcpe_tl1), %g3 - jmpl %g3 + %lo(do_dcpe_tl1), %g0 - nop - nop - nop - nop - - .globl cheetah_plus_icpe_trap_vector, cheetah_plus_icpe_trap_vector_tl1 -cheetah_plus_icpe_trap_vector: - membar #Sync - sethi %hi(do_cheetah_plus_insn_parity), %g7 - jmpl %g7 + %lo(do_cheetah_plus_insn_parity), %g0 - nop - nop - nop - nop - nop - -do_cheetah_plus_insn_parity: - rdpr %pil, %g2 - wrpr %g0, 15, %pil - ba,pt %xcc, etrap_irq - rd %pc, %g7 - mov 0x1, %o0 - call cheetah_plus_parity_error - add %sp, PTREGS_OFF, %o1 - ba,a,pt %xcc, rtrap_irq - -cheetah_plus_icpe_trap_vector_tl1: - membar #Sync - wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate - sethi %hi(do_icpe_tl1), %g3 - jmpl %g3 + %lo(do_icpe_tl1), %g0 - nop - nop - nop - nop - - /* If we take one of these traps when tl >= 1, then we - * jump to interrupt globals. If some trap level above us - * was also using interrupt globals, we cannot recover. - * We may use all interrupt global registers except %g6. - */ - .globl do_dcpe_tl1, do_icpe_tl1 -do_dcpe_tl1: - rdpr %tl, %g1 ! Save original trap level - mov 1, %g2 ! Setup TSTATE checking loop - sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit -1: wrpr %g2, %tl ! Set trap level to check - rdpr %tstate, %g4 ! Read TSTATE for this level - andcc %g4, %g3, %g0 ! Interrupt globals in use? - bne,a,pn %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable - wrpr %g1, %tl ! Restore original trap level - add %g2, 1, %g2 ! Next trap level - cmp %g2, %g1 ! Hit them all yet? - ble,pt %icc, 1b ! Not yet - nop - wrpr %g1, %tl ! Restore original trap level -do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ - sethi %hi(dcache_parity_tl1_occurred), %g2 - lduw [%g2 + %lo(dcache_parity_tl1_occurred)], %g1 - add %g1, 1, %g1 - stw %g1, [%g2 + %lo(dcache_parity_tl1_occurred)] - /* Reset D-cache parity */ - sethi %hi(1 << 16), %g1 ! D-cache size - mov (1 << 5), %g2 ! D-cache line size - sub %g1, %g2, %g1 ! Move down 1 cacheline -1: srl %g1, 14, %g3 ! Compute UTAG - membar #Sync - stxa %g3, [%g1] ASI_DCACHE_UTAG - membar #Sync - sub %g2, 8, %g3 ! 64-bit data word within line -2: membar #Sync - stxa %g0, [%g1 + %g3] ASI_DCACHE_DATA - membar #Sync - subcc %g3, 8, %g3 ! Next 64-bit data word - bge,pt %icc, 2b - nop - subcc %g1, %g2, %g1 ! Next cacheline - bge,pt %icc, 1b - nop - ba,pt %xcc, dcpe_icpe_tl1_common - nop - -do_dcpe_tl1_fatal: - sethi %hi(1f), %g7 - ba,pt %xcc, etraptl1 -1: or %g7, %lo(1b), %g7 - mov 0x2, %o0 - call cheetah_plus_parity_error - add %sp, PTREGS_OFF, %o1 - ba,pt %xcc, rtrap - clr %l6 - -do_icpe_tl1: - rdpr %tl, %g1 ! Save original trap level - mov 1, %g2 ! Setup TSTATE checking loop - sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit -1: wrpr %g2, %tl ! Set trap level to check - rdpr %tstate, %g4 ! Read TSTATE for this level - andcc %g4, %g3, %g0 ! Interrupt globals in use? - bne,a,pn %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable - wrpr %g1, %tl ! Restore original trap level - add %g2, 1, %g2 ! Next trap level - cmp %g2, %g1 ! Hit them all yet? - ble,pt %icc, 1b ! Not yet - nop - wrpr %g1, %tl ! Restore original trap level -do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ - sethi %hi(icache_parity_tl1_occurred), %g2 - lduw [%g2 + %lo(icache_parity_tl1_occurred)], %g1 - add %g1, 1, %g1 - stw %g1, [%g2 + %lo(icache_parity_tl1_occurred)] - /* Flush I-cache */ - sethi %hi(1 << 15), %g1 ! I-cache size - mov (1 << 5), %g2 ! I-cache line size - sub %g1, %g2, %g1 -1: or %g1, (2 << 3), %g3 - stxa %g0, [%g3] ASI_IC_TAG - membar #Sync - subcc %g1, %g2, %g1 - bge,pt %icc, 1b - nop - ba,pt %xcc, dcpe_icpe_tl1_common - nop - -do_icpe_tl1_fatal: - sethi %hi(1f), %g7 - ba,pt %xcc, etraptl1 -1: or %g7, %lo(1b), %g7 - mov 0x3, %o0 - call cheetah_plus_parity_error - add %sp, PTREGS_OFF, %o1 - ba,pt %xcc, rtrap - clr %l6 - -dcpe_icpe_tl1_common: - /* Flush D-cache, re-enable D/I caches in DCU and finally - * retry the trapping instruction. - */ - sethi %hi(1 << 16), %g1 ! D-cache size - mov (1 << 5), %g2 ! D-cache line size - sub %g1, %g2, %g1 -1: stxa %g0, [%g1] ASI_DCACHE_TAG - membar #Sync - subcc %g1, %g2, %g1 - bge,pt %icc, 1b - nop - ldxa [%g0] ASI_DCU_CONTROL_REG, %g1 - or %g1, (DCU_DC | DCU_IC), %g1 - stxa %g1, [%g0] ASI_DCU_CONTROL_REG - membar #Sync - retry - - /* Capture I/D/E-cache state into per-cpu error scoreboard. - * - * %g1: (TL>=0) ? 1 : 0 - * %g2: scratch - * %g3: scratch - * %g4: AFSR - * %g5: AFAR - * %g6: current thread ptr - * %g7: scratch - */ -__cheetah_log_error: - /* Put "TL1" software bit into AFSR. */ - and %g1, 0x1, %g1 - sllx %g1, 63, %g2 - or %g4, %g2, %g4 - - /* Get log entry pointer for this cpu at this trap level. */ - BRANCH_IF_JALAPENO(g2,g3,50f) - ldxa [%g0] ASI_SAFARI_CONFIG, %g2 - srlx %g2, 17, %g2 - ba,pt %xcc, 60f - and %g2, 0x3ff, %g2 - -50: ldxa [%g0] ASI_JBUS_CONFIG, %g2 - srlx %g2, 17, %g2 - and %g2, 0x1f, %g2 - -60: sllx %g2, 9, %g2 - sethi %hi(cheetah_error_log), %g3 - ldx [%g3 + %lo(cheetah_error_log)], %g3 - brz,pn %g3, 80f - nop - - add %g3, %g2, %g3 - sllx %g1, 8, %g1 - add %g3, %g1, %g1 - - /* %g1 holds pointer to the top of the logging scoreboard */ - ldx [%g1 + 0x0], %g7 - cmp %g7, -1 - bne,pn %xcc, 80f - nop - - stx %g4, [%g1 + 0x0] - stx %g5, [%g1 + 0x8] - add %g1, 0x10, %g1 - - /* %g1 now points to D-cache logging area */ - set 0x3ff8, %g2 /* DC_addr mask */ - and %g5, %g2, %g2 /* DC_addr bits of AFAR */ - srlx %g5, 12, %g3 - or %g3, 1, %g3 /* PHYS tag + valid */ - -10: ldxa [%g2] ASI_DCACHE_TAG, %g7 - cmp %g3, %g7 /* TAG match? */ - bne,pt %xcc, 13f - nop - - /* Yep, what we want, capture state. */ - stx %g2, [%g1 + 0x20] - stx %g7, [%g1 + 0x28] - - /* A membar Sync is required before and after utag access. */ - membar #Sync - ldxa [%g2] ASI_DCACHE_UTAG, %g7 - membar #Sync - stx %g7, [%g1 + 0x30] - ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7 - stx %g7, [%g1 + 0x38] - clr %g3 - -12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7 - stx %g7, [%g1] - add %g3, (1 << 5), %g3 - cmp %g3, (4 << 5) - bl,pt %xcc, 12b - add %g1, 0x8, %g1 - - ba,pt %xcc, 20f - add %g1, 0x20, %g1 - -13: sethi %hi(1 << 14), %g7 - add %g2, %g7, %g2 - srlx %g2, 14, %g7 - cmp %g7, 4 - bl,pt %xcc, 10b - nop - - add %g1, 0x40, %g1 - - /* %g1 now points to I-cache logging area */ -20: set 0x1fe0, %g2 /* IC_addr mask */ - and %g5, %g2, %g2 /* IC_addr bits of AFAR */ - sllx %g2, 1, %g2 /* IC_addr[13:6]==VA[12:5] */ - srlx %g5, (13 - 8), %g3 /* Make PTAG */ - andn %g3, 0xff, %g3 /* Mask off undefined bits */ - -21: ldxa [%g2] ASI_IC_TAG, %g7 - andn %g7, 0xff, %g7 - cmp %g3, %g7 - bne,pt %xcc, 23f - nop - - /* Yep, what we want, capture state. */ - stx %g2, [%g1 + 0x40] - stx %g7, [%g1 + 0x48] - add %g2, (1 << 3), %g2 - ldxa [%g2] ASI_IC_TAG, %g7 - add %g2, (1 << 3), %g2 - stx %g7, [%g1 + 0x50] - ldxa [%g2] ASI_IC_TAG, %g7 - add %g2, (1 << 3), %g2 - stx %g7, [%g1 + 0x60] - ldxa [%g2] ASI_IC_TAG, %g7 - stx %g7, [%g1 + 0x68] - sub %g2, (3 << 3), %g2 - ldxa [%g2] ASI_IC_STAG, %g7 - stx %g7, [%g1 + 0x58] - clr %g3 - srlx %g2, 2, %g2 - -22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7 - stx %g7, [%g1] - add %g3, (1 << 3), %g3 - cmp %g3, (8 << 3) - bl,pt %xcc, 22b - add %g1, 0x8, %g1 - - ba,pt %xcc, 30f - add %g1, 0x30, %g1 - -23: sethi %hi(1 << 14), %g7 - add %g2, %g7, %g2 - srlx %g2, 14, %g7 - cmp %g7, 4 - bl,pt %xcc, 21b - nop - - add %g1, 0x70, %g1 - - /* %g1 now points to E-cache logging area */ -30: andn %g5, (32 - 1), %g2 - stx %g2, [%g1 + 0x20] - ldxa [%g2] ASI_EC_TAG_DATA, %g7 - stx %g7, [%g1 + 0x28] - ldxa [%g2] ASI_EC_R, %g0 - clr %g3 - -31: ldxa [%g3] ASI_EC_DATA, %g7 - stx %g7, [%g1 + %g3] - add %g3, 0x8, %g3 - cmp %g3, 0x20 - - bl,pt %xcc, 31b - nop -80: - rdpr %tt, %g2 - cmp %g2, 0x70 - be c_fast_ecc - cmp %g2, 0x63 - be c_cee - nop - ba,pt %xcc, c_deferred - - /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc - * in the trap table. That code has done a memory barrier - * and has disabled both the I-cache and D-cache in the DCU - * control register. The I-cache is disabled so that we may - * capture the corrupted cache line, and the D-cache is disabled - * because corrupt data may have been placed there and we don't - * want to reference it. - * - * %g1 is one if this trap occurred at %tl >= 1. - * - * Next, we turn off error reporting so that we don't recurse. - */ - .globl cheetah_fast_ecc -cheetah_fast_ecc: - ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2 - andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2 - stxa %g2, [%g0] ASI_ESTATE_ERROR_EN - membar #Sync - - /* Fetch and clear AFSR/AFAR */ - ldxa [%g0] ASI_AFSR, %g4 - ldxa [%g0] ASI_AFAR, %g5 - stxa %g4, [%g0] ASI_AFSR - membar #Sync - - ba,pt %xcc, __cheetah_log_error - nop - -c_fast_ecc: - rdpr %pil, %g2 - wrpr %g0, 15, %pil - ba,pt %xcc, etrap_irq - rd %pc, %g7 - mov %l4, %o1 - mov %l5, %o2 - call cheetah_fecc_handler - add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_irq - - /* Our caller has disabled I-cache and performed membar Sync. */ - .globl cheetah_cee -cheetah_cee: - ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2 - andn %g2, ESTATE_ERROR_CEEN, %g2 - stxa %g2, [%g0] ASI_ESTATE_ERROR_EN - membar #Sync - - /* Fetch and clear AFSR/AFAR */ - ldxa [%g0] ASI_AFSR, %g4 - ldxa [%g0] ASI_AFAR, %g5 - stxa %g4, [%g0] ASI_AFSR - membar #Sync - - ba,pt %xcc, __cheetah_log_error - nop - -c_cee: - rdpr %pil, %g2 - wrpr %g0, 15, %pil - ba,pt %xcc, etrap_irq - rd %pc, %g7 - mov %l4, %o1 - mov %l5, %o2 - call cheetah_cee_handler - add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_irq - - /* Our caller has disabled I-cache+D-cache and performed membar Sync. */ - .globl cheetah_deferred_trap -cheetah_deferred_trap: - ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2 - andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2 - stxa %g2, [%g0] ASI_ESTATE_ERROR_EN - membar #Sync - - /* Fetch and clear AFSR/AFAR */ - ldxa [%g0] ASI_AFSR, %g4 - ldxa [%g0] ASI_AFAR, %g5 - stxa %g4, [%g0] ASI_AFSR - membar #Sync - - ba,pt %xcc, __cheetah_log_error - nop - -c_deferred: - rdpr %pil, %g2 - wrpr %g0, 15, %pil - ba,pt %xcc, etrap_irq - rd %pc, %g7 - mov %l4, %o1 - mov %l5, %o2 - call cheetah_deferred_handler - add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_irq - - .globl __do_privact -__do_privact: - mov TLB_SFSR, %g3 - stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit - membar #Sync - sethi %hi(109f), %g7 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - call do_privact - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - .globl do_mna -do_mna: - rdpr %tl, %g3 - cmp %g3, 1 - - /* Setup %g4/%g5 now as they are used in the - * winfixup code. - */ - mov TLB_SFSR, %g3 - mov DMMU_SFAR, %g4 - ldxa [%g4] ASI_DMMU, %g4 - ldxa [%g3] ASI_DMMU, %g5 - stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit - membar #Sync - bgu,pn %icc, winfix_mna - rdpr %tpc, %g3 - -1: sethi %hi(109f), %g7 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call mem_address_unaligned - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - .globl do_lddfmna -do_lddfmna: - sethi %hi(109f), %g7 - mov TLB_SFSR, %g4 - ldxa [%g4] ASI_DMMU, %g5 - stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit - membar #Sync - mov DMMU_SFAR, %g4 - ldxa [%g4] ASI_DMMU, %g4 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call handle_lddfmna - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - .globl do_stdfmna -do_stdfmna: - sethi %hi(109f), %g7 - mov TLB_SFSR, %g4 - ldxa [%g4] ASI_DMMU, %g5 - stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit - membar #Sync - mov DMMU_SFAR, %g4 - ldxa [%g4] ASI_DMMU, %g4 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call handle_stdfmna - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - .globl breakpoint_trap -breakpoint_trap: - call sparc_breakpoint - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - nop - -#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ - defined(CONFIG_SOLARIS_EMUL_MODULE) - /* SunOS uses syscall zero as the 'indirect syscall' it looks - * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. - * This is complete brain damage. - */ - .globl sunos_indir -sunos_indir: - srl %o0, 0, %o0 - mov %o7, %l4 - cmp %o0, NR_SYSCALLS - blu,a,pt %icc, 1f - sll %o0, 0x2, %o0 - sethi %hi(sunos_nosys), %l6 - b,pt %xcc, 2f - or %l6, %lo(sunos_nosys), %l6 -1: sethi %hi(sunos_sys_table), %l7 - or %l7, %lo(sunos_sys_table), %l7 - lduw [%l7 + %o0], %l6 -2: mov %o1, %o0 - mov %o2, %o1 - mov %o3, %o2 - mov %o4, %o3 - mov %o5, %o4 - call %l6 - mov %l4, %o7 - - .globl sunos_getpid -sunos_getpid: - call sys_getppid - nop - call sys_getpid - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_sys_call - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - - /* SunOS getuid() returns uid in %o0 and euid in %o1 */ - .globl sunos_getuid -sunos_getuid: - call sys32_geteuid16 - nop - call sys32_getuid16 - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_sys_call - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - - /* SunOS getgid() returns gid in %o0 and egid in %o1 */ - .globl sunos_getgid -sunos_getgid: - call sys32_getegid16 - nop - call sys32_getgid16 - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_sys_call - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] -#endif - - /* SunOS's execv() call only specifies the argv argument, the - * environment settings are the same as the calling processes. - */ - .globl sunos_execv -sys_execve: - sethi %hi(sparc_execve), %g1 - ba,pt %xcc, execve_merge - or %g1, %lo(sparc_execve), %g1 -#ifdef CONFIG_COMPAT - .globl sys_execve -sunos_execv: - stx %g0, [%sp + PTREGS_OFF + PT_V9_I2] - .globl sys32_execve -sys32_execve: - sethi %hi(sparc32_execve), %g1 - or %g1, %lo(sparc32_execve), %g1 -#endif -execve_merge: - flushw - jmpl %g1, %g0 - add %sp, PTREGS_OFF, %o0 - - .globl sys_pipe, sys_sigpause, sys_nis_syscall - .globl sys_rt_sigreturn - .globl sys_ptrace - .globl sys_sigaltstack - .align 32 -sys_pipe: ba,pt %xcc, sparc_pipe - add %sp, PTREGS_OFF, %o0 -sys_nis_syscall:ba,pt %xcc, c_sys_nis_syscall - add %sp, PTREGS_OFF, %o0 -sys_memory_ordering: - ba,pt %xcc, sparc_memory_ordering - add %sp, PTREGS_OFF, %o1 -sys_sigaltstack:ba,pt %xcc, do_sigaltstack - add %i6, STACK_BIAS, %o2 -#ifdef CONFIG_COMPAT - .globl sys32_sigstack -sys32_sigstack: ba,pt %xcc, do_sys32_sigstack - mov %i6, %o2 - .globl sys32_sigaltstack -sys32_sigaltstack: - ba,pt %xcc, do_sys32_sigaltstack - mov %i6, %o2 -#endif - .align 32 -#ifdef CONFIG_COMPAT - .globl sys32_sigreturn -sys32_sigreturn: - add %sp, PTREGS_OFF, %o0 - call do_sigreturn32 - add %o7, 1f-.-4, %o7 - nop -#endif -sys_rt_sigreturn: - add %sp, PTREGS_OFF, %o0 - call do_rt_sigreturn - add %o7, 1f-.-4, %o7 - nop -#ifdef CONFIG_COMPAT - .globl sys32_rt_sigreturn -sys32_rt_sigreturn: - add %sp, PTREGS_OFF, %o0 - call do_rt_sigreturn32 - add %o7, 1f-.-4, %o7 - nop -#endif -sys_ptrace: add %sp, PTREGS_OFF, %o0 - call do_ptrace - add %o7, 1f-.-4, %o7 - nop - .align 32 -1: ldx [%curptr + TI_FLAGS], %l5 - andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 - be,pt %icc, rtrap - clr %l6 - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 - - ba,pt %xcc, rtrap - clr %l6 - - /* This is how fork() was meant to be done, 8 instruction entry. - * - * I questioned the following code briefly, let me clear things - * up so you must not reason on it like I did. - * - * Know the fork_kpsr etc. we use in the sparc32 port? We don't - * need it here because the only piece of window state we copy to - * the child is the CWP register. Even if the parent sleeps, - * we are safe because we stuck it into pt_regs of the parent - * so it will not change. - * - * XXX This raises the question, whether we can do the same on - * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim. The - * XXX answer is yes. We stick fork_kpsr in UREG_G0 and - * XXX fork_kwim in UREG_G1 (global registers are considered - * XXX volatile across a system call in the sparc ABI I think - * XXX if it isn't we can use regs->y instead, anyone who depends - * XXX upon the Y register being preserved across a fork deserves - * XXX to lose). - * - * In fact we should take advantage of that fact for other things - * during system calls... - */ - .globl sys_fork, sys_vfork, sys_clone, sparc_exit - .globl ret_from_syscall - .align 32 -sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */ - sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0 - or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0 - ba,pt %xcc, sys_clone -sys_fork: clr %o1 - mov SIGCHLD, %o0 -sys_clone: flushw - movrz %o1, %fp, %o1 - mov 0, %o3 - ba,pt %xcc, sparc_do_fork - add %sp, PTREGS_OFF, %o2 -ret_from_syscall: - /* Clear current_thread_info()->new_child, and - * check performance counter stuff too. - */ - stb %g0, [%g6 + TI_NEW_CHILD] - ldx [%g6 + TI_FLAGS], %l0 - call schedule_tail - mov %g7, %o0 - andcc %l0, _TIF_PERFCTR, %g0 - be,pt %icc, 1f - nop - ldx [%g6 + TI_PCR], %o7 - wr %g0, %o7, %pcr - - /* Blackbird errata workaround. See commentary in - * smp.c:smp_percpu_timer_interrupt() for more - * information. - */ - ba,pt %xcc, 99f - nop - .align 64 -99: wr %g0, %g0, %pic - rd %pic, %g0 - -1: b,pt %xcc, ret_sys_call - ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 -sparc_exit: wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV), %pstate - rdpr %otherwin, %g1 - rdpr %cansave, %g3 - add %g3, %g1, %g3 - wrpr %g3, 0x0, %cansave - wrpr %g0, 0x0, %otherwin - wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate - ba,pt %xcc, sys_exit - stb %g0, [%g6 + TI_WSAVED] - -linux_sparc_ni_syscall: - sethi %hi(sys_ni_syscall), %l7 - b,pt %xcc, 4f - or %l7, %lo(sys_ni_syscall), %l7 - -linux_syscall_trace32: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - clr %o1 - srl %i0, 0, %o0 - srl %i4, 0, %o4 - srl %i1, 0, %o1 - srl %i2, 0, %o2 - b,pt %xcc, 2f - srl %i3, 0, %o3 - -linux_syscall_trace: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - clr %o1 - mov %i0, %o0 - mov %i1, %o1 - mov %i2, %o2 - mov %i3, %o3 - b,pt %xcc, 2f - mov %i4, %o4 - - - /* Linux 32-bit and SunOS system calls enter here... */ - .align 32 - .globl linux_sparc_syscall32 -linux_sparc_syscall32: - /* Direct access to user regs, much faster. */ - cmp %g1, NR_SYSCALLS ! IEU1 Group - bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI - srl %i0, 0, %o0 ! IEU0 - sll %g1, 2, %l4 ! IEU0 Group - srl %i4, 0, %o4 ! IEU1 - lduw [%l7 + %l4], %l7 ! Load - srl %i1, 0, %o1 ! IEU0 Group - ldx [%curptr + TI_FLAGS], %l0 ! Load - - srl %i5, 0, %o5 ! IEU1 - srl %i2, 0, %o2 ! IEU0 Group - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 - bne,pn %icc, linux_syscall_trace32 ! CTI - mov %i0, %l5 ! IEU1 - call %l7 ! CTI Group brk forced - srl %i3, 0, %o3 ! IEU0 - ba,a,pt %xcc, 3f - - /* Linux native and SunOS system calls enter here... */ - .align 32 - .globl linux_sparc_syscall, ret_sys_call -linux_sparc_syscall: - /* Direct access to user regs, much faster. */ - cmp %g1, NR_SYSCALLS ! IEU1 Group - bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI - mov %i0, %o0 ! IEU0 - sll %g1, 2, %l4 ! IEU0 Group - mov %i1, %o1 ! IEU1 - lduw [%l7 + %l4], %l7 ! Load -4: mov %i2, %o2 ! IEU0 Group - ldx [%curptr + TI_FLAGS], %l0 ! Load - - mov %i3, %o3 ! IEU1 - mov %i4, %o4 ! IEU0 Group - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 - bne,pn %icc, linux_syscall_trace ! CTI Group - mov %i0, %l5 ! IEU0 -2: call %l7 ! CTI Group brk forced - mov %i5, %o5 ! IEU0 - nop - -3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] -ret_sys_call: - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc - sra %o0, 0, %o0 - mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 - sllx %g2, 32, %g2 - - /* Check if force_successful_syscall_return() - * was invoked. - */ - ldub [%curptr + TI_SYS_NOERROR], %l2 - brnz,a,pn %l2, 80f - stb %g0, [%curptr + TI_SYS_NOERROR] - - cmp %o0, -ERESTART_RESTARTBLOCK - bgeu,pn %xcc, 1f - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6 -80: - /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, linux_syscall_trace2 - add %l1, 0x4, %l2 ! npc = npc+4 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] - ba,pt %xcc, rtrap_clr_l6 - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] - -1: - /* System call failure, set Carry condition code. - * Also, get abs(errno) to return to the process. - */ - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6 - sub %g0, %o0, %o0 - or %g3, %g2, %g3 - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - mov 1, %l6 - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, linux_syscall_trace2 - add %l1, 0x4, %l2 ! npc = npc+4 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] - - b,pt %xcc, rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] -linux_syscall_trace2: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] - ba,pt %xcc, rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] - - .align 32 - .globl __flushw_user -__flushw_user: - rdpr %otherwin, %g1 - brz,pn %g1, 2f - clr %g2 -1: save %sp, -128, %sp - rdpr %otherwin, %g1 - brnz,pt %g1, 1b - add %g2, 1, %g2 -1: sub %g2, 1, %g2 - brnz,pt %g2, 1b - restore %g0, %g0, %g0 -2: retl - nop diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S deleted file mode 100644 index 0d8eba21111..00000000000 --- a/arch/sparc64/kernel/etrap.S +++ /dev/null @@ -1,258 +0,0 @@ -/* $Id: etrap.S,v 1.46 2002/02/09 19:49:30 davem Exp $ - * etrap.S: Preparing for entry into the kernel on Sparc V9. - * - * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <linux/config.h> - -#include <asm/asi.h> -#include <asm/pstate.h> -#include <asm/ptrace.h> -#include <asm/page.h> -#include <asm/spitfire.h> -#include <asm/head.h> -#include <asm/processor.h> -#include <asm/mmu.h> - -#define TASK_REGOFF (THREAD_SIZE-TRACEREG_SZ-STACKFRAME_SZ) -#define ETRAP_PSTATE1 (PSTATE_RMO | PSTATE_PRIV) -#define ETRAP_PSTATE2 \ - (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE) - -/* - * On entry, %g7 is return address - 0x4. - * %g4 and %g5 will be preserved %l4 and %l5 respectively. - */ - - .text - .align 64 - .globl etrap, etrap_irq, etraptl1 -etrap: rdpr %pil, %g2 -etrap_irq: - rdpr %tstate, %g1 - sllx %g2, 20, %g3 - andcc %g1, TSTATE_PRIV, %g0 - or %g1, %g3, %g1 - bne,pn %xcc, 1f - sub %sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2 - wrpr %g0, 7, %cleanwin - - sethi %hi(TASK_REGOFF), %g2 - sethi %hi(TSTATE_PEF), %g3 - or %g2, %lo(TASK_REGOFF), %g2 - and %g1, %g3, %g3 - brnz,pn %g3, 1f - add %g6, %g2, %g2 - wr %g0, 0, %fprs -1: rdpr %tpc, %g3 - - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE] - rdpr %tnpc, %g1 - stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC] - rd %y, %g3 - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] - st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y] - save %g2, -STACK_BIAS, %sp ! Ordering here is critical - mov %g6, %l6 - - bne,pn %xcc, 3f - mov PRIMARY_CONTEXT, %l4 - rdpr %canrestore, %g3 - rdpr %wstate, %g2 - wrpr %g0, 0, %canrestore - sll %g2, 3, %g2 - mov 1, %l5 - stb %l5, [%l6 + TI_FPDEPTH] - - wrpr %g3, 0, %otherwin - wrpr %g2, 0, %wstate - sethi %hi(sparc64_kern_pri_context), %g2 - ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3 - stxa %g3, [%l4] ASI_DMMU - flush %l6 - wr %g0, ASI_AIUS, %asi -2: wrpr %g0, 0x0, %tl - mov %g4, %l4 - mov %g5, %l5 - - mov %g7, %l2 - wrpr %g0, ETRAP_PSTATE1, %pstate - stx %g1, [%sp + PTREGS_OFF + PT_V9_G1] - stx %g2, [%sp + PTREGS_OFF + PT_V9_G2] - stx %g3, [%sp + PTREGS_OFF + PT_V9_G3] - stx %g4, [%sp + PTREGS_OFF + PT_V9_G4] - stx %g5, [%sp + PTREGS_OFF + PT_V9_G5] - stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] - - stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] - stx %i0, [%sp + PTREGS_OFF + PT_V9_I0] - stx %i1, [%sp + PTREGS_OFF + PT_V9_I1] - stx %i2, [%sp + PTREGS_OFF + PT_V9_I2] - stx %i3, [%sp + PTREGS_OFF + PT_V9_I3] - stx %i4, [%sp + PTREGS_OFF + PT_V9_I4] - stx %i5, [%sp + PTREGS_OFF + PT_V9_I5] - - stx %i6, [%sp + PTREGS_OFF + PT_V9_I6] - stx %i7, [%sp + PTREGS_OFF + PT_V9_I7] - wrpr %g0, ETRAP_PSTATE2, %pstate - mov %l6, %g6 -#ifdef CONFIG_SMP - mov TSB_REG, %g3 - ldxa [%g3] ASI_IMMU, %g5 -#endif - jmpl %l2 + 0x4, %g0 - ldx [%g6 + TI_TASK], %g4 - -3: ldub [%l6 + TI_FPDEPTH], %l5 - add %l6, TI_FPSAVED + 1, %l4 - srl %l5, 1, %l3 - add %l5, 2, %l5 - stb %l5, [%l6 + TI_FPDEPTH] - ba,pt %xcc, 2b - stb %g0, [%l4 + %l3] - nop - -etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself. - * We place this right after pt_regs on the trap stack. - * The layout is: - * 0x00 TL1's TSTATE - * 0x08 TL1's TPC - * 0x10 TL1's TNPC - * 0x18 TL1's TT - * ... - * 0x58 TL4's TT - * 0x60 TL - */ - sub %sp, ((4 * 8) * 4) + 8, %g2 - rdpr %tl, %g1 - - wrpr %g0, 1, %tl - rdpr %tstate, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x00] - rdpr %tpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x08] - rdpr %tnpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x10] - rdpr %tt, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x18] - - wrpr %g0, 2, %tl - rdpr %tstate, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x20] - rdpr %tpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x28] - rdpr %tnpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x30] - rdpr %tt, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x38] - - wrpr %g0, 3, %tl - rdpr %tstate, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x40] - rdpr %tpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x48] - rdpr %tnpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x50] - rdpr %tt, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x58] - - wrpr %g0, 4, %tl - rdpr %tstate, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x60] - rdpr %tpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x68] - rdpr %tnpc, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x70] - rdpr %tt, %g3 - stx %g3, [%g2 + STACK_BIAS + 0x78] - - wrpr %g1, %tl - stx %g1, [%g2 + STACK_BIAS + 0x80] - - rdpr %tstate, %g1 - sub %g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2 - ba,pt %xcc, 1b - andcc %g1, TSTATE_PRIV, %g0 - - .align 64 - .globl scetrap -scetrap: rdpr %pil, %g2 - rdpr %tstate, %g1 - sllx %g2, 20, %g3 - andcc %g1, TSTATE_PRIV, %g0 - or %g1, %g3, %g1 - bne,pn %xcc, 1f - sub %sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2 - wrpr %g0, 7, %cleanwin - - sllx %g1, 51, %g3 - sethi %hi(TASK_REGOFF), %g2 - or %g2, %lo(TASK_REGOFF), %g2 - brlz,pn %g3, 1f - add %g6, %g2, %g2 - wr %g0, 0, %fprs -1: rdpr %tpc, %g3 - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE] - - rdpr %tnpc, %g1 - stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC] - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] - save %g2, -STACK_BIAS, %sp ! Ordering here is critical - mov %g6, %l6 - bne,pn %xcc, 2f - mov ASI_P, %l7 - rdpr %canrestore, %g3 - - rdpr %wstate, %g2 - wrpr %g0, 0, %canrestore - sll %g2, 3, %g2 - mov PRIMARY_CONTEXT, %l4 - wrpr %g3, 0, %otherwin - wrpr %g2, 0, %wstate - sethi %hi(sparc64_kern_pri_context), %g2 - ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3 - stxa %g3, [%l4] ASI_DMMU - flush %l6 - - mov ASI_AIUS, %l7 -2: mov %g4, %l4 - mov %g5, %l5 - add %g7, 0x4, %l2 - wrpr %g0, ETRAP_PSTATE1, %pstate - stx %g1, [%sp + PTREGS_OFF + PT_V9_G1] - stx %g2, [%sp + PTREGS_OFF + PT_V9_G2] - sllx %l7, 24, %l7 - - stx %g3, [%sp + PTREGS_OFF + PT_V9_G3] - rdpr %cwp, %l0 - stx %g4, [%sp + PTREGS_OFF + PT_V9_G4] - stx %g5, [%sp + PTREGS_OFF + PT_V9_G5] - stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] - stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] - or %l7, %l0, %l7 - sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0 - - or %l7, %l0, %l7 - wrpr %l2, %tnpc - wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate - stx %i0, [%sp + PTREGS_OFF + PT_V9_I0] - stx %i1, [%sp + PTREGS_OFF + PT_V9_I1] - stx %i2, [%sp + PTREGS_OFF + PT_V9_I2] - stx %i3, [%sp + PTREGS_OFF + PT_V9_I3] - stx %i4, [%sp + PTREGS_OFF + PT_V9_I4] - - stx %i5, [%sp + PTREGS_OFF + PT_V9_I5] - stx %i6, [%sp + PTREGS_OFF + PT_V9_I6] - mov %l6, %g6 - stx %i7, [%sp + PTREGS_OFF + PT_V9_I7] -#ifdef CONFIG_SMP - mov TSB_REG, %g3 - ldxa [%g3] ASI_IMMU, %g5 -#endif - ldx [%g6 + TI_TASK], %g4 - done - -#undef TASK_REGOFF -#undef ETRAP_PSTATE1 diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S deleted file mode 100644 index b49dcd4504b..00000000000 --- a/arch/sparc64/kernel/head.S +++ /dev/null @@ -1,577 +0,0 @@ -/* $Id: head.S,v 1.87 2002/02/09 19:49:31 davem Exp $ - * head.S: Initial boot code for the Sparc64 port of Linux. - * - * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 David Sitsky (David.Sitsky@anu.edu.au) - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) - */ - -#include <linux/config.h> -#include <linux/version.h> -#include <linux/errno.h> -#include <asm/thread_info.h> -#include <asm/asi.h> -#include <asm/pstate.h> -#include <asm/ptrace.h> -#include <asm/spitfire.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/errno.h> -#include <asm/signal.h> -#include <asm/processor.h> -#include <asm/lsu.h> -#include <asm/dcr.h> -#include <asm/dcu.h> -#include <asm/head.h> -#include <asm/ttable.h> -#include <asm/mmu.h> - -/* This section from from _start to sparc64_boot_end should fit into - * 0x0000000000404000 to 0x0000000000408000. - */ - .text - .globl start, _start, stext, _stext -_start: -start: -_stext: -stext: -! 0x0000000000404000 - b sparc64_boot - flushw /* Flush register file. */ - -/* This stuff has to be in sync with SILO and other potential boot loaders - * Fields should be kept upward compatible and whenever any change is made, - * HdrS version should be incremented. - */ - .global root_flags, ram_flags, root_dev - .global sparc_ramdisk_image, sparc_ramdisk_size - .global sparc_ramdisk_image64 - - .ascii "HdrS" - .word LINUX_VERSION_CODE - - /* History: - * - * 0x0300 : Supports being located at other than 0x4000 - * 0x0202 : Supports kernel params string - * 0x0201 : Supports reboot_command - */ - .half 0x0301 /* HdrS version */ - -root_flags: - .half 1 -root_dev: - .half 0 -ram_flags: - .half 0 -sparc_ramdisk_image: - .word 0 -sparc_ramdisk_size: - .word 0 - .xword reboot_command - .xword bootstr_info -sparc_ramdisk_image64: - .xword 0 - .word _end - - /* PROM cif handler code address is in %o4. */ -sparc64_boot: -1: rd %pc, %g7 - set 1b, %g1 - cmp %g1, %g7 - be,pn %xcc, sparc64_boot_after_remap - mov %o4, %l7 - - /* We need to remap the kernel. Use position independant - * code to remap us to KERNBASE. - * - * SILO can invoke us with 32-bit address masking enabled, - * so make sure that's clear. - */ - rdpr %pstate, %g1 - andn %g1, PSTATE_AM, %g1 - wrpr %g1, 0x0, %pstate - ba,a,pt %xcc, 1f - - .globl prom_finddev_name, prom_chosen_path - .globl prom_getprop_name, prom_mmu_name - .globl prom_callmethod_name, prom_translate_name - .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache - .globl prom_boot_mapped_pc, prom_boot_mapping_mode - .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low -prom_finddev_name: - .asciz "finddevice" -prom_chosen_path: - .asciz "/chosen" -prom_getprop_name: - .asciz "getprop" -prom_mmu_name: - .asciz "mmu" -prom_callmethod_name: - .asciz "call-method" -prom_translate_name: - .asciz "translate" -prom_map_name: - .asciz "map" -prom_unmap_name: - .asciz "unmap" - .align 4 -prom_mmu_ihandle_cache: - .word 0 -prom_boot_mapped_pc: - .word 0 -prom_boot_mapping_mode: - .word 0 - .align 8 -prom_boot_mapping_phys_high: - .xword 0 -prom_boot_mapping_phys_low: - .xword 0 -1: - rd %pc, %l0 - mov (1b - prom_finddev_name), %l1 - mov (1b - prom_chosen_path), %l2 - mov (1b - prom_boot_mapped_pc), %l3 - sub %l0, %l1, %l1 - sub %l0, %l2, %l2 - sub %l0, %l3, %l3 - stw %l0, [%l3] - sub %sp, (192 + 128), %sp - - /* chosen_node = prom_finddevice("/chosen") */ - stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice" - mov 1, %l3 - stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1 - stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 - stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/chosen" - stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1 - call %l7 - add %sp, (2047 + 128), %o0 ! argument array - - ldx [%sp + 2047 + 128 + 0x20], %l4 ! chosen device node - - mov (1b - prom_getprop_name), %l1 - mov (1b - prom_mmu_name), %l2 - mov (1b - prom_mmu_ihandle_cache), %l5 - sub %l0, %l1, %l1 - sub %l0, %l2, %l2 - sub %l0, %l5, %l5 - - /* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */ - stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop" - mov 4, %l3 - stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4 - mov 1, %l3 - stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 - stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, chosen_node - stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "mmu" - stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_mmu_ihandle_cache - mov 4, %l3 - stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, sizeof(arg3) - stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1 - call %l7 - add %sp, (2047 + 128), %o0 ! argument array - - mov (1b - prom_callmethod_name), %l1 - mov (1b - prom_translate_name), %l2 - sub %l0, %l1, %l1 - sub %l0, %l2, %l2 - lduw [%l5], %l5 ! prom_mmu_ihandle_cache - - stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "call-method" - mov 3, %l3 - stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 3 - mov 5, %l3 - stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 - stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" - stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache - /* PAGE align */ - srlx %l0, 13, %l3 - sllx %l3, 13, %l3 - stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC - stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 - stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 - stx %g0, [%sp + 2047 + 128 + 0x40] ! res3 - stx %g0, [%sp + 2047 + 128 + 0x48] ! res4 - stx %g0, [%sp + 2047 + 128 + 0x50] ! res5 - call %l7 - add %sp, (2047 + 128), %o0 ! argument array - - ldx [%sp + 2047 + 128 + 0x40], %l1 ! translation mode - mov (1b - prom_boot_mapping_mode), %l4 - sub %l0, %l4, %l4 - stw %l1, [%l4] - mov (1b - prom_boot_mapping_phys_high), %l4 - sub %l0, %l4, %l4 - ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high - stx %l2, [%l4 + 0x0] - ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low - /* 4MB align */ - srlx %l3, 22, %l3 - sllx %l3, 22, %l3 - stx %l3, [%l4 + 0x8] - - /* Leave service as-is, "call-method" */ - mov 7, %l3 - stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 7 - mov 1, %l3 - stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 - mov (1b - prom_map_name), %l3 - sub %l0, %l3, %l3 - stx %l3, [%sp + 2047 + 128 + 0x18] ! arg1: "map" - /* Leave arg2 as-is, prom_mmu_ihandle_cache */ - mov -1, %l3 - stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: mode (-1 default) - sethi %hi(8 * 1024 * 1024), %l3 - stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: size (8MB) - sethi %hi(KERNBASE), %l3 - stx %l3, [%sp + 2047 + 128 + 0x38] ! arg5: vaddr (KERNBASE) - stx %g0, [%sp + 2047 + 128 + 0x40] ! arg6: empty - mov (1b - prom_boot_mapping_phys_low), %l3 - sub %l0, %l3, %l3 - ldx [%l3], %l3 - stx %l3, [%sp + 2047 + 128 + 0x48] ! arg7: phys addr - call %l7 - add %sp, (2047 + 128), %o0 ! argument array - - add %sp, (192 + 128), %sp - -sparc64_boot_after_remap: - BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) - ba,pt %xcc, spitfire_boot - nop - -cheetah_plus_boot: - /* Preserve OBP chosen DCU and DCR register settings. */ - ba,pt %xcc, cheetah_generic_boot - nop - -cheetah_boot: - mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1 - wr %g1, %asr18 - - sethi %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7 - or %g7, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7 - sllx %g7, 32, %g7 - or %g7, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g7 - stxa %g7, [%g0] ASI_DCU_CONTROL_REG - membar #Sync - -cheetah_generic_boot: - mov TSB_EXTENSION_P, %g3 - stxa %g0, [%g3] ASI_DMMU - stxa %g0, [%g3] ASI_IMMU - membar #Sync - - mov TSB_EXTENSION_S, %g3 - stxa %g0, [%g3] ASI_DMMU - membar #Sync - - mov TSB_EXTENSION_N, %g3 - stxa %g0, [%g3] ASI_DMMU - stxa %g0, [%g3] ASI_IMMU - membar #Sync - - ba,a,pt %xcc, jump_to_sun4u_init - -spitfire_boot: - /* Typically PROM has already enabled both MMU's and both on-chip - * caches, but we do it here anyway just to be paranoid. - */ - mov (LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM), %g1 - stxa %g1, [%g0] ASI_LSU_CONTROL - membar #Sync - -jump_to_sun4u_init: - /* - * Make sure we are in privileged mode, have address masking, - * using the ordinary globals and have enabled floating - * point. - * - * Again, typically PROM has left %pil at 13 or similar, and - * (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate. - */ - wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate - wr %g0, 0, %fprs - - set sun4u_init, %g2 - jmpl %g2 + %g0, %g0 - nop - -sun4u_init: - /* Set ctx 0 */ - mov PRIMARY_CONTEXT, %g7 - stxa %g0, [%g7] ASI_DMMU - membar #Sync - - mov SECONDARY_CONTEXT, %g7 - stxa %g0, [%g7] ASI_DMMU - membar #Sync - - BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup) - - ba,pt %xcc, spitfire_tlb_fixup - nop - -cheetah_tlb_fixup: - mov 2, %g2 /* Set TLB type to cheetah+. */ - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) - - mov 1, %g2 /* Set TLB type to cheetah. */ - -1: sethi %hi(tlb_type), %g1 - stw %g2, [%g1 + %lo(tlb_type)] - - /* Patch copy/page operations to cheetah optimized versions. */ - call cheetah_patch_copyops - nop - call cheetah_patch_copy_page - nop - call cheetah_patch_cachetlbops - nop - - ba,pt %xcc, tlb_fixup_done - nop - -spitfire_tlb_fixup: - /* Set TLB type to spitfire. */ - mov 0, %g2 - sethi %hi(tlb_type), %g1 - stw %g2, [%g1 + %lo(tlb_type)] - -tlb_fixup_done: - sethi %hi(init_thread_union), %g6 - or %g6, %lo(init_thread_union), %g6 - ldx [%g6 + TI_TASK], %g4 - mov %sp, %l6 - mov %o4, %l7 - - wr %g0, ASI_P, %asi - mov 1, %g1 - sllx %g1, THREAD_SHIFT, %g1 - sub %g1, (STACKFRAME_SZ + STACK_BIAS), %g1 - add %g6, %g1, %sp - mov 0, %fp - - /* Set per-cpu pointer initially to zero, this makes - * the boot-cpu use the in-kernel-image per-cpu areas - * before setup_per_cpu_area() is invoked. - */ - clr %g5 - - wrpr %g0, 0, %wstate - wrpr %g0, 0x0, %tl - - /* Clear the bss */ - sethi %hi(__bss_start), %o0 - or %o0, %lo(__bss_start), %o0 - sethi %hi(_end), %o1 - or %o1, %lo(_end), %o1 - call __bzero - sub %o1, %o0, %o1 - - mov %l6, %o1 ! OpenPROM stack - call prom_init - mov %l7, %o0 ! OpenPROM cif handler - - /* Off we go.... */ - call start_kernel - nop - /* Not reached... */ - - /* This is meant to allow the sharing of this code between - * boot processor invocation (via setup_tba() below) and - * secondary processor startup (via trampoline.S). The - * former does use this code, the latter does not yet due - * to some complexities. That should be fixed up at some - * point. - * - * There used to be enormous complexity wrt. transferring - * over from the firwmare's trap table to the Linux kernel's. - * For example, there was a chicken & egg problem wrt. building - * the OBP page tables, yet needing to be on the Linux kernel - * trap table (to translate PAGE_OFFSET addresses) in order to - * do that. - * - * We now handle OBP tlb misses differently, via linear lookups - * into the prom_trans[] array. So that specific problem no - * longer exists. Yet, unfortunately there are still some issues - * preventing trampoline.S from using this code... ho hum. - */ - .globl setup_trap_table -setup_trap_table: - save %sp, -192, %sp - - /* Force interrupts to be disabled. */ - rdpr %pstate, %o1 - andn %o1, PSTATE_IE, %o1 - wrpr %o1, 0x0, %pstate - wrpr %g0, 15, %pil - - /* Make the firmware call to jump over to the Linux trap table. */ - call prom_set_trap_table - sethi %hi(sparc64_ttable_tl0), %o0 - - /* Start using proper page size encodings in ctx register. */ - sethi %hi(sparc64_kern_pri_context), %g3 - ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 - mov PRIMARY_CONTEXT, %g1 - stxa %g2, [%g1] ASI_DMMU - membar #Sync - - /* The Linux trap handlers expect various trap global registers - * to be setup with some fixed values. So here we set these - * up very carefully. These globals are: - * - * Alternate Globals (PSTATE_AG): - * - * %g6 --> current_thread_info() - * - * MMU Globals (PSTATE_MG): - * - * %g1 --> TLB_SFSR - * %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB | - * _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) - * ^ 0xfffff80000000000) - * (this %g2 value is used for computing the PAGE_OFFSET kernel - * TLB entries quickly, the virtual address of the fault XOR'd - * with this %g2 value is the PTE to load into the TLB) - * %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE - * - * Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()): - * - * %g6 --> __irq_work[smp_processor_id()] - */ - - rdpr %pstate, %o1 - mov %g6, %o2 - wrpr %o1, PSTATE_AG, %pstate - mov %o2, %g6 - -#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) -#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) - wrpr %o1, PSTATE_MG, %pstate - mov TSB_REG, %g1 - stxa %g0, [%g1] ASI_DMMU - membar #Sync - stxa %g0, [%g1] ASI_IMMU - membar #Sync - mov TLB_SFSR, %g1 - sethi %uhi(KERN_HIGHBITS), %g2 - or %g2, %ulo(KERN_HIGHBITS), %g2 - sllx %g2, 32, %g2 - or %g2, KERN_LOWBITS, %g2 - - BRANCH_IF_ANY_CHEETAH(g3,g7,8f) - ba,pt %xcc, 9f - nop - -8: - sethi %uhi(VPTE_BASE_CHEETAH), %g3 - or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 - ba,pt %xcc, 2f - sllx %g3, 32, %g3 - -9: - sethi %uhi(VPTE_BASE_SPITFIRE), %g3 - or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 - sllx %g3, 32, %g3 - -2: - clr %g7 -#undef KERN_HIGHBITS -#undef KERN_LOWBITS - - /* Kill PROM timer */ - sethi %hi(0x80000000), %o2 - sllx %o2, 32, %o2 - wr %o2, 0, %tick_cmpr - - BRANCH_IF_ANY_CHEETAH(o2,o3,1f) - - ba,pt %xcc, 2f - nop - - /* Disable STICK_INT interrupts. */ -1: - sethi %hi(0x80000000), %o2 - sllx %o2, 32, %o2 - wr %o2, %asr25 - -2: - wrpr %g0, %g0, %wstate - wrpr %o1, 0x0, %pstate - - call init_irqwork_curcpu - nop - - /* Now we can turn interrupts back on. */ - rdpr %pstate, %o1 - or %o1, PSTATE_IE, %o1 - wrpr %o1, 0, %pstate - wrpr %g0, 0x0, %pil - - ret - restore - - .globl setup_tba -setup_tba: /* i0 = is_starfire */ - save %sp, -192, %sp - - /* The boot processor is the only cpu which invokes this - * routine, the other cpus set things up via trampoline.S. - * So save the OBP trap table address here. - */ - rdpr %tba, %g7 - sethi %hi(prom_tba), %o1 - or %o1, %lo(prom_tba), %o1 - stx %g7, [%o1] - - call setup_trap_table - nop - - ret - restore -sparc64_boot_end: - -#include "systbls.S" -#include "ktlb.S" -#include "etrap.S" -#include "rtrap.S" -#include "winfixup.S" -#include "entry.S" - -/* - * The following skip makes sure the trap table in ttable.S is aligned - * on a 32K boundary as required by the v9 specs for TBA register. - */ -1: - .skip 0x4000 + _start - 1b - -#ifdef CONFIG_SBUS -/* This is just a hack to fool make depend config.h discovering - strategy: As the .S files below need config.h, but - make depend does not find it for them, we include config.h - in head.S */ -#endif - -! 0x0000000000408000 - -#include "ttable.S" - - .data - .align 8 - .globl prom_tba, tlb_type -prom_tba: .xword 0 -tlb_type: .word 0 /* Must NOT end up in BSS */ - .section ".fixup",#alloc,#execinstr - - .globl __ret_efault, __retl_efault -__ret_efault: - ret - restore %g0, -EFAULT, %o0 -__retl_efault: - retl - mov -EFAULT, %o0 diff --git a/arch/sparc64/kernel/idprom.c b/arch/sparc64/kernel/idprom.c deleted file mode 100644 index 3b6789e09a7..00000000000 --- a/arch/sparc64/kernel/idprom.c +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: idprom.c,v 1.3 1999/08/31 06:54:53 davem Exp $ - * idprom.c: Routines to load the idprom into kernel addresses and - * interpret the data contained within. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/init.h> - -#include <asm/oplib.h> -#include <asm/idprom.h> - -struct idprom *idprom; -static struct idprom idprom_buffer; - -/* Calculate the IDPROM checksum (xor of the data bytes). */ -static unsigned char __init calc_idprom_cksum(struct idprom *idprom) -{ - unsigned char cksum, i, *ptr = (unsigned char *)idprom; - - for (i = cksum = 0; i <= 0x0E; i++) - cksum ^= *ptr++; - - return cksum; -} - -/* Create a local IDPROM copy and verify integrity. */ -void __init idprom_init(void) -{ - prom_get_idprom((char *) &idprom_buffer, sizeof(idprom_buffer)); - - idprom = &idprom_buffer; - - if (idprom->id_format != 0x01) { - prom_printf("IDPROM: Warning, unknown format type!\n"); - } - - if (idprom->id_cksum != calc_idprom_cksum(idprom)) { - prom_printf("IDPROM: Warning, checksum failure (nvram=%x, calc=%x)!\n", - idprom->id_cksum, calc_idprom_cksum(idprom)); - } - - printk("Ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n", - idprom->id_ethaddr[0], idprom->id_ethaddr[1], - idprom->id_ethaddr[2], idprom->id_ethaddr[3], - idprom->id_ethaddr[4], idprom->id_ethaddr[5]); -} diff --git a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c deleted file mode 100644 index 329b38fa5c8..00000000000 --- a/arch/sparc64/kernel/init_task.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init_task.h> -#include <linux/mqueue.h> - -#include <asm/pgtable.h> -#include <asm/uaccess.h> -#include <asm/processor.h> - -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - -/* .text section in head.S is aligned at 2 page boundary and this gets linked - * right after that so that the init_thread_union is aligned properly as well. - * We really don't need this special alignment like the Intel does, but - * I do it anyways for completeness. - */ -__asm__ (".text"); -union thread_union init_thread_union = { INIT_THREAD_INFO(init_task) }; - -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -EXPORT_SYMBOL(init_task); - -__asm__(".data"); -struct task_struct init_task = INIT_TASK(init_task); diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c deleted file mode 100644 index 12c93a3eee2..00000000000 --- a/arch/sparc64/kernel/iommu_common.c +++ /dev/null @@ -1,231 +0,0 @@ -/* $Id: iommu_common.c,v 1.9 2001/12/17 07:05:09 davem Exp $ - * iommu_common.c: UltraSparc SBUS/PCI common iommu code. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#include "iommu_common.h" - -/* You are _strongly_ advised to enable the following debugging code - * any time you make changes to the sg code below, run it for a while - * with filesystems mounted read-only before buying the farm... -DaveM - */ - -#ifdef VERIFY_SG -static int verify_lengths(struct scatterlist *sg, int nents, int npages) -{ - int sg_len, dma_len; - int i, pgcount; - - sg_len = 0; - for (i = 0; i < nents; i++) - sg_len += sg[i].length; - - dma_len = 0; - for (i = 0; i < nents && sg[i].dma_length; i++) - dma_len += sg[i].dma_length; - - if (sg_len != dma_len) { - printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", - sg_len, dma_len); - return -1; - } - - pgcount = 0; - for (i = 0; i < nents && sg[i].dma_length; i++) { - unsigned long start, end; - - start = sg[i].dma_address; - start = start & IO_PAGE_MASK; - - end = sg[i].dma_address + sg[i].dma_length; - end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; - - pgcount += ((end - start) >> IO_PAGE_SHIFT); - } - - if (pgcount != npages) { - printk("verify_lengths: Error, page count wrong, " - "npages[%d] pgcount[%d]\n", - npages, pgcount); - return -1; - } - - /* This test passes... */ - return 0; -} - -static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte) -{ - struct scatterlist *sg = *__sg; - iopte_t *iopte = *__iopte; - u32 dlen = dma_sg->dma_length; - u32 daddr; - unsigned int sglen; - unsigned long sgaddr; - - daddr = dma_sg->dma_address; - sglen = sg->length; - sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); - while (dlen > 0) { - unsigned long paddr; - - /* SG and DMA_SG must begin at the same sub-page boundary. */ - if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) { - printk("verify_one_map: Wrong start offset " - "sg[%08lx] dma[%08x]\n", - sgaddr, daddr); - nents = -1; - goto out; - } - - /* Verify the IOPTE points to the right page. */ - paddr = iopte_val(*iopte) & IOPTE_PAGE; - if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) { - printk("verify_one_map: IOPTE[%08lx] maps the " - "wrong page, should be [%08lx]\n", - iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET); - nents = -1; - goto out; - } - - /* If this SG crosses a page, adjust to that next page - * boundary and loop. - */ - if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) { - unsigned long next_page, diff; - - next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK; - diff = next_page - sgaddr; - sgaddr += diff; - daddr += diff; - sglen -= diff; - dlen -= diff; - if (dlen > 0) - iopte++; - continue; - } - - /* SG wholly consumed within this page. */ - daddr += sglen; - dlen -= sglen; - - if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0)) - iopte++; - - sg++; - if (--nents <= 0) - break; - sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); - sglen = sg->length; - } - if (dlen < 0) { - /* Transfer overrun, big problems. */ - printk("verify_one_map: Transfer overrun by %d bytes.\n", - -dlen); - nents = -1; - } else { - /* Advance to next dma_sg implies that the next iopte will - * begin it. - */ - iopte++; - } - -out: - *__sg = sg; - *__iopte = iopte; - return nents; -} - -static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) -{ - struct scatterlist *dma_sg = sg; - struct scatterlist *orig_dma_sg = dma_sg; - int orig_nents = nents; - - for (;;) { - nents = verify_one_map(dma_sg, &sg, nents, &iopte); - if (nents <= 0) - break; - dma_sg++; - if (dma_sg->dma_length == 0) - break; - } - - if (nents > 0) { - printk("verify_maps: dma maps consumed by some sgs remain (%d)\n", - nents); - return -1; - } - - if (nents < 0) { - printk("verify_maps: Error, messed up mappings, " - "at sg %d dma_sg %d\n", - (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg)); - return -1; - } - - /* This test passes... */ - return 0; -} - -void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages) -{ - if (verify_lengths(sg, nents, npages) < 0 || - verify_maps(sg, nents, iopte) < 0) { - int i; - - printk("verify_sglist: Crap, messed up mappings, dumping, iodma at "); - printk("%016lx.\n", sg->dma_address & IO_PAGE_MASK); - - for (i = 0; i < nents; i++) { - printk("sg(%d): page_addr(%p) off(%x) length(%x) " - "dma_address[%016lx] dma_length[%016lx]\n", - i, - page_address(sg[i].page), sg[i].offset, - sg[i].length, - sg[i].dma_address, sg[i].dma_length); - } - } - - /* Seems to be ok */ -} -#endif - -unsigned long prepare_sg(struct scatterlist *sg, int nents) -{ - struct scatterlist *dma_sg = sg; - unsigned long prev; - u32 dent_addr, dent_len; - - prev = (unsigned long) (page_address(sg->page) + sg->offset); - prev += (unsigned long) (dent_len = sg->length); - dent_addr = (u32) ((unsigned long)(page_address(sg->page) + sg->offset) - & (IO_PAGE_SIZE - 1UL)); - while (--nents) { - unsigned long addr; - - sg++; - addr = (unsigned long) (page_address(sg->page) + sg->offset); - if (! VCONTIG(prev, addr)) { - dma_sg->dma_address = dent_addr; - dma_sg->dma_length = dent_len; - dma_sg++; - - dent_addr = ((dent_addr + - dent_len + - (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT); - dent_addr <<= IO_PAGE_SHIFT; - dent_addr += addr & (IO_PAGE_SIZE - 1UL); - dent_len = 0; - } - dent_len += sg->length; - prev = addr + sg->length; - } - dma_sg->dma_address = dent_addr; - dma_sg->dma_length = dent_len; - - return ((unsigned long) dent_addr + - (unsigned long) dent_len + - (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT; -} diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h deleted file mode 100644 index ad791014419..00000000000 --- a/arch/sparc64/kernel/iommu_common.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $Id: iommu_common.h,v 1.5 2001/12/11 09:41:01 davem Exp $ - * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/mm.h> - -#include <asm/iommu.h> -#include <asm/scatterlist.h> - -/* - * These give mapping size of each iommu pte/tlb. - */ -#define IO_PAGE_SHIFT 13 -#define IO_PAGE_SIZE (1UL << IO_PAGE_SHIFT) -#define IO_PAGE_MASK (~(IO_PAGE_SIZE-1)) -#define IO_PAGE_ALIGN(addr) (((addr)+IO_PAGE_SIZE-1)&IO_PAGE_MASK) - -#define IO_TSB_ENTRIES (128*1024) -#define IO_TSB_SIZE (IO_TSB_ENTRIES * 8) - -/* - * This is the hardwired shift in the iotlb tag/data parts. - */ -#define IOMMU_PAGE_SHIFT 13 - -/* You are _strongly_ advised to enable the following debugging code - * any time you make changes to the sg code below, run it for a while - * with filesystems mounted read-only before buying the farm... -DaveM - */ -#undef VERIFY_SG - -#ifdef VERIFY_SG -extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages); -#endif - -/* Two addresses are "virtually contiguous" if and only if: - * 1) They are equal, or... - * 2) They are both on a page boundary - */ -#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ - (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) - -extern unsigned long prepare_sg(struct scatterlist *sg, int nents); diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c deleted file mode 100644 index 233526ba3ab..00000000000 --- a/arch/sparc64/kernel/irq.c +++ /dev/null @@ -1,1009 +0,0 @@ -/* $Id: irq.c,v 1.114 2002/01/11 08:45:38 davem Exp $ - * irq.c: UltraSparc IRQ handling/init/registry. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -#include <asm/ptrace.h> -#include <asm/processor.h> -#include <asm/atomic.h> -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/sbus.h> -#include <asm/iommu.h> -#include <asm/upa.h> -#include <asm/oplib.h> -#include <asm/timer.h> -#include <asm/smp.h> -#include <asm/starfire.h> -#include <asm/uaccess.h> -#include <asm/cache.h> -#include <asm/cpudata.h> -#include <asm/auxio.h> - -#ifdef CONFIG_SMP -static void distribute_irqs(void); -#endif - -/* UPA nodes send interrupt packet to UltraSparc with first data reg - * value low 5 (7 on Starfire) bits holding the IRQ identifier being - * delivered. We must translate this into a non-vector IRQ so we can - * set the softint on this cpu. - * - * To make processing these packets efficient and race free we use - * an array of irq buckets below. The interrupt vector handler in - * entry.S feeds incoming packets into per-cpu pil-indexed lists. - * The IVEC handler does not need to act atomically, the PIL dispatch - * code uses CAS to get an atomic snapshot of the list and clear it - * at the same time. - */ - -struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES))); - -/* This has to be in the main kernel image, it cannot be - * turned into per-cpu data. The reason is that the main - * kernel image is locked into the TLB and this structure - * is accessed from the vectored interrupt trap handler. If - * access to this structure takes a TLB miss it could cause - * the 5-level sparc v9 trap stack to overflow. - */ -struct irq_work_struct { - unsigned int irq_worklists[16]; -}; -struct irq_work_struct __irq_work[NR_CPUS]; -#define irq_work(__cpu, __pil) &(__irq_work[(__cpu)].irq_worklists[(__pil)]) - -static struct irqaction *irq_action[NR_IRQS+1]; - -/* This only synchronizes entities which modify IRQ handler - * state and some selected user-level spots that want to - * read things in the table. IRQ handler processing orders - * its' accesses such that no locking is needed. - */ -static DEFINE_SPINLOCK(irq_action_lock); - -static void register_irq_proc (unsigned int irq); - -/* - * Upper 2b of irqaction->flags holds the ino. - * irqaction->mask holds the smp affinity information. - */ -#define put_ino_in_irqaction(action, irq) \ - action->flags &= 0xffffffffffffUL; \ - if (__bucket(irq) == &pil0_dummy_bucket) \ - action->flags |= 0xdeadUL << 48; \ - else \ - action->flags |= __irq_ino(irq) << 48; -#define get_ino_in_irqaction(action) (action->flags >> 48) - -#define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff) -#define get_smpaff_in_irqaction(action) ((action)->mask) - -int show_interrupts(struct seq_file *p, void *v) -{ - unsigned long flags; - int i = *(loff_t *) v; - struct irqaction *action; -#ifdef CONFIG_SMP - int j; -#endif - - spin_lock_irqsave(&irq_action_lock, flags); - if (i <= NR_IRQS) { - if (!(action = *(i + irq_action))) - goto out_unlock; - seq_printf(p, "%3d: ", i); -#ifndef CONFIG_SMP - seq_printf(p, "%10u ", kstat_irqs(i)); -#else - for (j = 0; j < NR_CPUS; j++) { - if (!cpu_online(j)) - continue; - seq_printf(p, "%10u ", - kstat_cpu(j).irqs[i]); - } -#endif - seq_printf(p, " %s:%lx", action->name, - get_ino_in_irqaction(action)); - for (action = action->next; action; action = action->next) { - seq_printf(p, ", %s:%lx", action->name, - get_ino_in_irqaction(action)); - } - seq_putc(p, '\n'); - } -out_unlock: - spin_unlock_irqrestore(&irq_action_lock, flags); - - return 0; -} - -/* Now these are always passed a true fully specified sun4u INO. */ -void enable_irq(unsigned int irq) -{ - struct ino_bucket *bucket = __bucket(irq); - unsigned long imap; - unsigned long tid; - - imap = bucket->imap; - if (imap == 0UL) - return; - - preempt_disable(); - - if (tlb_type == cheetah || tlb_type == cheetah_plus) { - unsigned long ver; - - __asm__ ("rdpr %%ver, %0" : "=r" (ver)); - if ((ver >> 32) == 0x003e0016) { - /* We set it to our JBUS ID. */ - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (tid) - : "i" (ASI_JBUS_CONFIG)); - tid = ((tid & (0x1fUL<<17)) << 9); - tid &= IMAP_TID_JBUS; - } else { - /* We set it to our Safari AID. */ - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (tid) - : "i" (ASI_SAFARI_CONFIG)); - tid = ((tid & (0x3ffUL<<17)) << 9); - tid &= IMAP_AID_SAFARI; - } - } else if (this_is_starfire == 0) { - /* We set it to our UPA MID. */ - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (tid) - : "i" (ASI_UPA_CONFIG)); - tid = ((tid & UPA_CONFIG_MID) << 9); - tid &= IMAP_TID_UPA; - } else { - tid = (starfire_translate(imap, smp_processor_id()) << 26); - tid &= IMAP_TID_UPA; - } - - /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product - * of this SYSIO's preconfigured IGN in the SYSIO Control - * Register, the hardware just mirrors that value here. - * However for Graphics and UPA Slave devices the full - * IMAP_INR field can be set by the programmer here. - * - * Things like FFB can now be handled via the new IRQ mechanism. - */ - upa_writel(tid | IMAP_VALID, imap); - - preempt_enable(); -} - -/* This now gets passed true ino's as well. */ -void disable_irq(unsigned int irq) -{ - struct ino_bucket *bucket = __bucket(irq); - unsigned long imap; - - imap = bucket->imap; - if (imap != 0UL) { - u32 tmp; - - /* NOTE: We do not want to futz with the IRQ clear registers - * and move the state to IDLE, the SCSI code does call - * disable_irq() to assure atomicity in the queue cmd - * SCSI adapter driver code. Thus we'd lose interrupts. - */ - tmp = upa_readl(imap); - tmp &= ~IMAP_VALID; - upa_writel(tmp, imap); - } -} - -/* The timer is the one "weird" interrupt which is generated by - * the CPU %tick register and not by some normal vectored interrupt - * source. To handle this special case, we use this dummy INO bucket. - */ -static struct irq_desc pil0_dummy_desc; -static struct ino_bucket pil0_dummy_bucket = { - .irq_info = &pil0_dummy_desc, -}; - -static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup, - unsigned long iclr, unsigned long imap, - struct ino_bucket *bucket) -{ - prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> " - "(%d:%d:%016lx:%016lx), halting...\n", - ino, bucket->pil, bucket->iclr, bucket->imap, - pil, inofixup, iclr, imap); - prom_halt(); -} - -unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap) -{ - struct ino_bucket *bucket; - int ino; - - if (pil == 0) { - if (iclr != 0UL || imap != 0UL) { - prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)\n", - iclr, imap); - prom_halt(); - } - return __irq(&pil0_dummy_bucket); - } - - /* RULE: Both must be specified in all other cases. */ - if (iclr == 0UL || imap == 0UL) { - prom_printf("Invalid build_irq %d %d %016lx %016lx\n", - pil, inofixup, iclr, imap); - prom_halt(); - } - - ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; - if (ino > NUM_IVECS) { - prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n", - ino, pil, inofixup, iclr, imap); - prom_halt(); - } - - bucket = &ivector_table[ino]; - if (bucket->flags & IBF_ACTIVE) - build_irq_error("IRQ: Trying to build active INO bucket.\n", - ino, pil, inofixup, iclr, imap, bucket); - - if (bucket->irq_info) { - if (bucket->imap != imap || bucket->iclr != iclr) - build_irq_error("IRQ: Trying to reinit INO bucket.\n", - ino, pil, inofixup, iclr, imap, bucket); - - goto out; - } - - bucket->irq_info = kmalloc(sizeof(struct irq_desc), GFP_ATOMIC); - if (!bucket->irq_info) { - prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n"); - prom_halt(); - } - memset(bucket->irq_info, 0, sizeof(struct irq_desc)); - - /* Ok, looks good, set it up. Don't touch the irq_chain or - * the pending flag. - */ - bucket->imap = imap; - bucket->iclr = iclr; - bucket->pil = pil; - bucket->flags = 0; - -out: - return __irq(bucket); -} - -static void atomic_bucket_insert(struct ino_bucket *bucket) -{ - unsigned long pstate; - unsigned int *ent; - - __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); - __asm__ __volatile__("wrpr %0, %1, %%pstate" - : : "r" (pstate), "i" (PSTATE_IE)); - ent = irq_work(smp_processor_id(), bucket->pil); - bucket->irq_chain = *ent; - *ent = __irq(bucket); - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); -} - -static int check_irq_sharing(int pil, unsigned long irqflags) -{ - struct irqaction *action, *tmp; - - action = *(irq_action + pil); - if (action) { - if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { - for (tmp = action; tmp->next; tmp = tmp->next) - ; - } else { - return -EBUSY; - } - } - return 0; -} - -static void append_irq_action(int pil, struct irqaction *action) -{ - struct irqaction **pp = irq_action + pil; - - while (*pp) - pp = &((*pp)->next); - *pp = action; -} - -static struct irqaction *get_action_slot(struct ino_bucket *bucket) -{ - struct irq_desc *desc = bucket->irq_info; - int max_irq, i; - - max_irq = 1; - if (bucket->flags & IBF_PCI) - max_irq = MAX_IRQ_DESC_ACTION; - for (i = 0; i < max_irq; i++) { - struct irqaction *p = &desc->action[i]; - u32 mask = (1 << i); - - if (desc->action_active_mask & mask) - continue; - - desc->action_active_mask |= mask; - return p; - } - return NULL; -} - -int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char *name, void *dev_id) -{ - struct irqaction *action; - struct ino_bucket *bucket = __bucket(irq); - unsigned long flags; - int pending = 0; - - if (unlikely(!handler)) - return -EINVAL; - - if (unlikely(!bucket->irq_info)) - return -ENODEV; - - if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. In SA_STATIC_ALLOC case, - * random driver's kmalloc will fail, but it is safe. - * If already initialized, random driver will not reinit. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - spin_lock_irqsave(&irq_action_lock, flags); - - if (check_irq_sharing(bucket->pil, irqflags)) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -EBUSY; - } - - action = get_action_slot(bucket); - if (!action) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -ENOMEM; - } - - bucket->flags |= IBF_ACTIVE; - pending = 0; - if (bucket != &pil0_dummy_bucket) { - pending = bucket->pending; - if (pending) - bucket->pending = 0; - } - - action->handler = handler; - action->flags = irqflags; - action->name = name; - action->next = NULL; - action->dev_id = dev_id; - put_ino_in_irqaction(action, irq); - put_smpaff_in_irqaction(action, CPU_MASK_NONE); - - append_irq_action(bucket->pil, action); - - enable_irq(irq); - - /* We ate the IVEC already, this makes sure it does not get lost. */ - if (pending) { - atomic_bucket_insert(bucket); - set_softint(1 << bucket->pil); - } - - spin_unlock_irqrestore(&irq_action_lock, flags); - - if (bucket != &pil0_dummy_bucket) - register_irq_proc(__irq_ino(irq)); - -#ifdef CONFIG_SMP - distribute_irqs(); -#endif - return 0; -} - -EXPORT_SYMBOL(request_irq); - -static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id) -{ - struct ino_bucket *bucket = __bucket(irq); - struct irqaction *action, **pp; - - pp = irq_action + bucket->pil; - action = *pp; - if (unlikely(!action)) - return NULL; - - if (unlikely(!action->handler)) { - printk("Freeing free IRQ %d\n", bucket->pil); - return NULL; - } - - while (action && action->dev_id != dev_id) { - pp = &action->next; - action = *pp; - } - - if (likely(action)) - *pp = action->next; - - return action; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *action; - struct ino_bucket *bucket; - unsigned long flags; - - spin_lock_irqsave(&irq_action_lock, flags); - - action = unlink_irq_action(irq, dev_id); - - spin_unlock_irqrestore(&irq_action_lock, flags); - - if (unlikely(!action)) - return; - - synchronize_irq(irq); - - spin_lock_irqsave(&irq_action_lock, flags); - - bucket = __bucket(irq); - if (bucket != &pil0_dummy_bucket) { - struct irq_desc *desc = bucket->irq_info; - unsigned long imap = bucket->imap; - int ent, i; - - for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { - struct irqaction *p = &desc->action[i]; - - if (p == action) { - desc->action_active_mask &= ~(1 << i); - break; - } - } - - if (!desc->action_active_mask) { - /* This unique interrupt source is now inactive. */ - bucket->flags &= ~IBF_ACTIVE; - - /* See if any other buckets share this bucket's IMAP - * and are still active. - */ - for (ent = 0; ent < NUM_IVECS; ent++) { - struct ino_bucket *bp = &ivector_table[ent]; - if (bp != bucket && - bp->imap == imap && - (bp->flags & IBF_ACTIVE) != 0) - break; - } - - /* Only disable when no other sub-irq levels of - * the same IMAP are active. - */ - if (ent == NUM_IVECS) - disable_irq(irq); - } - } - - spin_unlock_irqrestore(&irq_action_lock, flags); -} - -EXPORT_SYMBOL(free_irq); - -#ifdef CONFIG_SMP -void synchronize_irq(unsigned int irq) -{ - struct ino_bucket *bucket = __bucket(irq); - -#if 0 - /* The following is how I wish I could implement this. - * Unfortunately the ICLR registers are read-only, you can - * only write ICLR_foo values to them. To get the current - * IRQ status you would need to get at the IRQ diag registers - * in the PCI/SBUS controller and the layout of those vary - * from one controller to the next, sigh... -DaveM - */ - unsigned long iclr = bucket->iclr; - - while (1) { - u32 tmp = upa_readl(iclr); - - if (tmp == ICLR_TRANSMIT || - tmp == ICLR_PENDING) { - cpu_relax(); - continue; - } - break; - } -#else - /* So we have to do this with a INPROGRESS bit just like x86. */ - while (bucket->flags & IBF_INPROGRESS) - cpu_relax(); -#endif -} -#endif /* CONFIG_SMP */ - -static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs) -{ - struct irq_desc *desc = bp->irq_info; - unsigned char flags = bp->flags; - u32 action_mask, i; - int random; - - bp->flags |= IBF_INPROGRESS; - - if (unlikely(!(flags & IBF_ACTIVE))) { - bp->pending = 1; - goto out; - } - - if (desc->pre_handler) - desc->pre_handler(bp, - desc->pre_handler_arg1, - desc->pre_handler_arg2); - - action_mask = desc->action_active_mask; - random = 0; - for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { - struct irqaction *p = &desc->action[i]; - u32 mask = (1 << i); - - if (!(action_mask & mask)) - continue; - - action_mask &= ~mask; - - if (p->handler(__irq(bp), p->dev_id, regs) == IRQ_HANDLED) - random |= p->flags; - - if (!action_mask) - break; - } - if (bp->pil != 0) { - upa_writel(ICLR_IDLE, bp->iclr); - /* Test and add entropy */ - if (random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - } -out: - bp->flags &= ~IBF_INPROGRESS; -} - -void handler_irq(int irq, struct pt_regs *regs) -{ - struct ino_bucket *bp; - int cpu = smp_processor_id(); - -#ifndef CONFIG_SMP - /* - * Check for TICK_INT on level 14 softint. - */ - { - unsigned long clr_mask = 1 << irq; - unsigned long tick_mask = tick_ops->softint_mask; - - if ((irq == 14) && (get_softint() & tick_mask)) { - irq = 0; - clr_mask = tick_mask; - } - clear_softint(clr_mask); - } -#else - clear_softint(1 << irq); -#endif - - irq_enter(); - kstat_this_cpu.irqs[irq]++; - - /* Sliiiick... */ -#ifndef CONFIG_SMP - bp = ((irq != 0) ? - __bucket(xchg32(irq_work(cpu, irq), 0)) : - &pil0_dummy_bucket); -#else - bp = __bucket(xchg32(irq_work(cpu, irq), 0)); -#endif - while (bp) { - struct ino_bucket *nbp = __bucket(bp->irq_chain); - - bp->irq_chain = 0; - process_bucket(irq, bp, regs); - bp = nbp; - } - irq_exit(); -} - -#ifdef CONFIG_BLK_DEV_FD -extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *);; - -/* XXX No easy way to include asm/floppy.h XXX */ -extern unsigned char *pdma_vaddr; -extern unsigned long pdma_size; -extern volatile int doing_pdma; -extern unsigned long fdc_status; - -irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs) -{ - if (likely(doing_pdma)) { - void __iomem *stat = (void __iomem *) fdc_status; - unsigned char *vaddr = pdma_vaddr; - unsigned long size = pdma_size; - u8 val; - - while (size) { - val = readb(stat); - if (unlikely(!(val & 0x80))) { - pdma_vaddr = vaddr; - pdma_size = size; - return IRQ_HANDLED; - } - if (unlikely(!(val & 0x20))) { - pdma_vaddr = vaddr; - pdma_size = size; - doing_pdma = 0; - goto main_interrupt; - } - if (val & 0x40) { - /* read */ - *vaddr++ = readb(stat + 1); - } else { - unsigned char data = *vaddr++; - - /* write */ - writeb(data, stat + 1); - } - size--; - } - - pdma_vaddr = vaddr; - pdma_size = size; - - /* Send Terminal Count pulse to floppy controller. */ - val = readb(auxio_register); - val |= AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); - val &= AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); - - doing_pdma = 0; - } - -main_interrupt: - return floppy_interrupt(irq, dev_cookie, regs); -} -EXPORT_SYMBOL(sparc_floppy_irq); -#endif - -/* We really don't need these at all on the Sparc. We only have - * stubs here because they are exported to modules. - */ -unsigned long probe_irq_on(void) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_on); - -int probe_irq_off(unsigned long mask) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_off); - -#ifdef CONFIG_SMP -static int retarget_one_irq(struct irqaction *p, int goal_cpu) -{ - struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table; - unsigned long imap = bucket->imap; - unsigned int tid; - - while (!cpu_online(goal_cpu)) { - if (++goal_cpu >= NR_CPUS) - goal_cpu = 0; - } - - if (tlb_type == cheetah || tlb_type == cheetah_plus) { - tid = goal_cpu << 26; - tid &= IMAP_AID_SAFARI; - } else if (this_is_starfire == 0) { - tid = goal_cpu << 26; - tid &= IMAP_TID_UPA; - } else { - tid = (starfire_translate(imap, goal_cpu) << 26); - tid &= IMAP_TID_UPA; - } - upa_writel(tid | IMAP_VALID, imap); - - do { - if (++goal_cpu >= NR_CPUS) - goal_cpu = 0; - } while (!cpu_online(goal_cpu)); - - return goal_cpu; -} - -/* Called from request_irq. */ -static void distribute_irqs(void) -{ - unsigned long flags; - int cpu, level; - - spin_lock_irqsave(&irq_action_lock, flags); - cpu = 0; - - /* - * Skip the timer at [0], and very rare error/power intrs at [15]. - * Also level [12], it causes problems on Ex000 systems. - */ - for (level = 1; level < NR_IRQS; level++) { - struct irqaction *p = irq_action[level]; - - if (level == 12) - continue; - - while(p) { - cpu = retarget_one_irq(p, cpu); - p = p->next; - } - } - spin_unlock_irqrestore(&irq_action_lock, flags); -} -#endif - -struct sun5_timer { - u64 count0; - u64 limit0; - u64 count1; - u64 limit1; -}; - -static struct sun5_timer *prom_timers; -static u64 prom_limit0, prom_limit1; - -static void map_prom_timers(void) -{ - unsigned int addr[3]; - int tnode, err; - - /* PROM timer node hangs out in the top level of device siblings... */ - tnode = prom_finddevice("/counter-timer"); - - /* Assume if node is not present, PROM uses different tick mechanism - * which we should not care about. - */ - if (tnode == 0 || tnode == -1) { - prom_timers = (struct sun5_timer *) 0; - return; - } - - /* If PROM is really using this, it must be mapped by him. */ - err = prom_getproperty(tnode, "address", (char *)addr, sizeof(addr)); - if (err == -1) { - prom_printf("PROM does not have timer mapped, trying to continue.\n"); - prom_timers = (struct sun5_timer *) 0; - return; - } - prom_timers = (struct sun5_timer *) ((unsigned long)addr[0]); -} - -static void kill_prom_timer(void) -{ - if (!prom_timers) - return; - - /* Save them away for later. */ - prom_limit0 = prom_timers->limit0; - prom_limit1 = prom_timers->limit1; - - /* Just as in sun4c/sun4m PROM uses timer which ticks at IRQ 14. - * We turn both off here just to be paranoid. - */ - prom_timers->limit0 = 0; - prom_timers->limit1 = 0; - - /* Wheee, eat the interrupt packet too... */ - __asm__ __volatile__( -" mov 0x40, %%g2\n" -" ldxa [%%g0] %0, %%g1\n" -" ldxa [%%g2] %1, %%g1\n" -" stxa %%g0, [%%g0] %0\n" -" membar #Sync\n" - : /* no outputs */ - : "i" (ASI_INTR_RECEIVE), "i" (ASI_INTR_R) - : "g1", "g2"); -} - -void init_irqwork_curcpu(void) -{ - register struct irq_work_struct *workp asm("o2"); - register unsigned long tmp asm("o3"); - int cpu = hard_smp_processor_id(); - - memset(__irq_work + cpu, 0, sizeof(*workp)); - - /* Make sure we are called with PSTATE_IE disabled. */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - : "=r" (tmp)); - if (tmp & PSTATE_IE) { - prom_printf("BUG: init_irqwork_curcpu() called with " - "PSTATE_IE enabled, bailing.\n"); - __asm__ __volatile__("mov %%i7, %0\n\t" - : "=r" (tmp)); - prom_printf("BUG: Called from %lx\n", tmp); - prom_halt(); - } - - /* Set interrupt globals. */ - workp = &__irq_work[cpu]; - __asm__ __volatile__( - "rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate\n\t" - "mov %2, %%g6\n\t" - "wrpr %0, 0x0, %%pstate\n\t" - : "=&r" (tmp) - : "i" (PSTATE_IG), "r" (workp)); -} - -/* Only invoked on boot processor. */ -void __init init_IRQ(void) -{ - map_prom_timers(); - kill_prom_timer(); - memset(&ivector_table[0], 0, sizeof(ivector_table)); - - /* We need to clear any IRQ's pending in the soft interrupt - * registers, a spurious one could be left around from the - * PROM timer which we just disabled. - */ - clear_softint(get_softint()); - - /* Now that ivector table is initialized, it is safe - * to receive IRQ vector traps. We will normally take - * one or two right now, in case some device PROM used - * to boot us wants to speak to us. We just ignore them. - */ - __asm__ __volatile__("rdpr %%pstate, %%g1\n\t" - "or %%g1, %0, %%g1\n\t" - "wrpr %%g1, 0x0, %%pstate" - : /* No outputs */ - : "i" (PSTATE_IE) - : "g1"); -} - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NUM_IVECS]; - -#ifdef CONFIG_SMP - -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct ino_bucket *bp = ivector_table + (long)data; - struct irq_desc *desc = bp->irq_info; - struct irqaction *ap = desc->action; - cpumask_t mask; - int len; - - mask = get_smpaff_in_irqaction(ap); - if (cpus_empty(mask)) - mask = cpu_online_map; - - len = cpumask_scnprintf(page, count, mask); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static inline void set_intr_affinity(int irq, cpumask_t hw_aff) -{ - struct ino_bucket *bp = ivector_table + irq; - struct irq_desc *desc = bp->irq_info; - struct irqaction *ap = desc->action; - - /* Users specify affinity in terms of hw cpu ids. - * As soon as we do this, handler_irq() might see and take action. - */ - put_smpaff_in_irqaction(ap, hw_aff); - - /* Migration is simply done by the next cpu to service this - * interrupt. - */ -} - -static int irq_affinity_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - int irq = (long) data, full_count = count, err; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - - /* - * Do not allow disabling IRQs completely - it's a too easy - * way to make the system unusable accidentally :-) At least - * one online CPU still has to be targeted. - */ - cpus_and(new_value, new_value, cpu_online_map); - if (cpus_empty(new_value)) - return -EINVAL; - - set_intr_affinity(irq, new_value); - - return full_count; -} - -#endif - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%x", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - -#ifdef CONFIG_SMP - /* XXX SMP affinity not supported on starfire yet. */ - if (this_is_starfire == 0) { - struct proc_dir_entry *entry; - - /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); - - if (entry) { - entry->nlink = 1; - entry->data = (void *)(long)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - } - } -#endif -} - -void init_irq_proc (void) -{ - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); -} - diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c deleted file mode 100644 index 30862abee61..00000000000 --- a/arch/sparc64/kernel/isa.c +++ /dev/null @@ -1,329 +0,0 @@ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <asm/oplib.h> -#include <asm/isa.h> - -struct sparc_isa_bridge *isa_chain; - -static void __init fatal_err(const char *reason) -{ - prom_printf("ISA: fatal error, %s.\n", reason); -} - -static void __init report_dev(struct sparc_isa_device *isa_dev, int child) -{ - if (child) - printk(" (%s)", isa_dev->prom_name); - else - printk(" [%s", isa_dev->prom_name); -} - -static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, - struct linux_prom_registers *pregs, - int pregs_size) -{ - unsigned long base, len; - int prop_len; - - prop_len = prom_getproperty(isa_dev->prom_node, "reg", - (char *) pregs, pregs_size); - - if (prop_len <= 0) - return; - - /* Only the first one is interesting. */ - len = pregs[0].reg_size; - base = (((unsigned long)pregs[0].which_io << 32) | - (unsigned long)pregs[0].phys_addr); - base += isa_dev->bus->parent->io_space.start; - - isa_dev->resource.start = base; - isa_dev->resource.end = (base + len - 1UL); - isa_dev->resource.flags = IORESOURCE_IO; - isa_dev->resource.name = isa_dev->prom_name; - - request_resource(&isa_dev->bus->parent->io_space, - &isa_dev->resource); -} - -/* I can't believe they didn't put a real INO in the isa device - * interrupts property. The whole point of the OBP properties - * is to shield the kernel from IRQ routing details. - * - * The P1275 standard for ISA devices seems to also have been - * totally ignored. - * - * On later systems, an interrupt-map and interrupt-map-mask scheme - * akin to EBUS is used. - */ -static struct { - int obp_irq; - int pci_ino; -} grover_irq_table[] = { - { 1, 0x00 }, /* dma, unknown ino at this point */ - { 2, 0x27 }, /* floppy */ - { 3, 0x22 }, /* parallel */ - { 4, 0x2b }, /* serial */ - { 5, 0x25 }, /* acpi power management */ - - { 0, 0x00 } /* end of table */ -}; - -static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, - struct sparc_isa_bridge *isa_br, - int *interrupt, - struct linux_prom_registers *pregs) -{ - unsigned int hi, lo, irq; - int i; - - hi = pregs->which_io & isa_br->isa_intmask.phys_hi; - lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo; - irq = *interrupt & isa_br->isa_intmask.interrupt; - for (i = 0; i < isa_br->num_isa_intmap; i++) { - if ((isa_br->isa_intmap[i].phys_hi == hi) && - (isa_br->isa_intmap[i].phys_lo == lo) && - (isa_br->isa_intmap[i].interrupt == irq)) { - *interrupt = isa_br->isa_intmap[i].cinterrupt; - return 0; - } - } - return -1; -} - -static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, - struct linux_prom_registers *pregs) -{ - int irq_prop; - - irq_prop = prom_getintdefault(isa_dev->prom_node, - "interrupts", -1); - if (irq_prop <= 0) { - goto no_irq; - } else { - struct pci_controller_info *pcic; - struct pci_pbm_info *pbm; - int i; - - if (isa_dev->bus->num_isa_intmap) { - if (!isa_dev_get_irq_using_imap(isa_dev, - isa_dev->bus, - &irq_prop, - pregs)) - goto route_irq; - } - - for (i = 0; grover_irq_table[i].obp_irq != 0; i++) { - if (grover_irq_table[i].obp_irq == irq_prop) { - int ino = grover_irq_table[i].pci_ino; - - if (ino == 0) - goto no_irq; - - irq_prop = ino; - goto route_irq; - } - } - goto no_irq; - -route_irq: - pbm = isa_dev->bus->parent; - pcic = pbm->parent; - isa_dev->irq = pcic->irq_build(pbm, NULL, irq_prop); - return; - } - -no_irq: - isa_dev->irq = PCI_IRQ_NONE; -} - -static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) -{ - int node = prom_getchild(parent_isa_dev->prom_node); - - if (node == 0) - return; - - printk(" ->"); - while (node != 0) { - struct linux_prom_registers regs[PROMREG_MAX]; - struct sparc_isa_device *isa_dev; - int prop_len; - - isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); - if (!isa_dev) { - fatal_err("cannot allocate child isa_dev"); - prom_halt(); - } - - memset(isa_dev, 0, sizeof(*isa_dev)); - - /* Link it in to parent. */ - isa_dev->next = parent_isa_dev->child; - parent_isa_dev->child = isa_dev; - - isa_dev->bus = parent_isa_dev->bus; - isa_dev->prom_node = node; - prop_len = prom_getproperty(node, "name", - (char *) isa_dev->prom_name, - sizeof(isa_dev->prom_name)); - if (prop_len <= 0) { - fatal_err("cannot get child isa_dev OBP node name"); - prom_halt(); - } - - prop_len = prom_getproperty(node, "compatible", - (char *) isa_dev->compatible, - sizeof(isa_dev->compatible)); - - /* Not having this is OK. */ - if (prop_len <= 0) - isa_dev->compatible[0] = '\0'; - - isa_dev_get_resource(isa_dev, regs, sizeof(regs)); - isa_dev_get_irq(isa_dev, regs); - - report_dev(isa_dev, 1); - - node = prom_getsibling(node); - } -} - -static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) -{ - int node = prom_getchild(isa_br->prom_node); - - while (node != 0) { - struct linux_prom_registers regs[PROMREG_MAX]; - struct sparc_isa_device *isa_dev; - int prop_len; - - isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); - if (!isa_dev) { - fatal_err("cannot allocate isa_dev"); - prom_halt(); - } - - memset(isa_dev, 0, sizeof(*isa_dev)); - - /* Link it in. */ - isa_dev->next = NULL; - if (isa_br->devices == NULL) { - isa_br->devices = isa_dev; - } else { - struct sparc_isa_device *tmp = isa_br->devices; - - while (tmp->next) - tmp = tmp->next; - - tmp->next = isa_dev; - } - - isa_dev->bus = isa_br; - isa_dev->prom_node = node; - prop_len = prom_getproperty(node, "name", - (char *) isa_dev->prom_name, - sizeof(isa_dev->prom_name)); - if (prop_len <= 0) { - fatal_err("cannot get isa_dev OBP node name"); - prom_halt(); - } - - prop_len = prom_getproperty(node, "compatible", - (char *) isa_dev->compatible, - sizeof(isa_dev->compatible)); - - /* Not having this is OK. */ - if (prop_len <= 0) - isa_dev->compatible[0] = '\0'; - - isa_dev_get_resource(isa_dev, regs, sizeof(regs)); - isa_dev_get_irq(isa_dev, regs); - - report_dev(isa_dev, 0); - - isa_fill_children(isa_dev); - - printk("]"); - - node = prom_getsibling(node); - } -} - -void __init isa_init(void) -{ - struct pci_dev *pdev; - unsigned short vendor, device; - int index = 0; - - vendor = PCI_VENDOR_ID_AL; - device = PCI_DEVICE_ID_AL_M1533; - - pdev = NULL; - while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) { - struct pcidev_cookie *pdev_cookie; - struct pci_pbm_info *pbm; - struct sparc_isa_bridge *isa_br; - int prop_len; - - pdev_cookie = pdev->sysdata; - if (!pdev_cookie) { - printk("ISA: Warning, ISA bridge ignored due to " - "lack of OBP data.\n"); - continue; - } - pbm = pdev_cookie->pbm; - - isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); - if (!isa_br) { - fatal_err("cannot allocate sparc_isa_bridge"); - prom_halt(); - } - - memset(isa_br, 0, sizeof(*isa_br)); - - /* Link it in. */ - isa_br->next = isa_chain; - isa_chain = isa_br; - - isa_br->parent = pbm; - isa_br->self = pdev; - isa_br->index = index++; - isa_br->prom_node = pdev_cookie->prom_node; - strncpy(isa_br->prom_name, pdev_cookie->prom_name, - sizeof(isa_br->prom_name)); - - prop_len = prom_getproperty(isa_br->prom_node, - "ranges", - (char *) isa_br->isa_ranges, - sizeof(isa_br->isa_ranges)); - if (prop_len <= 0) - isa_br->num_isa_ranges = 0; - else - isa_br->num_isa_ranges = - (prop_len / sizeof(struct linux_prom_isa_ranges)); - - prop_len = prom_getproperty(isa_br->prom_node, - "interrupt-map", - (char *) isa_br->isa_intmap, - sizeof(isa_br->isa_intmap)); - if (prop_len <= 0) - isa_br->num_isa_intmap = 0; - else - isa_br->num_isa_intmap = - (prop_len / sizeof(struct linux_prom_isa_intmap)); - - prop_len = prom_getproperty(isa_br->prom_node, - "interrupt-map-mask", - (char *) &(isa_br->isa_intmask), - sizeof(isa_br->isa_intmask)); - - printk("isa%d:", isa_br->index); - - isa_fill_devices(isa_br); - - printk("\n"); - } -} diff --git a/arch/sparc64/kernel/itlb_base.S b/arch/sparc64/kernel/itlb_base.S deleted file mode 100644 index 4951ff8f687..00000000000 --- a/arch/sparc64/kernel/itlb_base.S +++ /dev/null @@ -1,79 +0,0 @@ -/* $Id: itlb_base.S,v 1.12 2002/02/09 19:49:30 davem Exp $ - * itlb_base.S: Front end to ITLB miss replacement strategy. - * This is included directly into the trap table. - * - * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#if PAGE_SHIFT == 13 -/* - * To compute vpte offset, we need to do ((addr >> 13) << 3), - * which can be optimized to (addr >> 10) if bits 10/11/12 can - * be guaranteed to be 0 ... mmu_context.h does guarantee this - * by only using 10 bits in the hwcontext value. - */ -#define CREATE_VPTE_OFFSET1(r1, r2) \ - srax r1, 10, r2 -#define CREATE_VPTE_OFFSET2(r1, r2) nop -#else /* PAGE_SHIFT */ -#define CREATE_VPTE_OFFSET1(r1, r2) \ - srax r1, PAGE_SHIFT, r2 -#define CREATE_VPTE_OFFSET2(r1, r2) \ - sllx r2, 3, r2 -#endif /* PAGE_SHIFT */ - - -/* Ways we can get here: - * - * 1) Nucleus instruction misses from module code. - * 2) All user instruction misses. - * - * All real page faults merge their code paths to the - * sparc64_realfault_common label below. - */ - -/* ITLB ** ICACHE line 1: Quick user TLB misses */ - mov TLB_SFSR, %g1 - ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS - CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset - CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset - ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE -1: brgez,pn %g5, 3f ! Not valid, branch out - sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot - andcc %g5, %g4, %g0 ! Executable? - -/* ITLB ** ICACHE line 2: Real faults */ - be,pn %xcc, 3f ! Nope, branch. - nop ! Delay-slot -2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB - retry ! Trap return -3: rdpr %pstate, %g4 ! Move into alt-globals - wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tpc, %g5 ! And load faulting VA - mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB - -/* ITLB ** ICACHE line 3: Finish faults */ -sparc64_realfault_common: ! Called by dtlb_miss - stb %g4, [%g6 + TI_FAULT_CODE] - stx %g5, [%g6 + TI_FAULT_ADDR] - ba,pt %xcc, etrap ! Save state -1: rd %pc, %g7 ! ... - call do_sparc64_fault ! Call fault handler - add %sp, PTREGS_OFF, %o0! Compute pt_regs arg - ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state - nop - -/* ITLB ** ICACHE line 4: Window fixups */ -winfix_trampoline: - rdpr %tpc, %g3 ! Prepare winfixup TNPC - or %g3, 0x7c, %g3 ! Compute branch offset - wrpr %g3, %tnpc ! Write it into TNPC - done ! Do it to it - nop - nop - nop - nop - -#undef CREATE_VPTE_OFFSET1 -#undef CREATE_VPTE_OFFSET2 diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c deleted file mode 100644 index b9a9ce70e55..00000000000 --- a/arch/sparc64/kernel/kprobes.c +++ /dev/null @@ -1,443 +0,0 @@ -/* arch/sparc64/kernel/kprobes.c - * - * Copyright (C) 2004 David S. Miller <davem@davemloft.net> - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/kprobes.h> -#include <asm/kdebug.h> -#include <asm/signal.h> -#include <asm/cacheflush.h> - -/* We do not have hardware single-stepping on sparc64. - * So we implement software single-stepping with breakpoint - * traps. The top-level scheme is similar to that used - * in the x86 kprobes implementation. - * - * In the kprobe->ainsn.insn[] array we store the original - * instruction at index zero and a break instruction at - * index one. - * - * When we hit a kprobe we: - * - Run the pre-handler - * - Remember "regs->tnpc" and interrupt level stored in - * "regs->tstate" so we can restore them later - * - Disable PIL interrupts - * - Set regs->tpc to point to kprobe->ainsn.insn[0] - * - Set regs->tnpc to point to kprobe->ainsn.insn[1] - * - Mark that we are actively in a kprobe - * - * At this point we wait for the second breakpoint at - * kprobe->ainsn.insn[1] to hit. When it does we: - * - Run the post-handler - * - Set regs->tpc to "remembered" regs->tnpc stored above, - * restore the PIL interrupt level in "regs->tstate" as well - * - Make any adjustments necessary to regs->tnpc in order - * to handle relative branches correctly. See below. - * - Mark that we are no longer actively in a kprobe. - */ - -DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; -DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); - -int __kprobes arch_prepare_kprobe(struct kprobe *p) -{ - p->ainsn.insn[0] = *p->addr; - p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2; - p->opcode = *p->addr; - return 0; -} - -void __kprobes arch_arm_kprobe(struct kprobe *p) -{ - *p->addr = BREAKPOINT_INSTRUCTION; - flushi(p->addr); -} - -void __kprobes arch_disarm_kprobe(struct kprobe *p) -{ - *p->addr = p->opcode; - flushi(p->addr); -} - -static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) -{ - kcb->prev_kprobe.kp = kprobe_running(); - kcb->prev_kprobe.status = kcb->kprobe_status; - kcb->prev_kprobe.orig_tnpc = kcb->kprobe_orig_tnpc; - kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil; -} - -static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) -{ - __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; - kcb->kprobe_status = kcb->prev_kprobe.status; - kcb->kprobe_orig_tnpc = kcb->prev_kprobe.orig_tnpc; - kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil; -} - -static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, - struct kprobe_ctlblk *kcb) -{ - __get_cpu_var(current_kprobe) = p; - kcb->kprobe_orig_tnpc = regs->tnpc; - kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL); -} - -static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs, - struct kprobe_ctlblk *kcb) -{ - regs->tstate |= TSTATE_PIL; - - /*single step inline, if it a breakpoint instruction*/ - if (p->opcode == BREAKPOINT_INSTRUCTION) { - regs->tpc = (unsigned long) p->addr; - regs->tnpc = kcb->kprobe_orig_tnpc; - } else { - regs->tpc = (unsigned long) &p->ainsn.insn[0]; - regs->tnpc = (unsigned long) &p->ainsn.insn[1]; - } -} - -static int __kprobes kprobe_handler(struct pt_regs *regs) -{ - struct kprobe *p; - void *addr = (void *) regs->tpc; - int ret = 0; - struct kprobe_ctlblk *kcb; - - /* - * We don't want to be preempted for the entire - * duration of kprobe processing - */ - preempt_disable(); - kcb = get_kprobe_ctlblk(); - - if (kprobe_running()) { - p = get_kprobe(addr); - if (p) { - if (kcb->kprobe_status == KPROBE_HIT_SS) { - regs->tstate = ((regs->tstate & ~TSTATE_PIL) | - kcb->kprobe_orig_tstate_pil); - goto no_kprobe; - } - /* We have reentered the kprobe_handler(), since - * another probe was hit while within the handler. - * We here save the original kprobes variables and - * just single step on the instruction of the new probe - * without calling any user handlers. - */ - save_previous_kprobe(kcb); - set_current_kprobe(p, regs, kcb); - kprobes_inc_nmissed_count(p); - kcb->kprobe_status = KPROBE_REENTER; - prepare_singlestep(p, regs, kcb); - return 1; - } else { - if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { - /* The breakpoint instruction was removed by - * another cpu right after we hit, no further - * handling of this interrupt is appropriate - */ - ret = 1; - goto no_kprobe; - } - p = __get_cpu_var(current_kprobe); - if (p->break_handler && p->break_handler(p, regs)) - goto ss_probe; - } - goto no_kprobe; - } - - p = get_kprobe(addr); - if (!p) { - if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { - /* - * The breakpoint instruction was removed right - * after we hit it. Another cpu has removed - * either a probepoint or a debugger breakpoint - * at this address. In either case, no further - * handling of this interrupt is appropriate. - */ - ret = 1; - } - /* Not one of ours: let kernel handle it */ - goto no_kprobe; - } - - set_current_kprobe(p, regs, kcb); - kcb->kprobe_status = KPROBE_HIT_ACTIVE; - if (p->pre_handler && p->pre_handler(p, regs)) - return 1; - -ss_probe: - prepare_singlestep(p, regs, kcb); - kcb->kprobe_status = KPROBE_HIT_SS; - return 1; - -no_kprobe: - preempt_enable_no_resched(); - return ret; -} - -/* If INSN is a relative control transfer instruction, - * return the corrected branch destination value. - * - * The original INSN location was REAL_PC, it actually - * executed at PC and produced destination address NPC. - */ -static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc, - unsigned long pc, - unsigned long npc) -{ - /* Branch not taken, no mods necessary. */ - if (npc == pc + 0x4UL) - return real_pc + 0x4UL; - - /* The three cases are call, branch w/prediction, - * and traditional branch. - */ - if ((insn & 0xc0000000) == 0x40000000 || - (insn & 0xc1c00000) == 0x00400000 || - (insn & 0xc1c00000) == 0x00800000) { - /* The instruction did all the work for us - * already, just apply the offset to the correct - * instruction location. - */ - return (real_pc + (npc - pc)); - } - - return real_pc + 0x4UL; -} - -/* If INSN is an instruction which writes it's PC location - * into a destination register, fix that up. - */ -static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, - unsigned long real_pc) -{ - unsigned long *slot = NULL; - - /* Simplest cast is call, which always uses %o7 */ - if ((insn & 0xc0000000) == 0x40000000) { - slot = ®s->u_regs[UREG_I7]; - } - - /* Jmpl encodes the register inside of the opcode */ - if ((insn & 0xc1f80000) == 0x81c00000) { - unsigned long rd = ((insn >> 25) & 0x1f); - - if (rd <= 15) { - slot = ®s->u_regs[rd]; - } else { - /* Hard case, it goes onto the stack. */ - flushw_all(); - - rd -= 16; - slot = (unsigned long *) - (regs->u_regs[UREG_FP] + STACK_BIAS); - slot += rd; - } - } - if (slot != NULL) - *slot = real_pc; -} - -/* - * Called after single-stepping. p->addr is the address of the - * instruction whose first byte has been replaced by the breakpoint - * instruction. To avoid the SMP problems that can occur when we - * temporarily put back the original opcode to single-step, we - * single-stepped a copy of the instruction. The address of this - * copy is p->ainsn.insn. - * - * This function prepares to return from the post-single-step - * breakpoint trap. - */ -static void __kprobes resume_execution(struct kprobe *p, - struct pt_regs *regs, struct kprobe_ctlblk *kcb) -{ - u32 insn = p->ainsn.insn[0]; - - regs->tpc = kcb->kprobe_orig_tnpc; - regs->tnpc = relbranch_fixup(insn, - (unsigned long) p->addr, - (unsigned long) &p->ainsn.insn[0], - regs->tnpc); - retpc_fixup(regs, insn, (unsigned long) p->addr); - - regs->tstate = ((regs->tstate & ~TSTATE_PIL) | - kcb->kprobe_orig_tstate_pil); -} - -static inline int post_kprobe_handler(struct pt_regs *regs) -{ - struct kprobe *cur = kprobe_running(); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - if (!cur) - return 0; - - if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { - kcb->kprobe_status = KPROBE_HIT_SSDONE; - cur->post_handler(cur, regs, 0); - } - - resume_execution(cur, regs, kcb); - - /*Restore back the original saved kprobes variables and continue. */ - if (kcb->kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(kcb); - goto out; - } - reset_current_kprobe(); -out: - preempt_enable_no_resched(); - - return 1; -} - -static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) -{ - struct kprobe *cur = kprobe_running(); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) - return 1; - - if (kcb->kprobe_status & KPROBE_HIT_SS) { - resume_execution(cur, regs, kcb); - - reset_current_kprobe(); - preempt_enable_no_resched(); - } - return 0; -} - -/* - * Wrapper routine to for handling exceptions. - */ -int __kprobes kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - struct die_args *args = (struct die_args *)data; - int ret = NOTIFY_DONE; - - switch (val) { - case DIE_DEBUG: - if (kprobe_handler(args->regs)) - ret = NOTIFY_STOP; - break; - case DIE_DEBUG_2: - if (post_kprobe_handler(args->regs)) - ret = NOTIFY_STOP; - break; - case DIE_GPF: - case DIE_PAGE_FAULT: - /* kprobe_running() needs smp_processor_id() */ - preempt_disable(); - if (kprobe_running() && - kprobe_fault_handler(args->regs, args->trapnr)) - ret = NOTIFY_STOP; - preempt_enable(); - break; - default: - break; - } - return ret; -} - -asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, - struct pt_regs *regs) -{ - BUG_ON(trap_level != 0x170 && trap_level != 0x171); - - if (user_mode(regs)) { - local_irq_enable(); - bad_trap(regs, trap_level); - return; - } - - /* trap_level == 0x170 --> ta 0x70 - * trap_level == 0x171 --> ta 0x71 - */ - if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_DEBUG_2, - (trap_level == 0x170) ? "debug" : "debug_2", - regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP) - bad_trap(regs, trap_level); -} - -/* Jprobes support. */ -int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - struct jprobe *jp = container_of(p, struct jprobe, kp); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - kcb->jprobe_saved_regs_location = regs; - memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs)); - - /* Save a whole stack frame, this gets arguments - * pushed onto the stack after using up all the - * arg registers. - */ - memcpy(&(kcb->jprobe_saved_stack), - (char *) (regs->u_regs[UREG_FP] + STACK_BIAS), - sizeof(kcb->jprobe_saved_stack)); - - regs->tpc = (unsigned long) jp->entry; - regs->tnpc = ((unsigned long) jp->entry) + 0x4UL; - regs->tstate |= TSTATE_PIL; - - return 1; -} - -void __kprobes jprobe_return(void) -{ - __asm__ __volatile__( - ".globl jprobe_return_trap_instruction\n" -"jprobe_return_trap_instruction:\n\t" - "ta 0x70"); -} - -extern void jprobe_return_trap_instruction(void); - -extern void __show_regs(struct pt_regs * regs); - -int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) -{ - u32 *addr = (u32 *) regs->tpc; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - if (addr == (u32 *) jprobe_return_trap_instruction) { - if (kcb->jprobe_saved_regs_location != regs) { - printk("JPROBE: Current regs (%p) does not match " - "saved regs (%p).\n", - regs, kcb->jprobe_saved_regs_location); - printk("JPROBE: Saved registers\n"); - __show_regs(kcb->jprobe_saved_regs_location); - printk("JPROBE: Current registers\n"); - __show_regs(regs); - BUG(); - } - /* Restore old register state. Do pt_regs - * first so that UREG_FP is the original one for - * the stack frame restore. - */ - memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs)); - - memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS), - &(kcb->jprobe_saved_stack), - sizeof(kcb->jprobe_saved_stack)); - - preempt_enable_no_resched(); - return 1; - } - return 0; -} - -/* architecture specific initialization */ -int arch_init_kprobes(void) -{ - return 0; -} diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S deleted file mode 100644 index d9244d3c9f7..00000000000 --- a/arch/sparc64/kernel/ktlb.S +++ /dev/null @@ -1,194 +0,0 @@ -/* arch/sparc64/kernel/ktlb.S: Kernel mapping TLB miss handling. - * - * Copyright (C) 1995, 1997, 2005 David S. Miller <davem@davemloft.net> - * Copyright (C) 1996 Eddie C. Dost (ecd@brainaid.de) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1996,98,99 Jakub Jelinek (jj@sunsite.mff.cuni.cz) -*/ - -#include <linux/config.h> -#include <asm/head.h> -#include <asm/asi.h> -#include <asm/page.h> -#include <asm/pgtable.h> - - .text - .align 32 - -/* - * On a second level vpte miss, check whether the original fault is to the OBP - * range (note that this is only possible for instruction miss, data misses to - * obp range do not use vpte). If so, go back directly to the faulting address. - * This is because we want to read the tpc, otherwise we have no way of knowing - * the 8k aligned faulting address if we are using >8k kernel pagesize. This - * also ensures no vpte range addresses are dropped into tlb while obp is - * executing (see inherit_locked_prom_mappings() rant). - */ -sparc64_vpte_nucleus: - /* Note that kvmap below has verified that the address is - * in the range MODULES_VADDR --> VMALLOC_END already. So - * here we need only check if it is an OBP address or not. - */ - sethi %hi(LOW_OBP_ADDRESS), %g5 - cmp %g4, %g5 - blu,pn %xcc, kern_vpte - mov 0x1, %g5 - sllx %g5, 32, %g5 - cmp %g4, %g5 - blu,pn %xcc, vpte_insn_obp - nop - - /* These two instructions are patched by paginig_init(). */ -kern_vpte: - sethi %hi(swapper_pgd_zero), %g5 - lduw [%g5 + %lo(swapper_pgd_zero)], %g5 - - /* With kernel PGD in %g5, branch back into dtlb_backend. */ - ba,pt %xcc, sparc64_kpte_continue - andn %g1, 0x3, %g1 /* Finish PMD offset adjustment. */ - -vpte_noent: - /* Restore previous TAG_ACCESS, %g5 is zero, and we will - * skip over the trap instruction so that the top level - * TLB miss handler will thing this %g5 value is just an - * invalid PTE, thus branching to full fault processing. - */ - mov TLB_SFSR, %g1 - stxa %g4, [%g1 + %g1] ASI_DMMU - done - -vpte_insn_obp: - /* Behave as if we are at TL0. */ - wrpr %g0, 1, %tl - rdpr %tpc, %g4 /* Find original faulting iaddr */ - srlx %g4, 13, %g4 /* Throw out context bits */ - sllx %g4, 13, %g4 /* g4 has vpn + ctx0 now */ - - /* Restore previous TAG_ACCESS. */ - mov TLB_SFSR, %g1 - stxa %g4, [%g1 + %g1] ASI_IMMU - - sethi %hi(prom_trans), %g5 - or %g5, %lo(prom_trans), %g5 - -1: ldx [%g5 + 0x00], %g6 ! base - brz,a,pn %g6, longpath ! no more entries, fail - mov TLB_SFSR, %g1 ! and restore %g1 - ldx [%g5 + 0x08], %g1 ! len - add %g6, %g1, %g1 ! end - cmp %g6, %g4 - bgu,pt %xcc, 2f - cmp %g4, %g1 - bgeu,pt %xcc, 2f - ldx [%g5 + 0x10], %g1 ! PTE - - /* TLB load, restore %g1, and return from trap. */ - sub %g4, %g6, %g6 - add %g1, %g6, %g5 - mov TLB_SFSR, %g1 - stxa %g5, [%g0] ASI_ITLB_DATA_IN - retry - -2: ba,pt %xcc, 1b - add %g5, (3 * 8), %g5 ! next entry - -kvmap_do_obp: - sethi %hi(prom_trans), %g5 - or %g5, %lo(prom_trans), %g5 - srlx %g4, 13, %g4 - sllx %g4, 13, %g4 - -1: ldx [%g5 + 0x00], %g6 ! base - brz,a,pn %g6, longpath ! no more entries, fail - mov TLB_SFSR, %g1 ! and restore %g1 - ldx [%g5 + 0x08], %g1 ! len - add %g6, %g1, %g1 ! end - cmp %g6, %g4 - bgu,pt %xcc, 2f - cmp %g4, %g1 - bgeu,pt %xcc, 2f - ldx [%g5 + 0x10], %g1 ! PTE - - /* TLB load, restore %g1, and return from trap. */ - sub %g4, %g6, %g6 - add %g1, %g6, %g5 - mov TLB_SFSR, %g1 - stxa %g5, [%g0] ASI_DTLB_DATA_IN - retry - -2: ba,pt %xcc, 1b - add %g5, (3 * 8), %g5 ! next entry - -/* - * On a first level data miss, check whether this is to the OBP range (note - * that such accesses can be made by prom, as well as by kernel using - * prom_getproperty on "address"), and if so, do not use vpte access ... - * rather, use information saved during inherit_prom_mappings() using 8k - * pagesize. - */ - .align 32 -kvmap: - brgez,pn %g4, kvmap_nonlinear - nop - -#ifdef CONFIG_DEBUG_PAGEALLOC - .globl kvmap_linear_patch -kvmap_linear_patch: -#endif - ba,pt %xcc, kvmap_load - xor %g2, %g4, %g5 - -#ifdef CONFIG_DEBUG_PAGEALLOC - sethi %hi(swapper_pg_dir), %g5 - or %g5, %lo(swapper_pg_dir), %g5 - sllx %g4, 64 - (PGDIR_SHIFT + PGDIR_BITS), %g6 - srlx %g6, 64 - PAGE_SHIFT, %g6 - andn %g6, 0x3, %g6 - lduw [%g5 + %g6], %g5 - brz,pn %g5, longpath - sllx %g4, 64 - (PMD_SHIFT + PMD_BITS), %g6 - srlx %g6, 64 - PAGE_SHIFT, %g6 - sllx %g5, 11, %g5 - andn %g6, 0x3, %g6 - lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brz,pn %g5, longpath - sllx %g4, 64 - PMD_SHIFT, %g6 - srlx %g6, 64 - PAGE_SHIFT, %g6 - sllx %g5, 11, %g5 - andn %g6, 0x7, %g6 - ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brz,pn %g5, longpath - nop - ba,a,pt %xcc, kvmap_load -#endif - -kvmap_nonlinear: - sethi %hi(MODULES_VADDR), %g5 - cmp %g4, %g5 - blu,pn %xcc, longpath - mov (VMALLOC_END >> 24), %g5 - sllx %g5, 24, %g5 - cmp %g4, %g5 - bgeu,pn %xcc, longpath - nop - -kvmap_check_obp: - sethi %hi(LOW_OBP_ADDRESS), %g5 - cmp %g4, %g5 - blu,pn %xcc, kvmap_vmalloc_addr - mov 0x1, %g5 - sllx %g5, 32, %g5 - cmp %g4, %g5 - blu,pn %xcc, kvmap_do_obp - nop - -kvmap_vmalloc_addr: - /* If we get here, a vmalloc addr was accessed, load kernel VPTE. */ - ldxa [%g3 + %g6] ASI_N, %g5 - brgez,pn %g5, longpath - nop - -kvmap_load: - /* PTE is valid, load into TLB and return from trap. */ - stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB - retry diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c deleted file mode 100644 index 6c83e372f75..00000000000 --- a/arch/sparc64/kernel/module.c +++ /dev/null @@ -1,209 +0,0 @@ -/* Kernel module help for sparc64. - * - * Copyright (C) 2001 Rusty Russell. - * Copyright (C) 2002 David S. Miller. - */ - -#include <linux/moduleloader.h> -#include <linux/kernel.h> -#include <linux/elf.h> -#include <linux/vmalloc.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> - -#include <asm/processor.h> -#include <asm/spitfire.h> - -static void *module_map(unsigned long size) -{ - struct vm_struct *area; - - size = PAGE_ALIGN(size); - if (!size || size > MODULES_LEN) - return NULL; - - area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); - if (!area) - return NULL; - - return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); -} - -void *module_alloc(unsigned long size) -{ - void *ret; - - /* We handle the zero case fine, unlike vmalloc */ - if (size == 0) - return NULL; - - ret = module_map(size); - if (!ret) - ret = ERR_PTR(-ENOMEM); - else - memset(ret, 0, size); - - return ret; -} - -/* Free memory returned from module_core_alloc/module_init_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ -} - -/* Make generic code ignore STT_REGISTER dummy undefined symbols. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) -{ - unsigned int symidx; - Elf64_Sym *sym; - const char *strtab; - int i; - - for (symidx = 0; sechdrs[symidx].sh_type != SHT_SYMTAB; symidx++) { - if (symidx == hdr->e_shnum-1) { - printk("%s: no symtab found.\n", mod->name); - return -ENOEXEC; - } - } - sym = (Elf64_Sym *)sechdrs[symidx].sh_addr; - strtab = (char *)sechdrs[sechdrs[symidx].sh_link].sh_addr; - - for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) { - if (sym[i].st_shndx == SHN_UNDEF && - ELF64_ST_TYPE(sym[i].st_info) == STT_REGISTER) - sym[i].st_shndx = SHN_ABS; - } - return 0; -} - -int apply_relocate(Elf64_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n", - me->name); - return -ENOEXEC; -} - -int apply_relocate_add(Elf64_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf64_Sym *sym; - u8 *location; - u32 *loc32; - - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - Elf64_Addr v; - - /* This is where to make the change */ - location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - loc32 = (u32 *) location; - - BUG_ON(((u64)location >> (u64)32) != (u64)0); - - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf64_Sym *)sechdrs[symindex].sh_addr - + ELF64_R_SYM(rel[i].r_info); - v = sym->st_value + rel[i].r_addend; - - switch (ELF64_R_TYPE(rel[i].r_info) & 0xff) { - case R_SPARC_64: - location[0] = v >> 56; - location[1] = v >> 48; - location[2] = v >> 40; - location[3] = v >> 32; - location[4] = v >> 24; - location[5] = v >> 16; - location[6] = v >> 8; - location[7] = v >> 0; - break; - - case R_SPARC_32: - location[0] = v >> 24; - location[1] = v >> 16; - location[2] = v >> 8; - location[3] = v >> 0; - break; - - case R_SPARC_WDISP30: - v -= (Elf64_Addr) location; - *loc32 = (*loc32 & ~0x3fffffff) | - ((v >> 2) & 0x3fffffff); - break; - - case R_SPARC_WDISP22: - v -= (Elf64_Addr) location; - *loc32 = (*loc32 & ~0x3fffff) | - ((v >> 2) & 0x3fffff); - break; - - case R_SPARC_WDISP19: - v -= (Elf64_Addr) location; - *loc32 = (*loc32 & ~0x7ffff) | - ((v >> 2) & 0x7ffff); - break; - - case R_SPARC_LO10: - *loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff); - break; - - case R_SPARC_HI22: - *loc32 = (*loc32 & ~0x3fffff) | - ((v >> 10) & 0x3fffff); - break; - - case R_SPARC_OLO10: - *loc32 = (*loc32 & ~0x1fff) | - (((v & 0x3ff) + - (ELF64_R_TYPE(rel[i].r_info) >> 8)) - & 0x1fff); - break; - - default: - printk(KERN_ERR "module %s: Unknown relocation: %x\n", - me->name, - (int) (ELF64_R_TYPE(rel[i].r_info) & 0xff)); - return -ENOEXEC; - }; - } - return 0; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) -{ - /* Cheetah's I-cache is fully coherent. */ - if (tlb_type == spitfire) { - unsigned long va; - - flushw_all(); - for (va = 0; va < (PAGE_SIZE << 1); va += 32) - spitfire_put_icache_tag(va, 0x0); - __asm__ __volatile__("flush %g6"); - } - - return 0; -} - -void module_arch_cleanup(struct module *mod) -{ -} diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c deleted file mode 100644 index 2ff7c32ab0c..00000000000 --- a/arch/sparc64/kernel/pci.c +++ /dev/null @@ -1,688 +0,0 @@ -/* $Id: pci.c,v 1.39 2002/01/05 01:13:43 davem Exp $ - * pci.c: UltraSparc PCI controller support. - * - * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) - * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/capability.h> -#include <linux/errno.h> -#include <linux/smp_lock.h> -#include <linux/init.h> - -#include <asm/uaccess.h> -#include <asm/pbm.h> -#include <asm/pgtable.h> -#include <asm/irq.h> -#include <asm/ebus.h> -#include <asm/isa.h> - -unsigned long pci_memspace_mask = 0xffffffffUL; - -#ifndef CONFIG_PCI -/* A "nop" PCI implementation. */ -asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - return 0; -} -asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - return 0; -} -#else - -/* List of all PCI controllers found in the system. */ -struct pci_controller_info *pci_controller_root = NULL; - -/* Each PCI controller found gets a unique index. */ -int pci_num_controllers = 0; - -/* At boot time the user can give the kernel a command - * line option which controls if and how PCI devices - * are reordered at PCI bus probing time. - */ -int pci_device_reorder = 0; - -volatile int pci_poke_in_progress; -volatile int pci_poke_cpu = -1; -volatile int pci_poke_faulted; - -static DEFINE_SPINLOCK(pci_poke_lock); - -void pci_config_read8(u8 *addr, u8 *ret) -{ - unsigned long flags; - u8 byte; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "lduba [%1] %2, %0\n\t" - "membar #Sync" - : "=r" (byte) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - if (!pci_poke_faulted) - *ret = byte; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -void pci_config_read16(u16 *addr, u16 *ret) -{ - unsigned long flags; - u16 word; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "lduha [%1] %2, %0\n\t" - "membar #Sync" - : "=r" (word) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - if (!pci_poke_faulted) - *ret = word; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -void pci_config_read32(u32 *addr, u32 *ret) -{ - unsigned long flags; - u32 dword; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "lduwa [%1] %2, %0\n\t" - "membar #Sync" - : "=r" (dword) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - if (!pci_poke_faulted) - *ret = dword; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -void pci_config_write8(u8 *addr, u8 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "stba %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -void pci_config_write16(u16 *addr, u16 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "stha %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -void pci_config_write32(u32 *addr, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "stwa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -/* Probe for all PCI controllers in the system. */ -extern void sabre_init(int, char *); -extern void psycho_init(int, char *); -extern void schizo_init(int, char *); -extern void schizo_plus_init(int, char *); -extern void tomatillo_init(int, char *); - -static struct { - char *model_name; - void (*init)(int, char *); -} pci_controller_table[] __initdata = { - { "SUNW,sabre", sabre_init }, - { "pci108e,a000", sabre_init }, - { "pci108e,a001", sabre_init }, - { "SUNW,psycho", psycho_init }, - { "pci108e,8000", psycho_init }, - { "SUNW,schizo", schizo_init }, - { "pci108e,8001", schizo_init }, - { "SUNW,schizo+", schizo_plus_init }, - { "pci108e,8002", schizo_plus_init }, - { "SUNW,tomatillo", tomatillo_init }, - { "pci108e,a801", tomatillo_init }, -}; -#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ - sizeof(pci_controller_table[0])) - -static int __init pci_controller_init(char *model_name, int namelen, int node) -{ - int i; - - for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { - if (!strncmp(model_name, - pci_controller_table[i].model_name, - namelen)) { - pci_controller_table[i].init(node, model_name); - return 1; - } - } - printk("PCI: Warning unknown controller, model name [%s]\n", - model_name); - printk("PCI: Ignoring controller...\n"); - - return 0; -} - -static int __init pci_is_controller(char *model_name, int namelen, int node) -{ - int i; - - for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { - if (!strncmp(model_name, - pci_controller_table[i].model_name, - namelen)) { - return 1; - } - } - return 0; -} - -static int __init pci_controller_scan(int (*handler)(char *, int, int)) -{ - char namebuf[64]; - int node; - int count = 0; - - node = prom_getchild(prom_root_node); - while ((node = prom_searchsiblings(node, "pci")) != 0) { - int len; - - if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 || - (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) { - int item_len = 0; - - /* Our value may be a multi-valued string in the - * case of some compatible properties. For sanity, - * only try the first one. */ - - while (namebuf[item_len] && len) { - len--; - item_len++; - } - - if (handler(namebuf, item_len, node)) - count++; - } - - node = prom_getsibling(node); - if (!node) - break; - } - - return count; -} - - -/* Is there some PCI controller in the system? */ -int __init pcic_present(void) -{ - return pci_controller_scan(pci_is_controller); -} - -/* Find each controller in the system, attach and initialize - * software state structure for each and link into the - * pci_controller_root. Setup the controller enough such - * that bus scanning can be done. - */ -static void __init pci_controller_probe(void) -{ - printk("PCI: Probing for controllers.\n"); - - pci_controller_scan(pci_controller_init); -} - -static void __init pci_scan_each_controller_bus(void) -{ - struct pci_controller_info *p; - - for (p = pci_controller_root; p; p = p->next) - p->scan_bus(p); -} - -/* Reorder the pci_dev chain, so that onboard devices come first - * and then come the pluggable cards. - */ -static void __init pci_reorder_devs(void) -{ - struct list_head *pci_onboard = &pci_devices; - struct list_head *walk = pci_onboard->next; - - while (walk != pci_onboard) { - struct pci_dev *pdev = pci_dev_g(walk); - struct list_head *walk_next = walk->next; - - if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) { - list_del(walk); - list_add(walk, pci_onboard); - } - - walk = walk_next; - } -} - -extern void clock_probe(void); -extern void power_init(void); - -static int __init pcibios_init(void) -{ - pci_controller_probe(); - if (pci_controller_root == NULL) - return 0; - - pci_scan_each_controller_bus(); - - if (pci_device_reorder) - pci_reorder_devs(); - - isa_init(); - ebus_init(); - clock_probe(); - power_init(); - - return 0; -} - -subsys_initcall(pcibios_init); - -void pcibios_fixup_bus(struct pci_bus *pbus) -{ - struct pci_pbm_info *pbm = pbus->sysdata; - - /* Generic PCI bus probing sets these to point at - * &io{port,mem}_resouce which is wrong for us. - */ - pbus->resource[0] = &pbm->io_space; - pbus->resource[1] = &pbm->mem_space; -} - -struct resource *pcibios_select_root(struct pci_dev *pdev, struct resource *r) -{ - struct pci_pbm_info *pbm = pdev->bus->sysdata; - struct resource *root = NULL; - - if (r->flags & IORESOURCE_IO) - root = &pbm->io_space; - if (r->flags & IORESOURCE_MEM) - root = &pbm->mem_space; - - return root; -} - -void pcibios_update_irq(struct pci_dev *pdev, int irq) -{ -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -int pcibios_enable_device(struct pci_dev *pdev, int mask) -{ - return 0; -} - -void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region, - struct resource *res) -{ - struct pci_pbm_info *pbm = pdev->bus->sysdata; - struct resource zero_res, *root; - - zero_res.start = 0; - zero_res.end = 0; - zero_res.flags = res->flags; - - if (res->flags & IORESOURCE_IO) - root = &pbm->io_space; - else - root = &pbm->mem_space; - - pbm->parent->resource_adjust(pdev, &zero_res, root); - - region->start = res->start - zero_res.start; - region->end = res->end - zero_res.start; -} - -void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, - struct pci_bus_region *region) -{ - struct pci_pbm_info *pbm = pdev->bus->sysdata; - struct resource *root; - - res->start = region->start; - res->end = region->end; - - if (res->flags & IORESOURCE_IO) - root = &pbm->io_space; - else - root = &pbm->mem_space; - - pbm->parent->resource_adjust(pdev, res, root); -} -EXPORT_SYMBOL(pcibios_bus_to_resource); - -char * __init pcibios_setup(char *str) -{ - if (!strcmp(str, "onboardfirst")) { - pci_device_reorder = 1; - return NULL; - } - if (!strcmp(str, "noreorder")) { - pci_device_reorder = 0; - return NULL; - } - return str; -} - -/* Platform support for /proc/bus/pci/X/Y mmap()s. */ - -/* If the user uses a host-bridge as the PCI device, he may use - * this to perform a raw mmap() of the I/O or MEM space behind - * that controller. - * - * This can be useful for execution of x86 PCI bios initialization code - * on a PCI card, like the xfree86 int10 stuff does. - */ -static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm; - struct pci_controller_info *p; - unsigned long space_size, user_offset, user_size; - - if (!pcp) - return -ENXIO; - pbm = pcp->pbm; - if (!pbm) - return -ENXIO; - - p = pbm->parent; - if (p->pbms_same_domain) { - unsigned long lowest, highest; - - lowest = ~0UL; highest = 0UL; - if (mmap_state == pci_mmap_io) { - if (p->pbm_A.io_space.flags) { - lowest = p->pbm_A.io_space.start; - highest = p->pbm_A.io_space.end + 1; - } - if (p->pbm_B.io_space.flags) { - if (lowest > p->pbm_B.io_space.start) - lowest = p->pbm_B.io_space.start; - if (highest < p->pbm_B.io_space.end + 1) - highest = p->pbm_B.io_space.end + 1; - } - space_size = highest - lowest; - } else { - if (p->pbm_A.mem_space.flags) { - lowest = p->pbm_A.mem_space.start; - highest = p->pbm_A.mem_space.end + 1; - } - if (p->pbm_B.mem_space.flags) { - if (lowest > p->pbm_B.mem_space.start) - lowest = p->pbm_B.mem_space.start; - if (highest < p->pbm_B.mem_space.end + 1) - highest = p->pbm_B.mem_space.end + 1; - } - space_size = highest - lowest; - } - } else { - if (mmap_state == pci_mmap_io) { - space_size = (pbm->io_space.end - - pbm->io_space.start) + 1; - } else { - space_size = (pbm->mem_space.end - - pbm->mem_space.start) + 1; - } - } - - /* Make sure the request is in range. */ - user_offset = vma->vm_pgoff << PAGE_SHIFT; - user_size = vma->vm_end - vma->vm_start; - - if (user_offset >= space_size || - (user_offset + user_size) > space_size) - return -EINVAL; - - if (p->pbms_same_domain) { - unsigned long lowest = ~0UL; - - if (mmap_state == pci_mmap_io) { - if (p->pbm_A.io_space.flags) - lowest = p->pbm_A.io_space.start; - if (p->pbm_B.io_space.flags && - lowest > p->pbm_B.io_space.start) - lowest = p->pbm_B.io_space.start; - } else { - if (p->pbm_A.mem_space.flags) - lowest = p->pbm_A.mem_space.start; - if (p->pbm_B.mem_space.flags && - lowest > p->pbm_B.mem_space.start) - lowest = p->pbm_B.mem_space.start; - } - vma->vm_pgoff = (lowest + user_offset) >> PAGE_SHIFT; - } else { - if (mmap_state == pci_mmap_io) { - vma->vm_pgoff = (pbm->io_space.start + - user_offset) >> PAGE_SHIFT; - } else { - vma->vm_pgoff = (pbm->mem_space.start + - user_offset) >> PAGE_SHIFT; - } - } - - return 0; -} - -/* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding - * to the 32-bit pci bus offset for DEV requested by the user. - * - * Basically, the user finds the base address for his device which he wishes - * to mmap. They read the 32-bit value from the config space base register, - * add whatever PAGE_SIZE multiple offset they wish, and feed this into the - * offset parameter of mmap on /proc/bus/pci/XXX for that device. - * - * Returns negative error code on failure, zero on success. - */ -static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) -{ - unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT; - unsigned long user32 = user_offset & pci_memspace_mask; - unsigned long largest_base, this_base, addr32; - int i; - - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) - return __pci_mmap_make_offset_bus(dev, vma, mmap_state); - - /* Figure out which base address this is for. */ - largest_base = 0UL; - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *rp = &dev->resource[i]; - - /* Active? */ - if (!rp->flags) - continue; - - /* Same type? */ - if (i == PCI_ROM_RESOURCE) { - if (mmap_state != pci_mmap_mem) - continue; - } else { - if ((mmap_state == pci_mmap_io && - (rp->flags & IORESOURCE_IO) == 0) || - (mmap_state == pci_mmap_mem && - (rp->flags & IORESOURCE_MEM) == 0)) - continue; - } - - this_base = rp->start; - - addr32 = (this_base & PAGE_MASK) & pci_memspace_mask; - - if (mmap_state == pci_mmap_io) - addr32 &= 0xffffff; - - if (addr32 <= user32 && this_base > largest_base) - largest_base = this_base; - } - - if (largest_base == 0UL) - return -EINVAL; - - /* Now construct the final physical address. */ - if (mmap_state == pci_mmap_io) - vma->vm_pgoff = (((largest_base & ~0xffffffUL) | user32) >> PAGE_SHIFT); - else - vma->vm_pgoff = (((largest_base & ~(pci_memspace_mask)) | user32) >> PAGE_SHIFT); - - return 0; -} - -/* Set vm_flags of VMA, as appropriate for this architecture, for a pci device - * mapping. - */ -static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) -{ - vma->vm_flags |= (VM_IO | VM_RESERVED); -} - -/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci - * device mapping. - */ -static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) -{ - /* Our io_remap_pfn_range takes care of this, do nothing. */ -} - -/* Perform the actual remap of the pages for a PCI device mapping, as appropriate - * for this architecture. The region in the process to map is described by vm_start - * and vm_end members of VMA, the base physical address is found in vm_pgoff. - * The pci device structure is provided so that architectures may make mapping - * decisions on a per-device or per-bus basis. - * - * Returns a negative error code on failure, zero on success. - */ -int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, - int write_combine) -{ - int ret; - - ret = __pci_mmap_make_offset(dev, vma, mmap_state); - if (ret < 0) - return ret; - - __pci_mmap_set_flags(dev, vma, mmap_state); - __pci_mmap_set_pgprot(dev, vma, mmap_state); - - ret = io_remap_pfn_range(vma, vma->vm_start, - vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - if (ret) - return ret; - - vma->vm_flags |= VM_IO; - return 0; -} - -/* Return the domain nuber for this pci bus */ - -int pci_domain_nr(struct pci_bus *pbus) -{ - struct pci_pbm_info *pbm = pbus->sysdata; - int ret; - - if (pbm == NULL || pbm->parent == NULL) { - ret = -ENXIO; - } else { - struct pci_controller_info *p = pbm->parent; - - ret = p->index; - if (p->pbms_same_domain == 0) - ret = ((ret << 1) + - ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); - } - - return ret; -} -EXPORT_SYMBOL(pci_domain_nr); - -int pcibios_prep_mwi(struct pci_dev *dev) -{ - /* We set correct PCI_CACHE_LINE_SIZE register values for every - * device probed on this platform. So there is nothing to check - * and this always succeeds. - */ - return 0; -} - -#endif /* !(CONFIG_PCI) */ diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c deleted file mode 100644 index 58310aacea2..00000000000 --- a/arch/sparc64/kernel/pci_common.c +++ /dev/null @@ -1,1040 +0,0 @@ -/* $Id: pci_common.c,v 1.29 2002/02/01 00:56:03 davem Exp $ - * pci_common.c: PCI controller common support. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/init.h> - -#include <asm/pbm.h> - -/* Fix self device of BUS and hook it into BUS->self. - * The pci_scan_bus does not do this for the host bridge. - */ -void __init pci_fixup_host_bridge_self(struct pci_bus *pbus) -{ - struct pci_dev *pdev; - - list_for_each_entry(pdev, &pbus->devices, bus_list) { - if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) { - pbus->self = pdev; - return; - } - } - - prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n"); - prom_halt(); -} - -/* Find the OBP PROM device tree node for a PCI device. - * Return zero if not found. - */ -static int __init find_device_prom_node(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - int bus_prom_node, - struct linux_prom_pci_registers *pregs, - int *nregs) -{ - int node; - - /* - * Return the PBM's PROM node in case we are it's PCI device, - * as the PBM's reg property is different to standard PCI reg - * properties. We would delete this device entry otherwise, - * which confuses XFree86's device probing... - */ - if ((pdev->bus->number == pbm->pci_bus->number) && (pdev->devfn == 0) && - (pdev->vendor == PCI_VENDOR_ID_SUN) && - (pdev->device == PCI_DEVICE_ID_SUN_PBM || - pdev->device == PCI_DEVICE_ID_SUN_SCHIZO || - pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO || - pdev->device == PCI_DEVICE_ID_SUN_SABRE || - pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) { - *nregs = 0; - return bus_prom_node; - } - - node = prom_getchild(bus_prom_node); - while (node != 0) { - int err = prom_getproperty(node, "reg", - (char *)pregs, - sizeof(*pregs) * PROMREG_MAX); - if (err == 0 || err == -1) - goto do_next_sibling; - if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { - *nregs = err / sizeof(*pregs); - return node; - } - - do_next_sibling: - node = prom_getsibling(node); - } - return 0; -} - -/* Older versions of OBP on PCI systems encode 64-bit MEM - * space assignments incorrectly, this fixes them up. We also - * take the opportunity here to hide other kinds of bogus - * assignments. - */ -static void __init fixup_obp_assignments(struct pci_dev *pdev, - struct pcidev_cookie *pcp) -{ - int i; - - if (pdev->vendor == PCI_VENDOR_ID_AL && - (pdev->device == PCI_DEVICE_ID_AL_M7101 || - pdev->device == PCI_DEVICE_ID_AL_M1533)) { - int i; - - /* Zap all of the normal resources, they are - * meaningless and generate bogus resource collision - * messages. This is OpenBoot's ill-fated attempt to - * represent the implicit resources that these devices - * have. - */ - pcp->num_prom_assignments = 0; - for (i = 0; i < 6; i++) { - pdev->resource[i].start = - pdev->resource[i].end = - pdev->resource[i].flags = 0; - } - pdev->resource[PCI_ROM_RESOURCE].start = - pdev->resource[PCI_ROM_RESOURCE].end = - pdev->resource[PCI_ROM_RESOURCE].flags = 0; - return; - } - - for (i = 0; i < pcp->num_prom_assignments; i++) { - struct linux_prom_pci_registers *ap; - int space; - - ap = &pcp->prom_assignments[i]; - space = ap->phys_hi >> 24; - if ((space & 0x3) == 2 && - (space & 0x4) != 0) { - ap->phys_hi &= ~(0x7 << 24); - ap->phys_hi |= 0x3 << 24; - } - } -} - -/* Fill in the PCI device cookie sysdata for the given - * PCI device. This cookie is the means by which one - * can get to OBP and PCI controller specific information - * for a PCI device. - */ -static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - int bus_prom_node) -{ - struct linux_prom_pci_registers pregs[PROMREG_MAX]; - struct pcidev_cookie *pcp; - int device_prom_node, nregs, err; - - device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node, - pregs, &nregs); - if (device_prom_node == 0) { - /* If it is not in the OBP device tree then - * there must be a damn good reason for it. - * - * So what we do is delete the device from the - * PCI device tree completely. This scenario - * is seen, for example, on CP1500 for the - * second EBUS/HappyMeal pair if the external - * connector for it is not present. - */ - pci_remove_bus_device(pdev); - return; - } - - pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC); - if (pcp == NULL) { - prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n"); - prom_halt(); - } - pcp->pbm = pbm; - pcp->prom_node = device_prom_node; - memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs)); - pcp->num_prom_regs = nregs; - err = prom_getproperty(device_prom_node, "name", - pcp->prom_name, sizeof(pcp->prom_name)); - if (err > 0) - pcp->prom_name[err] = 0; - else - pcp->prom_name[0] = 0; - - err = prom_getproperty(device_prom_node, - "assigned-addresses", - (char *)pcp->prom_assignments, - sizeof(pcp->prom_assignments)); - if (err == 0 || err == -1) - pcp->num_prom_assignments = 0; - else - pcp->num_prom_assignments = - (err / sizeof(pcp->prom_assignments[0])); - - if (strcmp(pcp->prom_name, "ebus") == 0) { - struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX]; - int iter; - - /* EBUS is special... */ - err = prom_getproperty(device_prom_node, "ranges", - (char *)&erng[0], sizeof(erng)); - if (err == 0 || err == -1) { - prom_printf("EBUS: Fatal error, no range property\n"); - prom_halt(); - } - err = (err / sizeof(erng[0])); - for(iter = 0; iter < err; iter++) { - struct linux_prom_ebus_ranges *ep = &erng[iter]; - struct linux_prom_pci_registers *ap; - - ap = &pcp->prom_assignments[iter]; - - ap->phys_hi = ep->parent_phys_hi; - ap->phys_mid = ep->parent_phys_mid; - ap->phys_lo = ep->parent_phys_lo; - ap->size_hi = 0; - ap->size_lo = ep->size; - } - pcp->num_prom_assignments = err; - } - - fixup_obp_assignments(pdev, pcp); - - pdev->sysdata = pcp; -} - -void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, - struct pci_pbm_info *pbm, - int prom_node) -{ - struct pci_dev *pdev, *pdev_next; - struct pci_bus *this_pbus, *pbus_next; - - /* This must be _safe because the cookie fillin - routine can delete devices from the tree. */ - list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list) - pdev_cookie_fillin(pbm, pdev, prom_node); - - list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { - struct pcidev_cookie *pcp = this_pbus->self->sysdata; - - pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node); - } -} - -static void __init bad_assignment(struct pci_dev *pdev, - struct linux_prom_pci_registers *ap, - struct resource *res, - int do_prom_halt) -{ - prom_printf("PCI: Bogus PROM assignment. BUS[%02x] DEVFN[%x]\n", - pdev->bus->number, pdev->devfn); - if (ap) - prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n", - ap->phys_hi, ap->phys_mid, ap->phys_lo, - ap->size_hi, ap->size_lo); - if (res) - prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n", - res->start, res->end, res->flags); - prom_printf("Please email this information to davem@redhat.com\n"); - if (do_prom_halt) - prom_halt(); -} - -static struct resource * -__init get_root_resource(struct linux_prom_pci_registers *ap, - struct pci_pbm_info *pbm) -{ - int space = (ap->phys_hi >> 24) & 3; - - switch (space) { - case 0: - /* Configuration space, silently ignore it. */ - return NULL; - - case 1: - /* 16-bit IO space */ - return &pbm->io_space; - - case 2: - /* 32-bit MEM space */ - return &pbm->mem_space; - - case 3: - /* 64-bit MEM space, these are allocated out of - * the 32-bit mem_space range for the PBM, ie. - * we just zero out the upper 32-bits. - */ - return &pbm->mem_space; - - default: - printk("PCI: What is resource space %x? " - "Tell davem@redhat.com about it!\n", space); - return NULL; - }; -} - -static struct resource * -__init get_device_resource(struct linux_prom_pci_registers *ap, - struct pci_dev *pdev) -{ - struct resource *res; - int breg = (ap->phys_hi & 0xff); - - switch (breg) { - case PCI_ROM_ADDRESS: - /* Unfortunately I have seen several cases where - * buggy FCODE uses a space value of '1' (I/O space) - * in the register property for the ROM address - * so disable this sanity check for now. - */ -#if 0 - { - int space = (ap->phys_hi >> 24) & 3; - - /* It had better be MEM space. */ - if (space != 2) - bad_assignment(pdev, ap, NULL, 0); - } -#endif - res = &pdev->resource[PCI_ROM_RESOURCE]; - break; - - case PCI_BASE_ADDRESS_0: - case PCI_BASE_ADDRESS_1: - case PCI_BASE_ADDRESS_2: - case PCI_BASE_ADDRESS_3: - case PCI_BASE_ADDRESS_4: - case PCI_BASE_ADDRESS_5: - res = &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4]; - break; - - default: - bad_assignment(pdev, ap, NULL, 0); - res = NULL; - break; - }; - - return res; -} - -static int __init pdev_resource_collisions_expected(struct pci_dev *pdev) -{ - if (pdev->vendor != PCI_VENDOR_ID_SUN) - return 0; - - if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS || - pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 || - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 1; - - return 0; -} - -static void __init pdev_record_assignments(struct pci_pbm_info *pbm, - struct pci_dev *pdev) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - int i; - - for (i = 0; i < pcp->num_prom_assignments; i++) { - struct linux_prom_pci_registers *ap; - struct resource *root, *res; - - /* The format of this property is specified in - * the PCI Bus Binding to IEEE1275-1994. - */ - ap = &pcp->prom_assignments[i]; - root = get_root_resource(ap, pbm); - res = get_device_resource(ap, pdev); - if (root == NULL || res == NULL || - res->flags == 0) - continue; - - /* Ok we know which resource this PROM assignment is - * for, sanity check it. - */ - if ((res->start & 0xffffffffUL) != ap->phys_lo) - bad_assignment(pdev, ap, res, 1); - - /* If it is a 64-bit MEM space assignment, verify that - * the resource is too and that the upper 32-bits match. - */ - if (((ap->phys_hi >> 24) & 3) == 3) { - if (((res->flags & IORESOURCE_MEM) == 0) || - ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - != PCI_BASE_ADDRESS_MEM_TYPE_64)) - bad_assignment(pdev, ap, res, 1); - if ((res->start >> 32) != ap->phys_mid) - bad_assignment(pdev, ap, res, 1); - - /* PBM cannot generate cpu initiated PIOs - * to the full 64-bit space. Therefore the - * upper 32-bits better be zero. If it is - * not, just skip it and we will assign it - * properly ourselves. - */ - if ((res->start >> 32) != 0UL) { - printk(KERN_ERR "PCI: OBP assigns out of range MEM address " - "%016lx for region %ld on device %s\n", - res->start, (res - &pdev->resource[0]), pci_name(pdev)); - continue; - } - } - - /* Adjust the resource into the physical address space - * of this PBM. - */ - pbm->parent->resource_adjust(pdev, res, root); - - if (request_resource(root, res) < 0) { - /* OK, there is some conflict. But this is fine - * since we'll reassign it in the fixup pass. - * - * We notify the user that OBP made an error if it - * is a case we don't expect. - */ - if (!pdev_resource_collisions_expected(pdev)) { - printk(KERN_ERR "PCI: Address space collision on region %ld " - "[%016lx:%016lx] of device %s\n", - (res - &pdev->resource[0]), - res->start, res->end, - pci_name(pdev)); - } - } - } -} - -void __init pci_record_assignments(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_record_assignments(pbm, dev); - - list_for_each_entry(bus, &pbus->children, node) - pci_record_assignments(pbm, bus); -} - -/* Return non-zero if PDEV has implicit I/O resources even - * though it may not have an I/O base address register - * active. - */ -static int __init has_implicit_io(struct pci_dev *pdev) -{ - int class = pdev->class >> 8; - - if (class == PCI_CLASS_NOT_DEFINED || - class == PCI_CLASS_NOT_DEFINED_VGA || - class == PCI_CLASS_STORAGE_IDE || - (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) - return 1; - - return 0; -} - -static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_dev *pdev) -{ - u32 reg; - u16 cmd; - int i, io_seen, mem_seen; - - io_seen = mem_seen = 0; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *root, *res; - unsigned long size, min, max, align; - - res = &pdev->resource[i]; - - if (res->flags & IORESOURCE_IO) - io_seen++; - else if (res->flags & IORESOURCE_MEM) - mem_seen++; - - /* If it is already assigned or the resource does - * not exist, there is nothing to do. - */ - if (res->parent != NULL || res->flags == 0UL) - continue; - - /* Determine the root we allocate from. */ - if (res->flags & IORESOURCE_IO) { - root = &pbm->io_space; - min = root->start + 0x400UL; - max = root->end; - } else { - root = &pbm->mem_space; - min = root->start; - max = min + 0x80000000UL; - } - - size = res->end - res->start; - align = size + 1; - if (allocate_resource(root, res, size + 1, min, max, align, NULL, NULL) < 0) { - /* uh oh */ - prom_printf("PCI: Failed to allocate resource %d for %s\n", - i, pci_name(pdev)); - prom_halt(); - } - - /* Update PCI config space. */ - pbm->parent->base_address_update(pdev, i); - } - - /* Special case, disable the ROM. Several devices - * act funny (ie. do not respond to memory space writes) - * when it is left enabled. A good example are Qlogic,ISP - * adapters. - */ - pci_read_config_dword(pdev, PCI_ROM_ADDRESS, ®); - reg &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(pdev, PCI_ROM_ADDRESS, reg); - - /* If we saw I/O or MEM resources, enable appropriate - * bits in PCI command register. - */ - if (io_seen || mem_seen) { - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (io_seen || has_implicit_io(pdev)) - cmd |= PCI_COMMAND_IO; - if (mem_seen) - cmd |= PCI_COMMAND_MEMORY; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - } - - /* If this is a PCI bridge or an IDE controller, - * enable bus mastering. In the former case also - * set the cache line size correctly. - */ - if (((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) || - (((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) && - ((pdev->class & 0x80) != 0))) { - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) - pci_write_config_byte(pdev, - PCI_CACHE_LINE_SIZE, - (64 / sizeof(u32))); - } -} - -void __init pci_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_assign_unassigned(pbm, dev); - - list_for_each_entry(bus, &pbus->children, node) - pci_assign_unassigned(pbm, bus); -} - -static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt) -{ - struct linux_prom_pci_intmap bridge_local_intmap[PROM_PCIIMAP_MAX], *intmap; - struct linux_prom_pci_intmask bridge_local_intmask, *intmask; - struct pcidev_cookie *dev_pcp = pdev->sysdata; - struct pci_pbm_info *pbm = dev_pcp->pbm; - struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs; - unsigned int hi, mid, lo, irq; - int i, num_intmap, map_slot; - - intmap = &pbm->pbm_intmap[0]; - intmask = &pbm->pbm_intmask; - num_intmap = pbm->num_pbm_intmap; - map_slot = 0; - - /* If we are underneath a PCI bridge, use PROM register - * property of the parent bridge which is closest to - * the PBM. - * - * However if that parent bridge has interrupt map/mask - * properties of its own we use the PROM register property - * of the next child device on the path to PDEV. - * - * In detail the two cases are (note that the 'X' below is the - * 'next child on the path to PDEV' mentioned above): - * - * 1) PBM --> PCI bus lacking int{map,mask} --> X ... PDEV - * - * Here we use regs of 'PCI bus' device. - * - * 2) PBM --> PCI bus with int{map,mask} --> X ... PDEV - * - * Here we use regs of 'X'. Note that X can be PDEV. - */ - if (pdev->bus->number != pbm->pci_first_busno) { - struct pcidev_cookie *bus_pcp, *regs_pcp; - struct pci_dev *bus_dev, *regs_dev; - int plen; - - bus_dev = pdev->bus->self; - regs_dev = pdev; - - while (bus_dev->bus && - bus_dev->bus->number != pbm->pci_first_busno) { - regs_dev = bus_dev; - bus_dev = bus_dev->bus->self; - } - - regs_pcp = regs_dev->sysdata; - pregs = regs_pcp->prom_regs; - - bus_pcp = bus_dev->sysdata; - - /* But if the PCI bridge has it's own interrupt map - * and mask properties, use that and the regs of the - * PCI entity at the next level down on the path to the - * device. - */ - plen = prom_getproperty(bus_pcp->prom_node, "interrupt-map", - (char *) &bridge_local_intmap[0], - sizeof(bridge_local_intmap)); - if (plen != -1) { - intmap = &bridge_local_intmap[0]; - num_intmap = plen / sizeof(struct linux_prom_pci_intmap); - plen = prom_getproperty(bus_pcp->prom_node, - "interrupt-map-mask", - (char *) &bridge_local_intmask, - sizeof(bridge_local_intmask)); - if (plen == -1) { - printk("pci_intmap_match: Warning! Bridge has intmap " - "but no intmask.\n"); - printk("pci_intmap_match: Trying to recover.\n"); - return 0; - } - - if (pdev->bus->self != bus_dev) - map_slot = 1; - } else { - pregs = bus_pcp->prom_regs; - map_slot = 1; - } - } - - if (map_slot) { - *interrupt = ((*interrupt - - 1 - + PCI_SLOT(pdev->devfn)) & 0x3) + 1; - } - - hi = pregs->phys_hi & intmask->phys_hi; - mid = pregs->phys_mid & intmask->phys_mid; - lo = pregs->phys_lo & intmask->phys_lo; - irq = *interrupt & intmask->interrupt; - - for (i = 0; i < num_intmap; i++) { - if (intmap[i].phys_hi == hi && - intmap[i].phys_mid == mid && - intmap[i].phys_lo == lo && - intmap[i].interrupt == irq) { - *interrupt = intmap[i].cinterrupt; - printk("PCI-IRQ: Routing bus[%2x] slot[%2x] map[%d] to INO[%02x]\n", - pdev->bus->number, PCI_SLOT(pdev->devfn), - map_slot, *interrupt); - return 1; - } - } - - /* We will run this code even if pbm->num_pbm_intmap is zero, just so - * we can apply the slot mapping to the PROM interrupt property value. - * So do not spit out these warnings in that case. - */ - if (num_intmap != 0) { - /* Print it both to OBP console and kernel one so that if bootup - * hangs here the user has the information to report. - */ - prom_printf("pci_intmap_match: bus %02x, devfn %02x: ", - pdev->bus->number, pdev->devfn); - prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n", - pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt); - prom_printf("Please email this information to davem@redhat.com\n"); - - printk("pci_intmap_match: bus %02x, devfn %02x: ", - pdev->bus->number, pdev->devfn); - printk("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n", - pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt); - printk("Please email this information to davem@redhat.com\n"); - } - - return 0; -} - -static void __init pdev_fixup_irq(struct pci_dev *pdev) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct pci_controller_info *p = pbm->parent; - unsigned int portid = pbm->portid; - unsigned int prom_irq; - int prom_node = pcp->prom_node; - int err; - - /* If this is an empty EBUS device, sometimes OBP fails to - * give it a valid fully specified interrupts property. - * The EBUS hooked up to SunHME on PCI I/O boards of - * Ex000 systems is one such case. - * - * The interrupt is not important so just ignore it. - */ - if (pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_EBUS && - !prom_getchild(prom_node)) { - pdev->irq = 0; - return; - } - - err = prom_getproperty(prom_node, "interrupts", - (char *)&prom_irq, sizeof(prom_irq)); - if (err == 0 || err == -1) { - pdev->irq = 0; - return; - } - - /* Fully specified already? */ - if (((prom_irq & PCI_IRQ_IGN) >> 6) == portid) { - pdev->irq = p->irq_build(pbm, pdev, prom_irq); - goto have_irq; - } - - /* An onboard device? (bit 5 set) */ - if ((prom_irq & PCI_IRQ_INO) & 0x20) { - pdev->irq = p->irq_build(pbm, pdev, (portid << 6 | prom_irq)); - goto have_irq; - } - - /* Can we find a matching entry in the interrupt-map? */ - if (pci_intmap_match(pdev, &prom_irq)) { - pdev->irq = p->irq_build(pbm, pdev, (portid << 6) | prom_irq); - goto have_irq; - } - - /* Ok, we have to do it the hard way. */ - { - unsigned int bus, slot, line; - - bus = (pbm == &pbm->parent->pbm_B) ? (1 << 4) : 0; - - /* If we have a legal interrupt property, use it as - * the IRQ line. - */ - if (prom_irq > 0 && prom_irq < 5) { - line = ((prom_irq - 1) & 3); - } else { - u8 pci_irq_line; - - /* Else just directly consult PCI config space. */ - pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pci_irq_line); - line = ((pci_irq_line - 1) & 3); - } - - /* Now figure out the slot. - * - * Basically, device number zero on the top-level bus is - * always the PCI host controller. Slot 0 is then device 1. - * PBM A supports two external slots (0 and 1), and PBM B - * supports 4 external slots (0, 1, 2, and 3). On-board PCI - * devices are wired to device numbers outside of these - * ranges. -DaveM - */ - if (pdev->bus->number == pbm->pci_first_busno) { - slot = PCI_SLOT(pdev->devfn) - pbm->pci_first_slot; - } else { - struct pci_dev *bus_dev; - - /* Underneath a bridge, use slot number of parent - * bridge which is closest to the PBM. - */ - bus_dev = pdev->bus->self; - while (bus_dev->bus && - bus_dev->bus->number != pbm->pci_first_busno) - bus_dev = bus_dev->bus->self; - - slot = PCI_SLOT(bus_dev->devfn) - pbm->pci_first_slot; - } - slot = slot << 2; - - pdev->irq = p->irq_build(pbm, pdev, - ((portid << 6) & PCI_IRQ_IGN) | - (bus | slot | line)); - } - -have_irq: - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, - pdev->irq & PCI_IRQ_INO); -} - -void __init pci_fixup_irq(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_fixup_irq(dev); - - list_for_each_entry(bus, &pbus->children, node) - pci_fixup_irq(pbm, bus); -} - -static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz) -{ - u16 cmd; - u8 hdr_type, min_gnt, ltimer; - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - /* Read it back, if the mastering bit did not - * get set, the device does not support bus - * mastering so we have nothing to do here. - */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if ((cmd & PCI_COMMAND_MASTER) == 0) - return; - - /* Set correct cache line size, 64-byte on all - * Sparc64 PCI systems. Note that the value is - * measured in 32-bit words. - */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, - 64 / sizeof(u32)); - - pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr_type); - hdr_type &= ~0x80; - if (hdr_type != PCI_HEADER_TYPE_NORMAL) - return; - - /* If the latency timer is already programmed with a non-zero - * value, assume whoever set it (OBP or whoever) knows what - * they are doing. - */ - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, <imer); - if (ltimer != 0) - return; - - /* XXX Since I'm tipping off the min grant value to - * XXX choose a suitable latency timer value, I also - * XXX considered making use of the max latency value - * XXX as well. Unfortunately I've seen too many bogusly - * XXX low settings for it to the point where it lacks - * XXX any usefulness. In one case, an ethernet card - * XXX claimed a min grant of 10 and a max latency of 5. - * XXX Now, if I had two such cards on the same bus I - * XXX could not set the desired burst period (calculated - * XXX from min grant) without violating the max latency - * XXX bound. Duh... - * XXX - * XXX I blame dumb PC bios implementors for stuff like - * XXX this, most of them don't even try to do something - * XXX sensible with latency timer values and just set some - * XXX default value (usually 32) into every device. - */ - - pci_read_config_byte(pdev, PCI_MIN_GNT, &min_gnt); - - if (min_gnt == 0) { - /* If no min_gnt setting then use a default - * value. - */ - if (is_66mhz) - ltimer = 16; - else - ltimer = 32; - } else { - int shift_factor; - - if (is_66mhz) - shift_factor = 2; - else - shift_factor = 3; - - /* Use a default value when the min_gnt value - * is erroneously high. - */ - if (((unsigned int) min_gnt << shift_factor) > 512 || - ((min_gnt << shift_factor) & 0xff) == 0) { - ltimer = 8 << shift_factor; - } else { - ltimer = min_gnt << shift_factor; - } - } - - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ltimer); -} - -void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *pdev; - int all_are_66mhz; - u16 status; - - if (pbm->is_66mhz_capable == 0) { - all_are_66mhz = 0; - goto out; - } - - all_are_66mhz = 1; - list_for_each_entry(pdev, &pbus->devices, bus_list) { - pci_read_config_word(pdev, PCI_STATUS, &status); - if (!(status & PCI_STATUS_66MHZ)) { - all_are_66mhz = 0; - break; - } - } -out: - pbm->all_devs_66mhz = all_are_66mhz; - - printk("PCI%d(PBM%c): Bus running at %dMHz\n", - pbm->parent->index, - (pbm == &pbm->parent->pbm_A) ? 'A' : 'B', - (all_are_66mhz ? 66 : 33)); -} - -void pci_setup_busmastering(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - int is_66mhz; - - is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_setup_busmastering(dev, is_66mhz); - - list_for_each_entry(bus, &pbus->children, node) - pci_setup_busmastering(pbm, bus); -} - -void pci_register_legacy_regions(struct resource *io_res, - struct resource *mem_res) -{ - struct resource *p; - - /* VGA Video RAM. */ - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return; - - memset(p, 0, sizeof(*p)); - p->name = "Video RAM area"; - p->start = mem_res->start + 0xa0000UL; - p->end = p->start + 0x1ffffUL; - p->flags = IORESOURCE_BUSY; - request_resource(mem_res, p); - - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return; - - memset(p, 0, sizeof(*p)); - p->name = "System ROM"; - p->start = mem_res->start + 0xf0000UL; - p->end = p->start + 0xffffUL; - p->flags = IORESOURCE_BUSY; - request_resource(mem_res, p); - - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return; - - memset(p, 0, sizeof(*p)); - p->name = "Video ROM"; - p->start = mem_res->start + 0xc0000UL; - p->end = p->start + 0x7fffUL; - p->flags = IORESOURCE_BUSY; - request_resource(mem_res, p); -} - -/* Generic helper routines for PCI error reporting. */ -void pci_scan_for_target_abort(struct pci_controller_info *p, - struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *pdev; - struct pci_bus *bus; - - list_for_each_entry(pdev, &pbus->devices, bus_list) { - u16 status, error_bits; - - pci_read_config_word(pdev, PCI_STATUS, &status); - error_bits = - (status & (PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT)); - if (error_bits) { - pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n", - p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pci_name(pdev), status); - } - } - - list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_target_abort(p, pbm, bus); -} - -void pci_scan_for_master_abort(struct pci_controller_info *p, - struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *pdev; - struct pci_bus *bus; - - list_for_each_entry(pdev, &pbus->devices, bus_list) { - u16 status, error_bits; - - pci_read_config_word(pdev, PCI_STATUS, &status); - error_bits = - (status & (PCI_STATUS_REC_MASTER_ABORT)); - if (error_bits) { - pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n", - p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pci_name(pdev), status); - } - } - - list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_master_abort(p, pbm, bus); -} - -void pci_scan_for_parity_error(struct pci_controller_info *p, - struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *pdev; - struct pci_bus *bus; - - list_for_each_entry(pdev, &pbus->devices, bus_list) { - u16 status, error_bits; - - pci_read_config_word(pdev, PCI_STATUS, &status); - error_bits = - (status & (PCI_STATUS_PARITY | - PCI_STATUS_DETECTED_PARITY)); - if (error_bits) { - pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n", - p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pci_name(pdev), status); - } - } - - list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_parity_error(p, pbm, bus); -} diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h deleted file mode 100644 index 6c320596254..00000000000 --- a/arch/sparc64/kernel/pci_impl.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: pci_impl.h,v 1.9 2001/06/13 06:34:30 davem Exp $ - * pci_impl.h: Helper definitions for PCI controller support. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#ifndef PCI_IMPL_H -#define PCI_IMPL_H - -#include <linux/types.h> -#include <linux/spinlock.h> -#include <asm/io.h> - -extern struct pci_controller_info *pci_controller_root; - -extern int pci_num_controllers; - -/* PCI bus scanning and fixup support. */ -extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); -extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, - struct pci_pbm_info *pbm, - int prom_node); -extern void pci_record_assignments(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_fixup_irq(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_setup_busmastering(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_register_legacy_regions(struct resource *io_res, - struct resource *mem_res); - -/* Error reporting support. */ -extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); -extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); -extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); - -/* Configuration space access. */ -extern void pci_config_read8(u8 *addr, u8 *ret); -extern void pci_config_read16(u16 *addr, u16 *ret); -extern void pci_config_read32(u32 *addr, u32 *ret); -extern void pci_config_write8(u8 *addr, u8 val); -extern void pci_config_write16(u16 *addr, u16 val); -extern void pci_config_write32(u32 *addr, u32 val); - -#endif /* !(PCI_IMPL_H) */ diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c deleted file mode 100644 index a11910be101..00000000000 --- a/arch/sparc64/kernel/pci_iommu.c +++ /dev/null @@ -1,825 +0,0 @@ -/* $Id: pci_iommu.c,v 1.17 2001/12/17 07:05:09 davem Exp $ - * pci_iommu.c: UltraSparc PCI controller IOM/STC support. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/delay.h> - -#include <asm/pbm.h> - -#include "iommu_common.h" - -#define PCI_STC_CTXMATCH_ADDR(STC, CTX) \ - ((STC)->strbuf_ctxmatch_base + ((CTX) << 3)) - -/* Accessing IOMMU and Streaming Buffer registers. - * REG parameter is a physical address. All registers - * are 64-bits in size. - */ -#define pci_iommu_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define pci_iommu_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E)) - -/* Must be invoked under the IOMMU lock. */ -static void __iommu_flushall(struct pci_iommu *iommu) -{ - unsigned long tag; - int entry; - - tag = iommu->iommu_flush + (0xa580UL - 0x0210UL); - for (entry = 0; entry < 16; entry++) { - pci_iommu_write(tag, 0); - tag += 8; - } - - /* Ensure completion of previous PIO writes. */ - (void) pci_iommu_read(iommu->write_complete_reg); -} - -#define IOPTE_CONSISTENT(CTX) \ - (IOPTE_VALID | IOPTE_CACHE | \ - (((CTX) << 47) & IOPTE_CONTEXT)) - -#define IOPTE_STREAMING(CTX) \ - (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF) - -/* Existing mappings are never marked invalid, instead they - * are pointed to a dummy page. - */ -#define IOPTE_IS_DUMMY(iommu, iopte) \ - ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa) - -static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) -{ - unsigned long val = iopte_val(*iopte); - - val &= ~IOPTE_PAGE; - val |= iommu->dummy_page_pa; - - iopte_val(*iopte) = val; -} - -/* Based largely upon the ppc64 iommu allocator. */ -static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages) -{ - struct pci_iommu_arena *arena = &iommu->arena; - unsigned long n, i, start, end, limit; - int pass; - - limit = arena->limit; - start = arena->hint; - pass = 0; - -again: - n = find_next_zero_bit(arena->map, limit, start); - end = n + npages; - if (unlikely(end >= limit)) { - if (likely(pass < 1)) { - limit = start; - start = 0; - __iommu_flushall(iommu); - pass++; - goto again; - } else { - /* Scanned the whole thing, give up. */ - return -1; - } - } - - for (i = n; i < end; i++) { - if (test_bit(i, arena->map)) { - start = i + 1; - goto again; - } - } - - for (i = n; i < end; i++) - __set_bit(i, arena->map); - - arena->hint = end; - - return n; -} - -static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, unsigned long npages) -{ - unsigned long i; - - for (i = base; i < (base + npages); i++) - __clear_bit(i, arena->map); -} - -void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask) -{ - unsigned long i, tsbbase, order, sz, num_tsb_entries; - - num_tsb_entries = tsbsize / sizeof(iopte_t); - - /* Setup initial software IOMMU state. */ - spin_lock_init(&iommu->lock); - iommu->ctx_lowest_free = 1; - iommu->page_table_map_base = dma_offset; - iommu->dma_addr_mask = dma_addr_mask; - - /* Allocate and initialize the free area map. */ - sz = num_tsb_entries / 8; - sz = (sz + 7UL) & ~7UL; - iommu->arena.map = kmalloc(sz, GFP_KERNEL); - if (!iommu->arena.map) { - prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); - prom_halt(); - } - memset(iommu->arena.map, 0, sz); - iommu->arena.limit = num_tsb_entries; - - /* Allocate and initialize the dummy page which we - * set inactive IO PTEs to point to. - */ - iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); - if (!iommu->dummy_page) { - prom_printf("PCI_IOMMU: Error, gfp(dummy_page) failed.\n"); - prom_halt(); - } - memset((void *)iommu->dummy_page, 0, PAGE_SIZE); - iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); - - /* Now allocate and setup the IOMMU page table itself. */ - order = get_order(tsbsize); - tsbbase = __get_free_pages(GFP_KERNEL, order); - if (!tsbbase) { - prom_printf("PCI_IOMMU: Error, gfp(tsb) failed.\n"); - prom_halt(); - } - iommu->page_table = (iopte_t *)tsbbase; - - for (i = 0; i < num_tsb_entries; i++) - iopte_make_dummy(iommu, &iommu->page_table[i]); -} - -static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npages) -{ - long entry; - - entry = pci_arena_alloc(iommu, npages); - if (unlikely(entry < 0)) - return NULL; - - return iommu->page_table + entry; -} - -static inline void free_npages(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages) -{ - pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages); -} - -static int iommu_alloc_ctx(struct pci_iommu *iommu) -{ - int lowest = iommu->ctx_lowest_free; - int sz = IOMMU_NUM_CTXS - lowest; - int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest); - - if (unlikely(n == sz)) { - n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1); - if (unlikely(n == lowest)) { - printk(KERN_WARNING "IOMMU: Ran out of contexts.\n"); - n = 0; - } - } - if (n) - __set_bit(n, iommu->ctx_bitmap); - - return n; -} - -static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) -{ - if (likely(ctx)) { - __clear_bit(ctx, iommu->ctx_bitmap); - if (ctx < iommu->ctx_lowest_free) - iommu->ctx_lowest_free = ctx; - } -} - -/* Allocate and map kernel buffer of size SIZE using consistent mode - * DMA for PCI device PDEV. Return non-NULL cpu-side address if - * successful and set *DMA_ADDRP to the PCI side dma address. - */ -void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - iopte_t *iopte; - unsigned long flags, order, first_page; - void *ret; - int npages; - - size = IO_PAGE_ALIGN(size); - order = get_order(size); - if (order >= 10) - return NULL; - - first_page = __get_free_pages(GFP_ATOMIC, order); - if (first_page == 0UL) - return NULL; - memset((char *)first_page, 0, PAGE_SIZE << order); - - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - - spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT); - spin_unlock_irqrestore(&iommu->lock, flags); - - if (unlikely(iopte == NULL)) { - free_pages(first_page, order); - return NULL; - } - - *dma_addrp = (iommu->page_table_map_base + - ((iopte - iommu->page_table) << IO_PAGE_SHIFT)); - ret = (void *) first_page; - npages = size >> IO_PAGE_SHIFT; - first_page = __pa(first_page); - while (npages--) { - iopte_val(*iopte) = (IOPTE_CONSISTENT(0UL) | - IOPTE_WRITE | - (first_page & IOPTE_PAGE)); - iopte++; - first_page += IO_PAGE_SIZE; - } - - return ret; -} - -/* Free and unmap a consistent DMA translation. */ -void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - iopte_t *iopte; - unsigned long flags, order, npages; - - npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - iopte = iommu->page_table + - ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); - - spin_lock_irqsave(&iommu->lock, flags); - - free_npages(iommu, dvma, npages); - - spin_unlock_irqrestore(&iommu->lock, flags); - - order = get_order(size); - if (order < 10) - free_pages((unsigned long)cpu, order); -} - -/* Map a single buffer at PTR of SZ bytes for PCI DMA - * in streaming mode. - */ -dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; - iopte_t *base; - unsigned long flags, npages, oaddr; - unsigned long i, base_paddr, ctx; - u32 bus_addr, ret; - unsigned long iopte_protection; - - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; - - if (unlikely(direction == PCI_DMA_NONE)) - goto bad_no_ctx; - - oaddr = (unsigned long)ptr; - npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK); - npages >>= IO_PAGE_SHIFT; - - spin_lock_irqsave(&iommu->lock, flags); - base = alloc_npages(iommu, npages); - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = iommu_alloc_ctx(iommu); - spin_unlock_irqrestore(&iommu->lock, flags); - - if (unlikely(!base)) - goto bad; - - bus_addr = (iommu->page_table_map_base + - ((base - iommu->page_table) << IO_PAGE_SHIFT)); - ret = bus_addr | (oaddr & ~IO_PAGE_MASK); - base_paddr = __pa(oaddr & IO_PAGE_MASK); - if (strbuf->strbuf_enabled) - iopte_protection = IOPTE_STREAMING(ctx); - else - iopte_protection = IOPTE_CONSISTENT(ctx); - if (direction != PCI_DMA_TODEVICE) - iopte_protection |= IOPTE_WRITE; - - for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE) - iopte_val(*base) = iopte_protection | base_paddr; - - return ret; - -bad: - iommu_free_ctx(iommu, ctx); -bad_no_ctx: - if (printk_ratelimit()) - WARN_ON(1); - return PCI_DMA_ERROR_CODE; -} - -static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) -{ - int limit; - - if (strbuf->strbuf_ctxflush && - iommu->iommu_ctxflush) { - unsigned long matchreg, flushreg; - u64 val; - - flushreg = strbuf->strbuf_ctxflush; - matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); - - pci_iommu_write(flushreg, ctx); - val = pci_iommu_read(matchreg); - val &= 0xffff; - if (!val) - goto do_flush_sync; - - while (val) { - if (val & 0x1) - pci_iommu_write(flushreg, ctx); - val >>= 1; - } - val = pci_iommu_read(matchreg); - if (unlikely(val)) { - printk(KERN_WARNING "pci_strbuf_flush: ctx flush " - "timeout matchreg[%lx] ctx[%lx]\n", - val, ctx); - goto do_page_flush; - } - } else { - unsigned long i; - - do_page_flush: - for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) - pci_iommu_write(strbuf->strbuf_pflush, vaddr); - } - -do_flush_sync: - /* If the device could not have possibly put dirty data into - * the streaming cache, no flush-flag synchronization needs - * to be performed. - */ - if (direction == PCI_DMA_TODEVICE) - return; - - PCI_STC_FLUSHFLAG_INIT(strbuf); - pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); - (void) pci_iommu_read(iommu->write_complete_reg); - - limit = 100000; - while (!PCI_STC_FLUSHFLAG_SET(strbuf)) { - limit--; - if (!limit) - break; - udelay(1); - rmb(); - } - if (!limit) - printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout " - "vaddr[%08x] ctx[%lx] npages[%ld]\n", - vaddr, ctx, npages); -} - -/* Unmap a single streaming mode DMA translation. */ -void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; - iopte_t *base; - unsigned long flags, npages, ctx, i; - - if (unlikely(direction == PCI_DMA_NONE)) { - if (printk_ratelimit()) - WARN_ON(1); - return; - } - - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; - - npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); - npages >>= IO_PAGE_SHIFT; - base = iommu->page_table + - ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); -#ifdef DEBUG_PCI_IOMMU - if (IOPTE_IS_DUMMY(iommu, base)) - printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", - bus_addr, sz, __builtin_return_address(0)); -#endif - bus_addr &= IO_PAGE_MASK; - - spin_lock_irqsave(&iommu->lock, flags); - - /* Record the context, if any. */ - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; - - /* Step 1: Kick data out of streaming buffers if necessary. */ - if (strbuf->strbuf_enabled) - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, - npages, direction); - - /* Step 2: Clear out TSB entries. */ - for (i = 0; i < npages; i++) - iopte_make_dummy(iommu, base + i); - - free_npages(iommu, bus_addr - iommu->page_table_map_base, npages); - - iommu_free_ctx(iommu, ctx); - - spin_unlock_irqrestore(&iommu->lock, flags); -} - -#define SG_ENT_PHYS_ADDRESS(SG) \ - (__pa(page_address((SG)->page)) + (SG)->offset) - -static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, - int nused, int nelems, unsigned long iopte_protection) -{ - struct scatterlist *dma_sg = sg; - struct scatterlist *sg_end = sg + nelems; - int i; - - for (i = 0; i < nused; i++) { - unsigned long pteval = ~0UL; - u32 dma_npages; - - dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) + - dma_sg->dma_length + - ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; - do { - unsigned long offset; - signed int len; - - /* If we are here, we know we have at least one - * more page to map. So walk forward until we - * hit a page crossing, and begin creating new - * mappings from that spot. - */ - for (;;) { - unsigned long tmp; - - tmp = SG_ENT_PHYS_ADDRESS(sg); - len = sg->length; - if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { - pteval = tmp & IO_PAGE_MASK; - offset = tmp & (IO_PAGE_SIZE - 1UL); - break; - } - if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { - pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; - offset = 0UL; - len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); - break; - } - sg++; - } - - pteval = iopte_protection | (pteval & IOPTE_PAGE); - while (len > 0) { - *iopte++ = __iopte(pteval); - pteval += IO_PAGE_SIZE; - len -= (IO_PAGE_SIZE - offset); - offset = 0; - dma_npages--; - } - - pteval = (pteval & IOPTE_PAGE) + len; - sg++; - - /* Skip over any tail mappings we've fully mapped, - * adjusting pteval along the way. Stop when we - * detect a page crossing event. - */ - while (sg < sg_end && - (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && - (pteval == SG_ENT_PHYS_ADDRESS(sg)) && - ((pteval ^ - (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { - pteval += sg->length; - sg++; - } - if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) - pteval = ~0UL; - } while (dma_npages != 0); - dma_sg++; - } -} - -/* Map a set of buffers described by SGLIST with NELEMS array - * elements in streaming mode for PCI DMA. - * When making changes here, inspect the assembly output. I was having - * hard time to kepp this routine out of using stack slots for holding variables. - */ -int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; - unsigned long flags, ctx, npages, iopte_protection; - iopte_t *base; - u32 dma_base; - struct scatterlist *sgtmp; - int used; - - /* Fast path single entry scatterlists. */ - if (nelems == 1) { - sglist->dma_address = - pci_map_single(pdev, - (page_address(sglist->page) + sglist->offset), - sglist->length, direction); - if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE)) - return 0; - sglist->dma_length = sglist->length; - return 1; - } - - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; - - if (unlikely(direction == PCI_DMA_NONE)) - goto bad_no_ctx; - - /* Step 1: Prepare scatter list. */ - - npages = prepare_sg(sglist, nelems); - - /* Step 2: Allocate a cluster and context, if necessary. */ - - spin_lock_irqsave(&iommu->lock, flags); - - base = alloc_npages(iommu, npages); - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = iommu_alloc_ctx(iommu); - - spin_unlock_irqrestore(&iommu->lock, flags); - - if (base == NULL) - goto bad; - - dma_base = iommu->page_table_map_base + - ((base - iommu->page_table) << IO_PAGE_SHIFT); - - /* Step 3: Normalize DMA addresses. */ - used = nelems; - - sgtmp = sglist; - while (used && sgtmp->dma_length) { - sgtmp->dma_address += dma_base; - sgtmp++; - used--; - } - used = nelems - used; - - /* Step 4: Create the mappings. */ - if (strbuf->strbuf_enabled) - iopte_protection = IOPTE_STREAMING(ctx); - else - iopte_protection = IOPTE_CONSISTENT(ctx); - if (direction != PCI_DMA_TODEVICE) - iopte_protection |= IOPTE_WRITE; - - fill_sg(base, sglist, used, nelems, iopte_protection); - -#ifdef VERIFY_SG - verify_sglist(sglist, nelems, base, npages); -#endif - - return used; - -bad: - iommu_free_ctx(iommu, ctx); -bad_no_ctx: - if (printk_ratelimit()) - WARN_ON(1); - return 0; -} - -/* Unmap a set of streaming mode DMA translations. */ -void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; - iopte_t *base; - unsigned long flags, ctx, i, npages; - u32 bus_addr; - - if (unlikely(direction == PCI_DMA_NONE)) { - if (printk_ratelimit()) - WARN_ON(1); - } - - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; - - bus_addr = sglist->dma_address & IO_PAGE_MASK; - - for (i = 1; i < nelems; i++) - if (sglist[i].dma_length == 0) - break; - i--; - npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - - bus_addr) >> IO_PAGE_SHIFT; - - base = iommu->page_table + - ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); - -#ifdef DEBUG_PCI_IOMMU - if (IOPTE_IS_DUMMY(iommu, base)) - printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0)); -#endif - - spin_lock_irqsave(&iommu->lock, flags); - - /* Record the context, if any. */ - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; - - /* Step 1: Kick data out of streaming buffers if necessary. */ - if (strbuf->strbuf_enabled) - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); - - /* Step 2: Clear out the TSB entries. */ - for (i = 0; i < npages; i++) - iopte_make_dummy(iommu, base + i); - - free_npages(iommu, bus_addr - iommu->page_table_map_base, npages); - - iommu_free_ctx(iommu, ctx); - - spin_unlock_irqrestore(&iommu->lock, flags); -} - -/* Make physical memory consistent for a single - * streaming mode DMA translation after a transfer. - */ -void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; - unsigned long flags, ctx, npages; - - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; - - if (!strbuf->strbuf_enabled) - return; - - spin_lock_irqsave(&iommu->lock, flags); - - npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); - npages >>= IO_PAGE_SHIFT; - bus_addr &= IO_PAGE_MASK; - - /* Step 1: Record the context, if any. */ - ctx = 0; - if (iommu->iommu_ctxflush && - strbuf->strbuf_ctxflush) { - iopte_t *iopte; - - iopte = iommu->page_table + - ((bus_addr - iommu->page_table_map_base)>>IO_PAGE_SHIFT); - ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; - } - - /* Step 2: Kick data out of streaming buffers. */ - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); - - spin_unlock_irqrestore(&iommu->lock, flags); -} - -/* Make physical memory consistent for a set of streaming - * mode DMA translations after a transfer. - */ -void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) -{ - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; - unsigned long flags, ctx, npages, i; - u32 bus_addr; - - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; - - if (!strbuf->strbuf_enabled) - return; - - spin_lock_irqsave(&iommu->lock, flags); - - /* Step 1: Record the context, if any. */ - ctx = 0; - if (iommu->iommu_ctxflush && - strbuf->strbuf_ctxflush) { - iopte_t *iopte; - - iopte = iommu->page_table + - ((sglist[0].dma_address - iommu->page_table_map_base) >> IO_PAGE_SHIFT); - ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; - } - - /* Step 2: Kick data out of streaming buffers. */ - bus_addr = sglist[0].dma_address & IO_PAGE_MASK; - for(i = 1; i < nelems; i++) - if (!sglist[i].dma_length) - break; - i--; - npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - - bus_addr) >> IO_PAGE_SHIFT; - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); - - spin_unlock_irqrestore(&iommu->lock, flags); -} - -static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) -{ - struct pci_dev *ali_isa_bridge; - u8 val; - - /* ALI sound chips generate 31-bits of DMA, a special register - * determines what bit 31 is emitted as. - */ - ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, - PCI_DEVICE_ID_AL_M1533, - NULL); - - pci_read_config_byte(ali_isa_bridge, 0x7e, &val); - if (set_bit) - val |= 0x01; - else - val &= ~0x01; - pci_write_config_byte(ali_isa_bridge, 0x7e, val); - pci_dev_put(ali_isa_bridge); -} - -int pci_dma_supported(struct pci_dev *pdev, u64 device_mask) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - u64 dma_addr_mask; - - if (pdev == NULL) { - dma_addr_mask = 0xffffffff; - } else { - struct pci_iommu *iommu = pcp->pbm->iommu; - - dma_addr_mask = iommu->dma_addr_mask; - - if (pdev->vendor == PCI_VENDOR_ID_AL && - pdev->device == PCI_DEVICE_ID_AL_M5451 && - device_mask == 0x7fffffff) { - ali_sound_dma_hack(pdev, - (dma_addr_mask & 0x80000000) != 0); - return 1; - } - } - - if (device_mask >= (1UL << 32UL)) - return 0; - - return (device_mask & dma_addr_mask) == dma_addr_mask; -} diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c deleted file mode 100644 index c03ed5f49d3..00000000000 --- a/arch/sparc64/kernel/pci_psycho.c +++ /dev/null @@ -1,1525 +0,0 @@ -/* $Id: pci_psycho.c,v 1.33 2002/02/01 00:58:33 davem Exp $ - * pci_psycho.c: PSYCHO/U2P specific PCI controller support. - * - * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) - * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> - -#include <asm/pbm.h> -#include <asm/iommu.h> -#include <asm/irq.h> -#include <asm/starfire.h> - -#include "pci_impl.h" -#include "iommu_common.h" - -/* All PSYCHO registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define psycho_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define psycho_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - -/* Misc. PSYCHO PCI controller register offsets and definitions. */ -#define PSYCHO_CONTROL 0x0010UL -#define PSYCHO_CONTROL_IMPL 0xf000000000000000UL /* Implementation of this PSYCHO*/ -#define PSYCHO_CONTROL_VER 0x0f00000000000000UL /* Version of this PSYCHO */ -#define PSYCHO_CONTROL_MID 0x00f8000000000000UL /* UPA Module ID of PSYCHO */ -#define PSYCHO_CONTROL_IGN 0x0007c00000000000UL /* Interrupt Group Number */ -#define PSYCHO_CONTROL_RESV 0x00003ffffffffff0UL /* Reserved */ -#define PSYCHO_CONTROL_APCKEN 0x0000000000000008UL /* Address Parity Check Enable */ -#define PSYCHO_CONTROL_APERR 0x0000000000000004UL /* Incoming System Addr Parerr */ -#define PSYCHO_CONTROL_IAP 0x0000000000000002UL /* Invert UPA Parity */ -#define PSYCHO_CONTROL_MODE 0x0000000000000001UL /* PSYCHO clock mode */ -#define PSYCHO_PCIA_CTRL 0x2000UL -#define PSYCHO_PCIB_CTRL 0x4000UL -#define PSYCHO_PCICTRL_RESV1 0xfffffff000000000UL /* Reserved */ -#define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000UL /* Streaming byte hole error */ -#define PSYCHO_PCICTRL_SERR 0x0000000400000000UL /* SERR signal asserted */ -#define PSYCHO_PCICTRL_SPEED 0x0000000200000000UL /* PCI speed (1 is U2P clock) */ -#define PSYCHO_PCICTRL_RESV2 0x00000001ffc00000UL /* Reserved */ -#define PSYCHO_PCICTRL_ARB_PARK 0x0000000000200000UL /* PCI arbitration parking */ -#define PSYCHO_PCICTRL_RESV3 0x00000000001ff800UL /* Reserved */ -#define PSYCHO_PCICTRL_SBH_INT 0x0000000000000400UL /* Streaming byte hole int enab */ -#define PSYCHO_PCICTRL_WEN 0x0000000000000200UL /* Power Mgmt Wake Enable */ -#define PSYCHO_PCICTRL_EEN 0x0000000000000100UL /* PCI Error Interrupt Enable */ -#define PSYCHO_PCICTRL_RESV4 0x00000000000000c0UL /* Reserved */ -#define PSYCHO_PCICTRL_AEN 0x000000000000003fUL /* PCI DVMA Arbitration Enable */ - -/* U2P Programmer's Manual, page 13-55, configuration space - * address format: - * - * 32 24 23 16 15 11 10 8 7 2 1 0 - * --------------------------------------------------------- - * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | - * --------------------------------------------------------- - */ -#define PSYCHO_CONFIG_BASE(PBM) \ - ((PBM)->config_space | (1UL << 24)) -#define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG) \ - (((unsigned long)(BUS) << 16) | \ - ((unsigned long)(DEVFN) << 8) | \ - ((unsigned long)(REG))) - -static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, - unsigned char bus, - unsigned int devfn, - int where) -{ - if (!pbm) - return NULL; - return (void *) - (PSYCHO_CONFIG_BASE(pbm) | - PSYCHO_CONFIG_ENCODE(bus, devfn, where)); -} - -static int psycho_out_of_range(struct pci_pbm_info *pbm, - unsigned char bus, - unsigned char devfn) -{ - return ((pbm->parent == 0) || - ((pbm == &pbm->parent->pbm_B) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8) || - ((pbm == &pbm->parent->pbm_A) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8)); -} - -/* PSYCHO PCI configuration space accessors. */ - -static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 *value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - u16 tmp16; - u8 tmp8; - - switch (size) { - case 1: - *value = 0xff; - break; - case 2: - *value = 0xffff; - break; - case 4: - *value = 0xffffffff; - break; - } - - addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - if (psycho_out_of_range(pbm, bus, devfn)) - return PCIBIOS_SUCCESSFUL; - switch (size) { - case 1: - pci_config_read8((u8 *)addr, &tmp8); - *value = (u32) tmp8; - break; - - case 2: - if (where & 0x01) { - printk("pci_read_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read16((u16 *)addr, &tmp16); - *value = (u32) tmp16; - break; - - case 4: - if (where & 0x03) { - printk("pci_read_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read32(addr, value); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - - addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - if (psycho_out_of_range(pbm, bus, devfn)) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_write8((u8 *)addr, value); - break; - - case 2: - if (where & 0x01) { - printk("pci_write_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write16((u16 *)addr, value); - break; - - case 4: - if (where & 0x03) { - printk("pci_write_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write32(addr, value); - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops psycho_ops = { - .read = psycho_read_pci_cfg, - .write = psycho_write_pci_cfg, -}; - -/* PSYCHO interrupt mapping support. */ -#define PSYCHO_IMAP_A_SLOT0 0x0c00UL -#define PSYCHO_IMAP_B_SLOT0 0x0c20UL -static unsigned long psycho_pcislot_imap_offset(unsigned long ino) -{ - unsigned int bus = (ino & 0x10) >> 4; - unsigned int slot = (ino & 0x0c) >> 2; - - if (bus == 0) - return PSYCHO_IMAP_A_SLOT0 + (slot * 8); - else - return PSYCHO_IMAP_B_SLOT0 + (slot * 8); -} - -#define PSYCHO_IMAP_SCSI 0x1000UL -#define PSYCHO_IMAP_ETH 0x1008UL -#define PSYCHO_IMAP_BPP 0x1010UL -#define PSYCHO_IMAP_AU_REC 0x1018UL -#define PSYCHO_IMAP_AU_PLAY 0x1020UL -#define PSYCHO_IMAP_PFAIL 0x1028UL -#define PSYCHO_IMAP_KMS 0x1030UL -#define PSYCHO_IMAP_FLPY 0x1038UL -#define PSYCHO_IMAP_SHW 0x1040UL -#define PSYCHO_IMAP_KBD 0x1048UL -#define PSYCHO_IMAP_MS 0x1050UL -#define PSYCHO_IMAP_SER 0x1058UL -#define PSYCHO_IMAP_TIM0 0x1060UL -#define PSYCHO_IMAP_TIM1 0x1068UL -#define PSYCHO_IMAP_UE 0x1070UL -#define PSYCHO_IMAP_CE 0x1078UL -#define PSYCHO_IMAP_A_ERR 0x1080UL -#define PSYCHO_IMAP_B_ERR 0x1088UL -#define PSYCHO_IMAP_PMGMT 0x1090UL -#define PSYCHO_IMAP_GFX 0x1098UL -#define PSYCHO_IMAP_EUPA 0x10a0UL - -static unsigned long __onboard_imap_off[] = { -/*0x20*/ PSYCHO_IMAP_SCSI, -/*0x21*/ PSYCHO_IMAP_ETH, -/*0x22*/ PSYCHO_IMAP_BPP, -/*0x23*/ PSYCHO_IMAP_AU_REC, -/*0x24*/ PSYCHO_IMAP_AU_PLAY, -/*0x25*/ PSYCHO_IMAP_PFAIL, -/*0x26*/ PSYCHO_IMAP_KMS, -/*0x27*/ PSYCHO_IMAP_FLPY, -/*0x28*/ PSYCHO_IMAP_SHW, -/*0x29*/ PSYCHO_IMAP_KBD, -/*0x2a*/ PSYCHO_IMAP_MS, -/*0x2b*/ PSYCHO_IMAP_SER, -/*0x2c*/ PSYCHO_IMAP_TIM0, -/*0x2d*/ PSYCHO_IMAP_TIM1, -/*0x2e*/ PSYCHO_IMAP_UE, -/*0x2f*/ PSYCHO_IMAP_CE, -/*0x30*/ PSYCHO_IMAP_A_ERR, -/*0x31*/ PSYCHO_IMAP_B_ERR, -/*0x32*/ PSYCHO_IMAP_PMGMT -}; -#define PSYCHO_ONBOARD_IRQ_BASE 0x20 -#define PSYCHO_ONBOARD_IRQ_LAST 0x32 -#define psycho_onboard_imap_offset(__ino) \ - __onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE] - -#define PSYCHO_ICLR_A_SLOT0 0x1400UL -#define PSYCHO_ICLR_SCSI 0x1800UL - -#define psycho_iclr_offset(ino) \ - ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ - (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) - -/* PCI PSYCHO INO number to Sparc PIL level. */ -static unsigned char psycho_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ -/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ -/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ -/*0x20*/4, /* SCSI */ -/*0x21*/5, /* Ethernet */ -/*0x22*/8, /* Parallel Port */ -/*0x23*/13, /* Audio Record */ -/*0x24*/14, /* Audio Playback */ -/*0x25*/15, /* PowerFail */ -/*0x26*/4, /* second SCSI */ -/*0x27*/11, /* Floppy */ -/*0x28*/4, /* Spare Hardware */ -/*0x29*/9, /* Keyboard */ -/*0x2a*/4, /* Mouse */ -/*0x2b*/12, /* Serial */ -/*0x2c*/10, /* Timer 0 */ -/*0x2d*/11, /* Timer 1 */ -/*0x2e*/15, /* Uncorrectable ECC */ -/*0x2f*/15, /* Correctable ECC */ -/*0x30*/15, /* PCI Bus A Error */ -/*0x31*/15, /* PCI Bus B Error */ -/*0x32*/15, /* Power Management */ -}; - -static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - ret = psycho_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 4; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 4; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 4; - break; - }; - } - - return ret; -} - -static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - unsigned int ino) -{ - struct ino_bucket *bucket; - unsigned long imap, iclr; - unsigned long imap_off, iclr_off; - int pil, inofixup = 0; - - ino &= PCI_IRQ_INO; - if (ino < PSYCHO_ONBOARD_IRQ_BASE) { - /* PCI slot */ - imap_off = psycho_pcislot_imap_offset(ino); - } else { - /* Onboard device */ - if (ino > PSYCHO_ONBOARD_IRQ_LAST) { - prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino); - prom_halt(); - } - imap_off = psycho_onboard_imap_offset(ino); - } - - /* Now build the IRQ bucket. */ - pil = psycho_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - - imap = pbm->controller_regs + imap_off; - imap += 4; - - iclr_off = psycho_iclr_offset(ino); - iclr = pbm->controller_regs + iclr_off; - iclr += 4; - - if ((ino & 0x20) == 0) - inofixup = ino & 0x03; - - bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); - bucket->flags |= IBF_PCI; - - return __irq(bucket); -} - -/* PSYCHO error handling support. */ -enum psycho_error_type { - UE_ERR, CE_ERR, PCI_ERR -}; - -/* Helper function of IOMMU error checking, which checks out - * the state of the streaming buffers. The IOMMU lock is - * held when this is called. - * - * For the PCI error case we know which PBM (and thus which - * streaming buffer) caused the error, but for the uncorrectable - * error case we do not. So we always check both streaming caches. - */ -#define PSYCHO_STRBUF_CONTROL_A 0x2800UL -#define PSYCHO_STRBUF_CONTROL_B 0x4800UL -#define PSYCHO_STRBUF_CTRL_LPTR 0x00000000000000f0UL /* LRU Lock Pointer */ -#define PSYCHO_STRBUF_CTRL_LENAB 0x0000000000000008UL /* LRU Lock Enable */ -#define PSYCHO_STRBUF_CTRL_RRDIS 0x0000000000000004UL /* Rerun Disable */ -#define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002UL /* Diagnostic Mode Enable */ -#define PSYCHO_STRBUF_CTRL_ENAB 0x0000000000000001UL /* Streaming Buffer Enable */ -#define PSYCHO_STRBUF_FLUSH_A 0x2808UL -#define PSYCHO_STRBUF_FLUSH_B 0x4808UL -#define PSYCHO_STRBUF_FSYNC_A 0x2810UL -#define PSYCHO_STRBUF_FSYNC_B 0x4810UL -#define PSYCHO_STC_DATA_A 0xb000UL -#define PSYCHO_STC_DATA_B 0xc000UL -#define PSYCHO_STC_ERR_A 0xb400UL -#define PSYCHO_STC_ERR_B 0xc400UL -#define PSYCHO_STCERR_WRITE 0x0000000000000002UL /* Write Error */ -#define PSYCHO_STCERR_READ 0x0000000000000001UL /* Read Error */ -#define PSYCHO_STC_TAG_A 0xb800UL -#define PSYCHO_STC_TAG_B 0xc800UL -#define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL /* Physical Page Number */ -#define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL /* Virtual Page Number */ -#define PSYCHO_STCTAG_VALID 0x0000000000000002UL /* Valid */ -#define PSYCHO_STCTAG_WRITE 0x0000000000000001UL /* Writable */ -#define PSYCHO_STC_LINE_A 0xb900UL -#define PSYCHO_STC_LINE_B 0xc900UL -#define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL /* LRU Index */ -#define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL /* Dirty Data Start Pointer */ -#define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL /* Line Address */ -#define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL /* Dirty Data End Pointer */ -#define PSYCHO_STCLINE_VALID 0x0000000000000002UL /* Valid */ -#define PSYCHO_STCLINE_FOFN 0x0000000000000001UL /* Fetch Outstanding / Flush Necessary */ - -static DEFINE_SPINLOCK(stc_buf_lock); -static unsigned long stc_error_buf[128]; -static unsigned long stc_tag_buf[16]; -static unsigned long stc_line_buf[16]; - -static void __psycho_check_one_stc(struct pci_controller_info *p, - struct pci_pbm_info *pbm, - int is_pbm_a) -{ - struct pci_strbuf *strbuf = &pbm->stc; - unsigned long regbase = p->pbm_A.controller_regs; - unsigned long err_base, tag_base, line_base; - u64 control; - int i; - - if (is_pbm_a) { - err_base = regbase + PSYCHO_STC_ERR_A; - tag_base = regbase + PSYCHO_STC_TAG_A; - line_base = regbase + PSYCHO_STC_LINE_A; - } else { - err_base = regbase + PSYCHO_STC_ERR_B; - tag_base = regbase + PSYCHO_STC_TAG_B; - line_base = regbase + PSYCHO_STC_LINE_B; - } - - spin_lock(&stc_buf_lock); - - /* This is __REALLY__ dangerous. When we put the - * streaming buffer into diagnostic mode to probe - * it's tags and error status, we _must_ clear all - * of the line tag valid bits before re-enabling - * the streaming buffer. If any dirty data lives - * in the STC when we do this, we will end up - * invalidating it before it has a chance to reach - * main memory. - */ - control = psycho_read(strbuf->strbuf_control); - psycho_write(strbuf->strbuf_control, - (control | PSYCHO_STRBUF_CTRL_DENAB)); - for (i = 0; i < 128; i++) { - unsigned long val; - - val = psycho_read(err_base + (i * 8UL)); - psycho_write(err_base + (i * 8UL), 0UL); - stc_error_buf[i] = val; - } - for (i = 0; i < 16; i++) { - stc_tag_buf[i] = psycho_read(tag_base + (i * 8UL)); - stc_line_buf[i] = psycho_read(line_base + (i * 8UL)); - psycho_write(tag_base + (i * 8UL), 0UL); - psycho_write(line_base + (i * 8UL), 0UL); - } - - /* OK, state is logged, exit diagnostic mode. */ - psycho_write(strbuf->strbuf_control, control); - - for (i = 0; i < 16; i++) { - int j, saw_error, first, last; - - saw_error = 0; - first = i * 8; - last = first + 8; - for (j = first; j < last; j++) { - unsigned long errval = stc_error_buf[j]; - if (errval != 0) { - saw_error++; - printk("PSYCHO%d(PBM%c): STC_ERR(%d)[wr(%d)rd(%d)]\n", - p->index, - (is_pbm_a ? 'A' : 'B'), - j, - (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, - (errval & PSYCHO_STCERR_READ) ? 1 : 0); - } - } - if (saw_error != 0) { - unsigned long tagval = stc_tag_buf[i]; - unsigned long lineval = stc_line_buf[i]; - printk("PSYCHO%d(PBM%c): STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", - p->index, - (is_pbm_a ? 'A' : 'B'), - i, - ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), - (tagval & PSYCHO_STCTAG_VPN), - ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), - ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); - printk("PSYCHO%d(PBM%c): STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" - "V(%d)FOFN(%d)]\n", - p->index, - (is_pbm_a ? 'A' : 'B'), - i, - ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), - ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), - ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), - ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), - ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), - ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); - } - } - - spin_unlock(&stc_buf_lock); -} - -static void __psycho_check_stc_error(struct pci_controller_info *p, - unsigned long afsr, - unsigned long afar, - enum psycho_error_type type) -{ - struct pci_pbm_info *pbm; - - pbm = &p->pbm_A; - if (pbm->stc.strbuf_enabled) - __psycho_check_one_stc(p, pbm, 1); - - pbm = &p->pbm_B; - if (pbm->stc.strbuf_enabled) - __psycho_check_one_stc(p, pbm, 0); -} - -/* When an Uncorrectable Error or a PCI Error happens, we - * interrogate the IOMMU state to see if it is the cause. - */ -#define PSYCHO_IOMMU_CONTROL 0x0200UL -#define PSYCHO_IOMMU_CTRL_RESV 0xfffffffff9000000UL /* Reserved */ -#define PSYCHO_IOMMU_CTRL_XLTESTAT 0x0000000006000000UL /* Translation Error Status */ -#define PSYCHO_IOMMU_CTRL_XLTEERR 0x0000000001000000UL /* Translation Error encountered */ -#define PSYCHO_IOMMU_CTRL_LCKEN 0x0000000000800000UL /* Enable translation locking */ -#define PSYCHO_IOMMU_CTRL_LCKPTR 0x0000000000780000UL /* Translation lock pointer */ -#define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL /* TSB Size */ -#define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000UL /* TSB Table 1024 8-byte entries */ -#define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000UL /* TSB Table 2048 8-byte entries */ -#define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000UL /* TSB Table 4096 8-byte entries */ -#define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000UL /* TSB Table 8192 8-byte entries */ -#define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000UL /* TSB Table 16k 8-byte entries */ -#define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000UL /* TSB Table 32k 8-byte entries */ -#define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000UL /* TSB Table 64k 8-byte entries */ -#define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000UL /* TSB Table 128k 8-byte entries */ -#define PSYCHO_IOMMU_CTRL_RESV2 0x000000000000fff8UL /* Reserved */ -#define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL /* Assumed page size, 0=8k 1=64k */ -#define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002UL /* Diagnostic mode enable */ -#define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001UL /* IOMMU Enable */ -#define PSYCHO_IOMMU_TSBBASE 0x0208UL -#define PSYCHO_IOMMU_FLUSH 0x0210UL -#define PSYCHO_IOMMU_TAG 0xa580UL -#define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) -#define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) -#define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) -#define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) -#define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) -#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL -#define PSYCHO_IOMMU_DATA 0xa600UL -#define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) -#define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) -#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL -static void psycho_check_iommu_error(struct pci_controller_info *p, - unsigned long afsr, - unsigned long afar, - enum psycho_error_type type) -{ - struct pci_iommu *iommu = p->pbm_A.iommu; - unsigned long iommu_tag[16]; - unsigned long iommu_data[16]; - unsigned long flags; - u64 control; - int i; - - spin_lock_irqsave(&iommu->lock, flags); - control = psycho_read(iommu->iommu_control); - if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { - char *type_string; - - /* Clear the error encountered bit. */ - control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; - psycho_write(iommu->iommu_control, control); - - switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("PSYCHO%d: IOMMU Error, type[%s]\n", - p->index, type_string); - - /* Put the IOMMU into diagnostic mode and probe - * it's TLB for entries with error status. - * - * It is very possible for another DVMA to occur - * while we do this probe, and corrupt the system - * further. But we are so screwed at this point - * that we are likely to crash hard anyways, so - * get as much diagnostic information to the - * console as we can. - */ - psycho_write(iommu->iommu_control, - control | PSYCHO_IOMMU_CTRL_DENAB); - for (i = 0; i < 16; i++) { - unsigned long base = p->pbm_A.controller_regs; - - iommu_tag[i] = - psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); - iommu_data[i] = - psycho_read(base + PSYCHO_IOMMU_DATA + (i * 8UL)); - - /* Now clear out the entry. */ - psycho_write(base + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(base + PSYCHO_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diagnostic mode. */ - psycho_write(iommu->iommu_control, control); - - for (i = 0; i < 16; i++) { - unsigned long tag, data; - - tag = iommu_tag[i]; - if (!(tag & PSYCHO_IOMMU_TAG_ERR)) - continue; - - data = iommu_data[i]; - switch((tag & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("PSYCHO%d: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", - p->index, i, type_string, - ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), - ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), - ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); - printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", - p->index, i, - ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), - ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); - } - } - __psycho_check_stc_error(p, afsr, afar, type); - spin_unlock_irqrestore(&iommu->lock, flags); -} - -/* Uncorrectable Errors. Cause of the error and the address are - * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors - * relating to UPA interface transactions. - */ -#define PSYCHO_UE_AFSR 0x0030UL -#define PSYCHO_UEAFSR_PPIO 0x8000000000000000UL /* Primary PIO is cause */ -#define PSYCHO_UEAFSR_PDRD 0x4000000000000000UL /* Primary DVMA read is cause */ -#define PSYCHO_UEAFSR_PDWR 0x2000000000000000UL /* Primary DVMA write is cause */ -#define PSYCHO_UEAFSR_SPIO 0x1000000000000000UL /* Secondary PIO is cause */ -#define PSYCHO_UEAFSR_SDRD 0x0800000000000000UL /* Secondary DVMA read is cause */ -#define PSYCHO_UEAFSR_SDWR 0x0400000000000000UL /* Secondary DVMA write is cause*/ -#define PSYCHO_UEAFSR_RESV1 0x03ff000000000000UL /* Reserved */ -#define PSYCHO_UEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ -#define PSYCHO_UEAFSR_DOFF 0x00000000e0000000UL /* Doubleword Offset */ -#define PSYCHO_UEAFSR_MID 0x000000001f000000UL /* UPA MID causing the fault */ -#define PSYCHO_UEAFSR_BLK 0x0000000000800000UL /* Trans was block operation */ -#define PSYCHO_UEAFSR_RESV2 0x00000000007fffffUL /* Reserved */ -#define PSYCHO_UE_AFAR 0x0038UL - -static irqreturn_t psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR; - unsigned long afsr, afar, error_bits; - int reported; - - /* Latch uncorrectable error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); - - /* Clear the primary/secondary error status bits. */ - error_bits = afsr & - (PSYCHO_UEAFSR_PPIO | PSYCHO_UEAFSR_PDRD | PSYCHO_UEAFSR_PDWR | - PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR); - if (!error_bits) - return IRQ_NONE; - psycho_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("PSYCHO%d: Uncorrectable Error, primary error type[%s]\n", - p->index, - (((error_bits & PSYCHO_UEAFSR_PPIO) ? - "PIO" : - ((error_bits & PSYCHO_UEAFSR_PDRD) ? - "DMA Read" : - ((error_bits & PSYCHO_UEAFSR_PDWR) ? - "DMA Write" : "???"))))); - printk("PSYCHO%d: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n", - p->index, - (afsr & PSYCHO_UEAFSR_BMSK) >> 32UL, - (afsr & PSYCHO_UEAFSR_DOFF) >> 29UL, - (afsr & PSYCHO_UEAFSR_MID) >> 24UL, - ((afsr & PSYCHO_UEAFSR_BLK) ? 1 : 0)); - printk("PSYCHO%d: UE AFAR [%016lx]\n", p->index, afar); - printk("PSYCHO%d: UE Secondary errors [", p->index); - reported = 0; - if (afsr & PSYCHO_UEAFSR_SPIO) { - reported++; - printk("(PIO)"); - } - if (afsr & PSYCHO_UEAFSR_SDRD) { - reported++; - printk("(DMA Read)"); - } - if (afsr & PSYCHO_UEAFSR_SDWR) { - reported++; - printk("(DMA Write)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* Interrogate IOMMU for error status. */ - psycho_check_iommu_error(p, afsr, afar, UE_ERR); - - return IRQ_HANDLED; -} - -/* Correctable Errors. */ -#define PSYCHO_CE_AFSR 0x0040UL -#define PSYCHO_CEAFSR_PPIO 0x8000000000000000UL /* Primary PIO is cause */ -#define PSYCHO_CEAFSR_PDRD 0x4000000000000000UL /* Primary DVMA read is cause */ -#define PSYCHO_CEAFSR_PDWR 0x2000000000000000UL /* Primary DVMA write is cause */ -#define PSYCHO_CEAFSR_SPIO 0x1000000000000000UL /* Secondary PIO is cause */ -#define PSYCHO_CEAFSR_SDRD 0x0800000000000000UL /* Secondary DVMA read is cause */ -#define PSYCHO_CEAFSR_SDWR 0x0400000000000000UL /* Secondary DVMA write is cause*/ -#define PSYCHO_CEAFSR_RESV1 0x0300000000000000UL /* Reserved */ -#define PSYCHO_CEAFSR_ESYND 0x00ff000000000000UL /* Syndrome Bits */ -#define PSYCHO_CEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ -#define PSYCHO_CEAFSR_DOFF 0x00000000e0000000UL /* Double Offset */ -#define PSYCHO_CEAFSR_MID 0x000000001f000000UL /* UPA MID causing the fault */ -#define PSYCHO_CEAFSR_BLK 0x0000000000800000UL /* Trans was block operation */ -#define PSYCHO_CEAFSR_RESV2 0x00000000007fffffUL /* Reserved */ -#define PSYCHO_CE_AFAR 0x0040UL - -static irqreturn_t psycho_ce_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR; - unsigned long afsr, afar, error_bits; - int reported; - - /* Latch error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (PSYCHO_CEAFSR_PPIO | PSYCHO_CEAFSR_PDRD | PSYCHO_CEAFSR_PDWR | - PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR); - if (!error_bits) - return IRQ_NONE; - psycho_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("PSYCHO%d: Correctable Error, primary error type[%s]\n", - p->index, - (((error_bits & PSYCHO_CEAFSR_PPIO) ? - "PIO" : - ((error_bits & PSYCHO_CEAFSR_PDRD) ? - "DMA Read" : - ((error_bits & PSYCHO_CEAFSR_PDWR) ? - "DMA Write" : "???"))))); - - /* XXX Use syndrome and afar to print out module string just like - * XXX UDB CE trap handler does... -DaveM - */ - printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " - "UPA_MID[%02lx] was_block(%d)\n", - p->index, - (afsr & PSYCHO_CEAFSR_ESYND) >> 48UL, - (afsr & PSYCHO_CEAFSR_BMSK) >> 32UL, - (afsr & PSYCHO_CEAFSR_DOFF) >> 29UL, - (afsr & PSYCHO_CEAFSR_MID) >> 24UL, - ((afsr & PSYCHO_CEAFSR_BLK) ? 1 : 0)); - printk("PSYCHO%d: CE AFAR [%016lx]\n", p->index, afar); - printk("PSYCHO%d: CE Secondary errors [", p->index); - reported = 0; - if (afsr & PSYCHO_CEAFSR_SPIO) { - reported++; - printk("(PIO)"); - } - if (afsr & PSYCHO_CEAFSR_SDRD) { - reported++; - printk("(DMA Read)"); - } - if (afsr & PSYCHO_CEAFSR_SDWR) { - reported++; - printk("(DMA Write)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - return IRQ_HANDLED; -} - -/* PCI Errors. They are signalled by the PCI bus module since they - * are associated with a specific bus segment. - */ -#define PSYCHO_PCI_AFSR_A 0x2010UL -#define PSYCHO_PCI_AFSR_B 0x4010UL -#define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL /* Primary Master Abort Error */ -#define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL /* Primary Target Abort Error */ -#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */ -#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */ -#define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort Error */ -#define PSYCHO_PCIAFSR_STA 0x0400000000000000UL /* Secondary Target Abort Error */ -#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */ -#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */ -#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL /* Reserved */ -#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ -#define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL /* Trans was block operation */ -#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL /* Reserved */ -#define PSYCHO_PCIAFSR_MID 0x000000003e000000UL /* MID causing the error */ -#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL /* Reserved */ -#define PSYCHO_PCI_AFAR_A 0x2018UL -#define PSYCHO_PCI_AFAR_B 0x4018UL - -static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm_a) -{ - unsigned long csr_reg, csr, csr_error_bits; - irqreturn_t ret = IRQ_NONE; - u16 stat; - - if (is_pbm_a) { - csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL; - } else { - csr_reg = pbm->controller_regs + PSYCHO_PCIB_CTRL; - } - csr = psycho_read(csr_reg); - csr_error_bits = - csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); - if (csr_error_bits) { - /* Clear the errors. */ - psycho_write(csr_reg, csr); - - /* Log 'em. */ - if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) - printk("%s: PCI streaming byte hole error asserted.\n", - pbm->name); - if (csr_error_bits & PSYCHO_PCICTRL_SERR) - printk("%s: PCI SERR signal asserted.\n", pbm->name); - ret = IRQ_HANDLED; - } - pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); - if (stat & (PCI_STATUS_PARITY | - PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | - PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("%s: PCI bus error, PCI_STATUS[%04x]\n", - pbm->name, stat); - pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); - ret = IRQ_HANDLED; - } - return ret; -} - -static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int is_pbm_a, reported; - - is_pbm_a = (pbm == &pbm->parent->pbm_A); - if (is_pbm_a) { - afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A; - afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A; - } else { - afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B; - afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B; - } - - /* Latch error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | - PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | - PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | - PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); - if (!error_bits) - return psycho_pcierr_intr_other(pbm, is_pbm_a); - psycho_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("PSYCHO%d(PBM%c): PCI Error, primary error type[%s]\n", - p->index, (is_pbm_a ? 'A' : 'B'), - (((error_bits & PSYCHO_PCIAFSR_PMA) ? - "Master Abort" : - ((error_bits & PSYCHO_PCIAFSR_PTA) ? - "Target Abort" : - ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? - "Excessive Retries" : - ((error_bits & PSYCHO_PCIAFSR_PPERR) ? - "Parity Error" : "???")))))); - printk("PSYCHO%d(PBM%c): bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", - p->index, (is_pbm_a ? 'A' : 'B'), - (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, - (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, - (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); - printk("PSYCHO%d(PBM%c): PCI AFAR [%016lx]\n", - p->index, (is_pbm_a ? 'A' : 'B'), afar); - printk("PSYCHO%d(PBM%c): PCI Secondary errors [", - p->index, (is_pbm_a ? 'A' : 'B')); - reported = 0; - if (afsr & PSYCHO_PCIAFSR_SMA) { - reported++; - printk("(Master Abort)"); - } - if (afsr & PSYCHO_PCIAFSR_STA) { - reported++; - printk("(Target Abort)"); - } - if (afsr & PSYCHO_PCIAFSR_SRTRY) { - reported++; - printk("(Excessive Retries)"); - } - if (afsr & PSYCHO_PCIAFSR_SPERR) { - reported++; - printk("(Parity Error)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* For the error types shown, scan PBM's PCI bus for devices - * which have logged that error type. - */ - - /* If we see a Target Abort, this could be the result of an - * IOMMU translation error of some sort. It is extremely - * useful to log this information as usually it indicates - * a bug in the IOMMU support code or a PCI device driver. - */ - if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { - psycho_check_iommu_error(p, afsr, afar, PCI_ERR); - pci_scan_for_target_abort(p, pbm, pbm->pci_bus); - } - if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) - pci_scan_for_master_abort(p, pbm, pbm->pci_bus); - - /* For excessive retries, PSYCHO/PBM will abort the device - * and there is no way to specifically check for excessive - * retries in the config space status registers. So what - * we hope is that we'll catch it via the master/target - * abort events. - */ - - if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(p, pbm, pbm->pci_bus); - - return IRQ_HANDLED; -} - -/* XXX What about PowerFail/PowerManagement??? -DaveM */ -#define PSYCHO_ECC_CTRL 0x0020 -#define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ -#define PSYCHO_ECCCTRL_UE 0x4000000000000000UL /* Enable UE Interrupts */ -#define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ -#define PSYCHO_UE_INO 0x2e -#define PSYCHO_CE_INO 0x2f -#define PSYCHO_PCIERR_A_INO 0x30 -#define PSYCHO_PCIERR_B_INO 0x31 -static void psycho_register_error_handlers(struct pci_controller_info *p) -{ - struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ - unsigned long base = p->pbm_A.controller_regs; - unsigned int irq, portid = pbm->portid; - u64 tmp; - - /* Build IRQs and register handlers. */ - irq = psycho_irq_build(pbm, NULL, (portid << 6) | PSYCHO_UE_INO); - if (request_irq(irq, psycho_ue_intr, - SA_SHIRQ, "PSYCHO UE", p) < 0) { - prom_printf("PSYCHO%d: Cannot register UE interrupt.\n", - p->index); - prom_halt(); - } - - irq = psycho_irq_build(pbm, NULL, (portid << 6) | PSYCHO_CE_INO); - if (request_irq(irq, psycho_ce_intr, - SA_SHIRQ, "PSYCHO CE", p) < 0) { - prom_printf("PSYCHO%d: Cannot register CE interrupt.\n", - p->index); - prom_halt(); - } - - pbm = &p->pbm_A; - irq = psycho_irq_build(pbm, NULL, (portid << 6) | PSYCHO_PCIERR_A_INO); - if (request_irq(irq, psycho_pcierr_intr, - SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_A) < 0) { - prom_printf("PSYCHO%d(PBMA): Cannot register PciERR interrupt.\n", - p->index); - prom_halt(); - } - - pbm = &p->pbm_B; - irq = psycho_irq_build(pbm, NULL, (portid << 6) | PSYCHO_PCIERR_B_INO); - if (request_irq(irq, psycho_pcierr_intr, - SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_B) < 0) { - prom_printf("PSYCHO%d(PBMB): Cannot register PciERR interrupt.\n", - p->index); - prom_halt(); - } - - /* Enable UE and CE interrupts for controller. */ - psycho_write(base + PSYCHO_ECC_CTRL, - (PSYCHO_ECCCTRL_EE | - PSYCHO_ECCCTRL_UE | - PSYCHO_ECCCTRL_CE)); - - /* Enable PCI Error interrupts and clear error - * bits for each PBM. - */ - tmp = psycho_read(base + PSYCHO_PCIA_CTRL); - tmp |= (PSYCHO_PCICTRL_SERR | - PSYCHO_PCICTRL_SBH_ERR | - PSYCHO_PCICTRL_EEN); - tmp &= ~(PSYCHO_PCICTRL_SBH_INT); - psycho_write(base + PSYCHO_PCIA_CTRL, tmp); - - tmp = psycho_read(base + PSYCHO_PCIB_CTRL); - tmp |= (PSYCHO_PCICTRL_SERR | - PSYCHO_PCICTRL_SBH_ERR | - PSYCHO_PCICTRL_EEN); - tmp &= ~(PSYCHO_PCICTRL_SBH_INT); - psycho_write(base + PSYCHO_PCIB_CTRL, tmp); -} - -/* PSYCHO boot time probing and initialization. */ -static void psycho_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - -static void psycho_base_address_update(struct pci_dev *pdev, int resource) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res, *root; - u32 reg; - int where, size, is_64bit; - - res = &pdev->resource[resource]; - if (resource < 6) { - where = PCI_BASE_ADDRESS_0 + (resource * 4); - } else if (resource == PCI_ROM_RESOURCE) { - where = pdev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - is_64bit = 0; - if (res->flags & IORESOURCE_IO) - root = &pbm->io_space; - else { - root = &pbm->mem_space; - if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - is_64bit = 1; - } - - size = res->end - res->start; - pci_read_config_dword(pdev, where, ®); - reg = ((reg & size) | - (((u32)(res->start - root->start)) & ~size)); - if (resource == PCI_ROM_RESOURCE) { - reg |= PCI_ROM_ADDRESS_ENABLE; - res->flags |= IORESOURCE_ROM_ENABLE; - } - pci_write_config_dword(pdev, where, reg); - - /* This knows that the upper 32-bits of the address - * must be zero. Our PCI common layer enforces this. - */ - if (is_64bit) - pci_write_config_dword(pdev, where + 4, 0); -} - -static void pbm_config_busmastering(struct pci_pbm_info *pbm) -{ - u8 *addr; - - /* Set cache-line size to 64 bytes, this is actually - * a nop but I do it for completeness. - */ - addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, - 0, PCI_CACHE_LINE_SIZE); - pci_config_write8(addr, 64 / sizeof(u32)); - - /* Set PBM latency timer to 64 PCI clocks. */ - addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, - 0, PCI_LATENCY_TIMER); - pci_config_write8(addr, 64); -} - -static void pbm_scan_bus(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("PSYCHO: Critical allocation failure.\n"); - prom_halt(); - } - - /* All we care about is the PBM. */ - memset(cookie, 0, sizeof(*cookie)); - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, - p->pci_ops, - pbm); - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; - - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); -} - -static void psycho_scan_bus(struct pci_controller_info *p) -{ - pbm_config_busmastering(&p->pbm_B); - p->pbm_B.is_66mhz_capable = 0; - pbm_config_busmastering(&p->pbm_A); - p->pbm_A.is_66mhz_capable = 1; - pbm_scan_bus(p, &p->pbm_B); - pbm_scan_bus(p, &p->pbm_A); - - /* After the PCI bus scan is complete, we can register - * the error interrupt handlers. - */ - psycho_register_error_handlers(p); -} - -static void psycho_iommu_init(struct pci_controller_info *p) -{ - struct pci_iommu *iommu = p->pbm_A.iommu; - unsigned long i; - u64 control; - - /* Register addresses. */ - iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; - iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE; - iommu->iommu_flush = p->pbm_A.controller_regs + PSYCHO_IOMMU_FLUSH; - /* PSYCHO's IOMMU lacks ctx flushing. */ - iommu->iommu_ctxflush = 0; - - /* We use the main control register of PSYCHO as the write - * completion register. - */ - iommu->write_complete_reg = p->pbm_A.controller_regs + PSYCHO_CONTROL; - - /* - * Invalidate TLB Entries. - */ - control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); - control |= PSYCHO_IOMMU_CTRL_DENAB; - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); - for(i = 0; i < 16; i++) { - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diag mode enabled for full-flushing done - * in pci_iommu.c - */ - pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff); - - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, - __pa(iommu->page_table)); - - control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); - control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); - control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); - - /* If necessary, hook us up for starfire IRQ translations. */ - if (this_is_starfire) - p->starfire_cookie = starfire_hookup(p->pbm_A.portid); - else - p->starfire_cookie = NULL; -} - -#define PSYCHO_IRQ_RETRY 0x1a00UL -#define PSYCHO_PCIA_DIAG 0x2020UL -#define PSYCHO_PCIB_DIAG 0x4020UL -#define PSYCHO_PCIDIAG_RESV 0xffffffffffffff80UL /* Reserved */ -#define PSYCHO_PCIDIAG_DRETRY 0x0000000000000040UL /* Disable retry limit */ -#define PSYCHO_PCIDIAG_DISYNC 0x0000000000000020UL /* Disable DMA wr / irq sync */ -#define PSYCHO_PCIDIAG_DDWSYNC 0x0000000000000010UL /* Disable DMA wr / PIO rd sync */ -#define PSYCHO_PCIDIAG_IDDPAR 0x0000000000000008UL /* Invert DMA data parity */ -#define PSYCHO_PCIDIAG_IPDPAR 0x0000000000000004UL /* Invert PIO data parity */ -#define PSYCHO_PCIDIAG_IPAPAR 0x0000000000000002UL /* Invert PIO address parity */ -#define PSYCHO_PCIDIAG_LPBACK 0x0000000000000001UL /* Enable loopback mode */ - -static void psycho_controller_hwinit(struct pci_controller_info *p) -{ - u64 tmp; - - psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 5); - - /* Enable arbiter for all PCI slots. */ - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL); - tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL, tmp); - - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL); - tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL, tmp); - - /* Disable DMA write / PIO read synchronization on - * both PCI bus segments. - * [ U2P Erratum 1243770, STP2223BGA data sheet ] - */ - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG); - tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG, tmp); - - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG); - tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp); -} - -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - char *name = pbm->name; - - sprintf(name, "PSYCHO%d PBM%c", - p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); - pbm->io_space.name = pbm->mem_space.name = name; - - request_resource(&ioport_resource, &pbm->io_space); - request_resource(&iomem_resource, &pbm->mem_space); - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - -static void psycho_pbm_strbuf_init(struct pci_controller_info *p, - struct pci_pbm_info *pbm, - int is_pbm_a) -{ - unsigned long base = pbm->controller_regs; - u64 control; - - if (is_pbm_a) { - pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; - pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; - pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; - } else { - pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; - pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; - pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; - } - /* PSYCHO's streaming buffer lacks ctx flushing. */ - pbm->stc.strbuf_ctxflush = 0; - pbm->stc.strbuf_ctxmatch_base = 0; - - pbm->stc.strbuf_flushflag = (volatile unsigned long *) - ((((unsigned long)&pbm->stc.__flushflag_buf[0]) - + 63UL) - & ~63UL); - pbm->stc.strbuf_flushflag_pa = (unsigned long) - __pa(pbm->stc.strbuf_flushflag); - - /* Enable the streaming buffer. We have to be careful - * just in case OBP left it with LRU locking enabled. - * - * It is possible to control if PBM will be rerun on - * line misses. Currently I just retain whatever setting - * OBP left us with. All checks so far show it having - * a value of zero. - */ -#undef PSYCHO_STRBUF_RERUN_ENABLE -#undef PSYCHO_STRBUF_RERUN_DISABLE - control = psycho_read(pbm->stc.strbuf_control); - control |= PSYCHO_STRBUF_CTRL_ENAB; - control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); -#ifdef PSYCHO_STRBUF_RERUN_ENABLE - control &= ~(PSYCHO_STRBUF_CTRL_RRDIS); -#else -#ifdef PSYCHO_STRBUF_RERUN_DISABLE - control |= PSYCHO_STRBUF_CTRL_RRDIS; -#endif -#endif - psycho_write(pbm->stc.strbuf_control, control); - - pbm->stc.strbuf_enabled = 1; -} - -#define PSYCHO_IOSPACE_A 0x002000000UL -#define PSYCHO_IOSPACE_B 0x002010000UL -#define PSYCHO_IOSPACE_SIZE 0x00000ffffUL -#define PSYCHO_MEMSPACE_A 0x100000000UL -#define PSYCHO_MEMSPACE_B 0x180000000UL -#define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL - -static void psycho_pbm_init(struct pci_controller_info *p, - int prom_node, int is_pbm_a) -{ - unsigned int busrange[2]; - struct pci_pbm_info *pbm; - int err; - - if (is_pbm_a) { - pbm = &p->pbm_A; - pbm->pci_first_slot = 1; - pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A; - pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A; - } else { - pbm = &p->pbm_B; - pbm->pci_first_slot = 2; - pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_B; - pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_B; - } - - pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; - pbm->chip_version = - prom_getintdefault(prom_node, "version#", 0); - pbm->chip_revision = - prom_getintdefault(prom_node, "module-revision#", 0); - - pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE; - pbm->io_space.flags = IORESOURCE_IO; - pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE; - pbm->mem_space.flags = IORESOURCE_MEM; - pbm_register_toplevel_resources(p, pbm); - - pbm->parent = p; - pbm->prom_node = prom_node; - prom_getstring(prom_node, "name", - pbm->prom_name, - sizeof(pbm->prom_name)); - - err = prom_getproperty(prom_node, "ranges", - (char *)pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err != -1) - pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); - else - pbm->num_pbm_ranges = 0; - - err = prom_getproperty(prom_node, "interrupt-map", - (char *)pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(prom_node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("PSYCHO-PBM: Fatal error, no " - "interrupt-map-mask.\n"); - prom_halt(); - } - } else { - pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); - } - - err = prom_getproperty(prom_node, "bus-range", - (char *)&busrange[0], - sizeof(busrange)); - if (err == 0 || err == -1) { - prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n"); - prom_halt(); - } - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; - - psycho_pbm_strbuf_init(p, pbm, is_pbm_a); -} - -#define PSYCHO_CONFIGSPACE 0x001000000UL - -void psycho_init(int node, char *model_name) -{ - struct linux_prom64_registers pr_regs[3]; - struct pci_controller_info *p; - struct pci_iommu *iommu; - u32 upa_portid; - int is_pbm_a, err; - - upa_portid = prom_getintdefault(node, "upa-portid", 0xff); - - for(p = pci_controller_root; p; p = p->next) { - if (p->pbm_A.portid == upa_portid) { - is_pbm_a = (p->pbm_A.prom_node == 0); - psycho_pbm_init(p, node, is_pbm_a); - return; - } - } - - p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - prom_printf("PSYCHO: Fatal memory allocation error.\n"); - prom_halt(); - } - memset(p, 0, sizeof(*p)); - iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); - if (!iommu) { - prom_printf("PSYCHO: Fatal memory allocation error.\n"); - prom_halt(); - } - memset(iommu, 0, sizeof(*iommu)); - p->pbm_A.iommu = p->pbm_B.iommu = iommu; - - p->next = pci_controller_root; - pci_controller_root = p; - - p->pbm_A.portid = upa_portid; - p->pbm_B.portid = upa_portid; - p->index = pci_num_controllers++; - p->pbms_same_domain = 0; - p->scan_bus = psycho_scan_bus; - p->irq_build = psycho_irq_build; - p->base_address_update = psycho_base_address_update; - p->resource_adjust = psycho_resource_adjust; - p->pci_ops = &psycho_ops; - - err = prom_getproperty(node, "reg", - (char *)&pr_regs[0], - sizeof(pr_regs)); - if (err == 0 || err == -1) { - prom_printf("PSYCHO: Fatal error, no reg property.\n"); - prom_halt(); - } - - p->pbm_A.controller_regs = pr_regs[2].phys_addr; - p->pbm_B.controller_regs = pr_regs[2].phys_addr; - printk("PCI: Found PSYCHO, control regs at %016lx\n", - p->pbm_A.controller_regs); - - p->pbm_A.config_space = p->pbm_B.config_space = - (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); - printk("PSYCHO: Shared PCI config space at %016lx\n", - p->pbm_A.config_space); - - /* - * Psycho's PCI MEM space is mapped to a 2GB aligned area, so - * we need to adjust our MEM space mask. - */ - pci_memspace_mask = 0x7fffffffUL; - - psycho_controller_hwinit(p); - - psycho_iommu_init(p); - - is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); - psycho_pbm_init(p, node, is_pbm_a); -} diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c deleted file mode 100644 index da8e1364194..00000000000 --- a/arch/sparc64/kernel/pci_sabre.c +++ /dev/null @@ -1,1677 +0,0 @@ -/* $Id: pci_sabre.c,v 1.42 2002/01/23 11:27:32 davem Exp $ - * pci_sabre.c: Sabre specific PCI controller support. - * - * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) - * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> - -#include <asm/apb.h> -#include <asm/pbm.h> -#include <asm/iommu.h> -#include <asm/irq.h> -#include <asm/smp.h> -#include <asm/oplib.h> - -#include "pci_impl.h" -#include "iommu_common.h" - -/* All SABRE registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define sabre_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define sabre_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - -/* SABRE PCI controller register offsets and definitions. */ -#define SABRE_UE_AFSR 0x0030UL -#define SABRE_UEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */ -#define SABRE_UEAFSR_PDWR 0x2000000000000000UL /* Primary PCI DMA Write */ -#define SABRE_UEAFSR_SDRD 0x0800000000000000UL /* Secondary PCI DMA Read */ -#define SABRE_UEAFSR_SDWR 0x0400000000000000UL /* Secondary PCI DMA Write */ -#define SABRE_UEAFSR_SDTE 0x0200000000000000UL /* Secondary DMA Translation Error */ -#define SABRE_UEAFSR_PDTE 0x0100000000000000UL /* Primary DMA Translation Error */ -#define SABRE_UEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask */ -#define SABRE_UEAFSR_OFF 0x00000000e0000000UL /* Offset (AFAR bits [5:3] */ -#define SABRE_UEAFSR_BLK 0x0000000000800000UL /* Was block operation */ -#define SABRE_UECE_AFAR 0x0038UL -#define SABRE_CE_AFSR 0x0040UL -#define SABRE_CEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */ -#define SABRE_CEAFSR_PDWR 0x2000000000000000UL /* Primary PCI DMA Write */ -#define SABRE_CEAFSR_SDRD 0x0800000000000000UL /* Secondary PCI DMA Read */ -#define SABRE_CEAFSR_SDWR 0x0400000000000000UL /* Secondary PCI DMA Write */ -#define SABRE_CEAFSR_ESYND 0x00ff000000000000UL /* ECC Syndrome */ -#define SABRE_CEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask */ -#define SABRE_CEAFSR_OFF 0x00000000e0000000UL /* Offset */ -#define SABRE_CEAFSR_BLK 0x0000000000800000UL /* Was block operation */ -#define SABRE_UECE_AFAR_ALIAS 0x0048UL /* Aliases to 0x0038 */ -#define SABRE_IOMMU_CONTROL 0x0200UL -#define SABRE_IOMMUCTRL_ERRSTS 0x0000000006000000UL /* Error status bits */ -#define SABRE_IOMMUCTRL_ERR 0x0000000001000000UL /* Error present in IOTLB */ -#define SABRE_IOMMUCTRL_LCKEN 0x0000000000800000UL /* IOTLB lock enable */ -#define SABRE_IOMMUCTRL_LCKPTR 0x0000000000780000UL /* IOTLB lock pointer */ -#define SABRE_IOMMUCTRL_TSBSZ 0x0000000000070000UL /* TSB Size */ -#define SABRE_IOMMU_TSBSZ_1K 0x0000000000000000 -#define SABRE_IOMMU_TSBSZ_2K 0x0000000000010000 -#define SABRE_IOMMU_TSBSZ_4K 0x0000000000020000 -#define SABRE_IOMMU_TSBSZ_8K 0x0000000000030000 -#define SABRE_IOMMU_TSBSZ_16K 0x0000000000040000 -#define SABRE_IOMMU_TSBSZ_32K 0x0000000000050000 -#define SABRE_IOMMU_TSBSZ_64K 0x0000000000060000 -#define SABRE_IOMMU_TSBSZ_128K 0x0000000000070000 -#define SABRE_IOMMUCTRL_TBWSZ 0x0000000000000004UL /* TSB assumed page size */ -#define SABRE_IOMMUCTRL_DENAB 0x0000000000000002UL /* Diagnostic Mode Enable */ -#define SABRE_IOMMUCTRL_ENAB 0x0000000000000001UL /* IOMMU Enable */ -#define SABRE_IOMMU_TSBBASE 0x0208UL -#define SABRE_IOMMU_FLUSH 0x0210UL -#define SABRE_IMAP_A_SLOT0 0x0c00UL -#define SABRE_IMAP_B_SLOT0 0x0c20UL -#define SABRE_IMAP_SCSI 0x1000UL -#define SABRE_IMAP_ETH 0x1008UL -#define SABRE_IMAP_BPP 0x1010UL -#define SABRE_IMAP_AU_REC 0x1018UL -#define SABRE_IMAP_AU_PLAY 0x1020UL -#define SABRE_IMAP_PFAIL 0x1028UL -#define SABRE_IMAP_KMS 0x1030UL -#define SABRE_IMAP_FLPY 0x1038UL -#define SABRE_IMAP_SHW 0x1040UL -#define SABRE_IMAP_KBD 0x1048UL -#define SABRE_IMAP_MS 0x1050UL -#define SABRE_IMAP_SER 0x1058UL -#define SABRE_IMAP_UE 0x1070UL -#define SABRE_IMAP_CE 0x1078UL -#define SABRE_IMAP_PCIERR 0x1080UL -#define SABRE_IMAP_GFX 0x1098UL -#define SABRE_IMAP_EUPA 0x10a0UL -#define SABRE_ICLR_A_SLOT0 0x1400UL -#define SABRE_ICLR_B_SLOT0 0x1480UL -#define SABRE_ICLR_SCSI 0x1800UL -#define SABRE_ICLR_ETH 0x1808UL -#define SABRE_ICLR_BPP 0x1810UL -#define SABRE_ICLR_AU_REC 0x1818UL -#define SABRE_ICLR_AU_PLAY 0x1820UL -#define SABRE_ICLR_PFAIL 0x1828UL -#define SABRE_ICLR_KMS 0x1830UL -#define SABRE_ICLR_FLPY 0x1838UL -#define SABRE_ICLR_SHW 0x1840UL -#define SABRE_ICLR_KBD 0x1848UL -#define SABRE_ICLR_MS 0x1850UL -#define SABRE_ICLR_SER 0x1858UL -#define SABRE_ICLR_UE 0x1870UL -#define SABRE_ICLR_CE 0x1878UL -#define SABRE_ICLR_PCIERR 0x1880UL -#define SABRE_WRSYNC 0x1c20UL -#define SABRE_PCICTRL 0x2000UL -#define SABRE_PCICTRL_MRLEN 0x0000001000000000UL /* Use MemoryReadLine for block loads/stores */ -#define SABRE_PCICTRL_SERR 0x0000000400000000UL /* Set when SERR asserted on PCI bus */ -#define SABRE_PCICTRL_ARBPARK 0x0000000000200000UL /* Bus Parking 0=Ultra-IIi 1=prev-bus-owner */ -#define SABRE_PCICTRL_CPUPRIO 0x0000000000100000UL /* Ultra-IIi granted every other bus cycle */ -#define SABRE_PCICTRL_ARBPRIO 0x00000000000f0000UL /* Slot which is granted every other bus cycle */ -#define SABRE_PCICTRL_ERREN 0x0000000000000100UL /* PCI Error Interrupt Enable */ -#define SABRE_PCICTRL_RTRYWE 0x0000000000000080UL /* DMA Flow Control 0=wait-if-possible 1=retry */ -#define SABRE_PCICTRL_AEN 0x000000000000000fUL /* Slot PCI arbitration enables */ -#define SABRE_PIOAFSR 0x2010UL -#define SABRE_PIOAFSR_PMA 0x8000000000000000UL /* Primary Master Abort */ -#define SABRE_PIOAFSR_PTA 0x4000000000000000UL /* Primary Target Abort */ -#define SABRE_PIOAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */ -#define SABRE_PIOAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */ -#define SABRE_PIOAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort */ -#define SABRE_PIOAFSR_STA 0x0400000000000000UL /* Secondary Target Abort */ -#define SABRE_PIOAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */ -#define SABRE_PIOAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */ -#define SABRE_PIOAFSR_BMSK 0x0000ffff00000000UL /* Byte Mask */ -#define SABRE_PIOAFSR_BLK 0x0000000080000000UL /* Was Block Operation */ -#define SABRE_PIOAFAR 0x2018UL -#define SABRE_PCIDIAG 0x2020UL -#define SABRE_PCIDIAG_DRTRY 0x0000000000000040UL /* Disable PIO Retry Limit */ -#define SABRE_PCIDIAG_IPAPAR 0x0000000000000008UL /* Invert PIO Address Parity */ -#define SABRE_PCIDIAG_IPDPAR 0x0000000000000004UL /* Invert PIO Data Parity */ -#define SABRE_PCIDIAG_IDDPAR 0x0000000000000002UL /* Invert DMA Data Parity */ -#define SABRE_PCIDIAG_ELPBK 0x0000000000000001UL /* Loopback Enable - not supported */ -#define SABRE_PCITASR 0x2028UL -#define SABRE_PCITASR_EF 0x0000000000000080UL /* Respond to 0xe0000000-0xffffffff */ -#define SABRE_PCITASR_CD 0x0000000000000040UL /* Respond to 0xc0000000-0xdfffffff */ -#define SABRE_PCITASR_AB 0x0000000000000020UL /* Respond to 0xa0000000-0xbfffffff */ -#define SABRE_PCITASR_89 0x0000000000000010UL /* Respond to 0x80000000-0x9fffffff */ -#define SABRE_PCITASR_67 0x0000000000000008UL /* Respond to 0x60000000-0x7fffffff */ -#define SABRE_PCITASR_45 0x0000000000000004UL /* Respond to 0x40000000-0x5fffffff */ -#define SABRE_PCITASR_23 0x0000000000000002UL /* Respond to 0x20000000-0x3fffffff */ -#define SABRE_PCITASR_01 0x0000000000000001UL /* Respond to 0x00000000-0x1fffffff */ -#define SABRE_PIOBUF_DIAG 0x5000UL -#define SABRE_DMABUF_DIAGLO 0x5100UL -#define SABRE_DMABUF_DIAGHI 0x51c0UL -#define SABRE_IMAP_GFX_ALIAS 0x6000UL /* Aliases to 0x1098 */ -#define SABRE_IMAP_EUPA_ALIAS 0x8000UL /* Aliases to 0x10a0 */ -#define SABRE_IOMMU_VADIAG 0xa400UL -#define SABRE_IOMMU_TCDIAG 0xa408UL -#define SABRE_IOMMU_TAG 0xa580UL -#define SABRE_IOMMUTAG_ERRSTS 0x0000000001800000UL /* Error status bits */ -#define SABRE_IOMMUTAG_ERR 0x0000000000400000UL /* Error present */ -#define SABRE_IOMMUTAG_WRITE 0x0000000000200000UL /* Page is writable */ -#define SABRE_IOMMUTAG_STREAM 0x0000000000100000UL /* Streamable bit - unused */ -#define SABRE_IOMMUTAG_SIZE 0x0000000000080000UL /* 0=8k 1=16k */ -#define SABRE_IOMMUTAG_VPN 0x000000000007ffffUL /* Virtual Page Number [31:13] */ -#define SABRE_IOMMU_DATA 0xa600UL -#define SABRE_IOMMUDATA_VALID 0x0000000040000000UL /* Valid */ -#define SABRE_IOMMUDATA_USED 0x0000000020000000UL /* Used (for LRU algorithm) */ -#define SABRE_IOMMUDATA_CACHE 0x0000000010000000UL /* Cacheable */ -#define SABRE_IOMMUDATA_PPN 0x00000000001fffffUL /* Physical Page Number [33:13] */ -#define SABRE_PCI_IRQSTATE 0xa800UL -#define SABRE_OBIO_IRQSTATE 0xa808UL -#define SABRE_FFBCFG 0xf000UL -#define SABRE_FFBCFG_SPRQS 0x000000000f000000 /* Slave P_RQST queue size */ -#define SABRE_FFBCFG_ONEREAD 0x0000000000004000 /* Slave supports one outstanding read */ -#define SABRE_MCCTRL0 0xf010UL -#define SABRE_MCCTRL0_RENAB 0x0000000080000000 /* Refresh Enable */ -#define SABRE_MCCTRL0_EENAB 0x0000000010000000 /* Enable all ECC functions */ -#define SABRE_MCCTRL0_11BIT 0x0000000000001000 /* Enable 11-bit column addressing */ -#define SABRE_MCCTRL0_DPP 0x0000000000000f00 /* DIMM Pair Present Bits */ -#define SABRE_MCCTRL0_RINTVL 0x00000000000000ff /* Refresh Interval */ -#define SABRE_MCCTRL1 0xf018UL -#define SABRE_MCCTRL1_AMDC 0x0000000038000000 /* Advance Memdata Clock */ -#define SABRE_MCCTRL1_ARDC 0x0000000007000000 /* Advance DRAM Read Data Clock */ -#define SABRE_MCCTRL1_CSR 0x0000000000e00000 /* CAS to RAS delay for CBR refresh */ -#define SABRE_MCCTRL1_CASRW 0x00000000001c0000 /* CAS length for read/write */ -#define SABRE_MCCTRL1_RCD 0x0000000000038000 /* RAS to CAS delay */ -#define SABRE_MCCTRL1_CP 0x0000000000007000 /* CAS Precharge */ -#define SABRE_MCCTRL1_RP 0x0000000000000e00 /* RAS Precharge */ -#define SABRE_MCCTRL1_RAS 0x00000000000001c0 /* Length of RAS for refresh */ -#define SABRE_MCCTRL1_CASRW2 0x0000000000000038 /* Must be same as CASRW */ -#define SABRE_MCCTRL1_RSC 0x0000000000000007 /* RAS after CAS hold time */ -#define SABRE_RESETCTRL 0xf020UL - -#define SABRE_CONFIGSPACE 0x001000000UL -#define SABRE_IOSPACE 0x002000000UL -#define SABRE_IOSPACE_SIZE 0x000ffffffUL -#define SABRE_MEMSPACE 0x100000000UL -#define SABRE_MEMSPACE_SIZE 0x07fffffffUL - -/* UltraSparc-IIi Programmer's Manual, page 325, PCI - * configuration space address format: - * - * 32 24 23 16 15 11 10 8 7 2 1 0 - * --------------------------------------------------------- - * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | - * --------------------------------------------------------- - */ -#define SABRE_CONFIG_BASE(PBM) \ - ((PBM)->config_space | (1UL << 24)) -#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ - (((unsigned long)(BUS) << 16) | \ - ((unsigned long)(DEVFN) << 8) | \ - ((unsigned long)(REG))) - -static int hummingbird_p; -static struct pci_bus *sabre_root_bus; - -static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm, - unsigned char bus, - unsigned int devfn, - int where) -{ - if (!pbm) - return NULL; - return (void *) - (SABRE_CONFIG_BASE(pbm) | - SABRE_CONFIG_ENCODE(bus, devfn, where)); -} - -static int sabre_out_of_range(unsigned char devfn) -{ - if (hummingbird_p) - return 0; - - return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) || - ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) || - (PCI_SLOT(devfn) > 1)); -} - -static int __sabre_out_of_range(struct pci_pbm_info *pbm, - unsigned char bus, - unsigned char devfn) -{ - if (hummingbird_p) - return 0; - - return ((pbm->parent == 0) || - ((pbm == &pbm->parent->pbm_B) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8) || - ((pbm == &pbm->parent->pbm_A) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8)); -} - -static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 *value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - u16 tmp16; - u8 tmp8; - - switch (size) { - case 1: - *value = 0xff; - break; - case 2: - *value = 0xffff; - break; - case 4: - *value = 0xffffffff; - break; - } - - addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - if (__sabre_out_of_range(pbm, bus, devfn)) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_read8((u8 *) addr, &tmp8); - *value = tmp8; - break; - - case 2: - if (where & 0x01) { - printk("pci_read_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read16((u16 *) addr, &tmp16); - *value = tmp16; - break; - - case 4: - if (where & 0x03) { - printk("pci_read_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read32(addr, value); - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 *value) -{ - if (!bus->number && sabre_out_of_range(devfn)) { - switch (size) { - case 1: - *value = 0xff; - break; - case 2: - *value = 0xffff; - break; - case 4: - *value = 0xffffffff; - break; - } - return PCIBIOS_SUCCESSFUL; - } - - if (bus->number || PCI_SLOT(devfn)) - return __sabre_read_pci_cfg(bus, devfn, where, size, value); - - /* When accessing PCI config space of the PCI controller itself (bus - * 0, device slot 0, function 0) there are restrictions. Each - * register must be accessed as it's natural size. Thus, for example - * the Vendor ID must be accessed as a 16-bit quantity. - */ - - switch (size) { - case 1: - if (where < 8) { - u32 tmp32; - u16 tmp16; - - __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); - tmp16 = (u16) tmp32; - if (where & 1) - *value = tmp16 >> 8; - else - *value = tmp16 & 0xff; - } else - return __sabre_read_pci_cfg(bus, devfn, where, 1, value); - break; - - case 2: - if (where < 8) - return __sabre_read_pci_cfg(bus, devfn, where, 2, value); - else { - u32 tmp32; - u8 tmp8; - - __sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32); - tmp8 = (u8) tmp32; - *value = tmp8; - __sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32); - tmp8 = (u8) tmp32; - *value |= tmp8 << 8; - } - break; - - case 4: { - u32 tmp32; - u16 tmp16; - - sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32); - tmp16 = (u16) tmp32; - *value = tmp16; - sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32); - tmp16 = (u16) tmp32; - *value |= tmp16 << 16; - break; - } - } - return PCIBIOS_SUCCESSFUL; -} - -static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - - addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - if (__sabre_out_of_range(pbm, bus, devfn)) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_write8((u8 *) addr, value); - break; - - case 2: - if (where & 0x01) { - printk("pci_write_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write16((u16 *) addr, value); - break; - - case 4: - if (where & 0x03) { - printk("pci_write_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write32(addr, value); - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 value) -{ - if (bus->number) - return __sabre_write_pci_cfg(bus, devfn, where, size, value); - - if (sabre_out_of_range(devfn)) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - if (where < 8) { - u32 tmp32; - u16 tmp16; - - __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); - tmp16 = (u16) tmp32; - if (where & 1) { - value &= 0x00ff; - value |= tmp16 << 8; - } else { - value &= 0xff00; - value |= tmp16; - } - tmp32 = (u32) tmp16; - return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32); - } else - return __sabre_write_pci_cfg(bus, devfn, where, 1, value); - break; - case 2: - if (where < 8) - return __sabre_write_pci_cfg(bus, devfn, where, 2, value); - else { - __sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff); - __sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8); - } - break; - case 4: - sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff); - sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops sabre_ops = { - .read = sabre_read_pci_cfg, - .write = sabre_write_pci_cfg, -}; - -static unsigned long sabre_pcislot_imap_offset(unsigned long ino) -{ - unsigned int bus = (ino & 0x10) >> 4; - unsigned int slot = (ino & 0x0c) >> 2; - - if (bus == 0) - return SABRE_IMAP_A_SLOT0 + (slot * 8); - else - return SABRE_IMAP_B_SLOT0 + (slot * 8); -} - -static unsigned long __onboard_imap_off[] = { -/*0x20*/ SABRE_IMAP_SCSI, -/*0x21*/ SABRE_IMAP_ETH, -/*0x22*/ SABRE_IMAP_BPP, -/*0x23*/ SABRE_IMAP_AU_REC, -/*0x24*/ SABRE_IMAP_AU_PLAY, -/*0x25*/ SABRE_IMAP_PFAIL, -/*0x26*/ SABRE_IMAP_KMS, -/*0x27*/ SABRE_IMAP_FLPY, -/*0x28*/ SABRE_IMAP_SHW, -/*0x29*/ SABRE_IMAP_KBD, -/*0x2a*/ SABRE_IMAP_MS, -/*0x2b*/ SABRE_IMAP_SER, -/*0x2c*/ 0 /* reserved */, -/*0x2d*/ 0 /* reserved */, -/*0x2e*/ SABRE_IMAP_UE, -/*0x2f*/ SABRE_IMAP_CE, -/*0x30*/ SABRE_IMAP_PCIERR, -}; -#define SABRE_ONBOARD_IRQ_BASE 0x20 -#define SABRE_ONBOARD_IRQ_LAST 0x30 -#define sabre_onboard_imap_offset(__ino) \ - __onboard_imap_off[(__ino) - SABRE_ONBOARD_IRQ_BASE] - -#define sabre_iclr_offset(ino) \ - ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ - (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) - -/* PCI SABRE INO number to Sparc PIL level. */ -static unsigned char sabre_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ -/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ -/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ -/*0x20*/4, /* SCSI */ -/*0x21*/5, /* Ethernet */ -/*0x22*/8, /* Parallel Port */ -/*0x23*/13, /* Audio Record */ -/*0x24*/14, /* Audio Playback */ -/*0x25*/15, /* PowerFail */ -/*0x26*/4, /* second SCSI */ -/*0x27*/11, /* Floppy */ -/*0x28*/4, /* Spare Hardware */ -/*0x29*/9, /* Keyboard */ -/*0x2a*/4, /* Mouse */ -/*0x2b*/12, /* Serial */ -/*0x2c*/10, /* Timer 0 */ -/*0x2d*/11, /* Timer 1 */ -/*0x2e*/15, /* Uncorrectable ECC */ -/*0x2f*/15, /* Correctable ECC */ -/*0x30*/15, /* PCI Bus A Error */ -/*0x31*/15, /* PCI Bus B Error */ -/*0x32*/15, /* Power Management */ -}; - -static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - if (pdev && - pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 9; - - ret = sabre_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 4; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 4; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 4; - break; - }; - } - return ret; -} - -/* When a device lives behind a bridge deeper in the PCI bus topology - * than APB, a special sequence must run to make sure all pending DMA - * transfers at the time of IRQ delivery are visible in the coherency - * domain by the cpu. This sequence is to perform a read on the far - * side of the non-APB bridge, then perform a read of Sabre's DMA - * write-sync register. - */ -static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) -{ - struct pci_dev *pdev = _arg1; - unsigned long sync_reg = (unsigned long) _arg2; - u16 _unused; - - pci_read_config_word(pdev, PCI_VENDOR_ID, &_unused); - sabre_read(sync_reg); -} - -static unsigned int sabre_irq_build(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - unsigned int ino) -{ - struct ino_bucket *bucket; - unsigned long imap, iclr; - unsigned long imap_off, iclr_off; - int pil, inofixup = 0; - - ino &= PCI_IRQ_INO; - if (ino < SABRE_ONBOARD_IRQ_BASE) { - /* PCI slot */ - imap_off = sabre_pcislot_imap_offset(ino); - } else { - /* onboard device */ - if (ino > SABRE_ONBOARD_IRQ_LAST) { - prom_printf("sabre_irq_build: Wacky INO [%x]\n", ino); - prom_halt(); - } - imap_off = sabre_onboard_imap_offset(ino); - } - - /* Now build the IRQ bucket. */ - pil = sabre_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - - imap = pbm->controller_regs + imap_off; - imap += 4; - - iclr_off = sabre_iclr_offset(ino); - iclr = pbm->controller_regs + iclr_off; - iclr += 4; - - if ((ino & 0x20) == 0) - inofixup = ino & 0x03; - - bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); - bucket->flags |= IBF_PCI; - - if (pdev) { - struct pcidev_cookie *pcp = pdev->sysdata; - - if (pdev->bus->number != pcp->pbm->pci_first_busno) { - struct pci_controller_info *p = pcp->pbm->parent; - struct irq_desc *d = bucket->irq_info; - - d->pre_handler = sabre_wsync_handler; - d->pre_handler_arg1 = pdev; - d->pre_handler_arg2 = (void *) - p->pbm_A.controller_regs + SABRE_WRSYNC; - } - } - return __irq(bucket); -} - -/* SABRE error handling support. */ -static void sabre_check_iommu_error(struct pci_controller_info *p, - unsigned long afsr, - unsigned long afar) -{ - struct pci_iommu *iommu = p->pbm_A.iommu; - unsigned long iommu_tag[16]; - unsigned long iommu_data[16]; - unsigned long flags; - u64 control; - int i; - - spin_lock_irqsave(&iommu->lock, flags); - control = sabre_read(iommu->iommu_control); - if (control & SABRE_IOMMUCTRL_ERR) { - char *type_string; - - /* Clear the error encountered bit. - * NOTE: On Sabre this is write 1 to clear, - * which is different from Psycho. - */ - sabre_write(iommu->iommu_control, control); - switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) { - case 1: - type_string = "Invalid Error"; - break; - case 3: - type_string = "ECC Error"; - break; - default: - type_string = "Unknown"; - break; - }; - printk("SABRE%d: IOMMU Error, type[%s]\n", - p->index, type_string); - - /* Enter diagnostic mode and probe for error'd - * entries in the IOTLB. - */ - control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR); - sabre_write(iommu->iommu_control, - (control | SABRE_IOMMUCTRL_DENAB)); - for (i = 0; i < 16; i++) { - unsigned long base = p->pbm_A.controller_regs; - - iommu_tag[i] = - sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); - iommu_data[i] = - sabre_read(base + SABRE_IOMMU_DATA + (i * 8UL)); - sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0); - } - sabre_write(iommu->iommu_control, control); - - for (i = 0; i < 16; i++) { - unsigned long tag, data; - - tag = iommu_tag[i]; - if (!(tag & SABRE_IOMMUTAG_ERR)) - continue; - - data = iommu_data[i]; - switch((tag & SABRE_IOMMUTAG_ERRSTS) >> 23UL) { - case 1: - type_string = "Invalid Error"; - break; - case 3: - type_string = "ECC Error"; - break; - default: - type_string = "Unknown"; - break; - }; - printk("SABRE%d: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", - p->index, i, tag, type_string, - ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), - ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), - ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); - printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", - p->index, i, data, - ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), - ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), - ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), - ((data & SABRE_IOMMUDATA_PPN) << IOMMU_PAGE_SHIFT)); - } - } - spin_unlock_irqrestore(&iommu->lock, flags); -} - -static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR; - unsigned long afsr, afar, error_bits; - int reported; - - /* Latch uncorrectable error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); - - /* Clear the primary/secondary error status bits. */ - error_bits = afsr & - (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | - SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | - SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); - if (!error_bits) - return IRQ_NONE; - sabre_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("SABRE%d: Uncorrectable Error, primary error type[%s%s]\n", - p->index, - ((error_bits & SABRE_UEAFSR_PDRD) ? - "DMA Read" : - ((error_bits & SABRE_UEAFSR_PDWR) ? - "DMA Write" : "???")), - ((error_bits & SABRE_UEAFSR_PDTE) ? - ":Translation Error" : "")); - printk("SABRE%d: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n", - p->index, - (afsr & SABRE_UEAFSR_BMSK) >> 32UL, - (afsr & SABRE_UEAFSR_OFF) >> 29UL, - ((afsr & SABRE_UEAFSR_BLK) ? 1 : 0)); - printk("SABRE%d: UE AFAR [%016lx]\n", p->index, afar); - printk("SABRE%d: UE Secondary errors [", p->index); - reported = 0; - if (afsr & SABRE_UEAFSR_SDRD) { - reported++; - printk("(DMA Read)"); - } - if (afsr & SABRE_UEAFSR_SDWR) { - reported++; - printk("(DMA Write)"); - } - if (afsr & SABRE_UEAFSR_SDTE) { - reported++; - printk("(Translation Error)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* Interrogate IOMMU for error status. */ - sabre_check_iommu_error(p, afsr, afar); - - return IRQ_HANDLED; -} - -static irqreturn_t sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR; - unsigned long afsr, afar, error_bits; - int reported; - - /* Latch error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | - SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); - if (!error_bits) - return IRQ_NONE; - sabre_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("SABRE%d: Correctable Error, primary error type[%s]\n", - p->index, - ((error_bits & SABRE_CEAFSR_PDRD) ? - "DMA Read" : - ((error_bits & SABRE_CEAFSR_PDWR) ? - "DMA Write" : "???"))); - - /* XXX Use syndrome and afar to print out module string just like - * XXX UDB CE trap handler does... -DaveM - */ - printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " - "was_block(%d)\n", - p->index, - (afsr & SABRE_CEAFSR_ESYND) >> 48UL, - (afsr & SABRE_CEAFSR_BMSK) >> 32UL, - (afsr & SABRE_CEAFSR_OFF) >> 29UL, - ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0)); - printk("SABRE%d: CE AFAR [%016lx]\n", p->index, afar); - printk("SABRE%d: CE Secondary errors [", p->index); - reported = 0; - if (afsr & SABRE_CEAFSR_SDRD) { - reported++; - printk("(DMA Read)"); - } - if (afsr & SABRE_CEAFSR_SDWR) { - reported++; - printk("(DMA Write)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - return IRQ_HANDLED; -} - -static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) -{ - unsigned long csr_reg, csr, csr_error_bits; - irqreturn_t ret = IRQ_NONE; - u16 stat; - - csr_reg = p->pbm_A.controller_regs + SABRE_PCICTRL; - csr = sabre_read(csr_reg); - csr_error_bits = - csr & SABRE_PCICTRL_SERR; - if (csr_error_bits) { - /* Clear the errors. */ - sabre_write(csr_reg, csr); - - /* Log 'em. */ - if (csr_error_bits & SABRE_PCICTRL_SERR) - printk("SABRE%d: PCI SERR signal asserted.\n", - p->index); - ret = IRQ_HANDLED; - } - pci_read_config_word(sabre_root_bus->self, - PCI_STATUS, &stat); - if (stat & (PCI_STATUS_PARITY | - PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | - PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n", - p->index, stat); - pci_write_config_word(sabre_root_bus->self, - PCI_STATUS, 0xffff); - ret = IRQ_HANDLED; - } - return ret; -} - -static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int reported; - - afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR; - afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR; - - /* Latch error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA | - SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR | - SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA | - SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR); - if (!error_bits) - return sabre_pcierr_intr_other(p); - sabre_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("SABRE%d: PCI Error, primary error type[%s]\n", - p->index, - (((error_bits & SABRE_PIOAFSR_PMA) ? - "Master Abort" : - ((error_bits & SABRE_PIOAFSR_PTA) ? - "Target Abort" : - ((error_bits & SABRE_PIOAFSR_PRTRY) ? - "Excessive Retries" : - ((error_bits & SABRE_PIOAFSR_PPERR) ? - "Parity Error" : "???")))))); - printk("SABRE%d: bytemask[%04lx] was_block(%d)\n", - p->index, - (afsr & SABRE_PIOAFSR_BMSK) >> 32UL, - (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0); - printk("SABRE%d: PCI AFAR [%016lx]\n", p->index, afar); - printk("SABRE%d: PCI Secondary errors [", p->index); - reported = 0; - if (afsr & SABRE_PIOAFSR_SMA) { - reported++; - printk("(Master Abort)"); - } - if (afsr & SABRE_PIOAFSR_STA) { - reported++; - printk("(Target Abort)"); - } - if (afsr & SABRE_PIOAFSR_SRTRY) { - reported++; - printk("(Excessive Retries)"); - } - if (afsr & SABRE_PIOAFSR_SPERR) { - reported++; - printk("(Parity Error)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* For the error types shown, scan both PCI buses for devices - * which have logged that error type. - */ - - /* If we see a Target Abort, this could be the result of an - * IOMMU translation error of some sort. It is extremely - * useful to log this information as usually it indicates - * a bug in the IOMMU support code or a PCI device driver. - */ - if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { - sabre_check_iommu_error(p, afsr, afar); - pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus); - } - if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) { - pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus); - } - /* For excessive retries, SABRE/PBM will abort the device - * and there is no way to specifically check for excessive - * retries in the config space status registers. So what - * we hope is that we'll catch it via the master/target - * abort events. - */ - - if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) { - pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus); - } - - return IRQ_HANDLED; -} - -/* XXX What about PowerFail/PowerManagement??? -DaveM */ -#define SABRE_UE_INO 0x2e -#define SABRE_CE_INO 0x2f -#define SABRE_PCIERR_INO 0x30 -static void sabre_register_error_handlers(struct pci_controller_info *p) -{ - struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ - unsigned long base = pbm->controller_regs; - unsigned long irq, portid = pbm->portid; - u64 tmp; - - /* We clear the error bits in the appropriate AFSR before - * registering the handler so that we don't get spurious - * interrupts. - */ - sabre_write(base + SABRE_UE_AFSR, - (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | - SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | - SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); - irq = sabre_irq_build(pbm, NULL, (portid << 6) | SABRE_UE_INO); - if (request_irq(irq, sabre_ue_intr, - SA_SHIRQ, "SABRE UE", p) < 0) { - prom_printf("SABRE%d: Cannot register UE interrupt.\n", - p->index); - prom_halt(); - } - - sabre_write(base + SABRE_CE_AFSR, - (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | - SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); - irq = sabre_irq_build(pbm, NULL, (portid << 6) | SABRE_CE_INO); - if (request_irq(irq, sabre_ce_intr, - SA_SHIRQ, "SABRE CE", p) < 0) { - prom_printf("SABRE%d: Cannot register CE interrupt.\n", - p->index); - prom_halt(); - } - - irq = sabre_irq_build(pbm, NULL, (portid << 6) | SABRE_PCIERR_INO); - if (request_irq(irq, sabre_pcierr_intr, - SA_SHIRQ, "SABRE PCIERR", p) < 0) { - prom_printf("SABRE%d: Cannot register PciERR interrupt.\n", - p->index); - prom_halt(); - } - - tmp = sabre_read(base + SABRE_PCICTRL); - tmp |= SABRE_PCICTRL_ERREN; - sabre_write(base + SABRE_PCICTRL, tmp); -} - -static void sabre_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - struct pci_pbm_info *pbm = pdev->bus->sysdata; - unsigned long base; - - if (res->flags & IORESOURCE_IO) - base = pbm->controller_regs + SABRE_IOSPACE; - else - base = pbm->controller_regs + SABRE_MEMSPACE; - - res->start += base; - res->end += base; -} - -static void sabre_base_address_update(struct pci_dev *pdev, int resource) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res; - unsigned long base; - u32 reg; - int where, size, is_64bit; - - res = &pdev->resource[resource]; - if (resource < 6) { - where = PCI_BASE_ADDRESS_0 + (resource * 4); - } else if (resource == PCI_ROM_RESOURCE) { - where = pdev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - is_64bit = 0; - if (res->flags & IORESOURCE_IO) - base = pbm->controller_regs + SABRE_IOSPACE; - else { - base = pbm->controller_regs + SABRE_MEMSPACE; - if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - is_64bit = 1; - } - - size = res->end - res->start; - pci_read_config_dword(pdev, where, ®); - reg = ((reg & size) | - (((u32)(res->start - base)) & ~size)); - if (resource == PCI_ROM_RESOURCE) { - reg |= PCI_ROM_ADDRESS_ENABLE; - res->flags |= IORESOURCE_ROM_ENABLE; - } - pci_write_config_dword(pdev, where, reg); - - /* This knows that the upper 32-bits of the address - * must be zero. Our PCI common layer enforces this. - */ - if (is_64bit) - pci_write_config_dword(pdev, where + 4, 0); -} - -static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) -{ - struct pci_dev *pdev; - - list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { - - if (pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { - u32 word32; - u16 word16; - - sabre_read_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, &word32); - word16 = (u16) word32; - word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | - PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | - PCI_COMMAND_IO; - word32 = (u32) word16; - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, word32); - - /* Status register bits are "write 1 to clear". */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_STATUS, 2, 0xffff); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_STATUS, 2, 0xffff); - - /* Use a primary/seconday latency timer value - * of 64. - */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_LATENCY_TIMER, 1, 64); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_LATENCY_TIMER, 1, 64); - - /* Enable reporting/forwarding of master aborts, - * parity, and SERR. - */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_BRIDGE_CONTROL, 1, - (PCI_BRIDGE_CTL_PARITY | - PCI_BRIDGE_CTL_SERR | - PCI_BRIDGE_CTL_MASTER_ABORT)); - } - } -} - -static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm) -{ - struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("SABRE: Critical allocation failure.\n"); - prom_halt(); - } - - /* All we care about is the PBM. */ - memset(cookie, 0, sizeof(*cookie)); - cookie->pbm = pbm; - - return cookie; -} - -static void sabre_scan_bus(struct pci_controller_info *p) -{ - static int once; - struct pci_bus *sabre_bus, *pbus; - struct pci_pbm_info *pbm; - struct pcidev_cookie *cookie; - int sabres_scanned; - - /* The APB bridge speaks to the Sabre host PCI bridge - * at 66Mhz, but the front side of APB runs at 33Mhz - * for both segments. - */ - p->pbm_A.is_66mhz_capable = 0; - p->pbm_B.is_66mhz_capable = 0; - - /* This driver has not been verified to handle - * multiple SABREs yet, so trap this. - * - * Also note that the SABRE host bridge is hardwired - * to live at bus 0. - */ - if (once != 0) { - prom_printf("SABRE: Multiple controllers unsupported.\n"); - prom_halt(); - } - once++; - - cookie = alloc_bridge_cookie(&p->pbm_A); - - sabre_bus = pci_scan_bus(p->pci_first_busno, - p->pci_ops, - &p->pbm_A); - pci_fixup_host_bridge_self(sabre_bus); - sabre_bus->self->sysdata = cookie; - - sabre_root_bus = sabre_bus; - - apb_init(p, sabre_bus); - - sabres_scanned = 0; - - list_for_each_entry(pbus, &sabre_bus->children, node) { - - if (pbus->number == p->pbm_A.pci_first_busno) { - pbm = &p->pbm_A; - } else if (pbus->number == p->pbm_B.pci_first_busno) { - pbm = &p->pbm_B; - } else - continue; - - cookie = alloc_bridge_cookie(pbm); - pbus->self->sysdata = cookie; - - sabres_scanned++; - - pbus->sysdata = pbm; - pbm->pci_bus = pbus; - pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbus); - pci_assign_unassigned(pbm, pbus); - pci_fixup_irq(pbm, pbus); - pci_determine_66mhz_disposition(pbm, pbus); - pci_setup_busmastering(pbm, pbus); - } - - if (!sabres_scanned) { - /* Hummingbird, no APBs. */ - pbm = &p->pbm_A; - sabre_bus->sysdata = pbm; - pbm->pci_bus = sabre_bus; - pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, sabre_bus); - pci_assign_unassigned(pbm, sabre_bus); - pci_fixup_irq(pbm, sabre_bus); - pci_determine_66mhz_disposition(pbm, sabre_bus); - pci_setup_busmastering(pbm, sabre_bus); - } - - sabre_register_error_handlers(p); -} - -static void sabre_iommu_init(struct pci_controller_info *p, - int tsbsize, unsigned long dvma_offset, - u32 dma_mask) -{ - struct pci_iommu *iommu = p->pbm_A.iommu; - unsigned long i; - u64 control; - - /* Register addresses. */ - iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; - iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE; - iommu->iommu_flush = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH; - iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC; - /* Sabre's IOMMU lacks ctx flushing. */ - iommu->iommu_ctxflush = 0; - - /* Invalidate TLB Entries. */ - control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); - control |= SABRE_IOMMUCTRL_DENAB; - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); - - for(i = 0; i < 16; i++) { - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diag mode enabled for full-flushing done - * in pci_iommu.c - */ - pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask); - - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, - __pa(iommu->page_table)); - - control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); - control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); - control |= SABRE_IOMMUCTRL_ENAB; - switch(tsbsize) { - case 64: - control |= SABRE_IOMMU_TSBSZ_64K; - break; - case 128: - control |= SABRE_IOMMU_TSBSZ_128K; - break; - default: - prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); - prom_halt(); - break; - } - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); -} - -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - char *name = pbm->name; - unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE; - unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE; - unsigned int devfn; - unsigned long first, last, i; - u8 *addr, map; - - sprintf(name, "SABRE%d PBM%c", - p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); - pbm->io_space.name = pbm->mem_space.name = name; - - devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1); - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->io_space.start = ibase + (first << 21UL); - pbm->io_space.end = ibase + (last << 21UL) + ((1 << 21UL) - 1); - pbm->io_space.flags = IORESOURCE_IO; - - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->mem_space.start = mbase + (first << 29UL); - pbm->mem_space.end = mbase + (last << 29UL) + ((1 << 29UL) - 1); - pbm->mem_space.flags = IORESOURCE_MEM; - - if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register PBM-%c's IO space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); - prom_halt(); - } - if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register PBM-%c's MEM space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); - prom_halt(); - } - - /* Register legacy regions if this PBM covers that area. */ - if (pbm->io_space.start == ibase && - pbm->mem_space.start == mbase) - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - -static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin) -{ - struct pci_pbm_info *pbm; - char namebuf[128]; - u32 busrange[2]; - int node, simbas_found; - - simbas_found = 0; - node = prom_getchild(sabre_node); - while ((node = prom_searchsiblings(node, "pci")) != 0) { - int err; - - err = prom_getproperty(node, "model", namebuf, sizeof(namebuf)); - if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err)) - goto next_pci; - - err = prom_getproperty(node, "bus-range", - (char *)&busrange[0], sizeof(busrange)); - if (err == 0 || err == -1) { - prom_printf("APB: Error, cannot get PCI bus-range.\n"); - prom_halt(); - } - - simbas_found++; - if (busrange[0] == 1) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->parent = p; - pbm->prom_node = node; - pbm->pci_first_slot = 1; - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; - - prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name)); - err = prom_getproperty(node, "ranges", - (char *)pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err != -1) - pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); - else - pbm->num_pbm_ranges = 0; - - err = prom_getproperty(node, "interrupt-map", - (char *)pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("APB: Fatal error, no interrupt-map-mask.\n"); - prom_halt(); - } - } else { - pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); - } - - pbm_register_toplevel_resources(p, pbm); - - next_pci: - node = prom_getsibling(node); - if (!node) - break; - } - if (simbas_found == 0) { - int err; - - /* No APBs underneath, probably this is a hummingbird - * system. - */ - pbm = &p->pbm_A; - pbm->parent = p; - pbm->prom_node = sabre_node; - pbm->pci_first_busno = p->pci_first_busno; - pbm->pci_last_busno = p->pci_last_busno; - - prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name)); - err = prom_getproperty(sabre_node, "ranges", - (char *) pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err != -1) - pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); - else - pbm->num_pbm_ranges = 0; - - err = prom_getproperty(sabre_node, "interrupt-map", - (char *) pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(sabre_node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n"); - prom_halt(); - } - } else { - pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); - } - - - sprintf(pbm->name, "SABRE%d PBM%c", p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); - pbm->io_space.name = pbm->mem_space.name = pbm->name; - - /* Hack up top-level resources. */ - pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; - pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; - pbm->io_space.flags = IORESOURCE_IO; - - pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE; - pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL; - pbm->mem_space.flags = IORESOURCE_MEM; - - if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register Hummingbird's IO space.\n"); - prom_halt(); - } - if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register Hummingbird's MEM space.\n"); - prom_halt(); - } - - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); - } -} - -void sabre_init(int pnode, char *model_name) -{ - struct linux_prom64_registers pr_regs[2]; - struct pci_controller_info *p; - struct pci_iommu *iommu; - int tsbsize, err; - u32 busrange[2]; - u32 vdma[2]; - u32 upa_portid, dma_mask; - u64 clear_irq; - - hummingbird_p = 0; - if (!strcmp(model_name, "pci108e,a001")) - hummingbird_p = 1; - else if (!strcmp(model_name, "SUNW,sabre")) { - char compat[64]; - - if (prom_getproperty(pnode, "compatible", - compat, sizeof(compat)) > 0 && - !strcmp(compat, "pci108e,a001")) { - hummingbird_p = 1; - } else { - int cpu_node; - - /* Of course, Sun has to encode things a thousand - * different ways, inconsistently. - */ - cpu_find_by_instance(0, &cpu_node, NULL); - if (prom_getproperty(cpu_node, "name", - compat, sizeof(compat)) > 0 && - !strcmp(compat, "SUNW,UltraSPARC-IIe")) - hummingbird_p = 1; - } - } - - p = kmalloc(sizeof(*p), GFP_ATOMIC); - if (!p) { - prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n"); - prom_halt(); - } - memset(p, 0, sizeof(*p)); - - iommu = kmalloc(sizeof(*iommu), GFP_ATOMIC); - if (!iommu) { - prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); - prom_halt(); - } - memset(iommu, 0, sizeof(*iommu)); - p->pbm_A.iommu = p->pbm_B.iommu = iommu; - - upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff); - - p->next = pci_controller_root; - pci_controller_root = p; - - p->pbm_A.portid = upa_portid; - p->pbm_B.portid = upa_portid; - p->index = pci_num_controllers++; - p->pbms_same_domain = 1; - p->scan_bus = sabre_scan_bus; - p->irq_build = sabre_irq_build; - p->base_address_update = sabre_base_address_update; - p->resource_adjust = sabre_resource_adjust; - p->pci_ops = &sabre_ops; - - /* - * Map in SABRE register set and report the presence of this SABRE. - */ - err = prom_getproperty(pnode, "reg", - (char *)&pr_regs[0], sizeof(pr_regs)); - if(err == 0 || err == -1) { - prom_printf("SABRE: Error, cannot get U2P registers " - "from PROM.\n"); - prom_halt(); - } - - /* - * First REG in property is base of entire SABRE register space. - */ - p->pbm_A.controller_regs = pr_regs[0].phys_addr; - p->pbm_B.controller_regs = pr_regs[0].phys_addr; - - printk("PCI: Found SABRE, main regs at %016lx\n", - p->pbm_A.controller_regs); - - /* Clear interrupts */ - - /* PCI first */ - for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) - sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL); - - /* Then OBIO */ - for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) - sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL); - - /* Error interrupts are enabled later after the bus scan. */ - sabre_write(p->pbm_A.controller_regs + SABRE_PCICTRL, - (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | - SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); - - /* Now map in PCI config space for entire SABRE. */ - p->pbm_A.config_space = p->pbm_B.config_space = - (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); - printk("SABRE: Shared PCI config space at %016lx\n", - p->pbm_A.config_space); - - err = prom_getproperty(pnode, "virtual-dma", - (char *)&vdma[0], sizeof(vdma)); - if(err == 0 || err == -1) { - prom_printf("SABRE: Error, cannot get virtual-dma property " - "from PROM.\n"); - prom_halt(); - } - - dma_mask = vdma[0]; - switch(vdma[1]) { - case 0x20000000: - dma_mask |= 0x1fffffff; - tsbsize = 64; - break; - case 0x40000000: - dma_mask |= 0x3fffffff; - tsbsize = 128; - break; - - case 0x80000000: - dma_mask |= 0x7fffffff; - tsbsize = 128; - break; - default: - prom_printf("SABRE: strange virtual-dma size.\n"); - prom_halt(); - } - - sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); - - printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]); - - err = prom_getproperty(pnode, "bus-range", - (char *)&busrange[0], sizeof(busrange)); - if(err == 0 || err == -1) { - prom_printf("SABRE: Error, cannot get PCI bus-range " - " from PROM.\n"); - prom_halt(); - } - - p->pci_first_busno = busrange[0]; - p->pci_last_busno = busrange[1]; - - /* - * Look for APB underneath. - */ - sabre_pbm_init(p, pnode, vdma[0]); -} diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c deleted file mode 100644 index d8c4e0919b4..00000000000 --- a/arch/sparc64/kernel/pci_schizo.c +++ /dev/null @@ -1,2178 +0,0 @@ -/* $Id: pci_schizo.c,v 1.24 2002/01/23 11:27:32 davem Exp $ - * pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. - * - * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> - -#include <asm/pbm.h> -#include <asm/iommu.h> -#include <asm/irq.h> -#include <asm/upa.h> -#include <asm/pstate.h> - -#include "pci_impl.h" -#include "iommu_common.h" - -/* All SCHIZO registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define schizo_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define schizo_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - -/* This is a convention that at least Excalibur and Merlin - * follow. I suppose the SCHIZO used in Starcat and friends - * will do similar. - * - * The only way I could see this changing is if the newlink - * block requires more space in Schizo's address space than - * they predicted, thus requiring an address space reorg when - * the newer Schizo is taped out. - */ - -/* Streaming buffer control register. */ -#define SCHIZO_STRBUF_CTRL_LPTR 0x00000000000000f0UL /* LRU Lock Pointer */ -#define SCHIZO_STRBUF_CTRL_LENAB 0x0000000000000008UL /* LRU Lock Enable */ -#define SCHIZO_STRBUF_CTRL_RRDIS 0x0000000000000004UL /* Rerun Disable */ -#define SCHIZO_STRBUF_CTRL_DENAB 0x0000000000000002UL /* Diagnostic Mode Enable */ -#define SCHIZO_STRBUF_CTRL_ENAB 0x0000000000000001UL /* Streaming Buffer Enable */ - -/* IOMMU control register. */ -#define SCHIZO_IOMMU_CTRL_RESV 0xfffffffff9000000UL /* Reserved */ -#define SCHIZO_IOMMU_CTRL_XLTESTAT 0x0000000006000000UL /* Translation Error Status */ -#define SCHIZO_IOMMU_CTRL_XLTEERR 0x0000000001000000UL /* Translation Error encountered */ -#define SCHIZO_IOMMU_CTRL_LCKEN 0x0000000000800000UL /* Enable translation locking */ -#define SCHIZO_IOMMU_CTRL_LCKPTR 0x0000000000780000UL /* Translation lock pointer */ -#define SCHIZO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL /* TSB Size */ -#define SCHIZO_IOMMU_TSBSZ_1K 0x0000000000000000UL /* TSB Table 1024 8-byte entries */ -#define SCHIZO_IOMMU_TSBSZ_2K 0x0000000000010000UL /* TSB Table 2048 8-byte entries */ -#define SCHIZO_IOMMU_TSBSZ_4K 0x0000000000020000UL /* TSB Table 4096 8-byte entries */ -#define SCHIZO_IOMMU_TSBSZ_8K 0x0000000000030000UL /* TSB Table 8192 8-byte entries */ -#define SCHIZO_IOMMU_TSBSZ_16K 0x0000000000040000UL /* TSB Table 16k 8-byte entries */ -#define SCHIZO_IOMMU_TSBSZ_32K 0x0000000000050000UL /* TSB Table 32k 8-byte entries */ -#define SCHIZO_IOMMU_TSBSZ_64K 0x0000000000060000UL /* TSB Table 64k 8-byte entries */ -#define SCHIZO_IOMMU_TSBSZ_128K 0x0000000000070000UL /* TSB Table 128k 8-byte entries */ -#define SCHIZO_IOMMU_CTRL_RESV2 0x000000000000fff8UL /* Reserved */ -#define SCHIZO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL /* Assumed page size, 0=8k 1=64k */ -#define SCHIZO_IOMMU_CTRL_DENAB 0x0000000000000002UL /* Diagnostic mode enable */ -#define SCHIZO_IOMMU_CTRL_ENAB 0x0000000000000001UL /* IOMMU Enable */ - -/* Schizo config space address format is nearly identical to - * that of PSYCHO: - * - * 32 24 23 16 15 11 10 8 7 2 1 0 - * --------------------------------------------------------- - * |0 0 0 0 0 0 0 0 0| bus | device | function | reg | 0 0 | - * --------------------------------------------------------- - */ -#define SCHIZO_CONFIG_BASE(PBM) ((PBM)->config_space) -#define SCHIZO_CONFIG_ENCODE(BUS, DEVFN, REG) \ - (((unsigned long)(BUS) << 16) | \ - ((unsigned long)(DEVFN) << 8) | \ - ((unsigned long)(REG))) - -static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm, - unsigned char bus, - unsigned int devfn, - int where) -{ - if (!pbm) - return NULL; - bus -= pbm->pci_first_busno; - return (void *) - (SCHIZO_CONFIG_BASE(pbm) | - SCHIZO_CONFIG_ENCODE(bus, devfn, where)); -} - -/* Just make sure the bus number is in range. */ -static int schizo_out_of_range(struct pci_pbm_info *pbm, - unsigned char bus, - unsigned char devfn) -{ - if (bus < pbm->pci_first_busno || - bus > pbm->pci_last_busno) - return 1; - return 0; -} - -/* SCHIZO PCI configuration space accessors. */ - -static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 *value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - u16 tmp16; - u8 tmp8; - - switch (size) { - case 1: - *value = 0xff; - break; - case 2: - *value = 0xffff; - break; - case 4: - *value = 0xffffffff; - break; - } - - addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - if (schizo_out_of_range(pbm, bus, devfn)) - return PCIBIOS_SUCCESSFUL; - switch (size) { - case 1: - pci_config_read8((u8 *)addr, &tmp8); - *value = tmp8; - break; - - case 2: - if (where & 0x01) { - printk("pci_read_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read16((u16 *)addr, &tmp16); - *value = tmp16; - break; - - case 4: - if (where & 0x03) { - printk("pci_read_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read32(addr, value); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - - addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - if (schizo_out_of_range(pbm, bus, devfn)) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_write8((u8 *)addr, value); - break; - - case 2: - if (where & 0x01) { - printk("pci_write_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write16((u16 *)addr, value); - break; - - case 4: - if (where & 0x03) { - printk("pci_write_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - - pci_config_write32(addr, value); - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops schizo_ops = { - .read = schizo_read_pci_cfg, - .write = schizo_write_pci_cfg, -}; - -/* SCHIZO interrupt mapping support. Unlike Psycho, for this controller the - * imap/iclr registers are per-PBM. - */ -#define SCHIZO_IMAP_BASE 0x1000UL -#define SCHIZO_ICLR_BASE 0x1400UL - -static unsigned long schizo_imap_offset(unsigned long ino) -{ - return SCHIZO_IMAP_BASE + (ino * 8UL); -} - -static unsigned long schizo_iclr_offset(unsigned long ino) -{ - return SCHIZO_ICLR_BASE + (ino * 8UL); -} - -/* PCI SCHIZO INO number to Sparc PIL level. This table only matters for - * INOs which will not have an associated PCI device struct, ie. onboard - * EBUS devices and PCI controller internal error interrupts. - */ -static unsigned char schizo_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */ -/*0x18*/4, /* SCSI */ -/*0x19*/4, /* second SCSI */ -/*0x1a*/0, /* UNKNOWN */ -/*0x1b*/0, /* UNKNOWN */ -/*0x1c*/8, /* Parallel */ -/*0x1d*/5, /* Ethernet */ -/*0x1e*/8, /* Firewire-1394 */ -/*0x1f*/9, /* USB */ -/*0x20*/13, /* Audio Record */ -/*0x21*/14, /* Audio Playback */ -/*0x22*/12, /* Serial */ -/*0x23*/4, /* EBUS I2C */ -/*0x24*/10, /* RTC Clock */ -/*0x25*/11, /* Floppy */ -/*0x26*/0, /* UNKNOWN */ -/*0x27*/0, /* UNKNOWN */ -/*0x28*/0, /* UNKNOWN */ -/*0x29*/0, /* UNKNOWN */ -/*0x2a*/10, /* UPA 1 */ -/*0x2b*/10, /* UPA 2 */ -/*0x2c*/0, /* UNKNOWN */ -/*0x2d*/0, /* UNKNOWN */ -/*0x2e*/0, /* UNKNOWN */ -/*0x2f*/0, /* UNKNOWN */ -/*0x30*/15, /* Uncorrectable ECC */ -/*0x31*/15, /* Correctable ECC */ -/*0x32*/15, /* PCI Bus A Error */ -/*0x33*/15, /* PCI Bus B Error */ -/*0x34*/15, /* Safari Bus Error */ -/*0x35*/0, /* Reserved */ -/*0x36*/0, /* Reserved */ -/*0x37*/0, /* Reserved */ -/*0x38*/0, /* Reserved for NewLink */ -/*0x39*/0, /* Reserved for NewLink */ -/*0x3a*/0, /* Reserved for NewLink */ -/*0x3b*/0, /* Reserved for NewLink */ -/*0x3c*/0, /* Reserved for NewLink */ -/*0x3d*/0, /* Reserved for NewLink */ -/*0x3e*/0, /* Reserved for NewLink */ -/*0x3f*/0, /* Reserved for NewLink */ -}; - -static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - if (pdev && - pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 9; - - ret = schizo_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 4; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 4; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 4; - break; - }; - } - - return ret; -} - -static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) -{ - unsigned long sync_reg = (unsigned long) _arg2; - u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO); - u64 val; - int limit; - - schizo_write(sync_reg, mask); - - limit = 100000; - val = 0; - while (--limit) { - val = schizo_read(sync_reg); - if (!(val & mask)) - break; - } - if (limit <= 0) { - printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n", - val, mask); - } - - if (_arg1) { - static unsigned char cacheline[64] - __attribute__ ((aligned (64))); - - __asm__ __volatile__("rd %%fprs, %0\n\t" - "or %0, %4, %1\n\t" - "wr %1, 0x0, %%fprs\n\t" - "stda %%f0, [%5] %6\n\t" - "wr %0, 0x0, %%fprs\n\t" - "membar #Sync" - : "=&r" (mask), "=&r" (val) - : "0" (mask), "1" (val), - "i" (FPRS_FEF), "r" (&cacheline[0]), - "i" (ASI_BLK_COMMIT_P)); - } -} - -static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - unsigned int ino) -{ - struct ino_bucket *bucket; - unsigned long imap, iclr; - unsigned long imap_off, iclr_off; - int pil, ign_fixup; - - ino &= PCI_IRQ_INO; - imap_off = schizo_imap_offset(ino); - - /* Now build the IRQ bucket. */ - pil = schizo_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - - imap = pbm->pbm_regs + imap_off; - imap += 4; - - iclr_off = schizo_iclr_offset(ino); - iclr = pbm->pbm_regs + iclr_off; - iclr += 4; - - /* On Schizo, no inofixup occurs. This is because each - * INO has it's own IMAP register. On Psycho and Sabre - * there is only one IMAP register for each PCI slot even - * though four different INOs can be generated by each - * PCI slot. - * - * But, for JBUS variants (essentially, Tomatillo), we have - * to fixup the lowest bit of the interrupt group number. - */ - ign_fixup = 0; - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - if (pbm->portid & 1) - ign_fixup = (1 << 6); - } - - bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap)); - bucket->flags |= IBF_PCI; - - if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - struct irq_desc *p = bucket->irq_info; - - p->pre_handler = tomatillo_wsync_handler; - p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? - (void *) 1 : (void *) 0); - p->pre_handler_arg2 = (void *) pbm->sync_reg; - } - - return __irq(bucket); -} - -/* SCHIZO error handling support. */ -enum schizo_error_type { - UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR -}; - -static DEFINE_SPINLOCK(stc_buf_lock); -static unsigned long stc_error_buf[128]; -static unsigned long stc_tag_buf[16]; -static unsigned long stc_line_buf[16]; - -#define SCHIZO_UE_INO 0x30 /* Uncorrectable ECC error */ -#define SCHIZO_CE_INO 0x31 /* Correctable ECC error */ -#define SCHIZO_PCIERR_A_INO 0x32 /* PBM A PCI bus error */ -#define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */ -#define SCHIZO_SERR_INO 0x34 /* Safari interface error */ - -struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) -{ - ino &= IMAP_INO; - if (p->pbm_A.ino_bitmap & (1UL << ino)) - return &p->pbm_A; - if (p->pbm_B.ino_bitmap & (1UL << ino)) - return &p->pbm_B; - - printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps " - "PBM_A[%016lx] PBM_B[%016lx]", - p->index, ino, - p->pbm_A.ino_bitmap, - p->pbm_B.ino_bitmap); - printk("PCI%d: Using PBM_A, report this problem immediately.\n", - p->index); - - return &p->pbm_A; -} - -static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) -{ - struct pci_pbm_info *pbm; - struct ino_bucket *bucket; - unsigned long iclr; - - /* Do not clear the interrupt for the other PCI bus. - * - * This "ACK both PBM IRQs" only needs to be performed - * for chip-wide error interrupts. - */ - if ((irq & IMAP_INO) == SCHIZO_PCIERR_A_INO || - (irq & IMAP_INO) == SCHIZO_PCIERR_B_INO) - return; - - pbm = pbm_for_ino(p, irq); - if (pbm == &p->pbm_A) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - - irq = schizo_irq_build(pbm, NULL, - (pbm->portid << 6) | (irq & IMAP_INO)); - bucket = __bucket(irq); - iclr = bucket->iclr; - - upa_writel(ICLR_IDLE, iclr); -} - -#define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */ -#define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */ -#define SCHIZO_STC_LINE 0xbb00UL /* --> 0xbb80 */ - -#define SCHIZO_STCERR_WRITE 0x2UL -#define SCHIZO_STCERR_READ 0x1UL - -#define SCHIZO_STCTAG_PPN 0x3fffffff00000000UL -#define SCHIZO_STCTAG_VPN 0x00000000ffffe000UL -#define SCHIZO_STCTAG_VALID 0x8000000000000000UL -#define SCHIZO_STCTAG_READ 0x4000000000000000UL - -#define SCHIZO_STCLINE_LINDX 0x0000000007800000UL -#define SCHIZO_STCLINE_SPTR 0x000000000007e000UL -#define SCHIZO_STCLINE_LADDR 0x0000000000001fc0UL -#define SCHIZO_STCLINE_EPTR 0x000000000000003fUL -#define SCHIZO_STCLINE_VALID 0x0000000000600000UL -#define SCHIZO_STCLINE_FOFN 0x0000000000180000UL - -static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, - enum schizo_error_type type) -{ - struct pci_strbuf *strbuf = &pbm->stc; - unsigned long regbase = pbm->pbm_regs; - unsigned long err_base, tag_base, line_base; - u64 control; - int i; - - err_base = regbase + SCHIZO_STC_ERR; - tag_base = regbase + SCHIZO_STC_TAG; - line_base = regbase + SCHIZO_STC_LINE; - - spin_lock(&stc_buf_lock); - - /* This is __REALLY__ dangerous. When we put the - * streaming buffer into diagnostic mode to probe - * it's tags and error status, we _must_ clear all - * of the line tag valid bits before re-enabling - * the streaming buffer. If any dirty data lives - * in the STC when we do this, we will end up - * invalidating it before it has a chance to reach - * main memory. - */ - control = schizo_read(strbuf->strbuf_control); - schizo_write(strbuf->strbuf_control, - (control | SCHIZO_STRBUF_CTRL_DENAB)); - for (i = 0; i < 128; i++) { - unsigned long val; - - val = schizo_read(err_base + (i * 8UL)); - schizo_write(err_base + (i * 8UL), 0UL); - stc_error_buf[i] = val; - } - for (i = 0; i < 16; i++) { - stc_tag_buf[i] = schizo_read(tag_base + (i * 8UL)); - stc_line_buf[i] = schizo_read(line_base + (i * 8UL)); - schizo_write(tag_base + (i * 8UL), 0UL); - schizo_write(line_base + (i * 8UL), 0UL); - } - - /* OK, state is logged, exit diagnostic mode. */ - schizo_write(strbuf->strbuf_control, control); - - for (i = 0; i < 16; i++) { - int j, saw_error, first, last; - - saw_error = 0; - first = i * 8; - last = first + 8; - for (j = first; j < last; j++) { - unsigned long errval = stc_error_buf[j]; - if (errval != 0) { - saw_error++; - printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n", - pbm->name, - j, - (errval & SCHIZO_STCERR_WRITE) ? 1 : 0, - (errval & SCHIZO_STCERR_READ) ? 1 : 0); - } - } - if (saw_error != 0) { - unsigned long tagval = stc_tag_buf[i]; - unsigned long lineval = stc_line_buf[i]; - printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)R(%d)]\n", - pbm->name, - i, - ((tagval & SCHIZO_STCTAG_PPN) >> 19UL), - (tagval & SCHIZO_STCTAG_VPN), - ((tagval & SCHIZO_STCTAG_VALID) ? 1 : 0), - ((tagval & SCHIZO_STCTAG_READ) ? 1 : 0)); - - /* XXX Should spit out per-bank error information... -DaveM */ - printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" - "V(%d)FOFN(%d)]\n", - pbm->name, - i, - ((lineval & SCHIZO_STCLINE_LINDX) >> 23UL), - ((lineval & SCHIZO_STCLINE_SPTR) >> 13UL), - ((lineval & SCHIZO_STCLINE_LADDR) >> 6UL), - ((lineval & SCHIZO_STCLINE_EPTR) >> 0UL), - ((lineval & SCHIZO_STCLINE_VALID) ? 1 : 0), - ((lineval & SCHIZO_STCLINE_FOFN) ? 1 : 0)); - } - } - - spin_unlock(&stc_buf_lock); -} - -/* IOMMU is per-PBM in Schizo, so interrogate both for anonymous - * controller level errors. - */ - -#define SCHIZO_IOMMU_TAG 0xa580UL -#define SCHIZO_IOMMU_DATA 0xa600UL - -#define SCHIZO_IOMMU_TAG_CTXT 0x0000001ffe000000UL -#define SCHIZO_IOMMU_TAG_ERRSTS 0x0000000001800000UL -#define SCHIZO_IOMMU_TAG_ERR 0x0000000000400000UL -#define SCHIZO_IOMMU_TAG_WRITE 0x0000000000200000UL -#define SCHIZO_IOMMU_TAG_STREAM 0x0000000000100000UL -#define SCHIZO_IOMMU_TAG_SIZE 0x0000000000080000UL -#define SCHIZO_IOMMU_TAG_VPAGE 0x000000000007ffffUL - -#define SCHIZO_IOMMU_DATA_VALID 0x0000000100000000UL -#define SCHIZO_IOMMU_DATA_CACHE 0x0000000040000000UL -#define SCHIZO_IOMMU_DATA_PPAGE 0x000000003fffffffUL - -static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, - enum schizo_error_type type) -{ - struct pci_iommu *iommu = pbm->iommu; - unsigned long iommu_tag[16]; - unsigned long iommu_data[16]; - unsigned long flags; - u64 control; - int i; - - spin_lock_irqsave(&iommu->lock, flags); - control = schizo_read(iommu->iommu_control); - if (control & SCHIZO_IOMMU_CTRL_XLTEERR) { - unsigned long base; - char *type_string; - - /* Clear the error encountered bit. */ - control &= ~SCHIZO_IOMMU_CTRL_XLTEERR; - schizo_write(iommu->iommu_control, control); - - switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("%s: IOMMU Error, type[%s]\n", - pbm->name, type_string); - - /* Put the IOMMU into diagnostic mode and probe - * it's TLB for entries with error status. - * - * It is very possible for another DVMA to occur - * while we do this probe, and corrupt the system - * further. But we are so screwed at this point - * that we are likely to crash hard anyways, so - * get as much diagnostic information to the - * console as we can. - */ - schizo_write(iommu->iommu_control, - control | SCHIZO_IOMMU_CTRL_DENAB); - - base = pbm->pbm_regs; - - for (i = 0; i < 16; i++) { - iommu_tag[i] = - schizo_read(base + SCHIZO_IOMMU_TAG + (i * 8UL)); - iommu_data[i] = - schizo_read(base + SCHIZO_IOMMU_DATA + (i * 8UL)); - - /* Now clear out the entry. */ - schizo_write(base + SCHIZO_IOMMU_TAG + (i * 8UL), 0); - schizo_write(base + SCHIZO_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diagnostic mode. */ - schizo_write(iommu->iommu_control, control); - - for (i = 0; i < 16; i++) { - unsigned long tag, data; - - tag = iommu_tag[i]; - if (!(tag & SCHIZO_IOMMU_TAG_ERR)) - continue; - - data = iommu_data[i]; - switch((tag & SCHIZO_IOMMU_TAG_ERRSTS) >> 23UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) " - "sz(%dK) vpg(%08lx)]\n", - pbm->name, i, type_string, - (int)((tag & SCHIZO_IOMMU_TAG_CTXT) >> 25UL), - ((tag & SCHIZO_IOMMU_TAG_WRITE) ? 1 : 0), - ((tag & SCHIZO_IOMMU_TAG_STREAM) ? 1 : 0), - ((tag & SCHIZO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & SCHIZO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); - printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", - pbm->name, i, - ((data & SCHIZO_IOMMU_DATA_VALID) ? 1 : 0), - ((data & SCHIZO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & SCHIZO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); - } - } - if (pbm->stc.strbuf_enabled) - __schizo_check_stc_error_pbm(pbm, type); - spin_unlock_irqrestore(&iommu->lock, flags); -} - -static void schizo_check_iommu_error(struct pci_controller_info *p, - enum schizo_error_type type) -{ - schizo_check_iommu_error_pbm(&p->pbm_A, type); - schizo_check_iommu_error_pbm(&p->pbm_B, type); -} - -/* Uncorrectable ECC error status gathering. */ -#define SCHIZO_UE_AFSR 0x10030UL -#define SCHIZO_UE_AFAR 0x10038UL - -#define SCHIZO_UEAFSR_PPIO 0x8000000000000000UL /* Safari */ -#define SCHIZO_UEAFSR_PDRD 0x4000000000000000UL /* Safari/Tomatillo */ -#define SCHIZO_UEAFSR_PDWR 0x2000000000000000UL /* Safari */ -#define SCHIZO_UEAFSR_SPIO 0x1000000000000000UL /* Safari */ -#define SCHIZO_UEAFSR_SDMA 0x0800000000000000UL /* Safari/Tomatillo */ -#define SCHIZO_UEAFSR_ERRPNDG 0x0300000000000000UL /* Safari */ -#define SCHIZO_UEAFSR_BMSK 0x000003ff00000000UL /* Safari */ -#define SCHIZO_UEAFSR_QOFF 0x00000000c0000000UL /* Safari/Tomatillo */ -#define SCHIZO_UEAFSR_AID 0x000000001f000000UL /* Safari/Tomatillo */ -#define SCHIZO_UEAFSR_PARTIAL 0x0000000000800000UL /* Safari */ -#define SCHIZO_UEAFSR_OWNEDIN 0x0000000000400000UL /* Safari */ -#define SCHIZO_UEAFSR_MTAGSYND 0x00000000000f0000UL /* Safari */ -#define SCHIZO_UEAFSR_MTAG 0x000000000000e000UL /* Safari */ -#define SCHIZO_UEAFSR_ECCSYND 0x00000000000001ffUL /* Safari */ - -static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR; - unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR; - unsigned long afsr, afar, error_bits; - int reported, limit; - - /* Latch uncorrectable error status. */ - afar = schizo_read(afar_reg); - - /* If either of the error pending bits are set in the - * AFSR, the error status is being actively updated by - * the hardware and we must re-read to get a clean value. - */ - limit = 1000; - do { - afsr = schizo_read(afsr_reg); - } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); - - /* Clear the primary/secondary error status bits. */ - error_bits = afsr & - (SCHIZO_UEAFSR_PPIO | SCHIZO_UEAFSR_PDRD | SCHIZO_UEAFSR_PDWR | - SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA); - if (!error_bits) - return IRQ_NONE; - schizo_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("PCI%d: Uncorrectable Error, primary error type[%s]\n", - p->index, - (((error_bits & SCHIZO_UEAFSR_PPIO) ? - "PIO" : - ((error_bits & SCHIZO_UEAFSR_PDRD) ? - "DMA Read" : - ((error_bits & SCHIZO_UEAFSR_PDWR) ? - "DMA Write" : "???"))))); - printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", - p->index, - (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL, - (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL, - (afsr & SCHIZO_UEAFSR_AID) >> 24UL); - printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", - p->index, - (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0, - (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0, - (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL, - (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL, - (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL); - printk("PCI%d: UE AFAR [%016lx]\n", p->index, afar); - printk("PCI%d: UE Secondary errors [", p->index); - reported = 0; - if (afsr & SCHIZO_UEAFSR_SPIO) { - reported++; - printk("(PIO)"); - } - if (afsr & SCHIZO_UEAFSR_SDMA) { - reported++; - printk("(DMA)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* Interrogate IOMMU for error status. */ - schizo_check_iommu_error(p, UE_ERR); - - schizo_clear_other_err_intr(p, irq); - - return IRQ_HANDLED; -} - -#define SCHIZO_CE_AFSR 0x10040UL -#define SCHIZO_CE_AFAR 0x10048UL - -#define SCHIZO_CEAFSR_PPIO 0x8000000000000000UL -#define SCHIZO_CEAFSR_PDRD 0x4000000000000000UL -#define SCHIZO_CEAFSR_PDWR 0x2000000000000000UL -#define SCHIZO_CEAFSR_SPIO 0x1000000000000000UL -#define SCHIZO_CEAFSR_SDMA 0x0800000000000000UL -#define SCHIZO_CEAFSR_ERRPNDG 0x0300000000000000UL -#define SCHIZO_CEAFSR_BMSK 0x000003ff00000000UL -#define SCHIZO_CEAFSR_QOFF 0x00000000c0000000UL -#define SCHIZO_CEAFSR_AID 0x000000001f000000UL -#define SCHIZO_CEAFSR_PARTIAL 0x0000000000800000UL -#define SCHIZO_CEAFSR_OWNEDIN 0x0000000000400000UL -#define SCHIZO_CEAFSR_MTAGSYND 0x00000000000f0000UL -#define SCHIZO_CEAFSR_MTAG 0x000000000000e000UL -#define SCHIZO_CEAFSR_ECCSYND 0x00000000000001ffUL - -static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR; - unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR; - unsigned long afsr, afar, error_bits; - int reported, limit; - - /* Latch error status. */ - afar = schizo_read(afar_reg); - - /* If either of the error pending bits are set in the - * AFSR, the error status is being actively updated by - * the hardware and we must re-read to get a clean value. - */ - limit = 1000; - do { - afsr = schizo_read(afsr_reg); - } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SCHIZO_CEAFSR_PPIO | SCHIZO_CEAFSR_PDRD | SCHIZO_CEAFSR_PDWR | - SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); - if (!error_bits) - return IRQ_NONE; - schizo_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("PCI%d: Correctable Error, primary error type[%s]\n", - p->index, - (((error_bits & SCHIZO_CEAFSR_PPIO) ? - "PIO" : - ((error_bits & SCHIZO_CEAFSR_PDRD) ? - "DMA Read" : - ((error_bits & SCHIZO_CEAFSR_PDWR) ? - "DMA Write" : "???"))))); - - /* XXX Use syndrome and afar to print out module string just like - * XXX UDB CE trap handler does... -DaveM - */ - printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", - p->index, - (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL, - (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL, - (afsr & SCHIZO_UEAFSR_AID) >> 24UL); - printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", - p->index, - (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0, - (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0, - (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL, - (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL, - (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL); - printk("PCI%d: CE AFAR [%016lx]\n", p->index, afar); - printk("PCI%d: CE Secondary errors [", p->index); - reported = 0; - if (afsr & SCHIZO_CEAFSR_SPIO) { - reported++; - printk("(PIO)"); - } - if (afsr & SCHIZO_CEAFSR_SDMA) { - reported++; - printk("(DMA)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - schizo_clear_other_err_intr(p, irq); - - return IRQ_HANDLED; -} - -#define SCHIZO_PCI_AFSR 0x2010UL -#define SCHIZO_PCI_AFAR 0x2018UL - -#define SCHIZO_PCIAFSR_PMA 0x8000000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_PTA 0x4000000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_PRTRY 0x2000000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_PPERR 0x1000000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_PTTO 0x0800000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_PUNUS 0x0400000000000000UL /* Schizo */ -#define SCHIZO_PCIAFSR_SMA 0x0200000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_STA 0x0100000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_SRTRY 0x0080000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_SPERR 0x0040000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_STTO 0x0020000000000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_SUNUS 0x0010000000000000UL /* Schizo */ -#define SCHIZO_PCIAFSR_BMSK 0x000003ff00000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_BLK 0x0000000080000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_CFG 0x0000000040000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_MEM 0x0000000020000000UL /* Schizo/Tomatillo */ -#define SCHIZO_PCIAFSR_IO 0x0000000010000000UL /* Schizo/Tomatillo */ - -#define SCHIZO_PCI_CTRL (0x2000UL) -#define SCHIZO_PCICTRL_BUS_UNUS (1UL << 63UL) /* Safari */ -#define SCHIZO_PCICTRL_DTO_INT (1UL << 61UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_ARB_PRIO (0x1ff << 52UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_ESLCK (1UL << 51UL) /* Safari */ -#define SCHIZO_PCICTRL_ERRSLOT (7UL << 48UL) /* Safari */ -#define SCHIZO_PCICTRL_TTO_ERR (1UL << 38UL) /* Safari/Tomatillo */ -#define SCHIZO_PCICTRL_RTRY_ERR (1UL << 37UL) /* Safari/Tomatillo */ -#define SCHIZO_PCICTRL_DTO_ERR (1UL << 36UL) /* Safari/Tomatillo */ -#define SCHIZO_PCICTRL_SBH_ERR (1UL << 35UL) /* Safari */ -#define SCHIZO_PCICTRL_SERR (1UL << 34UL) /* Safari/Tomatillo */ -#define SCHIZO_PCICTRL_PCISPD (1UL << 33UL) /* Safari */ -#define SCHIZO_PCICTRL_MRM_PREF (1UL << 30UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_RDO_PREF (1UL << 29UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_RDL_PREF (1UL << 28UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_PTO (3UL << 24UL) /* Safari/Tomatillo */ -#define SCHIZO_PCICTRL_PTO_SHIFT 24UL -#define SCHIZO_PCICTRL_TRWSW (7UL << 21UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_F_TGT_A (1UL << 20UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_S_DTO_INT (1UL << 19UL) /* Safari */ -#define SCHIZO_PCICTRL_F_TGT_RT (1UL << 19UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_SBH_INT (1UL << 18UL) /* Safari */ -#define SCHIZO_PCICTRL_T_DTO_INT (1UL << 18UL) /* Tomatillo */ -#define SCHIZO_PCICTRL_EEN (1UL << 17UL) /* Safari/Tomatillo */ -#define SCHIZO_PCICTRL_PARK (1UL << 16UL) /* Safari/Tomatillo */ -#define SCHIZO_PCICTRL_PCIRST (1UL << 8UL) /* Safari */ -#define SCHIZO_PCICTRL_ARB_S (0x3fUL << 0UL) /* Safari */ -#define SCHIZO_PCICTRL_ARB_T (0xffUL << 0UL) /* Tomatillo */ - -static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) -{ - unsigned long csr_reg, csr, csr_error_bits; - irqreturn_t ret = IRQ_NONE; - u16 stat; - - csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; - csr = schizo_read(csr_reg); - csr_error_bits = - csr & (SCHIZO_PCICTRL_BUS_UNUS | - SCHIZO_PCICTRL_TTO_ERR | - SCHIZO_PCICTRL_RTRY_ERR | - SCHIZO_PCICTRL_DTO_ERR | - SCHIZO_PCICTRL_SBH_ERR | - SCHIZO_PCICTRL_SERR); - if (csr_error_bits) { - /* Clear the errors. */ - schizo_write(csr_reg, csr); - - /* Log 'em. */ - if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) - printk("%s: Bus unusable error asserted.\n", - pbm->name); - if (csr_error_bits & SCHIZO_PCICTRL_TTO_ERR) - printk("%s: PCI TRDY# timeout error asserted.\n", - pbm->name); - if (csr_error_bits & SCHIZO_PCICTRL_RTRY_ERR) - printk("%s: PCI excessive retry error asserted.\n", - pbm->name); - if (csr_error_bits & SCHIZO_PCICTRL_DTO_ERR) - printk("%s: PCI discard timeout error asserted.\n", - pbm->name); - if (csr_error_bits & SCHIZO_PCICTRL_SBH_ERR) - printk("%s: PCI streaming byte hole error asserted.\n", - pbm->name); - if (csr_error_bits & SCHIZO_PCICTRL_SERR) - printk("%s: PCI SERR signal asserted.\n", - pbm->name); - ret = IRQ_HANDLED; - } - pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); - if (stat & (PCI_STATUS_PARITY | - PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | - PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("%s: PCI bus error, PCI_STATUS[%04x]\n", - pbm->name, stat); - pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); - ret = IRQ_HANDLED; - } - return ret; -} - -static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; - unsigned long afsr_reg, afar_reg, base; - unsigned long afsr, afar, error_bits; - int reported; - - base = pbm->pbm_regs; - - afsr_reg = base + SCHIZO_PCI_AFSR; - afar_reg = base + SCHIZO_PCI_AFAR; - - /* Latch error status. */ - afar = schizo_read(afar_reg); - afsr = schizo_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | - SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | - SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | - SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | - SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | - SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); - if (!error_bits) - return schizo_pcierr_intr_other(pbm); - schizo_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("%s: PCI Error, primary error type[%s]\n", - pbm->name, - (((error_bits & SCHIZO_PCIAFSR_PMA) ? - "Master Abort" : - ((error_bits & SCHIZO_PCIAFSR_PTA) ? - "Target Abort" : - ((error_bits & SCHIZO_PCIAFSR_PRTRY) ? - "Excessive Retries" : - ((error_bits & SCHIZO_PCIAFSR_PPERR) ? - "Parity Error" : - ((error_bits & SCHIZO_PCIAFSR_PTTO) ? - "Timeout" : - ((error_bits & SCHIZO_PCIAFSR_PUNUS) ? - "Bus Unusable" : "???")))))))); - printk("%s: bytemask[%04lx] was_block(%d) space(%s)\n", - pbm->name, - (afsr & SCHIZO_PCIAFSR_BMSK) >> 32UL, - (afsr & SCHIZO_PCIAFSR_BLK) ? 1 : 0, - ((afsr & SCHIZO_PCIAFSR_CFG) ? - "Config" : - ((afsr & SCHIZO_PCIAFSR_MEM) ? - "Memory" : - ((afsr & SCHIZO_PCIAFSR_IO) ? - "I/O" : "???")))); - printk("%s: PCI AFAR [%016lx]\n", - pbm->name, afar); - printk("%s: PCI Secondary errors [", - pbm->name); - reported = 0; - if (afsr & SCHIZO_PCIAFSR_SMA) { - reported++; - printk("(Master Abort)"); - } - if (afsr & SCHIZO_PCIAFSR_STA) { - reported++; - printk("(Target Abort)"); - } - if (afsr & SCHIZO_PCIAFSR_SRTRY) { - reported++; - printk("(Excessive Retries)"); - } - if (afsr & SCHIZO_PCIAFSR_SPERR) { - reported++; - printk("(Parity Error)"); - } - if (afsr & SCHIZO_PCIAFSR_STTO) { - reported++; - printk("(Timeout)"); - } - if (afsr & SCHIZO_PCIAFSR_SUNUS) { - reported++; - printk("(Bus Unusable)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* For the error types shown, scan PBM's PCI bus for devices - * which have logged that error type. - */ - - /* If we see a Target Abort, this could be the result of an - * IOMMU translation error of some sort. It is extremely - * useful to log this information as usually it indicates - * a bug in the IOMMU support code or a PCI device driver. - */ - if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { - schizo_check_iommu_error(p, PCI_ERR); - pci_scan_for_target_abort(p, pbm, pbm->pci_bus); - } - if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) - pci_scan_for_master_abort(p, pbm, pbm->pci_bus); - - /* For excessive retries, PSYCHO/PBM will abort the device - * and there is no way to specifically check for excessive - * retries in the config space status registers. So what - * we hope is that we'll catch it via the master/target - * abort events. - */ - - if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(p, pbm, pbm->pci_bus); - - schizo_clear_other_err_intr(p, irq); - - return IRQ_HANDLED; -} - -#define SCHIZO_SAFARI_ERRLOG 0x10018UL - -#define SAFARI_ERRLOG_ERROUT 0x8000000000000000UL - -#define BUS_ERROR_BADCMD 0x4000000000000000UL /* Schizo/Tomatillo */ -#define BUS_ERROR_SSMDIS 0x2000000000000000UL /* Safari */ -#define BUS_ERROR_BADMA 0x1000000000000000UL /* Safari */ -#define BUS_ERROR_BADMB 0x0800000000000000UL /* Safari */ -#define BUS_ERROR_BADMC 0x0400000000000000UL /* Safari */ -#define BUS_ERROR_SNOOP_GR 0x0000000000200000UL /* Tomatillo */ -#define BUS_ERROR_SNOOP_PCI 0x0000000000100000UL /* Tomatillo */ -#define BUS_ERROR_SNOOP_RD 0x0000000000080000UL /* Tomatillo */ -#define BUS_ERROR_SNOOP_RDS 0x0000000000020000UL /* Tomatillo */ -#define BUS_ERROR_SNOOP_RDSA 0x0000000000010000UL /* Tomatillo */ -#define BUS_ERROR_SNOOP_OWN 0x0000000000008000UL /* Tomatillo */ -#define BUS_ERROR_SNOOP_RDO 0x0000000000004000UL /* Tomatillo */ -#define BUS_ERROR_CPU1PS 0x0000000000002000UL /* Safari */ -#define BUS_ERROR_WDATA_PERR 0x0000000000002000UL /* Tomatillo */ -#define BUS_ERROR_CPU1PB 0x0000000000001000UL /* Safari */ -#define BUS_ERROR_CTRL_PERR 0x0000000000001000UL /* Tomatillo */ -#define BUS_ERROR_CPU0PS 0x0000000000000800UL /* Safari */ -#define BUS_ERROR_SNOOP_ERR 0x0000000000000800UL /* Tomatillo */ -#define BUS_ERROR_CPU0PB 0x0000000000000400UL /* Safari */ -#define BUS_ERROR_JBUS_ILL_B 0x0000000000000400UL /* Tomatillo */ -#define BUS_ERROR_CIQTO 0x0000000000000200UL /* Safari */ -#define BUS_ERROR_LPQTO 0x0000000000000100UL /* Safari */ -#define BUS_ERROR_JBUS_ILL_C 0x0000000000000100UL /* Tomatillo */ -#define BUS_ERROR_SFPQTO 0x0000000000000080UL /* Safari */ -#define BUS_ERROR_UFPQTO 0x0000000000000040UL /* Safari */ -#define BUS_ERROR_RD_PERR 0x0000000000000040UL /* Tomatillo */ -#define BUS_ERROR_APERR 0x0000000000000020UL /* Safari/Tomatillo */ -#define BUS_ERROR_UNMAP 0x0000000000000010UL /* Safari/Tomatillo */ -#define BUS_ERROR_BUSERR 0x0000000000000004UL /* Safari/Tomatillo */ -#define BUS_ERROR_TIMEOUT 0x0000000000000002UL /* Safari/Tomatillo */ -#define BUS_ERROR_ILL 0x0000000000000001UL /* Safari */ - -/* We only expect UNMAP errors here. The rest of the Safari errors - * are marked fatal and thus cause a system reset. - */ -static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pci_controller_info *p = dev_id; - u64 errlog; - - errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG); - schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG, - errlog & ~(SAFARI_ERRLOG_ERROUT)); - - if (!(errlog & BUS_ERROR_UNMAP)) { - printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", - p->index, errlog); - - schizo_clear_other_err_intr(p, irq); - return IRQ_HANDLED; - } - - printk("PCI%d: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", - p->index); - schizo_check_iommu_error(p, SAFARI_ERR); - - schizo_clear_other_err_intr(p, irq); - return IRQ_HANDLED; -} - -/* Nearly identical to PSYCHO equivalents... */ -#define SCHIZO_ECC_CTRL 0x10020UL -#define SCHIZO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ -#define SCHIZO_ECCCTRL_UE 0x4000000000000000UL /* Enable UE Interrupts */ -#define SCHIZO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ - -#define SCHIZO_SAFARI_ERRCTRL 0x10008UL -#define SCHIZO_SAFERRCTRL_EN 0x8000000000000000UL -#define SCHIZO_SAFARI_IRQCTRL 0x10010UL -#define SCHIZO_SAFIRQCTRL_EN 0x8000000000000000UL - -/* How the Tomatillo IRQs are routed around is pure guesswork here. - * - * All the Tomatillo devices I see in prtconf dumps seem to have only - * a single PCI bus unit attached to it. It would seem they are seperate - * devices because their PortID (ie. JBUS ID) values are all different - * and thus the registers are mapped to totally different locations. - * - * However, two Tomatillo's look "similar" in that the only difference - * in their PortID is the lowest bit. - * - * So if we were to ignore this lower bit, it certainly looks like two - * PCI bus units of the same Tomatillo. I still have not really - * figured this out... - */ -static void tomatillo_register_error_handlers(struct pci_controller_info *p) -{ - struct pci_pbm_info *pbm; - unsigned int irq; - struct ino_bucket *bucket; - u64 tmp, err_mask, err_no_mask; - - /* Build IRQs and register handlers. */ - pbm = pbm_for_ino(p, SCHIZO_UE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO); - if (request_irq(irq, schizo_ue_intr, - SA_SHIRQ, "TOMATILLO UE", p) < 0) { - prom_printf("%s: Cannot register UE interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_UE_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_CE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO); - if (request_irq(irq, schizo_ce_intr, - SA_SHIRQ, "TOMATILLO CE", p) < 0) { - prom_printf("%s: Cannot register CE interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_CE_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); - irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) | - SCHIZO_PCIERR_A_INO)); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { - prom_printf("%s: Cannot register PBM A PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); - irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) | - SCHIZO_PCIERR_B_INO)); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { - prom_printf("%s: Cannot register PBM B PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_SERR_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO); - if (request_irq(irq, schizo_safarierr_intr, - SA_SHIRQ, "TOMATILLO SERR", p) < 0) { - prom_printf("%s: Cannot register SafariERR interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_SERR_INO) + 4)); - - /* Enable UE and CE interrupts for controller. */ - schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); - - schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); - - /* Enable PCI Error interrupts and clear error - * bits. - */ - err_mask = (SCHIZO_PCICTRL_BUS_UNUS | - SCHIZO_PCICTRL_TTO_ERR | - SCHIZO_PCICTRL_RTRY_ERR | - SCHIZO_PCICTRL_SERR | - SCHIZO_PCICTRL_EEN); - - err_no_mask = SCHIZO_PCICTRL_DTO_ERR; - - tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL); - tmp |= err_mask; - tmp &= ~err_no_mask; - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp); - - tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL); - tmp |= err_mask; - tmp &= ~err_no_mask; - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp); - - err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | - SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | - SCHIZO_PCIAFSR_PTTO | - SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | - SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | - SCHIZO_PCIAFSR_STTO); - - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, err_mask); - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, err_mask); - - err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | - BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | - BUS_ERROR_SNOOP_RDS | BUS_ERROR_SNOOP_RDSA | - BUS_ERROR_SNOOP_OWN | BUS_ERROR_SNOOP_RDO | - BUS_ERROR_WDATA_PERR | BUS_ERROR_CTRL_PERR | - BUS_ERROR_SNOOP_ERR | BUS_ERROR_JBUS_ILL_B | - BUS_ERROR_JBUS_ILL_C | BUS_ERROR_RD_PERR | - BUS_ERROR_APERR | BUS_ERROR_UNMAP | - BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); - - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); - schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); - - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL, - (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); - schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_IRQCTRL, - (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); -} - -static void schizo_register_error_handlers(struct pci_controller_info *p) -{ - struct pci_pbm_info *pbm; - unsigned int irq; - struct ino_bucket *bucket; - u64 tmp, err_mask, err_no_mask; - - /* Build IRQs and register handlers. */ - pbm = pbm_for_ino(p, SCHIZO_UE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO); - if (request_irq(irq, schizo_ue_intr, - SA_SHIRQ, "SCHIZO UE", p) < 0) { - prom_printf("%s: Cannot register UE interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_CE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO); - if (request_irq(irq, schizo_ce_intr, - SA_SHIRQ, "SCHIZO CE", p) < 0) { - prom_printf("%s: Cannot register CE interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "SCHIZO PCIERR", pbm) < 0) { - prom_printf("%s: Cannot register PBM A PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "SCHIZO PCIERR", &p->pbm_B) < 0) { - prom_printf("%s: Cannot register PBM B PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); - - pbm = pbm_for_ino(p, SCHIZO_SERR_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO); - if (request_irq(irq, schizo_safarierr_intr, - SA_SHIRQ, "SCHIZO SERR", p) < 0) { - prom_printf("%s: Cannot register SafariERR interrupt.\n", - pbm->name); - prom_halt(); - } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); - - /* Enable UE and CE interrupts for controller. */ - schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); - - err_mask = (SCHIZO_PCICTRL_BUS_UNUS | - SCHIZO_PCICTRL_ESLCK | - SCHIZO_PCICTRL_TTO_ERR | - SCHIZO_PCICTRL_RTRY_ERR | - SCHIZO_PCICTRL_SBH_ERR | - SCHIZO_PCICTRL_SERR | - SCHIZO_PCICTRL_EEN); - - err_no_mask = (SCHIZO_PCICTRL_DTO_ERR | - SCHIZO_PCICTRL_SBH_INT); - - /* Enable PCI Error interrupts and clear error - * bits for each PBM. - */ - tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL); - tmp |= err_mask; - tmp &= ~err_no_mask; - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp); - - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, - (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | - SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | - SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | - SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | - SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | - SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); - - tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL); - tmp |= err_mask; - tmp &= ~err_no_mask; - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp); - - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, - (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | - SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | - SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | - SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | - SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | - SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); - - /* Make all Safari error conditions fatal except unmapped - * errors which we make generate interrupts. - */ - err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SSMDIS | - BUS_ERROR_BADMA | BUS_ERROR_BADMB | - BUS_ERROR_BADMC | - BUS_ERROR_CPU1PS | BUS_ERROR_CPU1PB | - BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB | - BUS_ERROR_CIQTO | - BUS_ERROR_LPQTO | BUS_ERROR_SFPQTO | - BUS_ERROR_UFPQTO | BUS_ERROR_APERR | - BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT | - BUS_ERROR_ILL); -#if 1 - /* XXX Something wrong with some Excalibur systems - * XXX Sun is shipping. The behavior on a 2-cpu - * XXX machine is that both CPU1 parity error bits - * XXX are set and are immediately set again when - * XXX their error status bits are cleared. Just - * XXX ignore them for now. -DaveM - */ - err_mask &= ~(BUS_ERROR_CPU1PS | BUS_ERROR_CPU1PB | - BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); -#endif - - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); - - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL, - (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); -} - -static void pbm_config_busmastering(struct pci_pbm_info *pbm) -{ - u8 *addr; - - /* Set cache-line size to 64 bytes, this is actually - * a nop but I do it for completeness. - */ - addr = schizo_pci_config_mkaddr(pbm, pbm->pci_first_busno, - 0, PCI_CACHE_LINE_SIZE); - pci_config_write8(addr, 64 / sizeof(u32)); - - /* Set PBM latency timer to 64 PCI clocks. */ - addr = schizo_pci_config_mkaddr(pbm, pbm->pci_first_busno, - 0, PCI_LATENCY_TIMER); - pci_config_write8(addr, 64); -} - -static void pbm_scan_bus(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("%s: Critical allocation failure.\n", pbm->name); - prom_halt(); - } - - /* All we care about is the PBM. */ - memset(cookie, 0, sizeof(*cookie)); - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, - p->pci_ops, - pbm); - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; - - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); -} - -static void __schizo_scan_bus(struct pci_controller_info *p, - int chip_type) -{ - if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) { - printk("PCI: Only one PCI bus module of controller found.\n"); - printk("PCI: Ignoring entire controller.\n"); - return; - } - - pbm_config_busmastering(&p->pbm_B); - p->pbm_B.is_66mhz_capable = - prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); - pbm_config_busmastering(&p->pbm_A); - p->pbm_A.is_66mhz_capable = - prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); - pbm_scan_bus(p, &p->pbm_B); - pbm_scan_bus(p, &p->pbm_A); - - /* After the PCI bus scan is complete, we can register - * the error interrupt handlers. - */ - if (chip_type == PBM_CHIP_TYPE_TOMATILLO) - tomatillo_register_error_handlers(p); - else - schizo_register_error_handlers(p); -} - -static void schizo_scan_bus(struct pci_controller_info *p) -{ - __schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO); -} - -static void tomatillo_scan_bus(struct pci_controller_info *p) -{ - __schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO); -} - -static void schizo_base_address_update(struct pci_dev *pdev, int resource) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res, *root; - u32 reg; - int where, size, is_64bit; - - res = &pdev->resource[resource]; - if (resource < 6) { - where = PCI_BASE_ADDRESS_0 + (resource * 4); - } else if (resource == PCI_ROM_RESOURCE) { - where = pdev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - is_64bit = 0; - if (res->flags & IORESOURCE_IO) - root = &pbm->io_space; - else { - root = &pbm->mem_space; - if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - is_64bit = 1; - } - - size = res->end - res->start; - pci_read_config_dword(pdev, where, ®); - reg = ((reg & size) | - (((u32)(res->start - root->start)) & ~size)); - if (resource == PCI_ROM_RESOURCE) { - reg |= PCI_ROM_ADDRESS_ENABLE; - res->flags |= IORESOURCE_ROM_ENABLE; - } - pci_write_config_dword(pdev, where, reg); - - /* This knows that the upper 32-bits of the address - * must be zero. Our PCI common layer enforces this. - */ - if (is_64bit) - pci_write_config_dword(pdev, where + 4, 0); -} - -static void schizo_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - -/* Use ranges property to determine where PCI MEM, I/O, and Config - * space are for this PCI bus module. - */ -static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm) -{ - int i, saw_cfg, saw_mem, saw_io; - - saw_cfg = saw_mem = saw_io = 0; - for (i = 0; i < pbm->num_pbm_ranges; i++) { - struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i]; - unsigned long a; - int type; - - type = (pr->child_phys_hi >> 24) & 0x3; - a = (((unsigned long)pr->parent_phys_hi << 32UL) | - ((unsigned long)pr->parent_phys_lo << 0UL)); - - switch (type) { - case 0: - /* PCI config space, 16MB */ - pbm->config_space = a; - saw_cfg = 1; - break; - - case 1: - /* 16-bit IO space, 16MB */ - pbm->io_space.start = a; - pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); - pbm->io_space.flags = IORESOURCE_IO; - saw_io = 1; - break; - - case 2: - /* 32-bit MEM space, 2GB */ - pbm->mem_space.start = a; - pbm->mem_space.end = a + (0x80000000UL - 1UL); - pbm->mem_space.flags = IORESOURCE_MEM; - saw_mem = 1; - break; - - default: - break; - }; - } - - if (!saw_cfg || !saw_io || !saw_mem) { - prom_printf("%s: Fatal error, missing %s PBM range.\n", - pbm->name, - ((!saw_cfg ? - "CFG" : - (!saw_io ? - "IO" : "MEM")))); - prom_halt(); - } - - printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n", - pbm->name, - pbm->config_space, - pbm->io_space.start, - pbm->mem_space.start); -} - -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - pbm->io_space.name = pbm->mem_space.name = pbm->name; - - request_resource(&ioport_resource, &pbm->io_space); - request_resource(&iomem_resource, &pbm->mem_space); - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - -#define SCHIZO_STRBUF_CONTROL (0x02800UL) -#define SCHIZO_STRBUF_FLUSH (0x02808UL) -#define SCHIZO_STRBUF_FSYNC (0x02810UL) -#define SCHIZO_STRBUF_CTXFLUSH (0x02818UL) -#define SCHIZO_STRBUF_CTXMATCH (0x10000UL) - -static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) -{ - unsigned long base = pbm->pbm_regs; - u64 control; - - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - /* TOMATILLO lacks streaming cache. */ - return; - } - - /* SCHIZO has context flushing. */ - pbm->stc.strbuf_control = base + SCHIZO_STRBUF_CONTROL; - pbm->stc.strbuf_pflush = base + SCHIZO_STRBUF_FLUSH; - pbm->stc.strbuf_fsync = base + SCHIZO_STRBUF_FSYNC; - pbm->stc.strbuf_ctxflush = base + SCHIZO_STRBUF_CTXFLUSH; - pbm->stc.strbuf_ctxmatch_base = base + SCHIZO_STRBUF_CTXMATCH; - - pbm->stc.strbuf_flushflag = (volatile unsigned long *) - ((((unsigned long)&pbm->stc.__flushflag_buf[0]) - + 63UL) - & ~63UL); - pbm->stc.strbuf_flushflag_pa = (unsigned long) - __pa(pbm->stc.strbuf_flushflag); - - /* Turn off LRU locking and diag mode, enable the - * streaming buffer and leave the rerun-disable - * setting however OBP set it. - */ - control = schizo_read(pbm->stc.strbuf_control); - control &= ~(SCHIZO_STRBUF_CTRL_LPTR | - SCHIZO_STRBUF_CTRL_LENAB | - SCHIZO_STRBUF_CTRL_DENAB); - control |= SCHIZO_STRBUF_CTRL_ENAB; - schizo_write(pbm->stc.strbuf_control, control); - - pbm->stc.strbuf_enabled = 1; -} - -#define SCHIZO_IOMMU_CONTROL (0x00200UL) -#define SCHIZO_IOMMU_TSBBASE (0x00208UL) -#define SCHIZO_IOMMU_FLUSH (0x00210UL) -#define SCHIZO_IOMMU_CTXFLUSH (0x00218UL) - -static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) -{ - struct pci_iommu *iommu = pbm->iommu; - unsigned long i, tagbase, database; - u32 vdma[2], dma_mask; - u64 control; - int err, tsbsize; - - err = prom_getproperty(pbm->prom_node, "virtual-dma", - (char *)&vdma[0], sizeof(vdma)); - if (err == 0 || err == -1) { - /* No property, use default values. */ - vdma[0] = 0xc0000000; - vdma[1] = 0x40000000; - } - - dma_mask = vdma[0]; - switch (vdma[1]) { - case 0x20000000: - dma_mask |= 0x1fffffff; - tsbsize = 64; - break; - - case 0x40000000: - dma_mask |= 0x3fffffff; - tsbsize = 128; - break; - - case 0x80000000: - dma_mask |= 0x7fffffff; - tsbsize = 128; - break; - - default: - prom_printf("SCHIZO: strange virtual-dma size.\n"); - prom_halt(); - }; - - /* Register addresses, SCHIZO has iommu ctx flushing. */ - iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; - iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE; - iommu->iommu_flush = pbm->pbm_regs + SCHIZO_IOMMU_FLUSH; - iommu->iommu_ctxflush = pbm->pbm_regs + SCHIZO_IOMMU_CTXFLUSH; - - /* We use the main control/status register of SCHIZO as the write - * completion register. - */ - iommu->write_complete_reg = pbm->controller_regs + 0x10000UL; - - /* - * Invalidate TLB Entries. - */ - control = schizo_read(iommu->iommu_control); - control |= SCHIZO_IOMMU_CTRL_DENAB; - schizo_write(iommu->iommu_control, control); - - tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; - - for(i = 0; i < 16; i++) { - schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); - schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); - } - - /* Leave diag mode enabled for full-flushing done - * in pci_iommu.c - */ - pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); - - schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); - - control = schizo_read(iommu->iommu_control); - control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); - switch (tsbsize) { - case 64: - control |= SCHIZO_IOMMU_TSBSZ_64K; - break; - case 128: - control |= SCHIZO_IOMMU_TSBSZ_128K; - break; - }; - - control |= SCHIZO_IOMMU_CTRL_ENAB; - schizo_write(iommu->iommu_control, control); -} - -#define SCHIZO_PCI_IRQ_RETRY (0x1a00UL) -#define SCHIZO_IRQ_RETRY_INF 0xffUL - -#define SCHIZO_PCI_DIAG (0x2020UL) -#define SCHIZO_PCIDIAG_D_BADECC (1UL << 10UL) /* Disable BAD ECC errors (Schizo) */ -#define SCHIZO_PCIDIAG_D_BYPASS (1UL << 9UL) /* Disable MMU bypass mode (Schizo/Tomatillo) */ -#define SCHIZO_PCIDIAG_D_TTO (1UL << 8UL) /* Disable TTO errors (Schizo/Tomatillo) */ -#define SCHIZO_PCIDIAG_D_RTRYARB (1UL << 7UL) /* Disable retry arbitration (Schizo) */ -#define SCHIZO_PCIDIAG_D_RETRY (1UL << 6UL) /* Disable retry limit (Schizo/Tomatillo) */ -#define SCHIZO_PCIDIAG_D_INTSYNC (1UL << 5UL) /* Disable interrupt/DMA synch (Schizo/Tomatillo) */ -#define SCHIZO_PCIDIAG_I_DMA_PARITY (1UL << 3UL) /* Invert DMA parity (Schizo/Tomatillo) */ -#define SCHIZO_PCIDIAG_I_PIOD_PARITY (1UL << 2UL) /* Invert PIO data parity (Schizo/Tomatillo) */ -#define SCHIZO_PCIDIAG_I_PIOA_PARITY (1UL << 1UL) /* Invert PIO address parity (Schizo/Tomatillo) */ - -#define TOMATILLO_PCI_IOC_CSR (0x2248UL) -#define TOMATILLO_IOC_PART_WPENAB 0x0000000000080000UL -#define TOMATILLO_IOC_RDMULT_PENAB 0x0000000000040000UL -#define TOMATILLO_IOC_RDONE_PENAB 0x0000000000020000UL -#define TOMATILLO_IOC_RDLINE_PENAB 0x0000000000010000UL -#define TOMATILLO_IOC_RDMULT_PLEN 0x000000000000c000UL -#define TOMATILLO_IOC_RDMULT_PLEN_SHIFT 14UL -#define TOMATILLO_IOC_RDONE_PLEN 0x0000000000003000UL -#define TOMATILLO_IOC_RDONE_PLEN_SHIFT 12UL -#define TOMATILLO_IOC_RDLINE_PLEN 0x0000000000000c00UL -#define TOMATILLO_IOC_RDLINE_PLEN_SHIFT 10UL -#define TOMATILLO_IOC_PREF_OFF 0x00000000000003f8UL -#define TOMATILLO_IOC_PREF_OFF_SHIFT 3UL -#define TOMATILLO_IOC_RDMULT_CPENAB 0x0000000000000004UL -#define TOMATILLO_IOC_RDONE_CPENAB 0x0000000000000002UL -#define TOMATILLO_IOC_RDLINE_CPENAB 0x0000000000000001UL - -#define TOMATILLO_PCI_IOC_TDIAG (0x2250UL) -#define TOMATILLO_PCI_IOC_DDIAG (0x2290UL) - -static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) -{ - u64 tmp; - - schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); - - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); - - /* Enable arbiter for all PCI slots. */ - tmp |= 0xff; - - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO && - pbm->chip_version >= 0x2) - tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; - - if (!prom_getbool(pbm->prom_node, "no-bus-parking")) - tmp |= SCHIZO_PCICTRL_PARK; - else - tmp &= ~SCHIZO_PCICTRL_PARK; - - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO && - pbm->chip_version <= 0x1) - tmp |= SCHIZO_PCICTRL_DTO_INT; - else - tmp &= ~SCHIZO_PCICTRL_DTO_INT; - - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) - tmp |= (SCHIZO_PCICTRL_MRM_PREF | - SCHIZO_PCICTRL_RDO_PREF | - SCHIZO_PCICTRL_RDL_PREF); - - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); - - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG); - tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | - SCHIZO_PCIDIAG_D_RETRY | - SCHIZO_PCIDIAG_D_INTSYNC); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp); - - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - /* Clear prefetch lengths to workaround a bug in - * Jalapeno... - */ - tmp = (TOMATILLO_IOC_PART_WPENAB | - (1 << TOMATILLO_IOC_PREF_OFF_SHIFT) | - TOMATILLO_IOC_RDMULT_CPENAB | - TOMATILLO_IOC_RDONE_CPENAB | - TOMATILLO_IOC_RDLINE_CPENAB); - - schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR, - tmp); - } -} - -static void schizo_pbm_init(struct pci_controller_info *p, - int prom_node, u32 portid, - int chip_type) -{ - struct linux_prom64_registers pr_regs[4]; - unsigned int busrange[2]; - struct pci_pbm_info *pbm; - const char *chipset_name; - u32 ino_bitmap[2]; - int is_pbm_a; - int err; - - switch (chip_type) { - case PBM_CHIP_TYPE_TOMATILLO: - chipset_name = "TOMATILLO"; - break; - - case PBM_CHIP_TYPE_SCHIZO_PLUS: - chipset_name = "SCHIZO+"; - break; - - case PBM_CHIP_TYPE_SCHIZO: - default: - chipset_name = "SCHIZO"; - break; - }; - - /* For SCHIZO, three OBP regs: - * 1) PBM controller regs - * 2) Schizo front-end controller regs (same for both PBMs) - * 3) PBM PCI config space - * - * For TOMATILLO, four OBP regs: - * 1) PBM controller regs - * 2) Tomatillo front-end controller regs - * 3) PBM PCI config space - * 4) Ichip regs - */ - err = prom_getproperty(prom_node, "reg", - (char *)&pr_regs[0], - sizeof(pr_regs)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no reg property.\n", - chipset_name); - prom_halt(); - } - - is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000); - - if (is_pbm_a) - pbm = &p->pbm_A; - else - pbm = &p->pbm_B; - - pbm->portid = portid; - pbm->parent = p; - pbm->prom_node = prom_node; - pbm->pci_first_slot = 1; - - pbm->chip_type = chip_type; - pbm->chip_version = - prom_getintdefault(prom_node, "version#", 0); - pbm->chip_revision = - prom_getintdefault(prom_node, "module-revision#", 0); - - pbm->pbm_regs = pr_regs[0].phys_addr; - pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; - - if (chip_type == PBM_CHIP_TYPE_TOMATILLO) - pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; - - sprintf(pbm->name, - (chip_type == PBM_CHIP_TYPE_TOMATILLO ? - "TOMATILLO%d PBM%c" : - "SCHIZO%d PBM%c"), - p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); - - printk("%s: ver[%x:%x], portid %x, " - "cregs[%lx] pregs[%lx]\n", - pbm->name, - pbm->chip_version, pbm->chip_revision, - pbm->portid, - pbm->controller_regs, - pbm->pbm_regs); - - schizo_pbm_hw_init(pbm); - - prom_getstring(prom_node, "name", - pbm->prom_name, - sizeof(pbm->prom_name)); - - err = prom_getproperty(prom_node, "ranges", - (char *) pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no ranges property.\n", - pbm->name); - prom_halt(); - } - - pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); - - schizo_determine_mem_io_space(pbm); - pbm_register_toplevel_resources(p, pbm); - - err = prom_getproperty(prom_node, "interrupt-map", - (char *)pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(prom_node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("%s: Fatal error, no " - "interrupt-map-mask.\n", pbm->name); - prom_halt(); - } - } else { - pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); - } - - err = prom_getproperty(prom_node, "ino-bitmap", - (char *) &ino_bitmap[0], - sizeof(ino_bitmap)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name); - prom_halt(); - } - pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | - ((u64)ino_bitmap[0] << 0UL)); - - err = prom_getproperty(prom_node, "bus-range", - (char *)&busrange[0], - sizeof(busrange)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no bus-range.\n", pbm->name); - prom_halt(); - } - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; - - schizo_pbm_iommu_init(pbm); - schizo_pbm_strbuf_init(pbm); -} - -static inline int portid_compare(u32 x, u32 y, int chip_type) -{ - if (chip_type == PBM_CHIP_TYPE_TOMATILLO) { - if (x == (y ^ 1)) - return 1; - return 0; - } - return (x == y); -} - -static void __schizo_init(int node, char *model_name, int chip_type) -{ - struct pci_controller_info *p; - struct pci_iommu *iommu; - int is_pbm_a; - u32 portid; - - portid = prom_getintdefault(node, "portid", 0xff); - - for(p = pci_controller_root; p; p = p->next) { - struct pci_pbm_info *pbm; - - if (p->pbm_A.prom_node && p->pbm_B.prom_node) - continue; - - pbm = (p->pbm_A.prom_node ? - &p->pbm_A : - &p->pbm_B); - - if (portid_compare(pbm->portid, portid, chip_type)) { - is_pbm_a = (p->pbm_A.prom_node == 0); - schizo_pbm_init(p, node, portid, chip_type); - return; - } - } - - p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); - } - memset(p, 0, sizeof(*p)); - - iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); - if (!iommu) { - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); - } - memset(iommu, 0, sizeof(*iommu)); - p->pbm_A.iommu = iommu; - - iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); - if (!iommu) { - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); - } - memset(iommu, 0, sizeof(*iommu)); - p->pbm_B.iommu = iommu; - - p->next = pci_controller_root; - pci_controller_root = p; - - p->index = pci_num_controllers++; - p->pbms_same_domain = 0; - p->scan_bus = (chip_type == PBM_CHIP_TYPE_TOMATILLO ? - tomatillo_scan_bus : - schizo_scan_bus); - p->irq_build = schizo_irq_build; - p->base_address_update = schizo_base_address_update; - p->resource_adjust = schizo_resource_adjust; - p->pci_ops = &schizo_ops; - - /* Like PSYCHO we have a 2GB aligned area for memory space. */ - pci_memspace_mask = 0x7fffffffUL; - - schizo_pbm_init(p, node, portid, chip_type); -} - -void schizo_init(int node, char *model_name) -{ - __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO); -} - -void schizo_plus_init(int node, char *model_name) -{ - __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); -} - -void tomatillo_init(int node, char *model_name) -{ - __schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO); -} diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c deleted file mode 100644 index 30bcaf58e3a..00000000000 --- a/arch/sparc64/kernel/power.c +++ /dev/null @@ -1,191 +0,0 @@ -/* $Id: power.c,v 1.10 2001/12/11 01:57:16 davem Exp $ - * power.c: Power management driver. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#define __KERNEL_SYSCALLS__ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/signal.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/pm.h> - -#include <asm/system.h> -#include <asm/ebus.h> -#include <asm/isa.h> -#include <asm/auxio.h> - -#include <linux/unistd.h> - -/* - * sysctl - toggle power-off restriction for serial console - * systems in machine_power_off() - */ -int scons_pwroff = 1; - -#ifdef CONFIG_PCI -static void __iomem *power_reg; - -static DECLARE_WAIT_QUEUE_HEAD(powerd_wait); -static int button_pressed; - -static irqreturn_t power_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - if (button_pressed == 0) { - button_pressed = 1; - wake_up(&powerd_wait); - } - - /* FIXME: Check registers for status... */ - return IRQ_HANDLED; -} -#endif /* CONFIG_PCI */ - -extern void machine_halt(void); -extern void machine_alt_power_off(void); -static void (*poweroff_method)(void) = machine_alt_power_off; - -void machine_power_off(void) -{ - if (!serial_console || scons_pwroff) { -#ifdef CONFIG_PCI - if (power_reg) { - /* Both register bits seem to have the - * same effect, so until I figure out - * what the difference is... - */ - writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg); - } else -#endif /* CONFIG_PCI */ - if (poweroff_method != NULL) { - poweroff_method(); - /* not reached */ - } - } - machine_halt(); -} - -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - -#ifdef CONFIG_PCI -static int powerd(void *__unused) -{ - static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - char *argv[] = { "/sbin/shutdown", "-h", "now", NULL }; - DECLARE_WAITQUEUE(wait, current); - - daemonize("powerd"); - - add_wait_queue(&powerd_wait, &wait); -again: - for (;;) { - set_task_state(current, TASK_INTERRUPTIBLE); - if (button_pressed) - break; - flush_signals(current); - schedule(); - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&powerd_wait, &wait); - - /* Ok, down we go... */ - button_pressed = 0; - if (execve("/sbin/shutdown", argv, envp) < 0) { - printk("powerd: shutdown execution failed\n"); - add_wait_queue(&powerd_wait, &wait); - goto again; - } - return 0; -} - -static int __init has_button_interrupt(unsigned int irq, int prom_node) -{ - if (irq == PCI_IRQ_NONE) - return 0; - if (!prom_node_has_property(prom_node, "button")) - return 0; - - return 1; -} - -static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) -{ - struct linux_ebus *ebus; - struct linux_ebus_device *edev; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "power")) { - *resp = &edev->resource[0]; - *irq_p = edev->irqs[0]; - *prom_node_p = edev->prom_node; - return 0; - } - } - } - return -ENODEV; -} - -static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p) -{ - struct sparc_isa_bridge *isa_bus; - struct sparc_isa_device *isa_dev; - - for_each_isa(isa_bus) { - for_each_isadev(isa_dev, isa_bus) { - if (!strcmp(isa_dev->prom_name, "power")) { - *resp = &isa_dev->resource; - *irq_p = isa_dev->irq; - *prom_node_p = isa_dev->prom_node; - return 0; - } - } - } - return -ENODEV; -} - -void __init power_init(void) -{ - struct resource *res = NULL; - unsigned int irq; - int prom_node; - static int invoked; - - if (invoked) - return; - invoked = 1; - - if (!power_probe_ebus(&res, &irq, &prom_node)) - goto found; - - if (!power_probe_isa(&res, &irq, &prom_node)) - goto found; - - return; - -found: - power_reg = ioremap(res->start, 0x4); - printk("power: Control reg at %p ... ", power_reg); - poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(irq, prom_node)) { - if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { - printk("Failed to start power daemon.\n"); - return; - } - printk("powerd running.\n"); - - if (request_irq(irq, - power_handler, SA_SHIRQ, "power", NULL) < 0) - printk("power: Error, cannot register IRQ handler.\n"); - } else { - printk("not using powerd.\n"); - } -} -#endif /* CONFIG_PCI */ diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c deleted file mode 100644 index 059b0d02522..00000000000 --- a/arch/sparc64/kernel/process.c +++ /dev/null @@ -1,872 +0,0 @@ -/* $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $ - * arch/sparc64/kernel/process.c - * - * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -/* - * This file handles the architecture-dependent parts of process handling.. - */ - -#include <stdarg.h> - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/kallsyms.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/stddef.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/user.h> -#include <linux/a.out.h> -#include <linux/config.h> -#include <linux/reboot.h> -#include <linux/delay.h> -#include <linux/compat.h> -#include <linux/init.h> - -#include <asm/oplib.h> -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/page.h> -#include <asm/pgalloc.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/pstate.h> -#include <asm/elf.h> -#include <asm/fpumacro.h> -#include <asm/head.h> -#include <asm/cpudata.h> -#include <asm/unistd.h> - -/* #define VERBOSE_SHOWREGS */ - -/* - * Nothing special yet... - */ -void default_idle(void) -{ -} - -#ifndef CONFIG_SMP - -/* - * the idle loop on a Sparc... ;) - */ -void cpu_idle(void) -{ - /* endless idle loop with no priority at all */ - for (;;) { - /* If current->work.need_resched is zero we should really - * setup for a system wakup event and execute a shutdown - * instruction. - * - * But this requires writing back the contents of the - * L2 cache etc. so implement this later. -DaveM - */ - while (!need_resched()) - barrier(); - - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - check_pgt_cache(); - } -} - -#else - -/* - * the idle loop on a UltraMultiPenguin... - * - * TIF_POLLING_NRFLAG is set because we do not sleep the cpu - * inside of the idler task, so an interrupt is not needed - * to get a clean fast response. - * - * XXX Reverify this assumption... -DaveM - * - * Addendum: We do want it to do something for the signal - * delivery case, we detect that by just seeing - * if we are trying to send this to an idler or not. - */ -void cpu_idle(void) -{ - cpuinfo_sparc *cpuinfo = &local_cpu_data(); - set_thread_flag(TIF_POLLING_NRFLAG); - - while(1) { - if (need_resched()) { - cpuinfo->idle_volume = 0; - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - check_pgt_cache(); - } - cpuinfo->idle_volume++; - - /* The store ordering is so that IRQ handlers on - * other cpus see our increasing idleness for the buddy - * redistribution algorithm. -DaveM - */ - membar_storeload_storestore(); - } -} - -#endif - -extern char reboot_command []; - -extern void (*prom_palette)(int); -extern void (*prom_keyboard)(void); - -void machine_halt(void) -{ - if (!serial_console && prom_palette) - prom_palette (1); - if (prom_keyboard) - prom_keyboard(); - prom_halt(); - panic("Halt failed!"); -} - -void machine_alt_power_off(void) -{ - if (!serial_console && prom_palette) - prom_palette(1); - if (prom_keyboard) - prom_keyboard(); - prom_halt_power_off(); - panic("Power-off failed!"); -} - -void machine_restart(char * cmd) -{ - char *p; - - p = strchr (reboot_command, '\n'); - if (p) *p = 0; - if (!serial_console && prom_palette) - prom_palette (1); - if (prom_keyboard) - prom_keyboard(); - if (cmd) - prom_reboot(cmd); - if (*reboot_command) - prom_reboot(reboot_command); - prom_reboot(""); - panic("Reboot failed!"); -} - -#ifdef CONFIG_COMPAT -static void show_regwindow32(struct pt_regs *regs) -{ - struct reg_window32 __user *rw; - struct reg_window32 r_w; - mm_segment_t old_fs; - - __asm__ __volatile__ ("flushw"); - rw = compat_ptr((unsigned)regs->u_regs[14]); - old_fs = get_fs(); - set_fs (USER_DS); - if (copy_from_user (&r_w, rw, sizeof(r_w))) { - set_fs (old_fs); - return; - } - - set_fs (old_fs); - printk("l0: %08x l1: %08x l2: %08x l3: %08x " - "l4: %08x l5: %08x l6: %08x l7: %08x\n", - r_w.locals[0], r_w.locals[1], r_w.locals[2], r_w.locals[3], - r_w.locals[4], r_w.locals[5], r_w.locals[6], r_w.locals[7]); - printk("i0: %08x i1: %08x i2: %08x i3: %08x " - "i4: %08x i5: %08x i6: %08x i7: %08x\n", - r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3], - r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]); -} -#else -#define show_regwindow32(regs) do { } while (0) -#endif - -static void show_regwindow(struct pt_regs *regs) -{ - struct reg_window __user *rw; - struct reg_window *rwk; - struct reg_window r_w; - mm_segment_t old_fs; - - if ((regs->tstate & TSTATE_PRIV) || !(test_thread_flag(TIF_32BIT))) { - __asm__ __volatile__ ("flushw"); - rw = (struct reg_window __user *) - (regs->u_regs[14] + STACK_BIAS); - rwk = (struct reg_window *) - (regs->u_regs[14] + STACK_BIAS); - if (!(regs->tstate & TSTATE_PRIV)) { - old_fs = get_fs(); - set_fs (USER_DS); - if (copy_from_user (&r_w, rw, sizeof(r_w))) { - set_fs (old_fs); - return; - } - rwk = &r_w; - set_fs (old_fs); - } - } else { - show_regwindow32(regs); - return; - } - printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n", - rwk->locals[0], rwk->locals[1], rwk->locals[2], rwk->locals[3]); - printk("l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n", - rwk->locals[4], rwk->locals[5], rwk->locals[6], rwk->locals[7]); - printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lx\n", - rwk->ins[0], rwk->ins[1], rwk->ins[2], rwk->ins[3]); - printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n", - rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]); - if (regs->tstate & TSTATE_PRIV) - print_symbol("I7: <%s>\n", rwk->ins[7]); -} - -void show_stackframe(struct sparc_stackf *sf) -{ - unsigned long size; - unsigned long *stk; - int i; - - printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n" - "l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n", - sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3], - sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]); - printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lx\n" - "i4: %016lx i5: %016lx fp: %016lx ret_pc: %016lx\n", - sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3], - sf->ins[4], sf->ins[5], (unsigned long)sf->fp, sf->callers_pc); - printk("sp: %016lx x0: %016lx x1: %016lx x2: %016lx\n" - "x3: %016lx x4: %016lx x5: %016lx xx: %016lx\n", - (unsigned long)sf->structptr, sf->xargs[0], sf->xargs[1], - sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5], - sf->xxargs[0]); - size = ((unsigned long)sf->fp) - ((unsigned long)sf); - size -= STACKFRAME_SZ; - stk = (unsigned long *)((unsigned long)sf + STACKFRAME_SZ); - i = 0; - do { - printk("s%d: %016lx\n", i++, *stk++); - } while ((size -= sizeof(unsigned long))); -} - -void show_stackframe32(struct sparc_stackf32 *sf) -{ - unsigned long size; - unsigned *stk; - int i; - - printk("l0: %08x l1: %08x l2: %08x l3: %08x\n", - sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3]); - printk("l4: %08x l5: %08x l6: %08x l7: %08x\n", - sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]); - printk("i0: %08x i1: %08x i2: %08x i3: %08x\n", - sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3]); - printk("i4: %08x i5: %08x fp: %08x ret_pc: %08x\n", - sf->ins[4], sf->ins[5], sf->fp, sf->callers_pc); - printk("sp: %08x x0: %08x x1: %08x x2: %08x\n" - "x3: %08x x4: %08x x5: %08x xx: %08x\n", - sf->structptr, sf->xargs[0], sf->xargs[1], - sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5], - sf->xxargs[0]); - size = ((unsigned long)sf->fp) - ((unsigned long)sf); - size -= STACKFRAME32_SZ; - stk = (unsigned *)((unsigned long)sf + STACKFRAME32_SZ); - i = 0; - do { - printk("s%d: %08x\n", i++, *stk++); - } while ((size -= sizeof(unsigned))); -} - -#ifdef CONFIG_SMP -static DEFINE_SPINLOCK(regdump_lock); -#endif - -void __show_regs(struct pt_regs * regs) -{ -#ifdef CONFIG_SMP - unsigned long flags; - - /* Protect against xcall ipis which might lead to livelock on the lock */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (flags) - : "i" (PSTATE_IE)); - spin_lock(®dump_lock); -#endif - printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate, - regs->tpc, regs->tnpc, regs->y, print_tainted()); - print_symbol("TPC: <%s>\n", regs->tpc); - printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n", - regs->u_regs[0], regs->u_regs[1], regs->u_regs[2], - regs->u_regs[3]); - printk("g4: %016lx g5: %016lx g6: %016lx g7: %016lx\n", - regs->u_regs[4], regs->u_regs[5], regs->u_regs[6], - regs->u_regs[7]); - printk("o0: %016lx o1: %016lx o2: %016lx o3: %016lx\n", - regs->u_regs[8], regs->u_regs[9], regs->u_regs[10], - regs->u_regs[11]); - printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n", - regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], - regs->u_regs[15]); - print_symbol("RPC: <%s>\n", regs->u_regs[15]); - show_regwindow(regs); -#ifdef CONFIG_SMP - spin_unlock(®dump_lock); - __asm__ __volatile__("wrpr %0, 0, %%pstate" - : : "r" (flags)); -#endif -} - -#ifdef VERBOSE_SHOWREGS -static void idump_from_user (unsigned int *pc) -{ - int i; - int code; - - if((((unsigned long) pc) & 3)) - return; - - pc -= 3; - for(i = -3; i < 6; i++) { - get_user(code, pc); - printk("%c%08x%c",i?' ':'<',code,i?' ':'>'); - pc++; - } - printk("\n"); -} -#endif - -void show_regs(struct pt_regs *regs) -{ -#ifdef VERBOSE_SHOWREGS - extern long etrap, etraptl1; -#endif - __show_regs(regs); -#ifdef CONFIG_SMP - { - extern void smp_report_regs(void); - - smp_report_regs(); - } -#endif - -#ifdef VERBOSE_SHOWREGS - if (regs->tpc >= &etrap && regs->tpc < &etraptl1 && - regs->u_regs[14] >= (long)current - PAGE_SIZE && - regs->u_regs[14] < (long)current + 6 * PAGE_SIZE) { - printk ("*********parent**********\n"); - __show_regs((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF)); - idump_from_user(((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF))->tpc); - printk ("*********endpar**********\n"); - } -#endif -} - -void show_regs32(struct pt_regs32 *regs) -{ - printk("PSR: %08x PC: %08x NPC: %08x Y: %08x %s\n", regs->psr, - regs->pc, regs->npc, regs->y, print_tainted()); - printk("g0: %08x g1: %08x g2: %08x g3: %08x ", - regs->u_regs[0], regs->u_regs[1], regs->u_regs[2], - regs->u_regs[3]); - printk("g4: %08x g5: %08x g6: %08x g7: %08x\n", - regs->u_regs[4], regs->u_regs[5], regs->u_regs[6], - regs->u_regs[7]); - printk("o0: %08x o1: %08x o2: %08x o3: %08x ", - regs->u_regs[8], regs->u_regs[9], regs->u_regs[10], - regs->u_regs[11]); - printk("o4: %08x o5: %08x sp: %08x ret_pc: %08x\n", - regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], - regs->u_regs[15]); -} - -unsigned long thread_saved_pc(struct task_struct *tsk) -{ - struct thread_info *ti = task_thread_info(tsk); - unsigned long ret = 0xdeadbeefUL; - - if (ti && ti->ksp) { - unsigned long *sp; - sp = (unsigned long *)(ti->ksp + STACK_BIAS); - if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL && - sp[14]) { - unsigned long *fp; - fp = (unsigned long *)(sp[14] + STACK_BIAS); - if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL) - ret = fp[15]; - } - } - return ret; -} - -/* Free current thread data structures etc.. */ -void exit_thread(void) -{ - struct thread_info *t = current_thread_info(); - - if (t->utraps) { - if (t->utraps[0] < 2) - kfree (t->utraps); - else - t->utraps[0]--; - } - - if (test_and_clear_thread_flag(TIF_PERFCTR)) { - t->user_cntd0 = t->user_cntd1 = NULL; - t->pcr_reg = 0; - write_pcr(0); - } -} - -void flush_thread(void) -{ - struct thread_info *t = current_thread_info(); - - if (t->flags & _TIF_ABI_PENDING) - t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); - - if (t->task->mm) { - unsigned long pgd_cache = 0UL; - if (test_thread_flag(TIF_32BIT)) { - struct mm_struct *mm = t->task->mm; - pgd_t *pgd0 = &mm->pgd[0]; - pud_t *pud0 = pud_offset(pgd0, 0); - - if (pud_none(*pud0)) { - pmd_t *page = pmd_alloc_one(mm, 0); - pud_set(pud0, page); - } - pgd_cache = get_pgd_cache(pgd0); - } - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (pgd_cache), - "r" (TSB_REG), - "i" (ASI_DMMU)); - } - set_thread_wsaved(0); - - /* Turn off performance counters if on. */ - if (test_and_clear_thread_flag(TIF_PERFCTR)) { - t->user_cntd0 = t->user_cntd1 = NULL; - t->pcr_reg = 0; - write_pcr(0); - } - - /* Clear FPU register state. */ - t->fpsaved[0] = 0; - - if (get_thread_current_ds() != ASI_AIUS) - set_fs(USER_DS); - - /* Init new signal delivery disposition. */ - clear_thread_flag(TIF_NEWSIGNALS); -} - -/* It's a bit more tricky when 64-bit tasks are involved... */ -static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) -{ - unsigned long fp, distance, rval; - - if (!(test_thread_flag(TIF_32BIT))) { - csp += STACK_BIAS; - psp += STACK_BIAS; - __get_user(fp, &(((struct reg_window __user *)psp)->ins[6])); - fp += STACK_BIAS; - } else - __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); - - /* Now 8-byte align the stack as this is mandatory in the - * Sparc ABI due to how register windows work. This hides - * the restriction from thread libraries etc. -DaveM - */ - csp &= ~7UL; - - distance = fp - psp; - rval = (csp - distance); - if (copy_in_user((void __user *) rval, (void __user *) psp, distance)) - rval = 0; - else if (test_thread_flag(TIF_32BIT)) { - if (put_user(((u32)csp), - &(((struct reg_window32 __user *)rval)->ins[6]))) - rval = 0; - } else { - if (put_user(((u64)csp - STACK_BIAS), - &(((struct reg_window __user *)rval)->ins[6]))) - rval = 0; - else - rval = rval - STACK_BIAS; - } - - return rval; -} - -/* Standard stuff. */ -static inline void shift_window_buffer(int first_win, int last_win, - struct thread_info *t) -{ - int i; - - for (i = first_win; i < last_win; i++) { - t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1]; - memcpy(&t->reg_window[i], &t->reg_window[i+1], - sizeof(struct reg_window)); - } -} - -void synchronize_user_stack(void) -{ - struct thread_info *t = current_thread_info(); - unsigned long window; - - flush_user_windows(); - if ((window = get_thread_wsaved()) != 0) { - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; - - window -= 1; - do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); - struct reg_window *rwin = &t->reg_window[window]; - - if (!copy_to_user((char __user *)sp, rwin, winsize)) { - shift_window_buffer(window, get_thread_wsaved() - 1, t); - set_thread_wsaved(get_thread_wsaved() - 1); - } - } while (window--); - } -} - -void fault_in_user_windows(void) -{ - struct thread_info *t = current_thread_info(); - unsigned long window; - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; - - flush_user_windows(); - window = get_thread_wsaved(); - - if (window != 0) { - window -= 1; - do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); - struct reg_window *rwin = &t->reg_window[window]; - - if (copy_to_user((char __user *)sp, rwin, winsize)) - goto barf; - } while (window--); - } - set_thread_wsaved(0); - return; - -barf: - set_thread_wsaved(window + 1); - do_exit(SIGILL); -} - -asmlinkage long sparc_do_fork(unsigned long clone_flags, - unsigned long stack_start, - struct pt_regs *regs, - unsigned long stack_size) -{ - int __user *parent_tid_ptr, *child_tid_ptr; - -#ifdef CONFIG_COMPAT - if (test_thread_flag(TIF_32BIT)) { - parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]); - child_tid_ptr = compat_ptr(regs->u_regs[UREG_I4]); - } else -#endif - { - parent_tid_ptr = (int __user *) regs->u_regs[UREG_I2]; - child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; - } - - return do_fork(clone_flags, stack_start, - regs, stack_size, - parent_tid_ptr, child_tid_ptr); -} - -/* Copy a Sparc thread. The fork() return value conventions - * under SunOS are nothing short of bletcherous: - * Parent --> %o0 == childs pid, %o1 == 0 - * Child --> %o0 == parents pid, %o1 == 1 - */ -int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) -{ - struct thread_info *t = task_thread_info(p); - char *child_trap_frame; - - /* Calculate offset to stack_frame & pt_regs */ - child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); - memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ)); - - t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | - (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT); - t->new_child = 1; - t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; - t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct sparc_stackf)); - t->fpsaved[0] = 0; - - if (regs->tstate & TSTATE_PRIV) { - /* Special case, if we are spawning a kernel thread from - * a userspace task (via KMOD, NFS, or similar) we must - * disable performance counters in the child because the - * address space and protection realm are changing. - */ - if (t->flags & _TIF_PERFCTR) { - t->user_cntd0 = t->user_cntd1 = NULL; - t->pcr_reg = 0; - t->flags &= ~_TIF_PERFCTR; - } - t->kregs->u_regs[UREG_FP] = t->ksp; - t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); - flush_register_windows(); - memcpy((void *)(t->ksp + STACK_BIAS), - (void *)(regs->u_regs[UREG_FP] + STACK_BIAS), - sizeof(struct sparc_stackf)); - t->kregs->u_regs[UREG_G6] = (unsigned long) t; - t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; - } else { - if (t->flags & _TIF_32BIT) { - sp &= 0x00000000ffffffffUL; - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - } - t->kregs->u_regs[UREG_FP] = sp; - t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT); - if (sp != regs->u_regs[UREG_FP]) { - unsigned long csp; - - csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); - if (!csp) - return -EFAULT; - t->kregs->u_regs[UREG_FP] = csp; - } - if (t->utraps) - t->utraps[0]++; - } - - /* Set the return value for the child. */ - t->kregs->u_regs[UREG_I0] = current->pid; - t->kregs->u_regs[UREG_I1] = 1; - - /* Set the second return value for the parent. */ - regs->u_regs[UREG_I1] = 0; - - if (clone_flags & CLONE_SETTLS) - t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3]; - - return 0; -} - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. - */ -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - long retval; - - /* If the parent runs before fn(arg) is called by the child, - * the input registers of this function can be clobbered. - * So we stash 'fn' and 'arg' into global registers which - * will not be modified by the parent. - */ - __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */ - "mov %5, %%g3\n\t" /* Save ARG into global */ - "mov %1, %%g1\n\t" /* Clone syscall nr. */ - "mov %2, %%o0\n\t" /* Clone flags. */ - "mov 0, %%o1\n\t" /* usp arg == 0 */ - "t 0x6d\n\t" /* Linux/Sparc clone(). */ - "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */ - " mov %%o0, %0\n\t" - "jmpl %%g2, %%o7\n\t" /* Call the function. */ - " mov %%g3, %%o0\n\t" /* Set arg in delay. */ - "mov %3, %%g1\n\t" - "t 0x6d\n\t" /* Linux/Sparc exit(). */ - /* Notreached by child. */ - "1:" : - "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), - "i" (__NR_exit), "r" (fn), "r" (arg) : - "g1", "g2", "g3", "o0", "o1", "memory", "cc"); - return retval; -} - -/* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ - /* Only should be used for SunOS and ancient a.out - * SparcLinux binaries... Not worth implementing. - */ - memset(dump, 0, sizeof(struct user)); -} - -typedef struct { - union { - unsigned int pr_regs[32]; - unsigned long pr_dregs[16]; - } pr_fr; - unsigned int __unused; - unsigned int pr_fsr; - unsigned char pr_qcnt; - unsigned char pr_q_entrysize; - unsigned char pr_en; - unsigned int pr_q[64]; -} elf_fpregset_t32; - -/* - * fill in the fpu structure for a core dump. - */ -int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) -{ - unsigned long *kfpregs = current_thread_info()->fpregs; - unsigned long fprs = current_thread_info()->fpsaved[0]; - - if (test_thread_flag(TIF_32BIT)) { - elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs; - - if (fprs & FPRS_DL) - memcpy(&fpregs32->pr_fr.pr_regs[0], kfpregs, - sizeof(unsigned int) * 32); - else - memset(&fpregs32->pr_fr.pr_regs[0], 0, - sizeof(unsigned int) * 32); - fpregs32->pr_qcnt = 0; - fpregs32->pr_q_entrysize = 8; - memset(&fpregs32->pr_q[0], 0, - (sizeof(unsigned int) * 64)); - if (fprs & FPRS_FEF) { - fpregs32->pr_fsr = (unsigned int) current_thread_info()->xfsr[0]; - fpregs32->pr_en = 1; - } else { - fpregs32->pr_fsr = 0; - fpregs32->pr_en = 0; - } - } else { - if(fprs & FPRS_DL) - memcpy(&fpregs->pr_regs[0], kfpregs, - sizeof(unsigned int) * 32); - else - memset(&fpregs->pr_regs[0], 0, - sizeof(unsigned int) * 32); - if(fprs & FPRS_DU) - memcpy(&fpregs->pr_regs[16], kfpregs+16, - sizeof(unsigned int) * 32); - else - memset(&fpregs->pr_regs[16], 0, - sizeof(unsigned int) * 32); - if(fprs & FPRS_FEF) { - fpregs->pr_fsr = current_thread_info()->xfsr[0]; - fpregs->pr_gsr = current_thread_info()->gsr[0]; - } else { - fpregs->pr_fsr = fpregs->pr_gsr = 0; - } - fpregs->pr_fprs = fprs; - } - return 1; -} - -/* - * sparc_execve() executes a new program after the asm stub has set - * things up for us. This should basically do what I want it to. - */ -asmlinkage int sparc_execve(struct pt_regs *regs) -{ - int error, base = 0; - char *filename; - - /* User register window flush is done by entry.S */ - - /* Check for indirect call. */ - if (regs->u_regs[UREG_G1] == 0) - base = 1; - - filename = getname((char __user *)regs->u_regs[base + UREG_I0]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, - (char __user * __user *) - regs->u_regs[base + UREG_I1], - (char __user * __user *) - regs->u_regs[base + UREG_I2], regs); - putname(filename); - if (!error) { - fprs_write(0); - current_thread_info()->xfsr[0] = 0; - current_thread_info()->fpsaved[0] = 0; - regs->tstate &= ~TSTATE_PEF; - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } -out: - return error; -} - -unsigned long get_wchan(struct task_struct *task) -{ - unsigned long pc, fp, bias = 0; - unsigned long thread_info_base; - struct reg_window *rw; - unsigned long ret = 0; - int count = 0; - - if (!task || task == current || - task->state == TASK_RUNNING) - goto out; - - thread_info_base = (unsigned long) task_stack_page(task); - bias = STACK_BIAS; - fp = task_thread_info(task)->ksp + bias; - - do { - /* Bogus frame pointer? */ - if (fp < (thread_info_base + sizeof(struct thread_info)) || - fp >= (thread_info_base + THREAD_SIZE)) - break; - rw = (struct reg_window *) fp; - pc = rw->ins[7]; - if (!in_sched_functions(pc)) { - ret = pc; - goto out; - } - fp = rw->ins[6] + bias; - } while (++count < 16); - -out: - return ret; -} diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c deleted file mode 100644 index 3f9746f856d..00000000000 --- a/arch/sparc64/kernel/ptrace.c +++ /dev/null @@ -1,663 +0,0 @@ -/* ptrace.c: Sparc process tracing support. - * - * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson, - * and David Mosberger. - * - * Added Linux support -miguel (weird, eh?, the original code was meant - * to emulate SunOS). - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/security.h> -#include <linux/seccomp.h> -#include <linux/audit.h> -#include <linux/signal.h> - -#include <asm/asi.h> -#include <asm/pgtable.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/psrcompat.h> -#include <asm/visasm.h> -#include <asm/spitfire.h> -#include <asm/page.h> -#include <asm/cpudata.h> - -/* Returning from ptrace is a bit tricky because the syscall return - * low level code assumes any value returned which is negative and - * is a valid errno will mean setting the condition codes to indicate - * an error return. This doesn't work, so we have this hook. - */ -static inline void pt_error_return(struct pt_regs *regs, unsigned long error) -{ - regs->u_regs[UREG_I0] = error; - regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY); - regs->tpc = regs->tnpc; - regs->tnpc += 4; -} - -static inline void pt_succ_return(struct pt_regs *regs, unsigned long value) -{ - regs->u_regs[UREG_I0] = value; - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY); - regs->tpc = regs->tnpc; - regs->tnpc += 4; -} - -static inline void -pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr) -{ - if (test_thread_flag(TIF_32BIT)) { - if (put_user(value, (unsigned int __user *) addr)) { - pt_error_return(regs, EFAULT); - return; - } - } else { - if (put_user(value, (long __user *) addr)) { - pt_error_return(regs, EFAULT); - return; - } - } - regs->u_regs[UREG_I0] = 0; - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY); - regs->tpc = regs->tnpc; - regs->tnpc += 4; -} - -static void -pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr) -{ - if (current->personality == PER_SUNOS) - pt_succ_return (regs, val); - else - pt_succ_return_linux (regs, val, addr); -} - -/* #define ALLOW_INIT_TRACING */ -/* #define DEBUG_PTRACE */ - -#ifdef DEBUG_PTRACE -char *pt_rq [] = { - /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR", - /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT", - /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH", - /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS", - /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT", - /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown", - /* 24 */ "SYSCALL", "" -}; -#endif - -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do */ -} - -/* To get the necessary page struct, access_process_vm() first calls - * get_user_pages(). This has done a flush_dcache_page() on the - * accessed page. Then our caller (copy_{to,from}_user_page()) did - * to memcpy to read/write the data from that page. - * - * Now, the only thing we have to do is: - * 1) flush the D-cache if it's possible than an illegal alias - * has been created - * 2) flush the I-cache if this is pre-cheetah and we did a write - */ -void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, - unsigned long uaddr, void *kaddr, - unsigned long len, int write) -{ - BUG_ON(len > PAGE_SIZE); - -#ifdef DCACHE_ALIASING_POSSIBLE - /* If bit 13 of the kernel address we used to access the - * user page is the same as the virtual address that page - * is mapped to in the user's address space, we can skip the - * D-cache flush. - */ - if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { - unsigned long start = __pa(kaddr); - unsigned long end = start + len; - unsigned long dcache_line_size; - - dcache_line_size = local_cpu_data().dcache_line_size; - - if (tlb_type == spitfire) { - for (; start < end; start += dcache_line_size) - spitfire_put_dcache_tag(start & 0x3fe0, 0x0); - } else { - start &= ~(dcache_line_size - 1); - for (; start < end; start += dcache_line_size) - __asm__ __volatile__( - "stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (start), - "i" (ASI_DCACHE_INVALIDATE)); - } - } -#endif - if (write && tlb_type == spitfire) { - unsigned long start = (unsigned long) kaddr; - unsigned long end = start + len; - unsigned long icache_line_size; - - icache_line_size = local_cpu_data().icache_line_size; - - for (; start < end; start += icache_line_size) - flushi(start); - } -} - -asmlinkage void do_ptrace(struct pt_regs *regs) -{ - int request = regs->u_regs[UREG_I0]; - pid_t pid = regs->u_regs[UREG_I1]; - unsigned long addr = regs->u_regs[UREG_I2]; - unsigned long data = regs->u_regs[UREG_I3]; - unsigned long addr2 = regs->u_regs[UREG_I4]; - struct task_struct *child; - int ret; - - if (test_thread_flag(TIF_32BIT)) { - addr &= 0xffffffffUL; - data &= 0xffffffffUL; - addr2 &= 0xffffffffUL; - } - lock_kernel(); -#ifdef DEBUG_PTRACE - { - char *s; - - if ((request >= 0) && (request <= 24)) - s = pt_rq [request]; - else - s = "unknown"; - - if (request == PTRACE_POKEDATA && data == 0x91d02001){ - printk ("do_ptrace: breakpoint pid=%d, addr=%016lx addr2=%016lx\n", - pid, addr, addr2); - } else - printk("do_ptrace: rq=%s(%d) pid=%d addr=%016lx data=%016lx addr2=%016lx\n", - s, request, pid, addr, data, addr2); - } -#endif - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - pt_succ_return(regs, 0); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - pt_error_return(regs, -ret); - goto out; - } - - if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) - || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { - if (ptrace_attach(child)) { - pt_error_return(regs, EPERM); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) { - pt_error_return(regs, -ret); - goto out_tsk; - } - - if (!(test_thread_flag(TIF_32BIT)) && - ((request == PTRACE_READDATA64) || - (request == PTRACE_WRITEDATA64) || - (request == PTRACE_READTEXT64) || - (request == PTRACE_WRITETEXT64) || - (request == PTRACE_PEEKTEXT64) || - (request == PTRACE_POKETEXT64) || - (request == PTRACE_PEEKDATA64) || - (request == PTRACE_POKEDATA64))) { - addr = regs->u_regs[UREG_G2]; - addr2 = regs->u_regs[UREG_G3]; - request -= 30; /* wheee... */ - } - - switch(request) { - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned long tmp64; - unsigned int tmp32; - int res, copied; - - res = -EIO; - if (test_thread_flag(TIF_32BIT)) { - copied = access_process_vm(child, addr, - &tmp32, sizeof(tmp32), 0); - tmp64 = (unsigned long) tmp32; - if (copied == sizeof(tmp32)) - res = 0; - } else { - copied = access_process_vm(child, addr, - &tmp64, sizeof(tmp64), 0); - if (copied == sizeof(tmp64)) - res = 0; - } - if (res < 0) - pt_error_return(regs, -res); - else - pt_os_succ_return(regs, tmp64, (void __user *) data); - goto out_tsk; - } - - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: { - unsigned long tmp64; - unsigned int tmp32; - int copied, res = -EIO; - - if (test_thread_flag(TIF_32BIT)) { - tmp32 = data; - copied = access_process_vm(child, addr, - &tmp32, sizeof(tmp32), 1); - if (copied == sizeof(tmp32)) - res = 0; - } else { - tmp64 = data; - copied = access_process_vm(child, addr, - &tmp64, sizeof(tmp64), 1); - if (copied == sizeof(tmp64)) - res = 0; - } - if (res < 0) - pt_error_return(regs, -res); - else - pt_succ_return(regs, res); - goto out_tsk; - } - - case PTRACE_GETREGS: { - struct pt_regs32 __user *pregs = - (struct pt_regs32 __user *) addr; - struct pt_regs *cregs = task_pt_regs(child); - int rval; - - if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || - __put_user(cregs->tpc, (&pregs->pc)) || - __put_user(cregs->tnpc, (&pregs->npc)) || - __put_user(cregs->y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - for (rval = 1; rval < 16; rval++) - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); -#ifdef DEBUG_PTRACE - printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]); -#endif - goto out_tsk; - } - - case PTRACE_GETREGS64: { - struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = task_pt_regs(child); - unsigned long tpc = cregs->tpc; - int rval; - - if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) - tpc &= 0xffffffff; - if (__put_user(cregs->tstate, (&pregs->tstate)) || - __put_user(tpc, (&pregs->tpc)) || - __put_user(cregs->tnpc, (&pregs->tnpc)) || - __put_user(cregs->y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - for (rval = 1; rval < 16; rval++) - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); -#ifdef DEBUG_PTRACE - printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]); -#endif - goto out_tsk; - } - - case PTRACE_SETREGS: { - struct pt_regs32 __user *pregs = - (struct pt_regs32 __user *) addr; - struct pt_regs *cregs = task_pt_regs(child); - unsigned int psr, pc, npc, y; - int i; - - /* Must be careful, tracing process can only set certain - * bits in the psr. - */ - if (__get_user(psr, (&pregs->psr)) || - __get_user(pc, (&pregs->pc)) || - __get_user(npc, (&pregs->npc)) || - __get_user(y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - cregs->tstate &= ~(TSTATE_ICC); - cregs->tstate |= psr_to_tstate_icc(psr); - if (!((pc | npc) & 3)) { - cregs->tpc = pc; - cregs->tnpc = npc; - } - cregs->y = y; - for (i = 1; i < 16; i++) { - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - case PTRACE_SETREGS64: { - struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = task_pt_regs(child); - unsigned long tstate, tpc, tnpc, y; - int i; - - /* Must be careful, tracing process can only set certain - * bits in the psr. - */ - if (__get_user(tstate, (&pregs->tstate)) || - __get_user(tpc, (&pregs->tpc)) || - __get_user(tnpc, (&pregs->tnpc)) || - __get_user(y, (&pregs->y))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) { - tpc &= 0xffffffff; - tnpc &= 0xffffffff; - } - tstate &= (TSTATE_ICC | TSTATE_XCC); - cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); - cregs->tstate |= tstate; - if (!((tpc | tnpc) & 3)) { - cregs->tpc = tpc; - cregs->tnpc = tnpc; - } - cregs->y = y; - for (i = 1; i < 16; i++) { - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - case PTRACE_GETFPREGS: { - struct fps { - unsigned int regs[32]; - unsigned int fsr; - unsigned int flags; - unsigned int extra; - unsigned int fpqd; - struct fq { - unsigned int insnaddr; - unsigned int insn; - } fpq[16]; - }; - struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = task_thread_info(child)->fpregs; - - if (copy_to_user(&fps->regs[0], fpregs, - (32 * sizeof(unsigned int))) || - __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) || - __put_user(0, (&fps->fpqd)) || - __put_user(0, (&fps->flags)) || - __put_user(0, (&fps->extra)) || - clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - case PTRACE_GETFPREGS64: { - struct fps { - unsigned int regs[64]; - unsigned long fsr; - }; - struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = task_thread_info(child)->fpregs; - - if (copy_to_user(&fps->regs[0], fpregs, - (64 * sizeof(unsigned int))) || - __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - case PTRACE_SETFPREGS: { - struct fps { - unsigned int regs[32]; - unsigned int fsr; - unsigned int flags; - unsigned int extra; - unsigned int fpqd; - struct fq { - unsigned int insnaddr; - unsigned int insn; - } fpq[16]; - }; - struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = task_thread_info(child)->fpregs; - unsigned fsr; - - if (copy_from_user(fpregs, &fps->regs[0], - (32 * sizeof(unsigned int))) || - __get_user(fsr, (&fps->fsr))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; - task_thread_info(child)->xfsr[0] |= fsr; - if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) - task_thread_info(child)->gsr[0] = 0; - task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); - pt_succ_return(regs, 0); - goto out_tsk; - } - - case PTRACE_SETFPREGS64: { - struct fps { - unsigned int regs[64]; - unsigned long fsr; - }; - struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = task_thread_info(child)->fpregs; - - if (copy_from_user(fpregs, &fps->regs[0], - (64 * sizeof(unsigned int))) || - __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { - pt_error_return(regs, EFAULT); - goto out_tsk; - } - if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) - task_thread_info(child)->gsr[0] = 0; - task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); - pt_succ_return(regs, 0); - goto out_tsk; - } - - case PTRACE_READTEXT: - case PTRACE_READDATA: { - int res = ptrace_readdata(child, addr, - (char __user *)addr2, data); - if (res == data) { - pt_succ_return(regs, 0); - goto out_tsk; - } - if (res >= 0) - res = -EIO; - pt_error_return(regs, -res); - goto out_tsk; - } - - case PTRACE_WRITETEXT: - case PTRACE_WRITEDATA: { - int res = ptrace_writedata(child, (char __user *) addr2, - addr, data); - if (res == data) { - pt_succ_return(regs, 0); - goto out_tsk; - } - if (res >= 0) - res = -EIO; - pt_error_return(regs, -res); - goto out_tsk; - } - case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ - addr = 1; - - case PTRACE_CONT: { /* restart after signal. */ - if (!valid_signal(data)) { - pt_error_return(regs, EIO); - goto out_tsk; - } - - if (request == PTRACE_SYSCALL) { - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } else { - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } - - child->exit_code = data; -#ifdef DEBUG_PTRACE - printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm, - child->pid, child->exit_code, - task_pt_regs(child)->tpc, - task_pt_regs(child)->tnpc); - -#endif - wake_up_process(child); - pt_succ_return(regs, 0); - goto out_tsk; - } - -/* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - case PTRACE_KILL: { - if (child->exit_state == EXIT_ZOMBIE) { /* already dead */ - pt_succ_return(regs, 0); - goto out_tsk; - } - child->exit_code = SIGKILL; - wake_up_process(child); - pt_succ_return(regs, 0); - goto out_tsk; - } - - case PTRACE_SUNDETACH: { /* detach a process that was attached. */ - int error = ptrace_detach(child, data); - if (error) { - pt_error_return(regs, EIO); - goto out_tsk; - } - pt_succ_return(regs, 0); - goto out_tsk; - } - - /* PTRACE_DUMPCORE unsupported... */ - - default: { - int err = ptrace_request(child, request, addr, data); - if (err) - pt_error_return(regs, -err); - else - pt_succ_return(regs, 0); - goto out_tsk; - } - } -out_tsk: - if (child) - put_task_struct(child); -out: - unlock_kernel(); -} - -asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p) -{ - /* do the secure computing check first */ - secure_computing(regs->u_regs[UREG_G1]); - - if (unlikely(current->audit_context) && syscall_exit_p) { - unsigned long tstate = regs->tstate; - int result = AUDITSC_SUCCESS; - - if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) - result = AUDITSC_FAILURE; - - audit_syscall_exit(current, result, regs->u_regs[UREG_I0]); - } - - if (!(current->ptrace & PT_PTRACED)) - goto out; - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - goto out; - - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - - /* - * 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; - } - -out: - if (unlikely(current->audit_context) && !syscall_exit_p) - audit_syscall_entry(current, - (test_thread_flag(TIF_32BIT) ? - AUDIT_ARCH_SPARC : - AUDIT_ARCH_SPARC64), - regs->u_regs[UREG_G1], - regs->u_regs[UREG_I0], - regs->u_regs[UREG_I1], - regs->u_regs[UREG_I2], - regs->u_regs[UREG_I3]); -} diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S deleted file mode 100644 index b80eba0081c..00000000000 --- a/arch/sparc64/kernel/rtrap.S +++ /dev/null @@ -1,344 +0,0 @@ -/* $Id: rtrap.S,v 1.61 2002/02/09 19:49:31 davem Exp $ - * rtrap.S: Preparing for return from trap on Sparc V9. - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/config.h> - -#include <asm/asi.h> -#include <asm/pstate.h> -#include <asm/ptrace.h> -#include <asm/spitfire.h> -#include <asm/head.h> -#include <asm/visasm.h> -#include <asm/processor.h> - -#define RTRAP_PSTATE (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) -#define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV) -#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) - - /* Register %l6 keeps track of whether we are returning - * from a system call or not. It is cleared if we call - * do_notify_resume, and it must not be otherwise modified - * until we fully commit to returning to userspace. - */ - - .text - .align 32 -__handle_softirq: - call do_softirq - nop - ba,a,pt %xcc, __handle_softirq_continue - nop -__handle_preemption: - call schedule - wrpr %g0, RTRAP_PSTATE, %pstate - ba,pt %xcc, __handle_preemption_continue - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - -__handle_user_windows: - call fault_in_user_windows - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - /* Redo sched+sig checks */ - ldx [%g6 + TI_FLAGS], %l0 - andcc %l0, _TIF_NEED_RESCHED, %g0 - - be,pt %xcc, 1f - nop - call schedule - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - ldx [%g6 + TI_FLAGS], %l0 - -1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 - be,pt %xcc, __handle_user_windows_continue - nop - mov %l5, %o1 - mov %l6, %o2 - add %sp, PTREGS_OFF, %o0 - mov %l0, %o3 - - call do_notify_resume - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - clr %l6 - /* Signal delivery can modify pt_regs tstate, so we must - * reload it. - */ - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 - sethi %hi(0xf << 20), %l4 - and %l1, %l4, %l4 - ba,pt %xcc, __handle_user_windows_continue - - andn %l1, %l4, %l1 -__handle_perfctrs: - call update_perfctrs - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - ldub [%g6 + TI_WSAVED], %o2 - brz,pt %o2, 1f - nop - /* Redo userwin+sched+sig checks */ - call fault_in_user_windows - - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - ldx [%g6 + TI_FLAGS], %l0 - andcc %l0, _TIF_NEED_RESCHED, %g0 - be,pt %xcc, 1f - - nop - call schedule - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - ldx [%g6 + TI_FLAGS], %l0 -1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 - - be,pt %xcc, __handle_perfctrs_continue - sethi %hi(TSTATE_PEF), %o0 - mov %l5, %o1 - mov %l6, %o2 - add %sp, PTREGS_OFF, %o0 - mov %l0, %o3 - call do_notify_resume - - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - clr %l6 - /* Signal delivery can modify pt_regs tstate, so we must - * reload it. - */ - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 - sethi %hi(0xf << 20), %l4 - and %l1, %l4, %l4 - andn %l1, %l4, %l1 - ba,pt %xcc, __handle_perfctrs_continue - - sethi %hi(TSTATE_PEF), %o0 -__handle_userfpu: - rd %fprs, %l5 - andcc %l5, FPRS_FEF, %g0 - sethi %hi(TSTATE_PEF), %o0 - be,a,pn %icc, __handle_userfpu_continue - andn %l1, %o0, %l1 - ba,a,pt %xcc, __handle_userfpu_continue - -__handle_signal: - mov %l5, %o1 - mov %l6, %o2 - add %sp, PTREGS_OFF, %o0 - mov %l0, %o3 - call do_notify_resume - wrpr %g0, RTRAP_PSTATE, %pstate - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - clr %l6 - - /* Signal delivery can modify pt_regs tstate, so we must - * reload it. - */ - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 - sethi %hi(0xf << 20), %l4 - and %l1, %l4, %l4 - ba,pt %xcc, __handle_signal_continue - andn %l1, %l4, %l1 - - .align 64 - .globl rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme, rtrap_xcall -rtrap_irq: -rtrap_clr_l6: clr %l6 -rtrap: -#ifndef CONFIG_SMP - sethi %hi(per_cpu____cpu_data), %l0 - lduw [%l0 + %lo(per_cpu____cpu_data)], %l1 -#else - sethi %hi(per_cpu____cpu_data), %l0 - or %l0, %lo(per_cpu____cpu_data), %l0 - lduw [%l0 + %g5], %l1 -#endif - cmp %l1, 0 - - /* mm/ultra.S:xcall_report_regs KNOWS about this load. */ - bne,pn %icc, __handle_softirq - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 -__handle_softirq_continue: -rtrap_xcall: - sethi %hi(0xf << 20), %l4 - andcc %l1, TSTATE_PRIV, %l3 - and %l1, %l4, %l4 - bne,pn %icc, to_kernel - andn %l1, %l4, %l1 - - /* We must hold IRQs off and atomically test schedule+signal - * state, then hold them off all the way back to userspace. - * If we are returning to kernel, none of this matters. - * - * If we do not do this, there is a window where we would do - * the tests, later the signal/resched event arrives but we do - * not process it since we are still in kernel mode. It would - * take until the next local IRQ before the signal/resched - * event would be handled. - * - * This also means that if we have to deal with performance - * counters or user windows, we have to redo all of these - * sched+signal checks with IRQs disabled. - */ -to_user: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - wrpr 0, %pil -__handle_preemption_continue: - ldx [%g6 + TI_FLAGS], %l0 - sethi %hi(_TIF_USER_WORK_MASK), %o0 - or %o0, %lo(_TIF_USER_WORK_MASK), %o0 - andcc %l0, %o0, %g0 - sethi %hi(TSTATE_PEF), %o0 - be,pt %xcc, user_nowork - andcc %l1, %o0, %g0 - andcc %l0, _TIF_NEED_RESCHED, %g0 - bne,pn %xcc, __handle_preemption - andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 - bne,pn %xcc, __handle_signal -__handle_signal_continue: - ldub [%g6 + TI_WSAVED], %o2 - brnz,pn %o2, __handle_user_windows - nop -__handle_user_windows_continue: - ldx [%g6 + TI_FLAGS], %l5 - andcc %l5, _TIF_PERFCTR, %g0 - sethi %hi(TSTATE_PEF), %o0 - bne,pn %xcc, __handle_perfctrs -__handle_perfctrs_continue: - andcc %l1, %o0, %g0 - - /* This fpdepth clear is necessary for non-syscall rtraps only */ -user_nowork: - bne,pn %xcc, __handle_userfpu - stb %g0, [%g6 + TI_FPDEPTH] -__handle_userfpu_continue: - -rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 - ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2 - - ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 - ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4 - ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5 - mov TSB_REG, %g6 - brnz,a,pn %l3, 1f - ldxa [%g6] ASI_IMMU, %g5 -1: ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6 - ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7 - wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate - ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 - ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 - - ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 - ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 - ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 - ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 - ldx [%sp + PTREGS_OFF + PT_V9_I6], %i6 - ldx [%sp + PTREGS_OFF + PT_V9_I7], %i7 - ldx [%sp + PTREGS_OFF + PT_V9_TPC], %l2 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %o2 - - ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 - wr %o3, %g0, %y - srl %l4, 20, %l4 - wrpr %l4, 0x0, %pil - wrpr %g0, 0x1, %tl - wrpr %l1, %g0, %tstate - wrpr %l2, %g0, %tpc - wrpr %o2, %g0, %tnpc - - brnz,pn %l3, kern_rtt - mov PRIMARY_CONTEXT, %l7 - ldxa [%l7 + %l7] ASI_DMMU, %l0 - sethi %hi(sparc64_kern_pri_nuc_bits), %l1 - ldx [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1 - or %l0, %l1, %l0 - stxa %l0, [%l7] ASI_DMMU - flush %g6 - rdpr %wstate, %l1 - rdpr %otherwin, %l2 - srl %l1, 3, %l1 - - wrpr %l2, %g0, %canrestore - wrpr %l1, %g0, %wstate - wrpr %g0, %g0, %otherwin - restore - rdpr %canrestore, %g1 - wrpr %g1, 0x0, %cleanwin - retry - nop - -kern_rtt: restore - retry -to_kernel: -#ifdef CONFIG_PREEMPT - ldsw [%g6 + TI_PRE_COUNT], %l5 - brnz %l5, kern_fpucheck - ldx [%g6 + TI_FLAGS], %l5 - andcc %l5, _TIF_NEED_RESCHED, %g0 - be,pt %xcc, kern_fpucheck - srl %l4, 20, %l5 - cmp %l5, 0 - bne,pn %xcc, kern_fpucheck - sethi %hi(PREEMPT_ACTIVE), %l6 - stw %l6, [%g6 + TI_PRE_COUNT] - call schedule - nop - ba,pt %xcc, rtrap - stw %g0, [%g6 + TI_PRE_COUNT] -#endif -kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5 - brz,pt %l5, rt_continue - srl %l5, 1, %o0 - add %g6, TI_FPSAVED, %l6 - ldub [%l6 + %o0], %l2 - sub %l5, 2, %l5 - - add %g6, TI_GSR, %o1 - andcc %l2, (FPRS_FEF|FPRS_DU), %g0 - be,pt %icc, 2f - and %l2, FPRS_DL, %l6 - andcc %l2, FPRS_FEF, %g0 - be,pn %icc, 5f - sll %o0, 3, %o5 - rd %fprs, %g1 - - wr %g1, FPRS_FEF, %fprs - ldx [%o1 + %o5], %g1 - add %g6, TI_XFSR, %o1 - sll %o0, 8, %o2 - add %g6, TI_FPREGS, %o3 - brz,pn %l6, 1f - add %g6, TI_FPREGS+0x40, %o4 - - membar #Sync - ldda [%o3 + %o2] ASI_BLK_P, %f0 - ldda [%o4 + %o2] ASI_BLK_P, %f16 - membar #Sync -1: andcc %l2, FPRS_DU, %g0 - be,pn %icc, 1f - wr %g1, 0, %gsr - add %o2, 0x80, %o2 - membar #Sync - ldda [%o3 + %o2] ASI_BLK_P, %f32 - ldda [%o4 + %o2] ASI_BLK_P, %f48 -1: membar #Sync - ldx [%o1 + %o5], %fsr -2: stb %l5, [%g6 + TI_FPDEPTH] - ba,pt %xcc, rt_continue - nop -5: wr %g0, FPRS_FEF, %fprs - sll %o0, 8, %o2 - - add %g6, TI_FPREGS+0x80, %o3 - add %g6, TI_FPREGS+0xc0, %o4 - membar #Sync - ldda [%o3 + %o2] ASI_BLK_P, %f32 - ldda [%o4 + %o2] ASI_BLK_P, %f48 - membar #Sync - wr %g0, FPRS_DU, %fprs - ba,pt %xcc, rt_continue - stb %l5, [%g6 + TI_FPDEPTH] diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c deleted file mode 100644 index d95a1bcf163..00000000000 --- a/arch/sparc64/kernel/sbus.c +++ /dev/null @@ -1,1266 +0,0 @@ -/* $Id: sbus.c,v 1.19 2002/01/23 11:27:32 davem Exp $ - * sbus.c: UltraSparc SBUS controller support. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/interrupt.h> - -#include <asm/page.h> -#include <asm/sbus.h> -#include <asm/io.h> -#include <asm/upa.h> -#include <asm/cache.h> -#include <asm/dma.h> -#include <asm/irq.h> -#include <asm/starfire.h> - -#include "iommu_common.h" - -/* These should be allocated on an SMP_CACHE_BYTES - * aligned boundary for optimal performance. - * - * On SYSIO, using an 8K page size we have 1GB of SBUS - * DMA space mapped. We divide this space into equally - * sized clusters. We allocate a DMA mapping from the - * cluster that matches the order of the allocation, or - * if the order is greater than the number of clusters, - * we try to allocate from the last cluster. - */ - -#define NCLUSTERS 8UL -#define ONE_GIG (1UL * 1024UL * 1024UL * 1024UL) -#define CLUSTER_SIZE (ONE_GIG / NCLUSTERS) -#define CLUSTER_MASK (CLUSTER_SIZE - 1) -#define CLUSTER_NPAGES (CLUSTER_SIZE >> IO_PAGE_SHIFT) -#define MAP_BASE ((u32)0xc0000000) - -struct sbus_iommu { -/*0x00*/spinlock_t lock; - -/*0x08*/iopte_t *page_table; -/*0x10*/unsigned long strbuf_regs; -/*0x18*/unsigned long iommu_regs; -/*0x20*/unsigned long sbus_control_reg; - -/*0x28*/volatile unsigned long strbuf_flushflag; - - /* If NCLUSTERS is ever decresed to 4 or lower, - * you must increase the size of the type of - * these counters. You have been duly warned. -DaveM - */ -/*0x30*/struct { - u16 next; - u16 flush; - } alloc_info[NCLUSTERS]; - - /* The lowest used consistent mapping entry. Since - * we allocate consistent maps out of cluster 0 this - * is relative to the beginning of closter 0. - */ -/*0x50*/u32 lowest_consistent_map; -}; - -/* Offsets from iommu_regs */ -#define SYSIO_IOMMUREG_BASE 0x2400UL -#define IOMMU_CONTROL (0x2400UL - 0x2400UL) /* IOMMU control register */ -#define IOMMU_TSBBASE (0x2408UL - 0x2400UL) /* TSB base address register */ -#define IOMMU_FLUSH (0x2410UL - 0x2400UL) /* IOMMU flush register */ -#define IOMMU_VADIAG (0x4400UL - 0x2400UL) /* SBUS virtual address diagnostic */ -#define IOMMU_TAGCMP (0x4408UL - 0x2400UL) /* TLB tag compare diagnostics */ -#define IOMMU_LRUDIAG (0x4500UL - 0x2400UL) /* IOMMU LRU queue diagnostics */ -#define IOMMU_TAGDIAG (0x4580UL - 0x2400UL) /* TLB tag diagnostics */ -#define IOMMU_DRAMDIAG (0x4600UL - 0x2400UL) /* TLB data RAM diagnostics */ - -#define IOMMU_DRAM_VALID (1UL << 30UL) - -static void __iommu_flushall(struct sbus_iommu *iommu) -{ - unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; - int entry; - - for (entry = 0; entry < 16; entry++) { - upa_writeq(0, tag); - tag += 8UL; - } - upa_readq(iommu->sbus_control_reg); - - for (entry = 0; entry < NCLUSTERS; entry++) { - iommu->alloc_info[entry].flush = - iommu->alloc_info[entry].next; - } -} - -static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) -{ - while (npages--) - upa_writeq(base + (npages << IO_PAGE_SHIFT), - iommu->iommu_regs + IOMMU_FLUSH); - upa_readq(iommu->sbus_control_reg); -} - -/* Offsets from strbuf_regs */ -#define SYSIO_STRBUFREG_BASE 0x2800UL -#define STRBUF_CONTROL (0x2800UL - 0x2800UL) /* Control */ -#define STRBUF_PFLUSH (0x2808UL - 0x2800UL) /* Page flush/invalidate */ -#define STRBUF_FSYNC (0x2810UL - 0x2800UL) /* Flush synchronization */ -#define STRBUF_DRAMDIAG (0x5000UL - 0x2800UL) /* data RAM diagnostic */ -#define STRBUF_ERRDIAG (0x5400UL - 0x2800UL) /* error status diagnostics */ -#define STRBUF_PTAGDIAG (0x5800UL - 0x2800UL) /* Page tag diagnostics */ -#define STRBUF_LTAGDIAG (0x5900UL - 0x2800UL) /* Line tag diagnostics */ - -#define STRBUF_TAG_VALID 0x02UL - -static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction) -{ - unsigned long n; - int limit; - - n = npages; - while (n--) - upa_writeq(base + (n << IO_PAGE_SHIFT), - iommu->strbuf_regs + STRBUF_PFLUSH); - - /* If the device could not have possibly put dirty data into - * the streaming cache, no flush-flag synchronization needs - * to be performed. - */ - if (direction == SBUS_DMA_TODEVICE) - return; - - iommu->strbuf_flushflag = 0UL; - - /* Whoopee cushion! */ - upa_writeq(__pa(&iommu->strbuf_flushflag), - iommu->strbuf_regs + STRBUF_FSYNC); - upa_readq(iommu->sbus_control_reg); - - limit = 100000; - while (iommu->strbuf_flushflag == 0UL) { - limit--; - if (!limit) - break; - udelay(1); - rmb(); - } - if (!limit) - printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout " - "vaddr[%08x] npages[%ld]\n", - base, npages); -} - -static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) -{ - iopte_t *iopte, *limit, *first, *cluster; - unsigned long cnum, ent, nent, flush_point, found; - - cnum = 0; - nent = 1; - while ((1UL << cnum) < npages) - cnum++; - if(cnum >= NCLUSTERS) { - nent = 1UL << (cnum - NCLUSTERS); - cnum = NCLUSTERS - 1; - } - iopte = iommu->page_table + (cnum * CLUSTER_NPAGES); - - if (cnum == 0) - limit = (iommu->page_table + - iommu->lowest_consistent_map); - else - limit = (iopte + CLUSTER_NPAGES); - - iopte += ((ent = iommu->alloc_info[cnum].next) << cnum); - flush_point = iommu->alloc_info[cnum].flush; - - first = iopte; - cluster = NULL; - found = 0; - for (;;) { - if (iopte_val(*iopte) == 0UL) { - found++; - if (!cluster) - cluster = iopte; - } else { - /* Used cluster in the way */ - cluster = NULL; - found = 0; - } - - if (found == nent) - break; - - iopte += (1 << cnum); - ent++; - if (iopte >= limit) { - iopte = (iommu->page_table + (cnum * CLUSTER_NPAGES)); - ent = 0; - - /* Multiple cluster allocations must not wrap */ - cluster = NULL; - found = 0; - } - if (ent == flush_point) - __iommu_flushall(iommu); - if (iopte == first) - goto bad; - } - - /* ent/iopte points to the last cluster entry we're going to use, - * so save our place for the next allocation. - */ - if ((iopte + (1 << cnum)) >= limit) - ent = 0; - else - ent = ent + 1; - iommu->alloc_info[cnum].next = ent; - if (ent == flush_point) - __iommu_flushall(iommu); - - /* I've got your streaming cluster right here buddy boy... */ - return cluster; - -bad: - printk(KERN_EMERG "sbus: alloc_streaming_cluster of npages(%ld) failed!\n", - npages); - return NULL; -} - -static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) -{ - unsigned long cnum, ent, nent; - iopte_t *iopte; - - cnum = 0; - nent = 1; - while ((1UL << cnum) < npages) - cnum++; - if(cnum >= NCLUSTERS) { - nent = 1UL << (cnum - NCLUSTERS); - cnum = NCLUSTERS - 1; - } - ent = (base & CLUSTER_MASK) >> (IO_PAGE_SHIFT + cnum); - iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); - do { - iopte_val(*iopte) = 0UL; - iopte += 1 << cnum; - } while(--nent); - - /* If the global flush might not have caught this entry, - * adjust the flush point such that we will flush before - * ever trying to reuse it. - */ -#define between(X,Y,Z) (((Z) - (Y)) >= ((X) - (Y))) - if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush)) - iommu->alloc_info[cnum].flush = ent; -#undef between -} - -/* We allocate consistent mappings from the end of cluster zero. */ -static iopte_t *alloc_consistent_cluster(struct sbus_iommu *iommu, unsigned long npages) -{ - iopte_t *iopte; - - iopte = iommu->page_table + (1 * CLUSTER_NPAGES); - while (iopte > iommu->page_table) { - iopte--; - if (!(iopte_val(*iopte) & IOPTE_VALID)) { - unsigned long tmp = npages; - - while (--tmp) { - iopte--; - if (iopte_val(*iopte) & IOPTE_VALID) - break; - } - if (tmp == 0) { - u32 entry = (iopte - iommu->page_table); - - if (entry < iommu->lowest_consistent_map) - iommu->lowest_consistent_map = entry; - return iopte; - } - } - } - return NULL; -} - -static void free_consistent_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) -{ - iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); - - if ((iopte - iommu->page_table) == iommu->lowest_consistent_map) { - iopte_t *walk = iopte + npages; - iopte_t *limit; - - limit = iommu->page_table + CLUSTER_NPAGES; - while (walk < limit) { - if (iopte_val(*walk) != 0UL) - break; - walk++; - } - iommu->lowest_consistent_map = - (walk - iommu->page_table); - } - - while (npages--) - *iopte++ = __iopte(0UL); -} - -void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr) -{ - unsigned long order, first_page, flags; - struct sbus_iommu *iommu; - iopte_t *iopte; - void *ret; - int npages; - - if (size <= 0 || sdev == NULL || dvma_addr == NULL) - return NULL; - - size = IO_PAGE_ALIGN(size); - order = get_order(size); - if (order >= 10) - return NULL; - first_page = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); - if (first_page == 0UL) - return NULL; - memset((char *)first_page, 0, PAGE_SIZE << order); - - iommu = sdev->bus->iommu; - - spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT); - if (iopte == NULL) { - spin_unlock_irqrestore(&iommu->lock, flags); - free_pages(first_page, order); - return NULL; - } - - /* Ok, we're committed at this point. */ - *dvma_addr = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); - ret = (void *) first_page; - npages = size >> IO_PAGE_SHIFT; - while (npages--) { - *iopte++ = __iopte(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | - (__pa(first_page) & IOPTE_PAGE)); - first_page += IO_PAGE_SIZE; - } - iommu_flush(iommu, *dvma_addr, size >> IO_PAGE_SHIFT); - spin_unlock_irqrestore(&iommu->lock, flags); - - return ret; -} - -void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma) -{ - unsigned long order, npages; - struct sbus_iommu *iommu; - - if (size <= 0 || sdev == NULL || cpu == NULL) - return; - - npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - iommu = sdev->bus->iommu; - - spin_lock_irq(&iommu->lock); - free_consistent_cluster(iommu, dvma, npages); - iommu_flush(iommu, dvma, npages); - spin_unlock_irq(&iommu->lock); - - order = get_order(size); - if (order < 10) - free_pages((unsigned long)cpu, order); -} - -dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int dir) -{ - struct sbus_iommu *iommu = sdev->bus->iommu; - unsigned long npages, pbase, flags; - iopte_t *iopte; - u32 dma_base, offset; - unsigned long iopte_bits; - - if (dir == SBUS_DMA_NONE) - BUG(); - - pbase = (unsigned long) ptr; - offset = (u32) (pbase & ~IO_PAGE_MASK); - size = (IO_PAGE_ALIGN(pbase + size) - (pbase & IO_PAGE_MASK)); - pbase = (unsigned long) __pa(pbase & IO_PAGE_MASK); - - spin_lock_irqsave(&iommu->lock, flags); - npages = size >> IO_PAGE_SHIFT; - iopte = alloc_streaming_cluster(iommu, npages); - if (iopte == NULL) - goto bad; - dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); - npages = size >> IO_PAGE_SHIFT; - iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; - if (dir != SBUS_DMA_TODEVICE) - iopte_bits |= IOPTE_WRITE; - while (npages--) { - *iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE)); - pbase += IO_PAGE_SIZE; - } - npages = size >> IO_PAGE_SHIFT; - spin_unlock_irqrestore(&iommu->lock, flags); - - return (dma_base | offset); - -bad: - spin_unlock_irqrestore(&iommu->lock, flags); - BUG(); - return 0; -} - -void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction) -{ - struct sbus_iommu *iommu = sdev->bus->iommu; - u32 dma_base = dma_addr & IO_PAGE_MASK; - unsigned long flags; - - size = (IO_PAGE_ALIGN(dma_addr + size) - dma_base); - - spin_lock_irqsave(&iommu->lock, flags); - free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); - sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction); - spin_unlock_irqrestore(&iommu->lock, flags); -} - -#define SG_ENT_PHYS_ADDRESS(SG) \ - (__pa(page_address((SG)->page)) + (SG)->offset) - -static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, int nelems, unsigned long iopte_bits) -{ - struct scatterlist *dma_sg = sg; - struct scatterlist *sg_end = sg + nelems; - int i; - - for (i = 0; i < nused; i++) { - unsigned long pteval = ~0UL; - u32 dma_npages; - - dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) + - dma_sg->dma_length + - ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; - do { - unsigned long offset; - signed int len; - - /* If we are here, we know we have at least one - * more page to map. So walk forward until we - * hit a page crossing, and begin creating new - * mappings from that spot. - */ - for (;;) { - unsigned long tmp; - - tmp = (unsigned long) SG_ENT_PHYS_ADDRESS(sg); - len = sg->length; - if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { - pteval = tmp & IO_PAGE_MASK; - offset = tmp & (IO_PAGE_SIZE - 1UL); - break; - } - if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { - pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; - offset = 0UL; - len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); - break; - } - sg++; - } - - pteval = ((pteval & IOPTE_PAGE) | iopte_bits); - while (len > 0) { - *iopte++ = __iopte(pteval); - pteval += IO_PAGE_SIZE; - len -= (IO_PAGE_SIZE - offset); - offset = 0; - dma_npages--; - } - - pteval = (pteval & IOPTE_PAGE) + len; - sg++; - - /* Skip over any tail mappings we've fully mapped, - * adjusting pteval along the way. Stop when we - * detect a page crossing event. - */ - while (sg < sg_end && - (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && - (pteval == SG_ENT_PHYS_ADDRESS(sg)) && - ((pteval ^ - (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { - pteval += sg->length; - sg++; - } - if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) - pteval = ~0UL; - } while (dma_npages != 0); - dma_sg++; - } -} - -int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int dir) -{ - struct sbus_iommu *iommu = sdev->bus->iommu; - unsigned long flags, npages; - iopte_t *iopte; - u32 dma_base; - struct scatterlist *sgtmp; - int used; - unsigned long iopte_bits; - - if (dir == SBUS_DMA_NONE) - BUG(); - - /* Fast path single entry scatterlists. */ - if (nents == 1) { - sg->dma_address = - sbus_map_single(sdev, - (page_address(sg->page) + sg->offset), - sg->length, dir); - sg->dma_length = sg->length; - return 1; - } - - npages = prepare_sg(sg, nents); - - spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_streaming_cluster(iommu, npages); - if (iopte == NULL) - goto bad; - dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); - - /* Normalize DVMA addresses. */ - sgtmp = sg; - used = nents; - - while (used && sgtmp->dma_length) { - sgtmp->dma_address += dma_base; - sgtmp++; - used--; - } - used = nents - used; - - iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; - if (dir != SBUS_DMA_TODEVICE) - iopte_bits |= IOPTE_WRITE; - - fill_sg(iopte, sg, used, nents, iopte_bits); -#ifdef VERIFY_SG - verify_sglist(sg, nents, iopte, npages); -#endif - spin_unlock_irqrestore(&iommu->lock, flags); - - return used; - -bad: - spin_unlock_irqrestore(&iommu->lock, flags); - BUG(); - return 0; -} - -void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction) -{ - unsigned long size, flags; - struct sbus_iommu *iommu; - u32 dvma_base; - int i; - - /* Fast path single entry scatterlists. */ - if (nents == 1) { - sbus_unmap_single(sdev, sg->dma_address, sg->dma_length, direction); - return; - } - - dvma_base = sg[0].dma_address & IO_PAGE_MASK; - for (i = 0; i < nents; i++) { - if (sg[i].dma_length == 0) - break; - } - i--; - size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - dvma_base; - - iommu = sdev->bus->iommu; - spin_lock_irqsave(&iommu->lock, flags); - free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); - sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction); - spin_unlock_irqrestore(&iommu->lock, flags); -} - -void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t size, int direction) -{ - struct sbus_iommu *iommu = sdev->bus->iommu; - unsigned long flags; - - size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); - - spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction); - spin_unlock_irqrestore(&iommu->lock, flags); -} - -void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t base, size_t size, int direction) -{ -} - -void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction) -{ - struct sbus_iommu *iommu = sdev->bus->iommu; - unsigned long flags, size; - u32 base; - int i; - - base = sg[0].dma_address & IO_PAGE_MASK; - for (i = 0; i < nents; i++) { - if (sg[i].dma_length == 0) - break; - } - i--; - size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; - - spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction); - spin_unlock_irqrestore(&iommu->lock, flags); -} - -void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction) -{ -} - -/* Enable 64-bit DVMA mode for the given device. */ -void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) -{ - struct sbus_iommu *iommu = sdev->bus->iommu; - int slot = sdev->slot; - unsigned long cfg_reg; - u64 val; - - cfg_reg = iommu->sbus_control_reg; - switch (slot) { - case 0: - cfg_reg += 0x20UL; - break; - case 1: - cfg_reg += 0x28UL; - break; - case 2: - cfg_reg += 0x30UL; - break; - case 3: - cfg_reg += 0x38UL; - break; - case 13: - cfg_reg += 0x40UL; - break; - case 14: - cfg_reg += 0x48UL; - break; - case 15: - cfg_reg += 0x50UL; - break; - - default: - return; - }; - - val = upa_readq(cfg_reg); - if (val & (1UL << 14UL)) { - /* Extended transfer mode already enabled. */ - return; - } - - val |= (1UL << 14UL); - - if (bursts & DMA_BURST8) - val |= (1UL << 1UL); - if (bursts & DMA_BURST16) - val |= (1UL << 2UL); - if (bursts & DMA_BURST32) - val |= (1UL << 3UL); - if (bursts & DMA_BURST64) - val |= (1UL << 4UL); - upa_writeq(val, cfg_reg); -} - -/* SBUS SYSIO INO number to Sparc PIL level. */ -static unsigned char sysio_ino_to_pil[] = { - 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 0 */ - 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 1 */ - 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 2 */ - 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 3 */ - 4, /* Onboard SCSI */ - 5, /* Onboard Ethernet */ -/*XXX*/ 8, /* Onboard BPP */ - 0, /* Bogon */ - 13, /* Audio */ -/*XXX*/15, /* PowerFail */ - 0, /* Bogon */ - 0, /* Bogon */ - 12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */ - 11, /* Floppy */ - 0, /* Spare Hardware (bogon for now) */ - 0, /* Keyboard (bogon for now) */ - 0, /* Mouse (bogon for now) */ - 0, /* Serial (bogon for now) */ - 0, 0, /* Bogon, Bogon */ - 10, /* Timer 0 */ - 11, /* Timer 1 */ - 0, 0, /* Bogon, Bogon */ - 15, /* Uncorrectable SBUS Error */ - 15, /* Correctable SBUS Error */ - 15, /* SBUS Error */ -/*XXX*/ 0, /* Power Management (bogon for now) */ -}; - -/* INO number to IMAP register offset for SYSIO external IRQ's. - * This should conform to both Sunfire/Wildfire server and Fusion - * desktop designs. - */ -#define SYSIO_IMAP_SLOT0 0x2c04UL -#define SYSIO_IMAP_SLOT1 0x2c0cUL -#define SYSIO_IMAP_SLOT2 0x2c14UL -#define SYSIO_IMAP_SLOT3 0x2c1cUL -#define SYSIO_IMAP_SCSI 0x3004UL -#define SYSIO_IMAP_ETH 0x300cUL -#define SYSIO_IMAP_BPP 0x3014UL -#define SYSIO_IMAP_AUDIO 0x301cUL -#define SYSIO_IMAP_PFAIL 0x3024UL -#define SYSIO_IMAP_KMS 0x302cUL -#define SYSIO_IMAP_FLPY 0x3034UL -#define SYSIO_IMAP_SHW 0x303cUL -#define SYSIO_IMAP_KBD 0x3044UL -#define SYSIO_IMAP_MS 0x304cUL -#define SYSIO_IMAP_SER 0x3054UL -#define SYSIO_IMAP_TIM0 0x3064UL -#define SYSIO_IMAP_TIM1 0x306cUL -#define SYSIO_IMAP_UE 0x3074UL -#define SYSIO_IMAP_CE 0x307cUL -#define SYSIO_IMAP_SBERR 0x3084UL -#define SYSIO_IMAP_PMGMT 0x308cUL -#define SYSIO_IMAP_GFX 0x3094UL -#define SYSIO_IMAP_EUPA 0x309cUL - -#define bogon ((unsigned long) -1) -static unsigned long sysio_irq_offsets[] = { - /* SBUS Slot 0 --> 3, level 1 --> 7 */ - SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, - SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, - SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, - SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, - SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, - SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, - SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, - SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, - - /* Onboard devices (not relevant/used on SunFire). */ - SYSIO_IMAP_SCSI, - SYSIO_IMAP_ETH, - SYSIO_IMAP_BPP, - bogon, - SYSIO_IMAP_AUDIO, - SYSIO_IMAP_PFAIL, - bogon, - bogon, - SYSIO_IMAP_KMS, - SYSIO_IMAP_FLPY, - SYSIO_IMAP_SHW, - SYSIO_IMAP_KBD, - SYSIO_IMAP_MS, - SYSIO_IMAP_SER, - bogon, - bogon, - SYSIO_IMAP_TIM0, - SYSIO_IMAP_TIM1, - bogon, - bogon, - SYSIO_IMAP_UE, - SYSIO_IMAP_CE, - SYSIO_IMAP_SBERR, - SYSIO_IMAP_PMGMT, -}; - -#undef bogon - -#define NUM_SYSIO_OFFSETS ARRAY_SIZE(sysio_irq_offsets) - -/* Convert Interrupt Mapping register pointer to associated - * Interrupt Clear register pointer, SYSIO specific version. - */ -#define SYSIO_ICLR_UNUSED0 0x3400UL -#define SYSIO_ICLR_SLOT0 0x340cUL -#define SYSIO_ICLR_SLOT1 0x344cUL -#define SYSIO_ICLR_SLOT2 0x348cUL -#define SYSIO_ICLR_SLOT3 0x34ccUL -static unsigned long sysio_imap_to_iclr(unsigned long imap) -{ - unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0; - return imap + diff; -} - -unsigned int sbus_build_irq(void *buscookie, unsigned int ino) -{ - struct sbus_bus *sbus = (struct sbus_bus *)buscookie; - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; - unsigned long imap, iclr; - int pil, sbus_level = 0; - - pil = sysio_ino_to_pil[ino]; - if (!pil) { - printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino); - panic("Bad SYSIO IRQ translations..."); - } - - if (PIL_RESERVED(pil)) - BUG(); - - imap = sysio_irq_offsets[ino]; - if (imap == ((unsigned long)-1)) { - prom_printf("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n", - ino, pil); - prom_halt(); - } - imap += reg_base; - - /* SYSIO inconsistency. For external SLOTS, we have to select - * the right ICLR register based upon the lower SBUS irq level - * bits. - */ - if (ino >= 0x20) { - iclr = sysio_imap_to_iclr(imap); - } else { - int sbus_slot = (ino & 0x18)>>3; - - sbus_level = ino & 0x7; - - switch(sbus_slot) { - case 0: - iclr = reg_base + SYSIO_ICLR_SLOT0; - break; - case 1: - iclr = reg_base + SYSIO_ICLR_SLOT1; - break; - case 2: - iclr = reg_base + SYSIO_ICLR_SLOT2; - break; - default: - case 3: - iclr = reg_base + SYSIO_ICLR_SLOT3; - break; - }; - - iclr += ((unsigned long)sbus_level - 1UL) * 8UL; - } - return build_irq(pil, sbus_level, iclr, imap); -} - -/* Error interrupt handling. */ -#define SYSIO_UE_AFSR 0x0030UL -#define SYSIO_UE_AFAR 0x0038UL -#define SYSIO_UEAFSR_PPIO 0x8000000000000000UL /* Primary PIO cause */ -#define SYSIO_UEAFSR_PDRD 0x4000000000000000UL /* Primary DVMA read cause */ -#define SYSIO_UEAFSR_PDWR 0x2000000000000000UL /* Primary DVMA write cause */ -#define SYSIO_UEAFSR_SPIO 0x1000000000000000UL /* Secondary PIO is cause */ -#define SYSIO_UEAFSR_SDRD 0x0800000000000000UL /* Secondary DVMA read cause */ -#define SYSIO_UEAFSR_SDWR 0x0400000000000000UL /* Secondary DVMA write cause*/ -#define SYSIO_UEAFSR_RESV1 0x03ff000000000000UL /* Reserved */ -#define SYSIO_UEAFSR_DOFF 0x0000e00000000000UL /* Doubleword Offset */ -#define SYSIO_UEAFSR_SIZE 0x00001c0000000000UL /* Bad transfer size 2^SIZE */ -#define SYSIO_UEAFSR_MID 0x000003e000000000UL /* UPA MID causing the fault */ -#define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ -static irqreturn_t sysio_ue_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - struct sbus_bus *sbus = dev_id; - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int reported; - - afsr_reg = reg_base + SYSIO_UE_AFSR; - afar_reg = reg_base + SYSIO_UE_AFAR; - - /* Latch error status. */ - afsr = upa_readq(afsr_reg); - afar = upa_readq(afar_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SYSIO_UEAFSR_PPIO | SYSIO_UEAFSR_PDRD | SYSIO_UEAFSR_PDWR | - SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); - upa_writeq(error_bits, afsr_reg); - - /* Log the error. */ - printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", - sbus->portid, - (((error_bits & SYSIO_UEAFSR_PPIO) ? - "PIO" : - ((error_bits & SYSIO_UEAFSR_PDRD) ? - "DVMA Read" : - ((error_bits & SYSIO_UEAFSR_PDWR) ? - "DVMA Write" : "???"))))); - printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", - sbus->portid, - (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, - (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, - (afsr & SYSIO_UEAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); - printk("SYSIO[%x]: Secondary UE errors [", sbus->portid); - reported = 0; - if (afsr & SYSIO_UEAFSR_SPIO) { - reported++; - printk("(PIO)"); - } - if (afsr & SYSIO_UEAFSR_SDRD) { - reported++; - printk("(DVMA Read)"); - } - if (afsr & SYSIO_UEAFSR_SDWR) { - reported++; - printk("(DVMA Write)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - return IRQ_HANDLED; -} - -#define SYSIO_CE_AFSR 0x0040UL -#define SYSIO_CE_AFAR 0x0048UL -#define SYSIO_CEAFSR_PPIO 0x8000000000000000UL /* Primary PIO cause */ -#define SYSIO_CEAFSR_PDRD 0x4000000000000000UL /* Primary DVMA read cause */ -#define SYSIO_CEAFSR_PDWR 0x2000000000000000UL /* Primary DVMA write cause */ -#define SYSIO_CEAFSR_SPIO 0x1000000000000000UL /* Secondary PIO cause */ -#define SYSIO_CEAFSR_SDRD 0x0800000000000000UL /* Secondary DVMA read cause */ -#define SYSIO_CEAFSR_SDWR 0x0400000000000000UL /* Secondary DVMA write cause*/ -#define SYSIO_CEAFSR_RESV1 0x0300000000000000UL /* Reserved */ -#define SYSIO_CEAFSR_ESYND 0x00ff000000000000UL /* Syndrome Bits */ -#define SYSIO_CEAFSR_DOFF 0x0000e00000000000UL /* Double Offset */ -#define SYSIO_CEAFSR_SIZE 0x00001c0000000000UL /* Bad transfer size 2^SIZE */ -#define SYSIO_CEAFSR_MID 0x000003e000000000UL /* UPA MID causing the fault */ -#define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ -static irqreturn_t sysio_ce_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - struct sbus_bus *sbus = dev_id; - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int reported; - - afsr_reg = reg_base + SYSIO_CE_AFSR; - afar_reg = reg_base + SYSIO_CE_AFAR; - - /* Latch error status. */ - afsr = upa_readq(afsr_reg); - afar = upa_readq(afar_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SYSIO_CEAFSR_PPIO | SYSIO_CEAFSR_PDRD | SYSIO_CEAFSR_PDWR | - SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); - upa_writeq(error_bits, afsr_reg); - - printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", - sbus->portid, - (((error_bits & SYSIO_CEAFSR_PPIO) ? - "PIO" : - ((error_bits & SYSIO_CEAFSR_PDRD) ? - "DVMA Read" : - ((error_bits & SYSIO_CEAFSR_PDWR) ? - "DVMA Write" : "???"))))); - - /* XXX Use syndrome and afar to print out module string just like - * XXX UDB CE trap handler does... -DaveM - */ - printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", - sbus->portid, - (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, - (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, - (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, - (afsr & SYSIO_CEAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); - - printk("SYSIO[%x]: Secondary CE errors [", sbus->portid); - reported = 0; - if (afsr & SYSIO_CEAFSR_SPIO) { - reported++; - printk("(PIO)"); - } - if (afsr & SYSIO_CEAFSR_SDRD) { - reported++; - printk("(DVMA Read)"); - } - if (afsr & SYSIO_CEAFSR_SDWR) { - reported++; - printk("(DVMA Write)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - return IRQ_HANDLED; -} - -#define SYSIO_SBUS_AFSR 0x2010UL -#define SYSIO_SBUS_AFAR 0x2018UL -#define SYSIO_SBAFSR_PLE 0x8000000000000000UL /* Primary Late PIO Error */ -#define SYSIO_SBAFSR_PTO 0x4000000000000000UL /* Primary SBUS Timeout */ -#define SYSIO_SBAFSR_PBERR 0x2000000000000000UL /* Primary SBUS Error ACK */ -#define SYSIO_SBAFSR_SLE 0x1000000000000000UL /* Secondary Late PIO Error */ -#define SYSIO_SBAFSR_STO 0x0800000000000000UL /* Secondary SBUS Timeout */ -#define SYSIO_SBAFSR_SBERR 0x0400000000000000UL /* Secondary SBUS Error ACK */ -#define SYSIO_SBAFSR_RESV1 0x03ff000000000000UL /* Reserved */ -#define SYSIO_SBAFSR_RD 0x0000800000000000UL /* Primary was late PIO read */ -#define SYSIO_SBAFSR_RESV2 0x0000600000000000UL /* Reserved */ -#define SYSIO_SBAFSR_SIZE 0x00001c0000000000UL /* Size of transfer */ -#define SYSIO_SBAFSR_MID 0x000003e000000000UL /* MID causing the error */ -#define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ -static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - struct sbus_bus *sbus = dev_id; - struct sbus_iommu *iommu = sbus->iommu; - unsigned long afsr_reg, afar_reg, reg_base; - unsigned long afsr, afar, error_bits; - int reported; - - reg_base = iommu->sbus_control_reg - 0x2000UL; - afsr_reg = reg_base + SYSIO_SBUS_AFSR; - afar_reg = reg_base + SYSIO_SBUS_AFAR; - - afsr = upa_readq(afsr_reg); - afar = upa_readq(afar_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SYSIO_SBAFSR_PLE | SYSIO_SBAFSR_PTO | SYSIO_SBAFSR_PBERR | - SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); - upa_writeq(error_bits, afsr_reg); - - /* Log the error. */ - printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", - sbus->portid, - (((error_bits & SYSIO_SBAFSR_PLE) ? - "Late PIO Error" : - ((error_bits & SYSIO_SBAFSR_PTO) ? - "Time Out" : - ((error_bits & SYSIO_SBAFSR_PBERR) ? - "Error Ack" : "???")))), - (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); - printk("SYSIO[%x]: size[%lx] MID[%lx]\n", - sbus->portid, - (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, - (afsr & SYSIO_SBAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); - printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid); - reported = 0; - if (afsr & SYSIO_SBAFSR_SLE) { - reported++; - printk("(Late PIO Error)"); - } - if (afsr & SYSIO_SBAFSR_STO) { - reported++; - printk("(Time Out)"); - } - if (afsr & SYSIO_SBAFSR_SBERR) { - reported++; - printk("(Error Ack)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* XXX check iommu/strbuf for further error status XXX */ - - return IRQ_HANDLED; -} - -#define ECC_CONTROL 0x0020UL -#define SYSIO_ECNTRL_ECCEN 0x8000000000000000UL /* Enable ECC Checking */ -#define SYSIO_ECNTRL_UEEN 0x4000000000000000UL /* Enable UE Interrupts */ -#define SYSIO_ECNTRL_CEEN 0x2000000000000000UL /* Enable CE Interrupts */ - -#define SYSIO_UE_INO 0x34 -#define SYSIO_CE_INO 0x35 -#define SYSIO_SBUSERR_INO 0x36 - -static void __init sysio_register_error_handlers(struct sbus_bus *sbus) -{ - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; - unsigned int irq; - u64 control; - - irq = sbus_build_irq(sbus, SYSIO_UE_INO); - if (request_irq(irq, sysio_ue_handler, - SA_SHIRQ, "SYSIO UE", sbus) < 0) { - prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", - sbus->portid); - prom_halt(); - } - - irq = sbus_build_irq(sbus, SYSIO_CE_INO); - if (request_irq(irq, sysio_ce_handler, - SA_SHIRQ, "SYSIO CE", sbus) < 0) { - prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", - sbus->portid); - prom_halt(); - } - - irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); - if (request_irq(irq, sysio_sbus_error_handler, - SA_SHIRQ, "SYSIO SBUS Error", sbus) < 0) { - prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", - sbus->portid); - prom_halt(); - } - - /* Now turn the error interrupts on and also enable ECC checking. */ - upa_writeq((SYSIO_ECNTRL_ECCEN | - SYSIO_ECNTRL_UEEN | - SYSIO_ECNTRL_CEEN), - reg_base + ECC_CONTROL); - - control = upa_readq(iommu->sbus_control_reg); - control |= 0x100UL; /* SBUS Error Interrupt Enable */ - upa_writeq(control, iommu->sbus_control_reg); -} - -/* Boot time initialization. */ -void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) -{ - struct linux_prom64_registers rprop; - struct sbus_iommu *iommu; - unsigned long regs, tsb_base; - u64 control; - int err, i; - - sbus->portid = prom_getintdefault(sbus->prom_node, - "upa-portid", -1); - - err = prom_getproperty(prom_node, "reg", - (char *)&rprop, sizeof(rprop)); - if (err < 0) { - prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n"); - prom_halt(); - } - regs = rprop.phys_addr; - - iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC); - if (iommu == NULL) { - prom_printf("sbus_iommu_init: Fatal error, kmalloc(iommu) failed\n"); - prom_halt(); - } - - /* Align on E$ line boundary. */ - iommu = (struct sbus_iommu *) - (((unsigned long)iommu + (SMP_CACHE_BYTES - 1UL)) & - ~(SMP_CACHE_BYTES - 1UL)); - - memset(iommu, 0, sizeof(*iommu)); - - /* We start with no consistent mappings. */ - iommu->lowest_consistent_map = CLUSTER_NPAGES; - - for (i = 0; i < NCLUSTERS; i++) { - iommu->alloc_info[i].flush = 0; - iommu->alloc_info[i].next = 0; - } - - /* Setup spinlock. */ - spin_lock_init(&iommu->lock); - - /* Init register offsets. */ - iommu->iommu_regs = regs + SYSIO_IOMMUREG_BASE; - iommu->strbuf_regs = regs + SYSIO_STRBUFREG_BASE; - - /* The SYSIO SBUS control register is used for dummy reads - * in order to ensure write completion. - */ - iommu->sbus_control_reg = regs + 0x2000UL; - - /* Link into SYSIO software state. */ - sbus->iommu = iommu; - - printk("SYSIO: UPA portID %x, at %016lx\n", - sbus->portid, regs); - - /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ - control = upa_readq(iommu->iommu_regs + IOMMU_CONTROL); - control = ((7UL << 16UL) | - (0UL << 2UL) | - (1UL << 1UL) | - (1UL << 0UL)); - - /* Using the above configuration we need 1MB iommu page - * table (128K ioptes * 8 bytes per iopte). This is - * page order 7 on UltraSparc. - */ - tsb_base = __get_free_pages(GFP_ATOMIC, get_order(IO_TSB_SIZE)); - if (tsb_base == 0UL) { - prom_printf("sbus_iommu_init: Fatal error, cannot alloc TSB table.\n"); - prom_halt(); - } - - iommu->page_table = (iopte_t *) tsb_base; - memset(iommu->page_table, 0, IO_TSB_SIZE); - - upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL); - - /* Clean out any cruft in the IOMMU using - * diagnostic accesses. - */ - for (i = 0; i < 16; i++) { - unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG; - unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; - - dram += (unsigned long)i * 8UL; - tag += (unsigned long)i * 8UL; - upa_writeq(0, dram); - upa_writeq(0, tag); - } - upa_readq(iommu->sbus_control_reg); - - /* Give the TSB to SYSIO. */ - upa_writeq(__pa(tsb_base), iommu->iommu_regs + IOMMU_TSBBASE); - - /* Setup streaming buffer, DE=1 SB_EN=1 */ - control = (1UL << 1UL) | (1UL << 0UL); - upa_writeq(control, iommu->strbuf_regs + STRBUF_CONTROL); - - /* Clear out the tags using diagnostics. */ - for (i = 0; i < 16; i++) { - unsigned long ptag, ltag; - - ptag = iommu->strbuf_regs + STRBUF_PTAGDIAG; - ltag = iommu->strbuf_regs + STRBUF_LTAGDIAG; - ptag += (unsigned long)i * 8UL; - ltag += (unsigned long)i * 8UL; - - upa_writeq(0UL, ptag); - upa_writeq(0UL, ltag); - } - - /* Enable DVMA arbitration for all devices/slots. */ - control = upa_readq(iommu->sbus_control_reg); - control |= 0x3fUL; - upa_writeq(control, iommu->sbus_control_reg); - - /* Now some Xfire specific grot... */ - if (this_is_starfire) - sbus->starfire_cookie = starfire_hookup(sbus->portid); - else - sbus->starfire_cookie = NULL; - - sysio_register_error_handlers(sbus); -} diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c deleted file mode 100644 index a809e63f03e..00000000000 --- a/arch/sparc64/kernel/semaphore.c +++ /dev/null @@ -1,255 +0,0 @@ -/* $Id: semaphore.c,v 1.9 2001/11/18 00:12:56 davem Exp $ - * semaphore.c: Sparc64 semaphore implementation. - * - * This is basically the PPC semaphore scheme ported to use - * the sparc64 atomic instructions, so see the PPC code for - * credits. - */ - -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/init.h> - -/* - * Atomically update sem->count. - * This does the equivalent of the following: - * - * old_count = sem->count; - * tmp = MAX(old_count, 0) + incr; - * sem->count = tmp; - * return old_count; - */ -static __inline__ int __sem_update_count(struct semaphore *sem, int incr) -{ - int old_count, tmp; - - __asm__ __volatile__("\n" -" ! __sem_update_count old_count(%0) tmp(%1) incr(%4) &sem->count(%3)\n" -"1: ldsw [%3], %0\n" -" mov %0, %1\n" -" cmp %0, 0\n" -" movl %%icc, 0, %1\n" -" add %1, %4, %1\n" -" cas [%3], %0, %1\n" -" cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" -" bne,pn %%icc, 1b\n" -" nop\n" - : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) - : "r" (&sem->count), "r" (incr), "m" (sem->count) - : "cc"); - - return old_count; -} - -static void __up(struct semaphore *sem) -{ - __sem_update_count(sem, 1); - wake_up(&sem->wait); -} - -void up(struct semaphore *sem) -{ - /* This atomically does: - * old_val = sem->count; - * new_val = sem->count + 1; - * sem->count = new_val; - * if (old_val < 0) - * __up(sem); - * - * The (old_val < 0) test is equivalent to - * the more straightforward (new_val <= 0), - * but it is easier to test the former because - * of how the CAS instruction works. - */ - - __asm__ __volatile__("\n" -" ! up sem(%0)\n" -" membar #StoreLoad | #LoadLoad\n" -"1: lduw [%0], %%g1\n" -" add %%g1, 1, %%g7\n" -" cas [%0], %%g1, %%g7\n" -" cmp %%g1, %%g7\n" -" bne,pn %%icc, 1b\n" -" addcc %%g7, 1, %%g0\n" -" membar #StoreLoad | #StoreStore\n" -" ble,pn %%icc, 3f\n" -" nop\n" -"2:\n" -" .subsection 2\n" -"3: mov %0, %%g1\n" -" save %%sp, -160, %%sp\n" -" call %1\n" -" mov %%g1, %%o0\n" -" ba,pt %%xcc, 2b\n" -" restore\n" -" .previous\n" - : : "r" (sem), "i" (__up) - : "g1", "g2", "g3", "g7", "memory", "cc"); -} - -static void __sched __down(struct semaphore * sem) -{ - struct task_struct *tsk = current; - DECLARE_WAITQUEUE(wait, tsk); - - tsk->state = TASK_UNINTERRUPTIBLE; - add_wait_queue_exclusive(&sem->wait, &wait); - - while (__sem_update_count(sem, -1) <= 0) { - schedule(); - tsk->state = TASK_UNINTERRUPTIBLE; - } - remove_wait_queue(&sem->wait, &wait); - tsk->state = TASK_RUNNING; - - wake_up(&sem->wait); -} - -void __sched down(struct semaphore *sem) -{ - might_sleep(); - /* This atomically does: - * old_val = sem->count; - * new_val = sem->count - 1; - * sem->count = new_val; - * if (old_val < 1) - * __down(sem); - * - * The (old_val < 1) test is equivalent to - * the more straightforward (new_val < 0), - * but it is easier to test the former because - * of how the CAS instruction works. - */ - - __asm__ __volatile__("\n" -" ! down sem(%0)\n" -"1: lduw [%0], %%g1\n" -" sub %%g1, 1, %%g7\n" -" cas [%0], %%g1, %%g7\n" -" cmp %%g1, %%g7\n" -" bne,pn %%icc, 1b\n" -" cmp %%g7, 1\n" -" membar #StoreLoad | #StoreStore\n" -" bl,pn %%icc, 3f\n" -" nop\n" -"2:\n" -" .subsection 2\n" -"3: mov %0, %%g1\n" -" save %%sp, -160, %%sp\n" -" call %1\n" -" mov %%g1, %%o0\n" -" ba,pt %%xcc, 2b\n" -" restore\n" -" .previous\n" - : : "r" (sem), "i" (__down) - : "g1", "g2", "g3", "g7", "memory", "cc"); -} - -int down_trylock(struct semaphore *sem) -{ - int ret; - - /* This atomically does: - * old_val = sem->count; - * new_val = sem->count - 1; - * if (old_val < 1) { - * ret = 1; - * } else { - * sem->count = new_val; - * ret = 0; - * } - * - * The (old_val < 1) test is equivalent to - * the more straightforward (new_val < 0), - * but it is easier to test the former because - * of how the CAS instruction works. - */ - - __asm__ __volatile__("\n" -" ! down_trylock sem(%1) ret(%0)\n" -"1: lduw [%1], %%g1\n" -" sub %%g1, 1, %%g7\n" -" cmp %%g1, 1\n" -" bl,pn %%icc, 2f\n" -" mov 1, %0\n" -" cas [%1], %%g1, %%g7\n" -" cmp %%g1, %%g7\n" -" bne,pn %%icc, 1b\n" -" mov 0, %0\n" -" membar #StoreLoad | #StoreStore\n" -"2:\n" - : "=&r" (ret) - : "r" (sem) - : "g1", "g7", "memory", "cc"); - - return ret; -} - -static int __sched __down_interruptible(struct semaphore * sem) -{ - int retval = 0; - struct task_struct *tsk = current; - DECLARE_WAITQUEUE(wait, tsk); - - tsk->state = TASK_INTERRUPTIBLE; - add_wait_queue_exclusive(&sem->wait, &wait); - - while (__sem_update_count(sem, -1) <= 0) { - if (signal_pending(current)) { - __sem_update_count(sem, 0); - retval = -EINTR; - break; - } - schedule(); - tsk->state = TASK_INTERRUPTIBLE; - } - tsk->state = TASK_RUNNING; - remove_wait_queue(&sem->wait, &wait); - wake_up(&sem->wait); - return retval; -} - -int __sched down_interruptible(struct semaphore *sem) -{ - int ret = 0; - - might_sleep(); - /* This atomically does: - * old_val = sem->count; - * new_val = sem->count - 1; - * sem->count = new_val; - * if (old_val < 1) - * ret = __down_interruptible(sem); - * - * The (old_val < 1) test is equivalent to - * the more straightforward (new_val < 0), - * but it is easier to test the former because - * of how the CAS instruction works. - */ - - __asm__ __volatile__("\n" -" ! down_interruptible sem(%2) ret(%0)\n" -"1: lduw [%2], %%g1\n" -" sub %%g1, 1, %%g7\n" -" cas [%2], %%g1, %%g7\n" -" cmp %%g1, %%g7\n" -" bne,pn %%icc, 1b\n" -" cmp %%g7, 1\n" -" membar #StoreLoad | #StoreStore\n" -" bl,pn %%icc, 3f\n" -" nop\n" -"2:\n" -" .subsection 2\n" -"3: mov %2, %%g1\n" -" save %%sp, -160, %%sp\n" -" call %3\n" -" mov %%g1, %%o0\n" -" ba,pt %%xcc, 2b\n" -" restore\n" -" .previous\n" - : "=r" (ret) - : "0" (ret), "r" (sem), "i" (__down_interruptible) - : "g1", "g2", "g3", "g7", "memory", "cc"); - return ret; -} diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c deleted file mode 100644 index 054461e6946..00000000000 --- a/arch/sparc64/kernel/setup.c +++ /dev/null @@ -1,708 +0,0 @@ -/* $Id: setup.c,v 1.72 2002/02/09 19:49:30 davem Exp $ - * linux/arch/sparc64/kernel/setup.c - * - * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/stddef.h> -#include <linux/unistd.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <asm/smp.h> -#include <linux/user.h> -#include <linux/a.out.h> -#include <linux/tty.h> -#include <linux/delay.h> -#include <linux/config.h> -#include <linux/fs.h> -#include <linux/seq_file.h> -#include <linux/syscalls.h> -#include <linux/kdev_t.h> -#include <linux/major.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/inet.h> -#include <linux/console.h> -#include <linux/root_dev.h> -#include <linux/interrupt.h> -#include <linux/cpu.h> -#include <linux/initrd.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/processor.h> -#include <asm/oplib.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/idprom.h> -#include <asm/head.h> -#include <asm/starfire.h> -#include <asm/mmu_context.h> -#include <asm/timer.h> -#include <asm/sections.h> -#include <asm/setup.h> -#include <asm/mmu.h> - -#ifdef CONFIG_IP_PNP -#include <net/ipconfig.h> -#endif - -struct screen_info screen_info = { - 0, 0, /* orig-x, orig-y */ - 0, /* unused */ - 0, /* orig-video-page */ - 0, /* orig-video-mode */ - 128, /* orig-video-cols */ - 0, 0, 0, /* unused, ega_bx, unused */ - 54, /* orig-video-lines */ - 0, /* orig-video-isVGA */ - 16 /* orig-video-points */ -}; - -/* Typing sync at the prom prompt calls the function pointed to by - * the sync callback which I set to the following function. - * This should sync all filesystems and return, for now it just - * prints out pretty messages and returns. - */ - -void (*prom_palette)(int); -void (*prom_keyboard)(void); - -static void -prom_console_write(struct console *con, const char *s, unsigned n) -{ - prom_write(s, n); -} - -static struct console prom_console = { - .name = "prom", - .write = prom_console_write, - .flags = CON_CONSDEV | CON_ENABLED, - .index = -1, -}; - -#define PROM_TRUE -1 -#define PROM_FALSE 0 - -/* Pretty sick eh? */ -int prom_callback(long *args) -{ - struct console *cons, *saved_console = NULL; - unsigned long flags; - char *cmd; - extern spinlock_t prom_entry_lock; - - if (!args) - return -1; - if (!(cmd = (char *)args[0])) - return -1; - - /* - * The callback can be invoked on the cpu that first dropped - * into prom_cmdline after taking the serial interrupt, or on - * a slave processor that was smp_captured() if the - * administrator has done a switch-cpu inside obp. In either - * case, the cpu is marked as in-interrupt. Drop IRQ locks. - */ - irq_exit(); - - /* XXX Revisit the locking here someday. This is a debugging - * XXX feature so it isnt all that critical. -DaveM - */ - local_irq_save(flags); - - spin_unlock(&prom_entry_lock); - cons = console_drivers; - while (cons) { - unregister_console(cons); - cons->flags &= ~(CON_PRINTBUFFER); - cons->next = saved_console; - saved_console = cons; - cons = console_drivers; - } - register_console(&prom_console); - if (!strcmp(cmd, "sync")) { - prom_printf("PROM `%s' command...\n", cmd); - show_free_areas(); - if (current->pid != 0) { - local_irq_enable(); - sys_sync(); - local_irq_disable(); - } - args[2] = 0; - args[args[1] + 3] = -1; - prom_printf("Returning to PROM\n"); - } else if (!strcmp(cmd, "va>tte-data")) { - unsigned long ctx, va; - unsigned long tte = 0; - long res = PROM_FALSE; - - ctx = args[3]; - va = args[4]; - if (ctx) { - /* - * Find process owning ctx, lookup mapping. - */ - struct task_struct *p; - struct mm_struct *mm = NULL; - pgd_t *pgdp; - pud_t *pudp; - pmd_t *pmdp; - pte_t *ptep; - pte_t pte; - - for_each_process(p) { - mm = p->mm; - if (CTX_NRBITS(mm->context) == ctx) - break; - } - if (!mm || - CTX_NRBITS(mm->context) != ctx) - goto done; - - pgdp = pgd_offset(mm, va); - if (pgd_none(*pgdp)) - goto done; - pudp = pud_offset(pgdp, va); - if (pud_none(*pudp)) - goto done; - pmdp = pmd_offset(pudp, va); - if (pmd_none(*pmdp)) - goto done; - - /* Preemption implicitly disabled by virtue of - * being called from inside OBP. - */ - ptep = pte_offset_map(pmdp, va); - pte = *ptep; - if (pte_present(pte)) { - tte = pte_val(pte); - res = PROM_TRUE; - } - pte_unmap(ptep); - goto done; - } - - if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { - extern unsigned long sparc64_kern_pri_context; - - /* Spitfire Errata #32 workaround */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (sparc64_kern_pri_context), - "r" (PRIMARY_CONTEXT), - "i" (ASI_DMMU)); - - /* - * Locked down tlb entry. - */ - - if (tlb_type == spitfire) - tte = spitfire_get_dtlb_data(SPITFIRE_HIGHEST_LOCKED_TLBENT); - else if (tlb_type == cheetah || tlb_type == cheetah_plus) - tte = cheetah_get_ldtlb_data(CHEETAH_HIGHEST_LOCKED_TLBENT); - - res = PROM_TRUE; - goto done; - } - - if (va < PGDIR_SIZE) { - /* - * vmalloc or prom_inherited mapping. - */ - pgd_t *pgdp; - pud_t *pudp; - pmd_t *pmdp; - pte_t *ptep; - pte_t pte; - int error; - - if ((va >= LOW_OBP_ADDRESS) && (va < HI_OBP_ADDRESS)) { - tte = prom_virt_to_phys(va, &error); - if (!error) - res = PROM_TRUE; - goto done; - } - pgdp = pgd_offset_k(va); - if (pgd_none(*pgdp)) - goto done; - pudp = pud_offset(pgdp, va); - if (pud_none(*pudp)) - goto done; - pmdp = pmd_offset(pudp, va); - if (pmd_none(*pmdp)) - goto done; - - /* Preemption implicitly disabled by virtue of - * being called from inside OBP. - */ - ptep = pte_offset_kernel(pmdp, va); - pte = *ptep; - if (pte_present(pte)) { - tte = pte_val(pte); - res = PROM_TRUE; - } - goto done; - } - - if (va < PAGE_OFFSET) { - /* - * No mappings here. - */ - goto done; - } - - if (va & (1UL << 40)) { - /* - * I/O page. - */ - - tte = (__pa(va) & _PAGE_PADDR) | - _PAGE_VALID | _PAGE_SZ4MB | - _PAGE_E | _PAGE_P | _PAGE_W; - res = PROM_TRUE; - goto done; - } - - /* - * Normal page. - */ - tte = (__pa(va) & _PAGE_PADDR) | - _PAGE_VALID | _PAGE_SZ4MB | - _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W; - res = PROM_TRUE; - - done: - if (res == PROM_TRUE) { - args[2] = 3; - args[args[1] + 3] = 0; - args[args[1] + 4] = res; - args[args[1] + 5] = tte; - } else { - args[2] = 2; - args[args[1] + 3] = 0; - args[args[1] + 4] = res; - } - } else if (!strcmp(cmd, ".soft1")) { - unsigned long tte; - - tte = args[3]; - prom_printf("%lx:\"%s%s%s%s%s\" ", - (tte & _PAGE_SOFT) >> 7, - tte & _PAGE_MODIFIED ? "M" : "-", - tte & _PAGE_ACCESSED ? "A" : "-", - tte & _PAGE_READ ? "W" : "-", - tte & _PAGE_WRITE ? "R" : "-", - tte & _PAGE_PRESENT ? "P" : "-"); - - args[2] = 2; - args[args[1] + 3] = 0; - args[args[1] + 4] = PROM_TRUE; - } else if (!strcmp(cmd, ".soft2")) { - unsigned long tte; - - tte = args[3]; - prom_printf("%lx ", (tte & 0x07FC000000000000UL) >> 50); - - args[2] = 2; - args[args[1] + 3] = 0; - args[args[1] + 4] = PROM_TRUE; - } else { - prom_printf("unknown PROM `%s' command...\n", cmd); - } - unregister_console(&prom_console); - while (saved_console) { - cons = saved_console; - saved_console = cons->next; - register_console(cons); - } - spin_lock(&prom_entry_lock); - local_irq_restore(flags); - - /* - * Restore in-interrupt status for a resume from obp. - */ - irq_enter(); - return 0; -} - -unsigned int boot_flags = 0; -#define BOOTME_DEBUG 0x1 -#define BOOTME_SINGLE 0x2 - -/* Exported for mm/init.c:paging_init. */ -unsigned long cmdline_memory_size = 0; - -static struct console prom_debug_console = { - .name = "debug", - .write = prom_console_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* XXX Implement this at some point... */ -void kernel_enter_debugger(void) -{ -} - -int obp_system_intr(void) -{ - if (boot_flags & BOOTME_DEBUG) { - printk("OBP: system interrupted\n"); - prom_halt(); - return 1; - } - return 0; -} - -/* - * Process kernel command line switches that are specific to the - * SPARC or that require special low-level processing. - */ -static void __init process_switch(char c) -{ - switch (c) { - case 'd': - boot_flags |= BOOTME_DEBUG; - break; - case 's': - boot_flags |= BOOTME_SINGLE; - break; - case 'h': - prom_printf("boot_flags_init: Halt!\n"); - prom_halt(); - break; - case 'p': - /* Use PROM debug console. */ - register_console(&prom_debug_console); - break; - case 'P': - /* Force UltraSPARC-III P-Cache on. */ - if (tlb_type != cheetah) { - printk("BOOT: Ignoring P-Cache force option.\n"); - break; - } - cheetah_pcache_forced_on = 1; - add_taint(TAINT_MACHINE_CHECK); - cheetah_enable_pcache(); - break; - - default: - printk("Unknown boot switch (-%c)\n", c); - break; - } -} - -static void __init process_console(char *commands) -{ - serial_console = 0; - commands += 8; - /* Linux-style serial */ - if (!strncmp(commands, "ttyS", 4)) - serial_console = simple_strtoul(commands + 4, NULL, 10) + 1; - else if (!strncmp(commands, "tty", 3)) { - char c = *(commands + 3); - /* Solaris-style serial */ - if (c == 'a' || c == 'b') { - serial_console = c - 'a' + 1; - prom_printf ("Using /dev/tty%c as console.\n", c); - } - /* else Linux-style fbcon, not serial */ - } -#if defined(CONFIG_PROM_CONSOLE) - if (!strncmp(commands, "prom", 4)) { - char *p; - - for (p = commands - 8; *p && *p != ' '; p++) - *p = ' '; - conswitchp = &prom_con; - } -#endif -} - -static void __init boot_flags_init(char *commands) -{ - while (*commands) { - /* Move to the start of the next "argument". */ - while (*commands && *commands == ' ') - commands++; - - /* Process any command switches, otherwise skip it. */ - if (*commands == '\0') - break; - if (*commands == '-') { - commands++; - while (*commands && *commands != ' ') - process_switch(*commands++); - continue; - } - if (!strncmp(commands, "console=", 8)) { - process_console(commands); - } else if (!strncmp(commands, "mem=", 4)) { - /* - * "mem=XXX[kKmM]" overrides the PROM-reported - * memory size. - */ - cmdline_memory_size = simple_strtoul(commands + 4, - &commands, 0); - if (*commands == 'K' || *commands == 'k') { - cmdline_memory_size <<= 10; - commands++; - } else if (*commands=='M' || *commands=='m') { - cmdline_memory_size <<= 20; - commands++; - } - } - while (*commands && *commands != ' ') - commands++; - } -} - -extern void panic_setup(char *, int *); - -extern unsigned short root_flags; -extern unsigned short root_dev; -extern unsigned short ram_flags; -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 - -extern int root_mountflags; - -char reboot_command[COMMAND_LINE_SIZE]; - -static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; - -void register_prom_callbacks(void) -{ - prom_setcallback(prom_callback); - prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; " - "' linux-va>tte-data to va>tte-data"); - prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; " - "' linux-.soft1 to .soft1"); - prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; " - "' linux-.soft2 to .soft2"); -} - -void __init setup_arch(char **cmdline_p) -{ - /* Initialize PROM console and command line. */ - *cmdline_p = prom_getbootargs(); - strcpy(saved_command_line, *cmdline_p); - - printk("ARCH: SUN4U\n"); - -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#elif defined(CONFIG_PROM_CONSOLE) - conswitchp = &prom_con; -#endif - - /* Work out if we are starfire early on */ - check_if_starfire(); - - boot_flags_init(*cmdline_p); - - idprom_init(); - - if (!root_flags) - root_mountflags &= ~MS_RDONLY; - ROOT_DEV = old_decode_dev(root_dev); -#ifdef CONFIG_BLK_DEV_INITRD - rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); -#endif - - task_thread_info(&init_task)->kregs = &fake_swapper_regs; - -#ifdef CONFIG_IP_PNP - if (!ic_set_manually) { - int chosen = prom_finddevice ("/chosen"); - u32 cl, sv, gw; - - cl = prom_getintdefault (chosen, "client-ip", 0); - sv = prom_getintdefault (chosen, "server-ip", 0); - gw = prom_getintdefault (chosen, "gateway-ip", 0); - if (cl && sv) { - ic_myaddr = cl; - ic_servaddr = sv; - if (gw) - ic_gateway = gw; -#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) - ic_proto_enabled = 0; -#endif - } - } -#endif - - paging_init(); -} - -static int __init set_preferred_console(void) -{ - int idev, odev; - - /* The user has requested a console so this is already set up. */ - if (serial_console >= 0) - return -EBUSY; - - idev = prom_query_input_device(); - odev = prom_query_output_device(); - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { - serial_console = 0; - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { - serial_console = 1; - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { - serial_console = 2; - } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) { - serial_console = 3; - } else { - prom_printf("Inconsistent console: " - "input %d, output %d\n", - idev, odev); - prom_halt(); - } - - if (serial_console) - return add_preferred_console("ttyS", serial_console - 1, NULL); - - return -ENODEV; -} -console_initcall(set_preferred_console); - -/* BUFFER is PAGE_SIZE bytes long. */ - -extern char *sparc_cpu_type; -extern char *sparc_fpu_type; - -extern void smp_info(struct seq_file *); -extern void smp_bogo(struct seq_file *); -extern void mmu_info(struct seq_file *); - -unsigned int dcache_parity_tl1_occurred; -unsigned int icache_parity_tl1_occurred; - -static int ncpus_probed; - -static int show_cpuinfo(struct seq_file *m, void *__unused) -{ - seq_printf(m, - "cpu\t\t: %s\n" - "fpu\t\t: %s\n" - "promlib\t\t: Version 3 Revision %d\n" - "prom\t\t: %d.%d.%d\n" - "type\t\t: sun4u\n" - "ncpus probed\t: %d\n" - "ncpus active\t: %d\n" - "D$ parity tl1\t: %u\n" - "I$ parity tl1\t: %u\n" -#ifndef CONFIG_SMP - "Cpu0Bogo\t: %lu.%02lu\n" - "Cpu0ClkTck\t: %016lx\n" -#endif - , - sparc_cpu_type, - sparc_fpu_type, - prom_rev, - prom_prev >> 16, - (prom_prev >> 8) & 0xff, - prom_prev & 0xff, - ncpus_probed, - num_online_cpus(), - dcache_parity_tl1_occurred, - icache_parity_tl1_occurred -#ifndef CONFIG_SMP - , cpu_data(0).udelay_val/(500000/HZ), - (cpu_data(0).udelay_val/(5000/HZ)) % 100, - cpu_data(0).clock_tick -#endif - ); -#ifdef CONFIG_SMP - smp_bogo(m); -#endif - mmu_info(m); -#ifdef CONFIG_SMP - smp_info(m); -#endif - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - /* The pointer we are returning is arbitrary, - * it just has to be non-NULL and not IS_ERR - * in the success case. - */ - return *pos == 0 ? &c_start : NULL; -} - -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return c_start(m, pos); -} - -static void c_stop(struct seq_file *m, void *v) -{ -} - -struct seq_operations cpuinfo_op = { - .start =c_start, - .next = c_next, - .stop = c_stop, - .show = show_cpuinfo, -}; - -extern int stop_a_enabled; - -void sun_do_break(void) -{ - if (!stop_a_enabled) - return; - - prom_printf("\n"); - flush_user_windows(); - - prom_cmdline(); -} - -int serial_console = -1; -int stop_a_enabled = 1; - -static int __init topology_init(void) -{ - int i, err; - - err = -ENOMEM; - - /* Count the number of physically present processors in - * the machine, even on uniprocessor, so that /proc/cpuinfo - * output is consistent with 2.4.x - */ - ncpus_probed = 0; - while (!cpu_find_by_instance(ncpus_probed, NULL, NULL)) - ncpus_probed++; - - for (i = 0; i < NR_CPUS; i++) { - if (cpu_possible(i)) { - struct cpu *p = kmalloc(sizeof(*p), GFP_KERNEL); - - if (p) { - memset(p, 0, sizeof(*p)); - register_cpu(p, i, NULL); - err = 0; - } - } - } - - return err; -} - -subsys_initcall(topology_init); diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c deleted file mode 100644 index ca11a4c457d..00000000000 --- a/arch/sparc64/kernel/signal.c +++ /dev/null @@ -1,616 +0,0 @@ -/* $Id: signal.c,v 1.60 2002/02/09 19:49:31 davem Exp $ - * arch/sparc64/kernel/signal.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/config.h> -#ifdef CONFIG_SPARC32_COMPAT -#include <linux/compat.h> /* for compat_old_sigset_t */ -#endif -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/errno.h> -#include <linux/wait.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/smp_lock.h> -#include <linux/binfmts.h> -#include <linux/bitops.h> - -#include <asm/uaccess.h> -#include <asm/ptrace.h> -#include <asm/svr4.h> -#include <asm/pgtable.h> -#include <asm/fpumacro.h> -#include <asm/uctx.h> -#include <asm/siginfo.h> -#include <asm/visasm.h> - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -/* {set, get}context() needed for 64-bit SparcLinux userland. */ -asmlinkage void sparc64_set_context(struct pt_regs *regs) -{ - struct ucontext __user *ucp = (struct ucontext __user *) - regs->u_regs[UREG_I0]; - mc_gregset_t __user *grp; - unsigned long pc, npc, tstate; - unsigned long fp, i7; - unsigned char fenab; - int err; - - flush_user_windows(); - if (get_thread_wsaved() || - (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || - (!__access_ok(ucp, sizeof(*ucp)))) - goto do_sigsegv; - grp = &ucp->uc_mcontext.mc_gregs; - err = __get_user(pc, &((*grp)[MC_PC])); - err |= __get_user(npc, &((*grp)[MC_NPC])); - if (err || ((pc | npc) & 3)) - goto do_sigsegv; - if (regs->u_regs[UREG_I1]) { - sigset_t set; - - if (_NSIG_WORDS == 1) { - if (__get_user(set.sig[0], &ucp->uc_sigmask.sig[0])) - goto do_sigsegv; - } else { - if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t))) - goto do_sigsegv; - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - if (test_thread_flag(TIF_32BIT)) { - pc &= 0xffffffff; - npc &= 0xffffffff; - } - regs->tpc = pc; - regs->tnpc = npc; - err |= __get_user(regs->y, &((*grp)[MC_Y])); - err |= __get_user(tstate, &((*grp)[MC_TSTATE])); - regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); - regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); - err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1])); - err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2])); - err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3])); - err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4])); - err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5])); - err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6])); - err |= __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7])); - err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0])); - err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1])); - err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2])); - err |= __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3])); - err |= __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4])); - err |= __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5])); - err |= __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6])); - err |= __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7])); - - err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); - err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7)); - err |= __put_user(fp, - (&(((struct reg_window __user *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); - err |= __put_user(i7, - (&(((struct reg_window __user *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); - - err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); - if (fenab) { - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - - fprs_write(0); - err |= __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); - if (fprs & FPRS_DL) - err |= copy_from_user(fpregs, - &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs), - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_from_user(fpregs+16, - ((unsigned long __user *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16, - (sizeof(unsigned int) * 32)); - err |= __get_user(current_thread_info()->xfsr[0], - &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); - err |= __get_user(current_thread_info()->gsr[0], - &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); - regs->tstate &= ~TSTATE_PEF; - } - if (err) - goto do_sigsegv; - - return; -do_sigsegv: - force_sig(SIGSEGV, current); -} - -asmlinkage void sparc64_get_context(struct pt_regs *regs) -{ - struct ucontext __user *ucp = (struct ucontext __user *) - regs->u_regs[UREG_I0]; - mc_gregset_t __user *grp; - mcontext_t __user *mcp; - unsigned long fp, i7; - unsigned char fenab; - int err; - - synchronize_user_stack(); - if (get_thread_wsaved() || clear_user(ucp, sizeof(*ucp))) - goto do_sigsegv; - -#if 1 - fenab = 0; /* IMO get_context is like any other system call, thus modifies FPU state -jj */ -#else - fenab = (current_thread_info()->fpsaved[0] & FPRS_FEF); -#endif - - mcp = &ucp->uc_mcontext; - grp = &mcp->mc_gregs; - - /* Skip over the trap instruction, first. */ - if (test_thread_flag(TIF_32BIT)) { - regs->tpc = (regs->tnpc & 0xffffffff); - regs->tnpc = (regs->tnpc + 4) & 0xffffffff; - } else { - regs->tpc = regs->tnpc; - regs->tnpc += 4; - } - err = 0; - if (_NSIG_WORDS == 1) - err |= __put_user(current->blocked.sig[0], - (unsigned long __user *)&ucp->uc_sigmask); - else - err |= __copy_to_user(&ucp->uc_sigmask, ¤t->blocked, - sizeof(sigset_t)); - - err |= __put_user(regs->tstate, &((*grp)[MC_TSTATE])); - err |= __put_user(regs->tpc, &((*grp)[MC_PC])); - err |= __put_user(regs->tnpc, &((*grp)[MC_NPC])); - err |= __put_user(regs->y, &((*grp)[MC_Y])); - err |= __put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1])); - err |= __put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2])); - err |= __put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3])); - err |= __put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4])); - err |= __put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5])); - err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6])); - err |= __put_user(regs->u_regs[UREG_G7], &((*grp)[MC_G7])); - err |= __put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0])); - err |= __put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1])); - err |= __put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2])); - err |= __put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3])); - err |= __put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4])); - err |= __put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5])); - err |= __put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6])); - err |= __put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7])); - - err |= __get_user(fp, - (&(((struct reg_window __user *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); - err |= __get_user(i7, - (&(((struct reg_window __user *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); - err |= __put_user(fp, &(mcp->mc_fp)); - err |= __put_user(i7, &(mcp->mc_i7)); - - err |= __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab)); - if (fenab) { - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - - fprs = current_thread_info()->fpsaved[0]; - if (fprs & FPRS_DL) - err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs, - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_to_user( - ((unsigned long __user *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16, - (sizeof(unsigned int) * 32)); - err |= __put_user(current_thread_info()->xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr)); - err |= __put_user(current_thread_info()->gsr[0], &(mcp->mc_fpregs.mcfpu_gsr)); - err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs)); - } - if (err) - goto do_sigsegv; - - return; -do_sigsegv: - force_sig(SIGSEGV, current); -} - -struct rt_signal_frame { - struct sparc_stackf ss; - siginfo_t info; - struct pt_regs regs; - __siginfo_fpu_t __user *fpu_save; - stack_t stack; - sigset_t mask; - __siginfo_fpu_t fpu_state; -}; - -/* Align macros */ -#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) - -static long _sigpause_common(old_sigset_t set) -{ - set &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, set); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - -asmlinkage long sys_sigpause(unsigned int set) -{ - return _sigpause_common(set); -} - -asmlinkage long sys_sigsuspend(old_sigset_t set) -{ - return _sigpause_common(set); -} - -static inline int -restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - int err; - - err = __get_user(fprs, &fpu->si_fprs); - fprs_write(0); - regs->tstate &= ~TSTATE_PEF; - if (fprs & FPRS_DL) - err |= copy_from_user(fpregs, &fpu->si_float_regs[0], - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], - (sizeof(unsigned int) * 32)); - err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr); - current_thread_info()->fpsaved[0] |= fprs; - return err; -} - -void do_rt_sigreturn(struct pt_regs *regs) -{ - struct rt_signal_frame __user *sf; - unsigned long tpc, tnpc, tstate; - __siginfo_fpu_t __user *fpu_save; - mm_segment_t old_fs; - sigset_t set; - stack_t st; - int err; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - synchronize_user_stack (); - sf = (struct rt_signal_frame __user *) - (regs->u_regs [UREG_FP] + STACK_BIAS); - - /* 1. Make sure we are not getting garbage from the user */ - if (((unsigned long) sf) & 3) - goto segv; - - err = get_user(tpc, &sf->regs.tpc); - err |= __get_user(tnpc, &sf->regs.tnpc); - if (test_thread_flag(TIF_32BIT)) { - tpc &= 0xffffffff; - tnpc &= 0xffffffff; - } - err |= ((tpc | tnpc) & 3); - - /* 2. Restore the state */ - err |= __get_user(regs->y, &sf->regs.y); - err |= __get_user(tstate, &sf->regs.tstate); - err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs)); - - /* User can only change condition codes and %asi in %tstate. */ - regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); - regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); - - err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) - err |= restore_fpu_state(regs, &sf->fpu_state); - - err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t)); - - if (err) - goto segv; - - regs->tpc = tpc; - regs->tnpc = tnpc; - - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); - set_fs(old_fs); - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return; -segv: - force_sig(SIGSEGV, current); -} - -/* Checks if the fp is valid */ -static int invalid_frame_pointer(void __user *fp, int fplen) -{ - if (((unsigned long) fp) & 7) - return 1; - return 0; -} - -static inline int -save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = (unsigned long *)(regs+1); - unsigned long fprs; - int err = 0; - - fprs = current_thread_info()->fpsaved[0]; - if (fprs & FPRS_DL) - err |= copy_to_user(&fpu->si_float_regs[0], fpregs, - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, - (sizeof(unsigned int) * 32)); - err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr); - err |= __put_user(fprs, &fpu->si_fprs); - - return err; -} - -static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) -{ - unsigned long sp; - - sp = regs->u_regs[UREG_FP] + STACK_BIAS; - - /* This is the X/Open sanctioned signal stack switching. */ - if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && - !((current->sas_ss_sp + current->sas_ss_size) & 7)) - sp = current->sas_ss_sp + current->sas_ss_size; - } - return (void __user *)(sp - framesize); -} - -static inline void -setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset, siginfo_t *info) -{ - struct rt_signal_frame __user *sf; - int sigframe_size, err; - - /* 1. Make sure everything is clean */ - synchronize_user_stack(); - save_and_clear_fpu(); - - sigframe_size = RT_ALIGNEDSZ; - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) - sigframe_size -= sizeof(__siginfo_fpu_t); - - sf = (struct rt_signal_frame __user *) - get_sigframe(ka, regs, sigframe_size); - - if (invalid_frame_pointer (sf, sigframe_size)) - goto sigill; - - if (get_thread_wsaved() != 0) - goto sigill; - - /* 2. Save the current process state */ - err = copy_to_user(&sf->regs, regs, sizeof (*regs)); - - if (current_thread_info()->fpsaved[0] & FPRS_FEF) { - err |= save_fpu_state(regs, &sf->fpu_state); - err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); - } else { - err |= __put_user(0, &sf->fpu_save); - } - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); - - err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); - - err |= copy_in_user((u64 __user *)sf, - (u64 __user *)(regs->u_regs[UREG_FP]+STACK_BIAS), - sizeof(struct reg_window)); - - if (info) - err |= copy_siginfo_to_user(&sf->info, info); - else { - err |= __put_user(signo, &sf->info.si_signo); - err |= __put_user(SI_NOINFO, &sf->info.si_code); - } - if (err) - goto sigsegv; - - /* 3. signal handler back-trampoline and parameters */ - regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; - regs->u_regs[UREG_I0] = signo; - regs->u_regs[UREG_I1] = (unsigned long) &sf->info; - - /* The sigcontext is passed in this way because of how it - * is defined in GLIBC's /usr/include/bits/sigcontext.h - * for sparc64. It includes the 128 bytes of siginfo_t. - */ - regs->u_regs[UREG_I2] = (unsigned long) &sf->info; - - /* 5. signal handler */ - regs->tpc = (unsigned long) ka->sa.sa_handler; - regs->tnpc = (regs->tpc + 4); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - /* 4. return to kernel instructions */ - regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - return; - -sigill: - do_exit(SIGILL); -sigsegv: - force_sigsegv(signo, current); -} - -static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) -{ - setup_rt_frame(ka, regs, signr, oldset, - (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NOMASK)) - sigaddset(¤t->blocked,signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); -} - -static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, - struct sigaction *sa) -{ - switch (regs->u_regs[UREG_I0]) { - case ERESTART_RESTARTBLOCK: - case ERESTARTNOHAND: - no_system_call_restart: - regs->u_regs[UREG_I0] = EINTR; - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - break; - case ERESTARTSYS: - if (!(sa->sa_flags & SA_RESTART)) - goto no_system_call_restart; - /* fallthrough */ - case ERESTARTNOINTR: - regs->u_regs[UREG_I0] = orig_i0; - regs->tpc -= 4; - regs->tnpc -= 4; - } -} - -/* Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - */ -static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall) -{ - siginfo_t info; - struct signal_deliver_cookie cookie; - struct k_sigaction ka; - int signr; - sigset_t *oldset; - - cookie.restart_syscall = restart_syscall; - cookie.orig_i0 = orig_i0; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - -#ifdef CONFIG_SPARC32_COMPAT - if (test_thread_flag(TIF_32BIT)) { - extern void do_signal32(sigset_t *, struct pt_regs *, - unsigned long, int); - do_signal32(oldset, regs, orig_i0, - cookie.restart_syscall); - return; - } -#endif - - signr = get_signal_to_deliver(&info, &ka, regs, &cookie); - if (signr > 0) { - if (cookie.restart_syscall) - syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, oldset, regs); - - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - return; - } - if (cookie.restart_syscall && - (regs->u_regs[UREG_I0] == ERESTARTNOHAND || - regs->u_regs[UREG_I0] == ERESTARTSYS || - regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { - /* replay the system call when we are done */ - regs->u_regs[UREG_I0] = cookie.orig_i0; - regs->tpc -= 4; - regs->tnpc -= 4; - } - if (cookie.restart_syscall && - regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { - regs->u_regs[UREG_G1] = __NR_restart_syscall; - regs->tpc -= 4; - regs->tnpc -= 4; - } - - /* if there's no signal to deliver, we just put the saved sigmask - * back - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } -} - -void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall, - unsigned long thread_info_flags) -{ - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) - do_signal(regs, orig_i0, restart_syscall); -} - -void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) -{ - struct signal_deliver_cookie *cp = cookie; - - if (cp->restart_syscall && - (regs->u_regs[UREG_I0] == ERESTARTNOHAND || - regs->u_regs[UREG_I0] == ERESTARTSYS || - regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { - /* replay the system call when we are done */ - regs->u_regs[UREG_I0] = cp->orig_i0; - regs->tpc -= 4; - regs->tnpc -= 4; - cp->restart_syscall = 0; - } - if (cp->restart_syscall && - regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { - regs->u_regs[UREG_G1] = __NR_restart_syscall; - regs->tpc -= 4; - regs->tnpc -= 4; - cp->restart_syscall = 0; - } -} diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c deleted file mode 100644 index 708ba9b42cd..00000000000 --- a/arch/sparc64/kernel/signal32.c +++ /dev/null @@ -1,1391 +0,0 @@ -/* $Id: signal32.c,v 1.74 2002/02/09 19:49:30 davem Exp $ - * arch/sparc64/kernel/signal32.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/errno.h> -#include <linux/wait.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/smp_lock.h> -#include <linux/binfmts.h> -#include <linux/compat.h> -#include <linux/bitops.h> - -#include <asm/uaccess.h> -#include <asm/ptrace.h> -#include <asm/svr4.h> -#include <asm/pgtable.h> -#include <asm/psrcompat.h> -#include <asm/fpumacro.h> -#include <asm/visasm.h> - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -/* Signal frames: the original one (compatible with SunOS): - * - * Set up a signal frame... Make the stack look the way SunOS - * expects it to look which is basically: - * - * ---------------------------------- <-- %sp at signal time - * Struct sigcontext - * Signal address - * Ptr to sigcontext area above - * Signal code - * The signal number itself - * One register window - * ---------------------------------- <-- New %sp - */ -struct signal_sframe32 { - struct reg_window32 sig_window; - int sig_num; - int sig_code; - /* struct sigcontext32 * */ u32 sig_scptr; - int sig_address; - struct sigcontext32 sig_context; - unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; -}; - -/* This magic should be in g_upper[0] for all upper parts - * to be valid. - */ -#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269 -typedef struct { - unsigned int g_upper[8]; - unsigned int o_upper[8]; - unsigned int asi; -} siginfo_extra_v8plus_t; - -/* - * And the new one, intended to be used for Linux applications only - * (we have enough in there to work with clone). - * All the interesting bits are in the info field. - */ -struct new_signal_frame32 { - struct sparc_stackf32 ss; - __siginfo32_t info; - /* __siginfo_fpu32_t * */ u32 fpu_save; - unsigned int insns[2]; - unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; - unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ - /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ - siginfo_extra_v8plus_t v8plus; - __siginfo_fpu_t fpu_state; -}; - -typedef struct compat_siginfo{ - int si_signo; - int si_errno; - int si_code; - - union { - int _pad[SI_PAD_SIZE32]; - - /* kill() */ - struct { - compat_pid_t _pid; /* sender's pid */ - unsigned int _uid; /* sender's uid */ - } _kill; - - /* POSIX.1b timers */ - struct { - compat_timer_t _tid; /* timer id */ - int _overrun; /* overrun count */ - compat_sigval_t _sigval; /* same as below */ - int _sys_private; /* not to be passed to user */ - } _timer; - - /* POSIX.1b signals */ - struct { - compat_pid_t _pid; /* sender's pid */ - unsigned int _uid; /* sender's uid */ - compat_sigval_t _sigval; - } _rt; - - /* SIGCHLD */ - struct { - compat_pid_t _pid; /* which child */ - unsigned int _uid; /* sender's uid */ - int _status; /* exit code */ - compat_clock_t _utime; - compat_clock_t _stime; - } _sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */ - struct { - u32 _addr; /* faulting insn/memory ref. */ - int _trapno; - } _sigfault; - - /* SIGPOLL */ - struct { - int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ - int _fd; - } _sigpoll; - } _sifields; -}compat_siginfo_t; - -struct rt_signal_frame32 { - struct sparc_stackf32 ss; - compat_siginfo_t info; - struct pt_regs32 regs; - compat_sigset_t mask; - /* __siginfo_fpu32_t * */ u32 fpu_save; - unsigned int insns[2]; - stack_t32 stack; - unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ - /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ - siginfo_extra_v8plus_t v8plus; - __siginfo_fpu_t fpu_state; -}; - -/* Align macros */ -#define SF_ALIGNEDSZ (((sizeof(struct signal_sframe32) + 7) & (~7))) -#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7))) -#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) - -int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) -{ - int err; - - if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) - return -EFAULT; - - /* If you change siginfo_t structure, please be sure - this code is fixed accordingly. - It should never copy any pad contained in the structure - to avoid security leaks, but must copy the generic - 3 ints plus the relevant union member. - This routine must convert siginfo from 64bit to 32bit as well - at the same time. */ - err = __put_user(from->si_signo, &to->si_signo); - err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); - if (from->si_code < 0) - err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); - else { - switch (from->si_code >> 16) { - case __SI_TIMER >> 16: - err |= __put_user(from->si_tid, &to->si_tid); - err |= __put_user(from->si_overrun, &to->si_overrun); - err |= __put_user(from->si_int, &to->si_int); - break; - case __SI_CHLD >> 16: - err |= __put_user(from->si_utime, &to->si_utime); - err |= __put_user(from->si_stime, &to->si_stime); - err |= __put_user(from->si_status, &to->si_status); - default: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; - case __SI_FAULT >> 16: - err |= __put_user(from->si_trapno, &to->si_trapno); - err |= __put_user((unsigned long)from->si_addr, &to->si_addr); - break; - case __SI_POLL >> 16: - err |= __put_user(from->si_band, &to->si_band); - err |= __put_user(from->si_fd, &to->si_fd); - break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user(from->si_int, &to->si_int); - break; - } - } - return err; -} - -/* CAUTION: This is just a very minimalist implementation for the - * sake of compat_sys_rt_sigqueueinfo() - */ -int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) -{ - if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t))) - return -EFAULT; - - if (copy_from_user(to, from, 3*sizeof(int)) || - copy_from_user(to->_sifields._pad, from->_sifields._pad, - SI_PAD_SIZE)) - return -EFAULT; - - return 0; -} - -static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - int err; - - err = __get_user(fprs, &fpu->si_fprs); - fprs_write(0); - regs->tstate &= ~TSTATE_PEF; - if (fprs & FPRS_DL) - err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32)); - err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr); - current_thread_info()->fpsaved[0] |= fprs; - return err; -} - -void do_new_sigreturn32(struct pt_regs *regs) -{ - struct new_signal_frame32 __user *sf; - unsigned int psr; - unsigned pc, npc, fpu_save; - sigset_t set; - unsigned seta[_COMPAT_NSIG_WORDS]; - int err, i; - - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - sf = (struct new_signal_frame32 __user *) regs->u_regs[UREG_FP]; - - /* 1. Make sure we are not getting garbage from the user */ - if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || - (((unsigned long) sf) & 3)) - goto segv; - - get_user(pc, &sf->info.si_regs.pc); - __get_user(npc, &sf->info.si_regs.npc); - - if ((pc | npc) & 3) - goto segv; - - if (test_thread_flag(TIF_32BIT)) { - pc &= 0xffffffff; - npc &= 0xffffffff; - } - regs->tpc = pc; - regs->tnpc = npc; - - /* 2. Restore the state */ - err = __get_user(regs->y, &sf->info.si_regs.y); - err |= __get_user(psr, &sf->info.si_regs.psr); - - for (i = UREG_G1; i <= UREG_I7; i++) - err |= __get_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]); - if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) { - err |= __get_user(i, &sf->v8plus.g_upper[0]); - if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) { - unsigned long asi; - - for (i = UREG_G1; i <= UREG_I7; i++) - err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); - err |= __get_user(asi, &sf->v8plus.asi); - regs->tstate &= ~TSTATE_ASI; - regs->tstate |= ((asi & 0xffUL) << 24UL); - } - } - - /* User can only change condition codes in %tstate. */ - regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); - regs->tstate |= psr_to_tstate_icc(psr); - - err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) - err |= restore_fpu_state32(regs, &sf->fpu_state); - err |= __get_user(seta[0], &sf->info.si_mask); - err |= copy_from_user(seta+1, &sf->extramask, - (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); - if (err) - goto segv; - switch (_NSIG_WORDS) { - case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32); - case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32); - case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32); - case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return; - -segv: - force_sig(SIGSEGV, current); -} - -asmlinkage void do_sigreturn32(struct pt_regs *regs) -{ - struct sigcontext32 __user *scptr; - unsigned int pc, npc, psr; - sigset_t set; - unsigned int seta[_COMPAT_NSIG_WORDS]; - int err; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - synchronize_user_stack(); - if (test_thread_flag(TIF_NEWSIGNALS)) { - do_new_sigreturn32(regs); - return; - } - - scptr = (struct sigcontext32 __user *) - (regs->u_regs[UREG_I0] & 0x00000000ffffffffUL); - /* Check sanity of the user arg. */ - if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext32)) || - (((unsigned long) scptr) & 3)) - goto segv; - - err = __get_user(pc, &scptr->sigc_pc); - err |= __get_user(npc, &scptr->sigc_npc); - - if ((pc | npc) & 3) - goto segv; /* Nice try. */ - - err |= __get_user(seta[0], &scptr->sigc_mask); - /* Note that scptr + 1 points to extramask */ - err |= copy_from_user(seta+1, scptr + 1, - (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); - if (err) - goto segv; - switch (_NSIG_WORDS) { - case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32); - case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32); - case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32); - case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (test_thread_flag(TIF_32BIT)) { - pc &= 0xffffffff; - npc &= 0xffffffff; - } - regs->tpc = pc; - regs->tnpc = npc; - err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp); - err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0); - err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1); - - /* User can only change condition codes in %tstate. */ - err |= __get_user(psr, &scptr->sigc_psr); - if (err) - goto segv; - regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); - regs->tstate |= psr_to_tstate_icc(psr); - return; - -segv: - force_sig(SIGSEGV, current); -} - -asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) -{ - struct rt_signal_frame32 __user *sf; - unsigned int psr, pc, npc, fpu_save, u_ss_sp; - mm_segment_t old_fs; - sigset_t set; - compat_sigset_t seta; - stack_t st; - int err, i; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - synchronize_user_stack(); - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP]; - - /* 1. Make sure we are not getting garbage from the user */ - if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || - (((unsigned long) sf) & 3)) - goto segv; - - get_user(pc, &sf->regs.pc); - __get_user(npc, &sf->regs.npc); - - if ((pc | npc) & 3) - goto segv; - - if (test_thread_flag(TIF_32BIT)) { - pc &= 0xffffffff; - npc &= 0xffffffff; - } - regs->tpc = pc; - regs->tnpc = npc; - - /* 2. Restore the state */ - err = __get_user(regs->y, &sf->regs.y); - err |= __get_user(psr, &sf->regs.psr); - - for (i = UREG_G1; i <= UREG_I7; i++) - err |= __get_user(regs->u_regs[i], &sf->regs.u_regs[i]); - if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) { - err |= __get_user(i, &sf->v8plus.g_upper[0]); - if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) { - unsigned long asi; - - for (i = UREG_G1; i <= UREG_I7; i++) - err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); - err |= __get_user(asi, &sf->v8plus.asi); - regs->tstate &= ~TSTATE_ASI; - regs->tstate |= ((asi & 0xffUL) << 24UL); - } - } - - /* User can only change condition codes in %tstate. */ - regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); - regs->tstate |= psr_to_tstate_icc(psr); - - err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) - err |= restore_fpu_state32(regs, &sf->fpu_state); - err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t)); - err |= __get_user(u_ss_sp, &sf->stack.ss_sp); - st.ss_sp = compat_ptr(u_ss_sp); - err |= __get_user(st.ss_flags, &sf->stack.ss_flags); - err |= __get_user(st.ss_size, &sf->stack.ss_size); - if (err) - goto segv; - - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf); - set_fs(old_fs); - - switch (_NSIG_WORDS) { - case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32); - case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32); - case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32); - case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return; -segv: - force_sig(SIGSEGV, current); -} - -/* Checks if the fp is valid */ -static int invalid_frame_pointer(void __user *fp, int fplen) -{ - if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen) - return 1; - return 0; -} - -static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) -{ - unsigned long sp; - - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - sp = regs->u_regs[UREG_FP]; - - /* This is the X/Open sanctioned signal stack switching. */ - if (sa->sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) - sp = current->sas_ss_sp + current->sas_ss_size; - } - return (void __user *)(sp - framesize); -} - -static void -setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info) -{ - struct signal_sframe32 __user *sframep; - struct sigcontext32 __user *sc; - unsigned int seta[_COMPAT_NSIG_WORDS]; - int err = 0; - void __user *sig_address; - int sig_code; - unsigned long pc = regs->tpc; - unsigned long npc = regs->tnpc; - unsigned int psr; - - if (test_thread_flag(TIF_32BIT)) { - pc &= 0xffffffff; - npc &= 0xffffffff; - } - - synchronize_user_stack(); - save_and_clear_fpu(); - - sframep = (struct signal_sframe32 __user *) - get_sigframe(sa, regs, SF_ALIGNEDSZ); - if (invalid_frame_pointer(sframep, sizeof(*sframep))){ - /* Don't change signal code and address, so that - * post mortem debuggers can have a look. - */ - do_exit(SIGILL); - } - - sc = &sframep->sig_context; - - /* We've already made sure frame pointer isn't in kernel space... */ - err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), - &sc->sigc_onstack); - - switch (_NSIG_WORDS) { - case 4: seta[7] = (oldset->sig[3] >> 32); - seta[6] = oldset->sig[3]; - case 3: seta[5] = (oldset->sig[2] >> 32); - seta[4] = oldset->sig[2]; - case 2: seta[3] = (oldset->sig[1] >> 32); - seta[2] = oldset->sig[1]; - case 1: seta[1] = (oldset->sig[0] >> 32); - seta[0] = oldset->sig[0]; - } - err |= __put_user(seta[0], &sc->sigc_mask); - err |= __copy_to_user(sframep->extramask, seta + 1, - (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); - err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); - err |= __put_user(pc, &sc->sigc_pc); - err |= __put_user(npc, &sc->sigc_npc); - psr = tstate_to_psr(regs->tstate); - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &sc->sigc_psr); - err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); - err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - err |= __put_user(get_thread_wsaved(), &sc->sigc_oswins); - - err |= copy_in_user((u32 __user *)sframep, - (u32 __user *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); - - set_thread_wsaved(0); /* So process is allowed to execute. */ - err |= __put_user(signr, &sframep->sig_num); - sig_address = NULL; - sig_code = 0; - if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) { - sig_address = info->si_addr; - switch (signr) { - case SIGSEGV: - switch (info->si_code) { - case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break; - default: sig_code = SUBSIG_PROTECTION; break; - } - break; - case SIGILL: - switch (info->si_code) { - case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break; - case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break; - case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break; - default: sig_code = SUBSIG_STACK; break; - } - break; - case SIGFPE: - switch (info->si_code) { - case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break; - case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break; - case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break; - case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break; - case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break; - case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break; - case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break; - default: sig_code = SUBSIG_FPERROR; break; - } - break; - case SIGBUS: - switch (info->si_code) { - case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break; - case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break; - default: sig_code = SUBSIG_BUSTIMEOUT; break; - } - break; - case SIGEMT: - switch (info->si_code) { - case EMT_TAGOVF: sig_code = SUBSIG_TAG; break; - } - break; - case SIGSYS: - if (info->si_code == (__SI_FAULT|0x100)) { - /* See sys_sunos32.c */ - sig_code = info->si_trapno; - break; - } - default: - sig_address = NULL; - } - } - err |= __put_user(ptr_to_compat(sig_address), &sframep->sig_address); - err |= __put_user(sig_code, &sframep->sig_code); - err |= __put_user(ptr_to_compat(sc), &sframep->sig_scptr); - if (err) - goto sigsegv; - - regs->u_regs[UREG_FP] = (unsigned long) sframep; - regs->tpc = (unsigned long) sa->sa_handler; - regs->tnpc = (regs->tpc + 4); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - return; - -sigsegv: - force_sigsegv(signr, current); -} - - -static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - int err = 0; - - fprs = current_thread_info()->fpsaved[0]; - if (fprs & FPRS_DL) - err |= copy_to_user(&fpu->si_float_regs[0], fpregs, - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, - (sizeof(unsigned int) * 32)); - err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr); - err |= __put_user(fprs, &fpu->si_fprs); - - return err; -} - -static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) -{ - struct new_signal_frame32 __user *sf; - int sigframe_size; - u32 psr; - int i, err; - unsigned int seta[_COMPAT_NSIG_WORDS]; - - /* 1. Make sure everything is clean */ - synchronize_user_stack(); - save_and_clear_fpu(); - - sigframe_size = NF_ALIGNEDSZ; - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) - sigframe_size -= sizeof(__siginfo_fpu_t); - - sf = (struct new_signal_frame32 __user *) - get_sigframe(&ka->sa, regs, sigframe_size); - - if (invalid_frame_pointer(sf, sigframe_size)) - goto sigill; - - if (get_thread_wsaved() != 0) - goto sigill; - - /* 2. Save the current process state */ - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err = put_user(regs->tpc, &sf->info.si_regs.pc); - err |= __put_user(regs->tnpc, &sf->info.si_regs.npc); - err |= __put_user(regs->y, &sf->info.si_regs.y); - psr = tstate_to_psr(regs->tstate); - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &sf->info.si_regs.psr); - for (i = 0; i < 16; i++) - err |= __put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]); - err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size); - err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]); - for (i = 1; i < 16; i++) - err |= __put_user(((u32 *)regs->u_regs)[2*i], - &sf->v8plus.g_upper[i]); - err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL, - &sf->v8plus.asi); - - if (psr & PSR_EF) { - err |= save_fpu_state32(regs, &sf->fpu_state); - err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); - } else { - err |= __put_user(0, &sf->fpu_save); - } - - switch (_NSIG_WORDS) { - case 4: seta[7] = (oldset->sig[3] >> 32); - seta[6] = oldset->sig[3]; - case 3: seta[5] = (oldset->sig[2] >> 32); - seta[4] = oldset->sig[2]; - case 2: seta[3] = (oldset->sig[1] >> 32); - seta[2] = oldset->sig[1]; - case 1: seta[1] = (oldset->sig[0] >> 32); - seta[0] = oldset->sig[0]; - } - err |= __put_user(seta[0], &sf->info.si_mask); - err |= __copy_to_user(sf->extramask, seta + 1, - (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); - - err |= copy_in_user((u32 __user *)sf, - (u32 __user *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); - - if (err) - goto sigsegv; - - /* 3. signal handler back-trampoline and parameters */ - regs->u_regs[UREG_FP] = (unsigned long) sf; - regs->u_regs[UREG_I0] = signo; - regs->u_regs[UREG_I1] = (unsigned long) &sf->info; - regs->u_regs[UREG_I2] = (unsigned long) &sf->info; - - /* 4. signal handler */ - regs->tpc = (unsigned long) ka->sa.sa_handler; - regs->tnpc = (regs->tpc + 4); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* 5. return to kernel instructions */ - if (ka->ka_restorer) { - regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - } else { - /* Flush instruction space. */ - unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pud_t *pudp = pud_offset(pgdp, address); - pmd_t *pmdp = pmd_offset(pudp, address); - pte_t *ptep; - pte_t pte; - - regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - - err = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/ - err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/ - if (err) - goto sigsegv; - - preempt_disable(); - ptep = pte_offset_map(pmdp, address); - pte = *ptep; - if (pte_present(pte)) { - unsigned long page = (unsigned long) - page_address(pte_page(pte)); - - wmb(); - __asm__ __volatile__("flush %0 + %1" - : /* no outputs */ - : "r" (page), - "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - pte_unmap(ptep); - preempt_enable(); - } - return; - -sigill: - do_exit(SIGILL); -sigsegv: - force_sigsegv(signo, current); -} - -/* Setup a Solaris stack frame */ -static void -setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, - struct pt_regs *regs, int signr, sigset_t *oldset) -{ - svr4_signal_frame_t __user *sfp; - svr4_gregset_t __user *gr; - svr4_siginfo_t __user *si; - svr4_mcontext_t __user *mc; - svr4_gwindows_t __user *gw; - svr4_ucontext_t __user *uc; - svr4_sigset_t setv; - unsigned int psr; - int i, err; - - synchronize_user_stack(); - save_and_clear_fpu(); - - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - sfp = (svr4_signal_frame_t __user *) - get_sigframe(sa, regs, - sizeof(struct reg_window32) + SVR4_SF_ALIGNED); - - if (invalid_frame_pointer(sfp, sizeof(*sfp))) - do_exit(SIGILL); - - /* Start with a clean frame pointer and fill it */ - err = clear_user(sfp, sizeof(*sfp)); - - /* Setup convenience variables */ - si = &sfp->si; - uc = &sfp->uc; - gw = &sfp->gw; - mc = &uc->mcontext; - gr = &mc->greg; - - /* FIXME: where am I supposed to put this? - * sc->sigc_onstack = old_status; - * anyways, it does not look like it is used for anything at all. - */ - setv.sigbits[0] = oldset->sig[0]; - setv.sigbits[1] = (oldset->sig[0] >> 32); - if (_NSIG_WORDS >= 2) { - setv.sigbits[2] = oldset->sig[1]; - setv.sigbits[3] = (oldset->sig[1] >> 32); - err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); - } else - err |= __copy_to_user(&uc->sigmask, &setv, - 2 * sizeof(unsigned int)); - - /* Store registers */ - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err |= __put_user(regs->tpc, &((*gr)[SVR4_PC])); - err |= __put_user(regs->tnpc, &((*gr)[SVR4_NPC])); - psr = tstate_to_psr(regs->tstate); - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &((*gr)[SVR4_PSR])); - err |= __put_user(regs->y, &((*gr)[SVR4_Y])); - - /* Copy g[1..7] and o[0..7] registers */ - for (i = 0; i < 7; i++) - err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); - for (i = 0; i < 8; i++) - err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &uc->stack.sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - err |= __put_user(current->sas_ss_size, &uc->stack.size); - - /* Save the currently window file: */ - - /* 1. Link sfp->uc->gwins to our windows */ - err |= __put_user(ptr_to_compat(gw), &mc->gwin); - - /* 2. Number of windows to restore at setcontext (): */ - err |= __put_user(get_thread_wsaved(), &gw->count); - - /* 3. We just pay attention to the gw->count field on setcontext */ - set_thread_wsaved(0); /* So process is allowed to execute. */ - - /* Setup the signal information. Solaris expects a bunch of - * information to be passed to the signal handler, we don't provide - * that much currently, should use siginfo. - */ - err |= __put_user(signr, &si->siginfo.signo); - err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); - if (err) - goto sigsegv; - - regs->u_regs[UREG_FP] = (unsigned long) sfp; - regs->tpc = (unsigned long) sa->sa_handler; - regs->tnpc = (regs->tpc + 4); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* Arguments passed to signal handler */ - if (regs->u_regs[14]){ - struct reg_window32 __user *rw = (struct reg_window32 __user *) - (regs->u_regs[14] & 0x00000000ffffffffUL); - - err |= __put_user(signr, &rw->ins[0]); - err |= __put_user((u64)si, &rw->ins[1]); - err |= __put_user((u64)uc, &rw->ins[2]); - err |= __put_user((u64)sfp, &rw->ins[6]); /* frame pointer */ - if (err) - goto sigsegv; - - regs->u_regs[UREG_I0] = signr; - regs->u_regs[UREG_I1] = (u32)(u64) si; - regs->u_regs[UREG_I2] = (u32)(u64) uc; - } - return; - -sigsegv: - force_sigsegv(signr, current); -} - -asmlinkage int -svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs) -{ - svr4_gregset_t __user *gr; - svr4_mcontext_t __user *mc; - svr4_sigset_t setv; - int i, err; - u32 psr; - - synchronize_user_stack(); - save_and_clear_fpu(); - - if (get_thread_wsaved()) - do_exit(SIGSEGV); - - err = clear_user(uc, sizeof(*uc)); - - /* Setup convenience variables */ - mc = &uc->mcontext; - gr = &mc->greg; - - setv.sigbits[0] = current->blocked.sig[0]; - setv.sigbits[1] = (current->blocked.sig[0] >> 32); - if (_NSIG_WORDS >= 2) { - setv.sigbits[2] = current->blocked.sig[1]; - setv.sigbits[3] = (current->blocked.sig[1] >> 32); - err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); - } else - err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned)); - - /* Store registers */ - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err |= __put_user(regs->tpc, &uc->mcontext.greg[SVR4_PC]); - err |= __put_user(regs->tnpc, &uc->mcontext.greg[SVR4_NPC]); - - psr = tstate_to_psr(regs->tstate) & ~PSR_EF; - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &uc->mcontext.greg[SVR4_PSR]); - - err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]); - - /* Copy g[1..7] and o[0..7] registers */ - for (i = 0; i < 7; i++) - err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); - for (i = 0; i < 8; i++) - err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &uc->stack.sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - err |= __put_user(current->sas_ss_size, &uc->stack.size); - - /* The register file is not saved - * we have already stuffed all of it with sync_user_stack - */ - return (err ? -EFAULT : 0); -} - - -/* Set the context for a svr4 application, this is Solaris way to sigreturn */ -asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs) -{ - svr4_gregset_t __user *gr; - mm_segment_t old_fs; - u32 pc, npc, psr, u_ss_sp; - sigset_t set; - svr4_sigset_t setv; - int i, err; - stack_t st; - - /* Fixme: restore windows, or is this already taken care of in - * svr4_setup_frame when sync_user_windows is done? - */ - flush_user_windows(); - - if (get_thread_wsaved()) - goto sigsegv; - - if (((unsigned long) c) & 3){ - printk("Unaligned structure passed\n"); - goto sigsegv; - } - - if (!__access_ok(c, sizeof(*c))) { - /* Miguel, add nice debugging msg _here_. ;-) */ - goto sigsegv; - } - - /* Check for valid PC and nPC */ - gr = &c->mcontext.greg; - err = __get_user(pc, &((*gr)[SVR4_PC])); - err |= __get_user(npc, &((*gr)[SVR4_NPC])); - if ((pc | npc) & 3) - goto sigsegv; - - /* Retrieve information from passed ucontext */ - /* note that nPC is ored a 1, this is used to inform entry.S */ - /* that we don't want it to mess with our PC and nPC */ - - err |= copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t)); - set.sig[0] = setv.sigbits[0] | (((long)setv.sigbits[1]) << 32); - if (_NSIG_WORDS >= 2) - set.sig[1] = setv.sigbits[2] | (((long)setv.sigbits[3]) << 32); - - err |= __get_user(u_ss_sp, &c->stack.sp); - st.ss_sp = compat_ptr(u_ss_sp); - err |= __get_user(st.ss_flags, &c->stack.flags); - err |= __get_user(st.ss_size, &c->stack.size); - if (err) - goto sigsegv; - - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((stack_t __user *) &st, NULL, regs->u_regs[UREG_I6]); - set_fs(old_fs); - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - regs->tpc = pc; - regs->tnpc = npc | 1; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err |= __get_user(regs->y, &((*gr)[SVR4_Y])); - err |= __get_user(psr, &((*gr)[SVR4_PSR])); - regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); - regs->tstate |= psr_to_tstate_icc(psr); - - /* Restore g[1..7] and o[0..7] registers */ - for (i = 0; i < 7; i++) - err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); - for (i = 0; i < 8; i++) - err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); - if (err) - goto sigsegv; - - return -EINTR; -sigsegv: - return -EFAULT; -} - -static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, - unsigned long signr, sigset_t *oldset, - siginfo_t *info) -{ - struct rt_signal_frame32 __user *sf; - int sigframe_size; - u32 psr; - int i, err; - compat_sigset_t seta; - - /* 1. Make sure everything is clean */ - synchronize_user_stack(); - save_and_clear_fpu(); - - sigframe_size = RT_ALIGNEDSZ; - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) - sigframe_size -= sizeof(__siginfo_fpu_t); - - sf = (struct rt_signal_frame32 __user *) - get_sigframe(&ka->sa, regs, sigframe_size); - - if (invalid_frame_pointer(sf, sigframe_size)) - goto sigill; - - if (get_thread_wsaved() != 0) - goto sigill; - - /* 2. Save the current process state */ - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err = put_user(regs->tpc, &sf->regs.pc); - err |= __put_user(regs->tnpc, &sf->regs.npc); - err |= __put_user(regs->y, &sf->regs.y); - psr = tstate_to_psr(regs->tstate); - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &sf->regs.psr); - for (i = 0; i < 16; i++) - err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]); - err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size); - err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]); - for (i = 1; i < 16; i++) - err |= __put_user(((u32 *)regs->u_regs)[2*i], - &sf->v8plus.g_upper[i]); - err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL, - &sf->v8plus.asi); - - if (psr & PSR_EF) { - err |= save_fpu_state32(regs, &sf->fpu_state); - err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); - } else { - err |= __put_user(0, &sf->fpu_save); - } - - /* Update the siginfo structure. */ - err |= copy_siginfo_to_user32(&sf->info, info); - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); - - switch (_NSIG_WORDS) { - case 4: seta.sig[7] = (oldset->sig[3] >> 32); - seta.sig[6] = oldset->sig[3]; - case 3: seta.sig[5] = (oldset->sig[2] >> 32); - seta.sig[4] = oldset->sig[2]; - case 2: seta.sig[3] = (oldset->sig[1] >> 32); - seta.sig[2] = oldset->sig[1]; - case 1: seta.sig[1] = (oldset->sig[0] >> 32); - seta.sig[0] = oldset->sig[0]; - } - err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t)); - - err |= copy_in_user((u32 __user *)sf, - (u32 __user *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); - if (err) - goto sigsegv; - - /* 3. signal handler back-trampoline and parameters */ - regs->u_regs[UREG_FP] = (unsigned long) sf; - regs->u_regs[UREG_I0] = signr; - regs->u_regs[UREG_I1] = (unsigned long) &sf->info; - regs->u_regs[UREG_I2] = (unsigned long) &sf->regs; - - /* 4. signal handler */ - regs->tpc = (unsigned long) ka->sa.sa_handler; - regs->tnpc = (regs->tpc + 4); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* 5. return to kernel instructions */ - if (ka->ka_restorer) - regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - else { - /* Flush instruction space. */ - unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pud_t *pudp = pud_offset(pgdp, address); - pmd_t *pmdp = pmd_offset(pudp, address); - pte_t *ptep; - - regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - - /* mov __NR_rt_sigreturn, %g1 */ - err |= __put_user(0x82102065, &sf->insns[0]); - - /* t 0x10 */ - err |= __put_user(0x91d02010, &sf->insns[1]); - if (err) - goto sigsegv; - - preempt_disable(); - ptep = pte_offset_map(pmdp, address); - if (pte_present(*ptep)) { - unsigned long page = (unsigned long) - page_address(pte_page(*ptep)); - - wmb(); - __asm__ __volatile__("flush %0 + %1" - : /* no outputs */ - : "r" (page), - "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - pte_unmap(ptep); - preempt_enable(); - } - return; - -sigill: - do_exit(SIGILL); -sigsegv: - force_sigsegv(signr, current); -} - -static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs, - int svr4_signal) -{ - if (svr4_signal) - setup_svr4_frame32(&ka->sa, regs->tpc, regs->tnpc, - regs, signr, oldset); - else { - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame32(ka, regs, signr, oldset, info); - else if (test_thread_flag(TIF_NEWSIGNALS)) - new_setup_frame32(ka, regs, signr, oldset); - else - setup_frame32(&ka->sa, regs, signr, oldset, info); - } - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NOMASK)) - sigaddset(¤t->blocked,signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); -} - -static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, - struct sigaction *sa) -{ - switch (regs->u_regs[UREG_I0]) { - case ERESTART_RESTARTBLOCK: - case ERESTARTNOHAND: - no_system_call_restart: - regs->u_regs[UREG_I0] = EINTR; - regs->tstate |= TSTATE_ICARRY; - break; - case ERESTARTSYS: - if (!(sa->sa_flags & SA_RESTART)) - goto no_system_call_restart; - /* fallthrough */ - case ERESTARTNOINTR: - regs->u_regs[UREG_I0] = orig_i0; - regs->tpc -= 4; - regs->tnpc -= 4; - } -} - -/* Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - */ -void do_signal32(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) -{ - siginfo_t info; - struct signal_deliver_cookie cookie; - struct k_sigaction ka; - int signr; - int svr4_signal = current->personality == PER_SVR4; - - cookie.restart_syscall = restart_syscall; - cookie.orig_i0 = orig_i0; - - signr = get_signal_to_deliver(&info, &ka, regs, &cookie); - if (signr > 0) { - if (cookie.restart_syscall) - syscall_restart32(orig_i0, regs, &ka.sa); - handle_signal32(signr, &ka, &info, oldset, - regs, svr4_signal); - - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - return; - } - if (cookie.restart_syscall && - (regs->u_regs[UREG_I0] == ERESTARTNOHAND || - regs->u_regs[UREG_I0] == ERESTARTSYS || - regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { - /* replay the system call when we are done */ - regs->u_regs[UREG_I0] = cookie.orig_i0; - regs->tpc -= 4; - regs->tnpc -= 4; - } - if (cookie.restart_syscall && - regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { - regs->u_regs[UREG_G1] = __NR_restart_syscall; - regs->tpc -= 4; - regs->tnpc -= 4; - } - - /* if there's no signal to deliver, we just put the saved sigmask - * back - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } -} - -struct sigstack32 { - u32 the_stack; - int cur_status; -}; - -asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp) -{ - struct sigstack32 __user *ssptr = - (struct sigstack32 __user *)((unsigned long)(u_ssptr)); - struct sigstack32 __user *ossptr = - (struct sigstack32 __user *)((unsigned long)(u_ossptr)); - int ret = -EFAULT; - - /* First see if old state is wanted. */ - if (ossptr) { - if (put_user(current->sas_ss_sp + current->sas_ss_size, - &ossptr->the_stack) || - __put_user(on_sig_stack(sp), &ossptr->cur_status)) - goto out; - } - - /* Now see if we want to update the new state. */ - if (ssptr) { - u32 ss_sp; - - if (get_user(ss_sp, &ssptr->the_stack)) - goto out; - - /* If the current stack was set with sigaltstack, don't - * swap stacks while we are on it. - */ - ret = -EPERM; - if (current->sas_ss_sp && on_sig_stack(sp)) - goto out; - - /* Since we don't know the extent of the stack, and we don't - * track onstack-ness, but rather calculate it, we must - * presume a size. Ho hum this interface is lossy. - */ - current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ; - current->sas_ss_size = SIGSTKSZ; - } - - ret = 0; -out: - return ret; -} - -asmlinkage long do_sys32_sigaltstack(u32 ussa, u32 uossa, unsigned long sp) -{ - stack_t uss, uoss; - u32 u_ss_sp = 0; - int ret; - mm_segment_t old_fs; - stack_t32 __user *uss32 = compat_ptr(ussa); - stack_t32 __user *uoss32 = compat_ptr(uossa); - - if (ussa && (get_user(u_ss_sp, &uss32->ss_sp) || - __get_user(uss.ss_flags, &uss32->ss_flags) || - __get_user(uss.ss_size, &uss32->ss_size))) - return -EFAULT; - uss.ss_sp = compat_ptr(u_ss_sp); - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = do_sigaltstack(ussa ? (stack_t __user *) &uss : NULL, - uossa ? (stack_t __user *) &uoss : NULL, sp); - set_fs(old_fs); - if (!ret && uossa && (put_user(ptr_to_compat(uoss.ss_sp), &uoss32->ss_sp) || - __put_user(uoss.ss_flags, &uoss32->ss_flags) || - __put_user(uoss.ss_size, &uoss32->ss_size))) - return -EFAULT; - return ret; -} diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c deleted file mode 100644 index 1fb6323e65a..00000000000 --- a/arch/sparc64/kernel/smp.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* smp.c: Sparc64 SMP support. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/pagemap.h> -#include <linux/threads.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/interrupt.h> -#include <linux/kernel_stat.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/fs.h> -#include <linux/seq_file.h> -#include <linux/cache.h> -#include <linux/jiffies.h> -#include <linux/profile.h> -#include <linux/bootmem.h> - -#include <asm/head.h> -#include <asm/ptrace.h> -#include <asm/atomic.h> -#include <asm/tlbflush.h> -#include <asm/mmu_context.h> -#include <asm/cpudata.h> - -#include <asm/irq.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/oplib.h> -#include <asm/uaccess.h> -#include <asm/timer.h> -#include <asm/starfire.h> -#include <asm/tlb.h> - -extern void calibrate_delay(void); - -/* Please don't make this stuff initdata!!! --DaveM */ -static unsigned char boot_cpu_id; - -cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; -cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE; -static cpumask_t smp_commenced_mask; -static cpumask_t cpu_callout_map; - -void smp_info(struct seq_file *m) -{ - int i; - - seq_printf(m, "State:\n"); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - seq_printf(m, - "CPU%d:\t\tonline\n", i); - } -} - -void smp_bogo(struct seq_file *m) -{ - int i; - - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - seq_printf(m, - "Cpu%dBogo\t: %lu.%02lu\n" - "Cpu%dClkTck\t: %016lx\n", - i, cpu_data(i).udelay_val / (500000/HZ), - (cpu_data(i).udelay_val / (5000/HZ)) % 100, - i, cpu_data(i).clock_tick); -} - -void __init smp_store_cpu_info(int id) -{ - int cpu_node; - - /* multiplier and counter set by - smp_setup_percpu_timer() */ - cpu_data(id).udelay_val = loops_per_jiffy; - - cpu_find_by_mid(id, &cpu_node); - cpu_data(id).clock_tick = prom_getintdefault(cpu_node, - "clock-frequency", 0); - - cpu_data(id).pgcache_size = 0; - cpu_data(id).pte_cache[0] = NULL; - cpu_data(id).pte_cache[1] = NULL; - cpu_data(id).pgd_cache = NULL; - cpu_data(id).idle_volume = 1; - - cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size", - 16 * 1024); - cpu_data(id).dcache_line_size = - prom_getintdefault(cpu_node, "dcache-line-size", 32); - cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size", - 16 * 1024); - cpu_data(id).icache_line_size = - prom_getintdefault(cpu_node, "icache-line-size", 32); - cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size", - 4 * 1024 * 1024); - cpu_data(id).ecache_line_size = - prom_getintdefault(cpu_node, "ecache-line-size", 64); - printk("CPU[%d]: Caches " - "D[sz(%d):line_sz(%d)] " - "I[sz(%d):line_sz(%d)] " - "E[sz(%d):line_sz(%d)]\n", - id, - cpu_data(id).dcache_size, cpu_data(id).dcache_line_size, - cpu_data(id).icache_size, cpu_data(id).icache_line_size, - cpu_data(id).ecache_size, cpu_data(id).ecache_line_size); -} - -static void smp_setup_percpu_timer(void); - -static volatile unsigned long callin_flag = 0; - -extern void inherit_locked_prom_mappings(int save_p); - -static inline void cpu_setup_percpu_base(unsigned long cpu_id) -{ - __asm__ __volatile__("mov %0, %%g5\n\t" - "stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (__per_cpu_offset(cpu_id)), - "r" (TSB_REG), "i" (ASI_IMMU)); -} - -void __init smp_callin(void) -{ - int cpuid = hard_smp_processor_id(); - - inherit_locked_prom_mappings(0); - - __flush_tlb_all(); - - cpu_setup_percpu_base(cpuid); - - smp_setup_percpu_timer(); - - if (cheetah_pcache_forced_on) - cheetah_enable_pcache(); - - local_irq_enable(); - - calibrate_delay(); - smp_store_cpu_info(cpuid); - callin_flag = 1; - __asm__ __volatile__("membar #Sync\n\t" - "flush %%g6" : : : "memory"); - - /* Clear this or we will die instantly when we - * schedule back to this idler... - */ - current_thread_info()->new_child = 0; - - /* Attach to the address space of init_task. */ - atomic_inc(&init_mm.mm_count); - current->active_mm = &init_mm; - - while (!cpu_isset(cpuid, smp_commenced_mask)) - rmb(); - - cpu_set(cpuid, cpu_online_map); - - /* idle thread is expected to have preempt disabled */ - preempt_disable(); -} - -void cpu_panic(void) -{ - printk("CPU[%d]: Returns from cpu_idle!\n", smp_processor_id()); - panic("SMP bolixed\n"); -} - -static unsigned long current_tick_offset __read_mostly; - -/* This tick register synchronization scheme is taken entirely from - * the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit. - * - * The only change I've made is to rework it so that the master - * initiates the synchonization instead of the slave. -DaveM - */ - -#define MASTER 0 -#define SLAVE (SMP_CACHE_BYTES/sizeof(unsigned long)) - -#define NUM_ROUNDS 64 /* magic value */ -#define NUM_ITERS 5 /* likewise */ - -static DEFINE_SPINLOCK(itc_sync_lock); -static unsigned long go[SLAVE + 1]; - -#define DEBUG_TICK_SYNC 0 - -static inline long get_delta (long *rt, long *master) -{ - unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0; - unsigned long tcenter, t0, t1, tm; - unsigned long i; - - for (i = 0; i < NUM_ITERS; i++) { - t0 = tick_ops->get_tick(); - go[MASTER] = 1; - membar_storeload(); - while (!(tm = go[SLAVE])) - rmb(); - go[SLAVE] = 0; - wmb(); - t1 = tick_ops->get_tick(); - - if (t1 - t0 < best_t1 - best_t0) - best_t0 = t0, best_t1 = t1, best_tm = tm; - } - - *rt = best_t1 - best_t0; - *master = best_tm - best_t0; - - /* average best_t0 and best_t1 without overflow: */ - tcenter = (best_t0/2 + best_t1/2); - if (best_t0 % 2 + best_t1 % 2 == 2) - tcenter++; - return tcenter - best_tm; -} - -void smp_synchronize_tick_client(void) -{ - long i, delta, adj, adjust_latency = 0, done = 0; - unsigned long flags, rt, master_time_stamp, bound; -#if DEBUG_TICK_SYNC - struct { - long rt; /* roundtrip time */ - long master; /* master's timestamp */ - long diff; /* difference between midpoint and master's timestamp */ - long lat; /* estimate of itc adjustment latency */ - } t[NUM_ROUNDS]; -#endif - - go[MASTER] = 1; - - while (go[MASTER]) - rmb(); - - local_irq_save(flags); - { - for (i = 0; i < NUM_ROUNDS; i++) { - delta = get_delta(&rt, &master_time_stamp); - if (delta == 0) { - done = 1; /* let's lock on to this... */ - bound = rt; - } - - if (!done) { - if (i > 0) { - adjust_latency += -delta; - adj = -delta + adjust_latency/4; - } else - adj = -delta; - - tick_ops->add_tick(adj, current_tick_offset); - } -#if DEBUG_TICK_SYNC - t[i].rt = rt; - t[i].master = master_time_stamp; - t[i].diff = delta; - t[i].lat = adjust_latency/4; -#endif - } - } - local_irq_restore(flags); - -#if DEBUG_TICK_SYNC - for (i = 0; i < NUM_ROUNDS; i++) - printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n", - t[i].rt, t[i].master, t[i].diff, t[i].lat); -#endif - - printk(KERN_INFO "CPU %d: synchronized TICK with master CPU (last diff %ld cycles," - "maxerr %lu cycles)\n", smp_processor_id(), delta, rt); -} - -static void smp_start_sync_tick_client(int cpu); - -static void smp_synchronize_one_tick(int cpu) -{ - unsigned long flags, i; - - go[MASTER] = 0; - - smp_start_sync_tick_client(cpu); - - /* wait for client to be ready */ - while (!go[MASTER]) - rmb(); - - /* now let the client proceed into his loop */ - go[MASTER] = 0; - membar_storeload(); - - spin_lock_irqsave(&itc_sync_lock, flags); - { - for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) { - while (!go[MASTER]) - rmb(); - go[MASTER] = 0; - wmb(); - go[SLAVE] = tick_ops->get_tick(); - membar_storeload(); - } - } - spin_unlock_irqrestore(&itc_sync_lock, flags); -} - -extern unsigned long sparc64_cpu_startup; - -/* The OBP cpu startup callback truncates the 3rd arg cookie to - * 32-bits (I think) so to be safe we have it read the pointer - * contained here so we work on >4GB machines. -DaveM - */ -static struct thread_info *cpu_new_thread = NULL; - -static int __devinit smp_boot_one_cpu(unsigned int cpu) -{ - unsigned long entry = - (unsigned long)(&sparc64_cpu_startup); - unsigned long cookie = - (unsigned long)(&cpu_new_thread); - struct task_struct *p; - int timeout, ret, cpu_node; - - p = fork_idle(cpu); - callin_flag = 0; - cpu_new_thread = task_thread_info(p); - cpu_set(cpu, cpu_callout_map); - - cpu_find_by_mid(cpu, &cpu_node); - prom_startcpu(cpu_node, entry, cookie); - - for (timeout = 0; timeout < 5000000; timeout++) { - if (callin_flag) - break; - udelay(100); - } - if (callin_flag) { - ret = 0; - } else { - printk("Processor %d is stuck.\n", cpu); - cpu_clear(cpu, cpu_callout_map); - ret = -ENODEV; - } - cpu_new_thread = NULL; - - return ret; -} - -static void spitfire_xcall_helper(u64 data0, u64 data1, u64 data2, u64 pstate, unsigned long cpu) -{ - u64 result, target; - int stuck, tmp; - - if (this_is_starfire) { - /* map to real upaid */ - cpu = (((cpu & 0x3c) << 1) | - ((cpu & 0x40) >> 4) | - (cpu & 0x3)); - } - - target = (cpu << 14) | 0x70; -again: - /* Ok, this is the real Spitfire Errata #54. - * One must read back from a UDB internal register - * after writes to the UDB interrupt dispatch, but - * before the membar Sync for that write. - * So we use the high UDB control register (ASI 0x7f, - * ADDR 0x20) for the dummy read. -DaveM - */ - tmp = 0x40; - __asm__ __volatile__( - "wrpr %1, %2, %%pstate\n\t" - "stxa %4, [%0] %3\n\t" - "stxa %5, [%0+%8] %3\n\t" - "add %0, %8, %0\n\t" - "stxa %6, [%0+%8] %3\n\t" - "membar #Sync\n\t" - "stxa %%g0, [%7] %3\n\t" - "membar #Sync\n\t" - "mov 0x20, %%g1\n\t" - "ldxa [%%g1] 0x7f, %%g0\n\t" - "membar #Sync" - : "=r" (tmp) - : "r" (pstate), "i" (PSTATE_IE), "i" (ASI_INTR_W), - "r" (data0), "r" (data1), "r" (data2), "r" (target), - "r" (0x10), "0" (tmp) - : "g1"); - - /* NOTE: PSTATE_IE is still clear. */ - stuck = 100000; - do { - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (result) - : "i" (ASI_INTR_DISPATCH_STAT)); - if (result == 0) { - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : : "r" (pstate)); - return; - } - stuck -= 1; - if (stuck == 0) - break; - } while (result & 0x1); - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : : "r" (pstate)); - if (stuck == 0) { - printk("CPU[%d]: mondo stuckage result[%016lx]\n", - smp_processor_id(), result); - } else { - udelay(2); - goto again; - } -} - -static __inline__ void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask) -{ - u64 pstate; - int i; - - __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); - for_each_cpu_mask(i, mask) - spitfire_xcall_helper(data0, data1, data2, pstate, i); -} - -/* Cheetah now allows to send the whole 64-bytes of data in the interrupt - * packet, but we have no use for that. However we do take advantage of - * the new pipelining feature (ie. dispatch to multiple cpus simultaneously). - */ -static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask) -{ - u64 pstate, ver; - int nack_busy_id, is_jalapeno; - - if (cpus_empty(mask)) - return; - - /* Unfortunately, someone at Sun had the brilliant idea to make the - * busy/nack fields hard-coded by ITID number for this Ultra-III - * derivative processor. - */ - __asm__ ("rdpr %%ver, %0" : "=r" (ver)); - is_jalapeno = ((ver >> 32) == 0x003e0016); - - __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); - -retry: - __asm__ __volatile__("wrpr %0, %1, %%pstate\n\t" - : : "r" (pstate), "i" (PSTATE_IE)); - - /* Setup the dispatch data registers. */ - __asm__ __volatile__("stxa %0, [%3] %6\n\t" - "stxa %1, [%4] %6\n\t" - "stxa %2, [%5] %6\n\t" - "membar #Sync\n\t" - : /* no outputs */ - : "r" (data0), "r" (data1), "r" (data2), - "r" (0x40), "r" (0x50), "r" (0x60), - "i" (ASI_INTR_W)); - - nack_busy_id = 0; - { - int i; - - for_each_cpu_mask(i, mask) { - u64 target = (i << 14) | 0x70; - - if (!is_jalapeno) - target |= (nack_busy_id << 24); - __asm__ __volatile__( - "stxa %%g0, [%0] %1\n\t" - "membar #Sync\n\t" - : /* no outputs */ - : "r" (target), "i" (ASI_INTR_W)); - nack_busy_id++; - } - } - - /* Now, poll for completion. */ - { - u64 dispatch_stat; - long stuck; - - stuck = 100000 * nack_busy_id; - do { - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (dispatch_stat) - : "i" (ASI_INTR_DISPATCH_STAT)); - if (dispatch_stat == 0UL) { - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : : "r" (pstate)); - return; - } - if (!--stuck) - break; - } while (dispatch_stat & 0x5555555555555555UL); - - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : : "r" (pstate)); - - if ((dispatch_stat & ~(0x5555555555555555UL)) == 0) { - /* Busy bits will not clear, continue instead - * of freezing up on this cpu. - */ - printk("CPU[%d]: mondo stuckage result[%016lx]\n", - smp_processor_id(), dispatch_stat); - } else { - int i, this_busy_nack = 0; - - /* Delay some random time with interrupts enabled - * to prevent deadlock. - */ - udelay(2 * nack_busy_id); - - /* Clear out the mask bits for cpus which did not - * NACK us. - */ - for_each_cpu_mask(i, mask) { - u64 check_mask; - - if (is_jalapeno) - check_mask = (0x2UL << (2*i)); - else - check_mask = (0x2UL << - this_busy_nack); - if ((dispatch_stat & check_mask) == 0) - cpu_clear(i, mask); - this_busy_nack += 2; - } - - goto retry; - } - } -} - -/* Send cross call to all processors mentioned in MASK - * except self. - */ -static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 data2, cpumask_t mask) -{ - u64 data0 = (((u64)ctx)<<32 | (((u64)func) & 0xffffffff)); - int this_cpu = get_cpu(); - - cpus_and(mask, mask, cpu_online_map); - cpu_clear(this_cpu, mask); - - if (tlb_type == spitfire) - spitfire_xcall_deliver(data0, data1, data2, mask); - else - cheetah_xcall_deliver(data0, data1, data2, mask); - /* NOTE: Caller runs local copy on master. */ - - put_cpu(); -} - -extern unsigned long xcall_sync_tick; - -static void smp_start_sync_tick_client(int cpu) -{ - cpumask_t mask = cpumask_of_cpu(cpu); - - smp_cross_call_masked(&xcall_sync_tick, - 0, 0, 0, mask); -} - -/* Send cross call to all processors except self. */ -#define smp_cross_call(func, ctx, data1, data2) \ - smp_cross_call_masked(func, ctx, data1, data2, cpu_online_map) - -struct call_data_struct { - void (*func) (void *info); - void *info; - atomic_t finished; - int wait; -}; - -static DEFINE_SPINLOCK(call_lock); -static struct call_data_struct *call_data; - -extern unsigned long xcall_call_function; - -/* - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler or from a bottom half handler. - */ -int smp_call_function(void (*func)(void *info), void *info, - int nonatomic, int wait) -{ - struct call_data_struct data; - int cpus = num_online_cpus() - 1; - long timeout; - - if (!cpus) - return 0; - - /* Can deadlock when called with interrupts disabled */ - WARN_ON(irqs_disabled()); - - data.func = func; - data.info = info; - atomic_set(&data.finished, 0); - data.wait = wait; - - spin_lock(&call_lock); - - call_data = &data; - - smp_cross_call(&xcall_call_function, 0, 0, 0); - - /* - * Wait for other cpus to complete function or at - * least snap the call data. - */ - timeout = 1000000; - while (atomic_read(&data.finished) != cpus) { - if (--timeout <= 0) - goto out_timeout; - barrier(); - udelay(1); - } - - spin_unlock(&call_lock); - - return 0; - -out_timeout: - spin_unlock(&call_lock); - printk("XCALL: Remote cpus not responding, ncpus=%ld finished=%ld\n", - (long) num_online_cpus() - 1L, - (long) atomic_read(&data.finished)); - return 0; -} - -void smp_call_function_client(int irq, struct pt_regs *regs) -{ - void (*func) (void *info) = call_data->func; - void *info = call_data->info; - - clear_softint(1 << irq); - if (call_data->wait) { - /* let initiator proceed only after completion */ - func(info); - atomic_inc(&call_data->finished); - } else { - /* let initiator proceed after getting data */ - atomic_inc(&call_data->finished); - func(info); - } -} - -extern unsigned long xcall_flush_tlb_mm; -extern unsigned long xcall_flush_tlb_pending; -extern unsigned long xcall_flush_tlb_kernel_range; -extern unsigned long xcall_flush_tlb_all_spitfire; -extern unsigned long xcall_flush_tlb_all_cheetah; -extern unsigned long xcall_report_regs; -extern unsigned long xcall_receive_signal; - -#ifdef DCACHE_ALIASING_POSSIBLE -extern unsigned long xcall_flush_dcache_page_cheetah; -#endif -extern unsigned long xcall_flush_dcache_page_spitfire; - -#ifdef CONFIG_DEBUG_DCFLUSH -extern atomic_t dcpage_flushes; -extern atomic_t dcpage_flushes_xcall; -#endif - -static __inline__ void __local_flush_dcache_page(struct page *page) -{ -#ifdef DCACHE_ALIASING_POSSIBLE - __flush_dcache_page(page_address(page), - ((tlb_type == spitfire) && - page_mapping(page) != NULL)); -#else - if (page_mapping(page) != NULL && - tlb_type == spitfire) - __flush_icache_page(__pa(page_address(page))); -#endif -} - -void smp_flush_dcache_page_impl(struct page *page, int cpu) -{ - cpumask_t mask = cpumask_of_cpu(cpu); - int this_cpu = get_cpu(); - -#ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes); -#endif - if (cpu == this_cpu) { - __local_flush_dcache_page(page); - } else if (cpu_online(cpu)) { - void *pg_addr = page_address(page); - u64 data0; - - if (tlb_type == spitfire) { - data0 = - ((u64)&xcall_flush_dcache_page_spitfire); - if (page_mapping(page) != NULL) - data0 |= ((u64)1 << 32); - spitfire_xcall_deliver(data0, - __pa(pg_addr), - (u64) pg_addr, - mask); - } else { -#ifdef DCACHE_ALIASING_POSSIBLE - data0 = - ((u64)&xcall_flush_dcache_page_cheetah); - cheetah_xcall_deliver(data0, - __pa(pg_addr), - 0, mask); -#endif - } -#ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes_xcall); -#endif - } - - put_cpu(); -} - -void flush_dcache_page_all(struct mm_struct *mm, struct page *page) -{ - void *pg_addr = page_address(page); - cpumask_t mask = cpu_online_map; - u64 data0; - int this_cpu = get_cpu(); - - cpu_clear(this_cpu, mask); - -#ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes); -#endif - if (cpus_empty(mask)) - goto flush_self; - if (tlb_type == spitfire) { - data0 = ((u64)&xcall_flush_dcache_page_spitfire); - if (page_mapping(page) != NULL) - data0 |= ((u64)1 << 32); - spitfire_xcall_deliver(data0, - __pa(pg_addr), - (u64) pg_addr, - mask); - } else { -#ifdef DCACHE_ALIASING_POSSIBLE - data0 = ((u64)&xcall_flush_dcache_page_cheetah); - cheetah_xcall_deliver(data0, - __pa(pg_addr), - 0, mask); -#endif - } -#ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes_xcall); -#endif - flush_self: - __local_flush_dcache_page(page); - - put_cpu(); -} - -void smp_receive_signal(int cpu) -{ - cpumask_t mask = cpumask_of_cpu(cpu); - - if (cpu_online(cpu)) { - u64 data0 = (((u64)&xcall_receive_signal) & 0xffffffff); - - if (tlb_type == spitfire) - spitfire_xcall_deliver(data0, 0, 0, mask); - else - cheetah_xcall_deliver(data0, 0, 0, mask); - } -} - -void smp_receive_signal_client(int irq, struct pt_regs *regs) -{ - /* Just return, rtrap takes care of the rest. */ - clear_softint(1 << irq); -} - -void smp_report_regs(void) -{ - smp_cross_call(&xcall_report_regs, 0, 0, 0); -} - -void smp_flush_tlb_all(void) -{ - if (tlb_type == spitfire) - smp_cross_call(&xcall_flush_tlb_all_spitfire, 0, 0, 0); - else - smp_cross_call(&xcall_flush_tlb_all_cheetah, 0, 0, 0); - __flush_tlb_all(); -} - -/* We know that the window frames of the user have been flushed - * to the stack before we get here because all callers of us - * are flush_tlb_*() routines, and these run after flush_cache_*() - * which performs the flushw. - * - * The SMP TLB coherency scheme we use works as follows: - * - * 1) mm->cpu_vm_mask is a bit mask of which cpus an address - * space has (potentially) executed on, this is the heuristic - * we use to avoid doing cross calls. - * - * Also, for flushing from kswapd and also for clones, we - * use cpu_vm_mask as the list of cpus to make run the TLB. - * - * 2) TLB context numbers are shared globally across all processors - * in the system, this allows us to play several games to avoid - * cross calls. - * - * One invariant is that when a cpu switches to a process, and - * that processes tsk->active_mm->cpu_vm_mask does not have the - * current cpu's bit set, that tlb context is flushed locally. - * - * If the address space is non-shared (ie. mm->count == 1) we avoid - * cross calls when we want to flush the currently running process's - * tlb state. This is done by clearing all cpu bits except the current - * processor's in current->active_mm->cpu_vm_mask and performing the - * flush locally only. This will force any subsequent cpus which run - * this task to flush the context from the local tlb if the process - * migrates to another cpu (again). - * - * 3) For shared address spaces (threads) and swapping we bite the - * bullet for most cases and perform the cross call (but only to - * the cpus listed in cpu_vm_mask). - * - * The performance gain from "optimizing" away the cross call for threads is - * questionable (in theory the big win for threads is the massive sharing of - * address space state across processors). - */ - -/* This currently is only used by the hugetlb arch pre-fault - * hook on UltraSPARC-III+ and later when changing the pagesize - * bits of the context register for an address space. - */ -void smp_flush_tlb_mm(struct mm_struct *mm) -{ - u32 ctx = CTX_HWBITS(mm->context); - int cpu = get_cpu(); - - if (atomic_read(&mm->mm_users) == 1) { - mm->cpu_vm_mask = cpumask_of_cpu(cpu); - goto local_flush_and_out; - } - - smp_cross_call_masked(&xcall_flush_tlb_mm, - ctx, 0, 0, - mm->cpu_vm_mask); - -local_flush_and_out: - __flush_tlb_mm(ctx, SECONDARY_CONTEXT); - - put_cpu(); -} - -void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs) -{ - u32 ctx = CTX_HWBITS(mm->context); - int cpu = get_cpu(); - - if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) - mm->cpu_vm_mask = cpumask_of_cpu(cpu); - else - smp_cross_call_masked(&xcall_flush_tlb_pending, - ctx, nr, (unsigned long) vaddrs, - mm->cpu_vm_mask); - - __flush_tlb_pending(ctx, nr, vaddrs); - - put_cpu(); -} - -void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end) -{ - start &= PAGE_MASK; - end = PAGE_ALIGN(end); - if (start != end) { - smp_cross_call(&xcall_flush_tlb_kernel_range, - 0, start, end); - - __flush_tlb_kernel_range(start, end); - } -} - -/* CPU capture. */ -/* #define CAPTURE_DEBUG */ -extern unsigned long xcall_capture; - -static atomic_t smp_capture_depth = ATOMIC_INIT(0); -static atomic_t smp_capture_registry = ATOMIC_INIT(0); -static unsigned long penguins_are_doing_time; - -void smp_capture(void) -{ - int result = atomic_add_ret(1, &smp_capture_depth); - - if (result == 1) { - int ncpus = num_online_cpus(); - -#ifdef CAPTURE_DEBUG - printk("CPU[%d]: Sending penguins to jail...", - smp_processor_id()); -#endif - penguins_are_doing_time = 1; - membar_storestore_loadstore(); - atomic_inc(&smp_capture_registry); - smp_cross_call(&xcall_capture, 0, 0, 0); - while (atomic_read(&smp_capture_registry) != ncpus) - rmb(); -#ifdef CAPTURE_DEBUG - printk("done\n"); -#endif - } -} - -void smp_release(void) -{ - if (atomic_dec_and_test(&smp_capture_depth)) { -#ifdef CAPTURE_DEBUG - printk("CPU[%d]: Giving pardon to " - "imprisoned penguins\n", - smp_processor_id()); -#endif - penguins_are_doing_time = 0; - membar_storeload_storestore(); - atomic_dec(&smp_capture_registry); - } -} - -/* Imprisoned penguins run with %pil == 15, but PSTATE_IE set, so they - * can service tlb flush xcalls... - */ -extern void prom_world(int); -extern void save_alternate_globals(unsigned long *); -extern void restore_alternate_globals(unsigned long *); -void smp_penguin_jailcell(int irq, struct pt_regs *regs) -{ - unsigned long global_save[24]; - - clear_softint(1 << irq); - - preempt_disable(); - - __asm__ __volatile__("flushw"); - save_alternate_globals(global_save); - prom_world(1); - atomic_inc(&smp_capture_registry); - membar_storeload_storestore(); - while (penguins_are_doing_time) - rmb(); - restore_alternate_globals(global_save); - atomic_dec(&smp_capture_registry); - prom_world(0); - - preempt_enable(); -} - -#define prof_multiplier(__cpu) cpu_data(__cpu).multiplier -#define prof_counter(__cpu) cpu_data(__cpu).counter - -void smp_percpu_timer_interrupt(struct pt_regs *regs) -{ - unsigned long compare, tick, pstate; - int cpu = smp_processor_id(); - int user = user_mode(regs); - - /* - * Check for level 14 softint. - */ - { - unsigned long tick_mask = tick_ops->softint_mask; - - if (!(get_softint() & tick_mask)) { - extern void handler_irq(int, struct pt_regs *); - - handler_irq(14, regs); - return; - } - clear_softint(tick_mask); - } - - do { - profile_tick(CPU_PROFILING, regs); - if (!--prof_counter(cpu)) { - irq_enter(); - - if (cpu == boot_cpu_id) { - kstat_this_cpu.irqs[0]++; - timer_tick_interrupt(regs); - } - - update_process_times(user); - - irq_exit(); - - prof_counter(cpu) = prof_multiplier(cpu); - } - - /* Guarantee that the following sequences execute - * uninterrupted. - */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - compare = tick_ops->add_compare(current_tick_offset); - tick = tick_ops->get_tick(); - - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); - } while (time_after_eq(tick, compare)); -} - -static void __init smp_setup_percpu_timer(void) -{ - int cpu = smp_processor_id(); - unsigned long pstate; - - prof_counter(cpu) = prof_multiplier(cpu) = 1; - - /* Guarantee that the following sequences execute - * uninterrupted. - */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - tick_ops->init_tick(current_tick_offset); - - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); -} - -void __init smp_tick_init(void) -{ - boot_cpu_id = hard_smp_processor_id(); - current_tick_offset = timer_tick_offset; - - cpu_set(boot_cpu_id, cpu_online_map); - prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1; -} - -/* /proc/profile writes can call this, don't __init it please. */ -static DEFINE_SPINLOCK(prof_setup_lock); - -int setup_profiling_timer(unsigned int multiplier) -{ - unsigned long flags; - int i; - - if ((!multiplier) || (timer_tick_offset / multiplier) < 1000) - return -EINVAL; - - spin_lock_irqsave(&prof_setup_lock, flags); - for (i = 0; i < NR_CPUS; i++) - prof_multiplier(i) = multiplier; - current_tick_offset = (timer_tick_offset / multiplier); - spin_unlock_irqrestore(&prof_setup_lock, flags); - - return 0; -} - -void __init smp_prepare_cpus(unsigned int max_cpus) -{ - int instance, mid; - - instance = 0; - while (!cpu_find_by_instance(instance, NULL, &mid)) { - if (mid < max_cpus) - cpu_set(mid, phys_cpu_present_map); - instance++; - } - - if (num_possible_cpus() > max_cpus) { - instance = 0; - while (!cpu_find_by_instance(instance, NULL, &mid)) { - if (mid != boot_cpu_id) { - cpu_clear(mid, phys_cpu_present_map); - if (num_possible_cpus() <= max_cpus) - break; - } - instance++; - } - } - - smp_store_cpu_info(boot_cpu_id); -} - -void __devinit smp_prepare_boot_cpu(void) -{ - if (hard_smp_processor_id() >= NR_CPUS) { - prom_printf("Serious problem, boot cpu id >= NR_CPUS\n"); - prom_halt(); - } - - current_thread_info()->cpu = hard_smp_processor_id(); - - cpu_set(smp_processor_id(), cpu_online_map); - cpu_set(smp_processor_id(), phys_cpu_present_map); -} - -int __devinit __cpu_up(unsigned int cpu) -{ - int ret = smp_boot_one_cpu(cpu); - - if (!ret) { - cpu_set(cpu, smp_commenced_mask); - while (!cpu_isset(cpu, cpu_online_map)) - mb(); - if (!cpu_isset(cpu, cpu_online_map)) { - ret = -ENODEV; - } else { - smp_synchronize_one_tick(cpu); - } - } - return ret; -} - -void __init smp_cpus_done(unsigned int max_cpus) -{ - unsigned long bogosum = 0; - int i; - - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - bogosum += cpu_data(i).udelay_val; - } - printk("Total of %ld processors activated " - "(%lu.%02lu BogoMIPS).\n", - (long) num_online_cpus(), - bogosum/(500000/HZ), - (bogosum/(5000/HZ))%100); -} - -void smp_send_reschedule(int cpu) -{ - smp_receive_signal(cpu); -} - -/* This is a nop because we capture all other cpus - * anyways when making the PROM active. - */ -void smp_send_stop(void) -{ -} - -unsigned long __per_cpu_base __read_mostly; -unsigned long __per_cpu_shift __read_mostly; - -EXPORT_SYMBOL(__per_cpu_base); -EXPORT_SYMBOL(__per_cpu_shift); - -void __init setup_per_cpu_areas(void) -{ - unsigned long goal, size, i; - char *ptr; - /* Created by linker magic */ - extern char __per_cpu_start[], __per_cpu_end[]; - - /* Copy section for each CPU (we discard the original) */ - goal = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE); - -#ifdef CONFIG_MODULES - if (goal < PERCPU_ENOUGH_ROOM) - goal = PERCPU_ENOUGH_ROOM; -#endif - __per_cpu_shift = 0; - for (size = 1UL; size < goal; size <<= 1UL) - __per_cpu_shift++; - - /* Make sure the resulting __per_cpu_base value - * will fit in the 43-bit sign extended IMMU - * TSB register. - */ - ptr = __alloc_bootmem(size * NR_CPUS, PAGE_SIZE, - (unsigned long) __per_cpu_start); - - __per_cpu_base = ptr - __per_cpu_start; - - if ((__per_cpu_shift < PAGE_SHIFT) || - (__per_cpu_base & ~PAGE_MASK) || - (__per_cpu_base != (((long) __per_cpu_base << 20) >> 20))) { - prom_printf("PER_CPU: Invalid layout, " - "ptr[%p] shift[%lx] base[%lx]\n", - ptr, __per_cpu_shift, __per_cpu_base); - prom_halt(); - } - - for (i = 0; i < NR_CPUS; i++, ptr += size) - memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); - - /* Finally, load in the boot cpu's base value. - * We abuse the IMMU TSB register for trap handler - * entry and exit loading of %g5. That is why it - * has to be page aligned. - */ - cpu_setup_percpu_base(hard_smp_processor_id()); -} diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c deleted file mode 100644 index 3c06bfb92a8..00000000000 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ /dev/null @@ -1,395 +0,0 @@ -/* $Id: sparc64_ksyms.c,v 1.121 2002/02/09 19:49:31 davem Exp $ - * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -/* Tell string.h we don't want memcpy etc. as cpp defines */ -#define EXPORT_SYMTAB_STROPS -#define PROMLIB_INTERNAL - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/in6.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/fs_struct.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/socket.h> -#include <linux/syscalls.h> -#include <linux/percpu.h> -#include <linux/init.h> -#include <net/compat.h> - -#include <asm/oplib.h> -#include <asm/delay.h> -#include <asm/system.h> -#include <asm/auxio.h> -#include <asm/pgtable.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/idprom.h> -#include <asm/svr4.h> -#include <asm/elf.h> -#include <asm/head.h> -#include <asm/smp.h> -#include <asm/mostek.h> -#include <asm/ptrace.h> -#include <asm/user.h> -#include <asm/uaccess.h> -#include <asm/checksum.h> -#include <asm/fpumacro.h> -#include <asm/pgalloc.h> -#include <asm/cacheflush.h> -#ifdef CONFIG_SBUS -#include <asm/sbus.h> -#include <asm/dma.h> -#endif -#ifdef CONFIG_PCI -#include <asm/ebus.h> -#include <asm/isa.h> -#endif -#include <asm/a.out.h> -#include <asm/ns87303.h> -#include <asm/timer.h> -#include <asm/cpudata.h> -#include <asm/rwsem.h> - -struct poll { - int fd; - short events; - short revents; -}; - -extern void die_if_kernel(char *str, struct pt_regs *regs); -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); -extern void *__bzero(void *, size_t); -extern void *__memscan_zero(void *, size_t); -extern void *__memscan_generic(void *, int, size_t); -extern int __memcmp(const void *, const void *, __kernel_size_t); -extern __kernel_size_t strlen(const char *); -extern void linux_sparc_syscall(void); -extern void rtrap(void); -extern void show_regs(struct pt_regs *); -extern void solaris_syscall(void); -extern void syscall_trace(struct pt_regs *, int); -extern u32 sunos_sys_table[], sys_call_table32[]; -extern void tl0_solaris(void); -extern void sys_sigsuspend(void); -extern int svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs); -extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs); -extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); -extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); -extern long sparc32_open(const char __user * filename, int flags, int mode); -extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, - unsigned long pfn, unsigned long size, pgprot_t prot); -extern void (*prom_palette)(int); - -extern int __ashrdi3(int, int); - -extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); - -extern unsigned long phys_base; -extern unsigned long pfn_base; - -extern unsigned int sys_call_table[]; - -extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *); -extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *, - unsigned long *); -extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *, - unsigned long *, unsigned long *); -extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *, - unsigned long *, unsigned long *, unsigned long *); - -/* Per-CPU information table */ -EXPORT_PER_CPU_SYMBOL(__cpu_data); - -/* used by various drivers */ -#ifdef CONFIG_SMP -/* Out of line rw-locking implementation. */ -EXPORT_SYMBOL(__read_lock); -EXPORT_SYMBOL(__read_unlock); -EXPORT_SYMBOL(__write_lock); -EXPORT_SYMBOL(__write_unlock); -EXPORT_SYMBOL(__write_trylock); - -/* Hard IRQ locking */ -EXPORT_SYMBOL(synchronize_irq); - -#if defined(CONFIG_MCOUNT) -extern void _mcount(void); -EXPORT_SYMBOL(_mcount); -#endif - -/* CPU online map and active count. */ -EXPORT_SYMBOL(cpu_online_map); -EXPORT_SYMBOL(phys_cpu_present_map); - -EXPORT_SYMBOL(smp_call_function); -#endif /* CONFIG_SMP */ - -EXPORT_SYMBOL(sparc64_get_clock_tick); - -/* semaphores */ -EXPORT_SYMBOL(down); -EXPORT_SYMBOL(down_trylock); -EXPORT_SYMBOL(down_interruptible); -EXPORT_SYMBOL(up); - -/* RW semaphores */ -EXPORT_SYMBOL(__down_read); -EXPORT_SYMBOL(__down_read_trylock); -EXPORT_SYMBOL(__down_write); -EXPORT_SYMBOL(__down_write_trylock); -EXPORT_SYMBOL(__up_read); -EXPORT_SYMBOL(__up_write); -EXPORT_SYMBOL(__downgrade_write); - -/* Atomic counter implementation. */ -EXPORT_SYMBOL(atomic_add); -EXPORT_SYMBOL(atomic_add_ret); -EXPORT_SYMBOL(atomic_sub); -EXPORT_SYMBOL(atomic_sub_ret); -EXPORT_SYMBOL(atomic64_add); -EXPORT_SYMBOL(atomic64_add_ret); -EXPORT_SYMBOL(atomic64_sub); -EXPORT_SYMBOL(atomic64_sub_ret); - -/* Atomic bit operations. */ -EXPORT_SYMBOL(test_and_set_bit); -EXPORT_SYMBOL(test_and_clear_bit); -EXPORT_SYMBOL(test_and_change_bit); -EXPORT_SYMBOL(set_bit); -EXPORT_SYMBOL(clear_bit); -EXPORT_SYMBOL(change_bit); - -/* Bit searching */ -EXPORT_SYMBOL(find_next_bit); -EXPORT_SYMBOL(find_next_zero_bit); -EXPORT_SYMBOL(find_next_zero_le_bit); - -EXPORT_SYMBOL(ivector_table); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); - -EXPORT_SYMBOL(__flushw_user); - -EXPORT_SYMBOL(tlb_type); -EXPORT_SYMBOL(get_fb_unmapped_area); -EXPORT_SYMBOL(flush_icache_range); - -EXPORT_SYMBOL(flush_dcache_page); -#ifdef DCACHE_ALIASING_POSSIBLE -EXPORT_SYMBOL(__flush_dcache_range); -#endif - -EXPORT_SYMBOL(mostek_lock); -EXPORT_SYMBOL(mstk48t02_regs); -#ifdef CONFIG_SUN_AUXIO -EXPORT_SYMBOL(auxio_set_led); -EXPORT_SYMBOL(auxio_set_lte); -#endif -#ifdef CONFIG_SBUS -EXPORT_SYMBOL(sbus_root); -EXPORT_SYMBOL(dma_chain); -EXPORT_SYMBOL(sbus_set_sbus64); -EXPORT_SYMBOL(sbus_alloc_consistent); -EXPORT_SYMBOL(sbus_free_consistent); -EXPORT_SYMBOL(sbus_map_single); -EXPORT_SYMBOL(sbus_unmap_single); -EXPORT_SYMBOL(sbus_map_sg); -EXPORT_SYMBOL(sbus_unmap_sg); -EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_single_for_device); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); -#endif -EXPORT_SYMBOL(outsb); -EXPORT_SYMBOL(outsw); -EXPORT_SYMBOL(outsl); -EXPORT_SYMBOL(insb); -EXPORT_SYMBOL(insw); -EXPORT_SYMBOL(insl); -#ifdef CONFIG_PCI -EXPORT_SYMBOL(ebus_chain); -EXPORT_SYMBOL(isa_chain); -EXPORT_SYMBOL(pci_memspace_mask); -EXPORT_SYMBOL(pci_alloc_consistent); -EXPORT_SYMBOL(pci_free_consistent); -EXPORT_SYMBOL(pci_map_single); -EXPORT_SYMBOL(pci_unmap_single); -EXPORT_SYMBOL(pci_map_sg); -EXPORT_SYMBOL(pci_unmap_sg); -EXPORT_SYMBOL(pci_dma_sync_single_for_cpu); -EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu); -EXPORT_SYMBOL(pci_dma_supported); -#endif - -/* I/O device mmaping on Sparc64. */ -EXPORT_SYMBOL(io_remap_pfn_range); - -#ifdef CONFIG_COMPAT -/* Solaris/SunOS binary compatibility */ -EXPORT_SYMBOL(verify_compat_iovec); -#endif - -EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(pte_alloc_one_kernel); -#ifndef CONFIG_SMP -EXPORT_SYMBOL(pgt_quicklists); -#endif -EXPORT_SYMBOL(put_fs_struct); - -/* math-emu wants this */ -EXPORT_SYMBOL(die_if_kernel); - -/* Kernel thread creation. */ -EXPORT_SYMBOL(kernel_thread); - -/* prom symbols */ -EXPORT_SYMBOL(idprom); -EXPORT_SYMBOL(prom_root_node); -EXPORT_SYMBOL(prom_getchild); -EXPORT_SYMBOL(prom_getsibling); -EXPORT_SYMBOL(prom_searchsiblings); -EXPORT_SYMBOL(prom_firstprop); -EXPORT_SYMBOL(prom_nextprop); -EXPORT_SYMBOL(prom_getproplen); -EXPORT_SYMBOL(prom_getproperty); -EXPORT_SYMBOL(prom_node_has_property); -EXPORT_SYMBOL(prom_setprop); -EXPORT_SYMBOL(saved_command_line); -EXPORT_SYMBOL(prom_getname); -EXPORT_SYMBOL(prom_finddevice); -EXPORT_SYMBOL(prom_feval); -EXPORT_SYMBOL(prom_getbool); -EXPORT_SYMBOL(prom_getstring); -EXPORT_SYMBOL(prom_getint); -EXPORT_SYMBOL(prom_getintdefault); -EXPORT_SYMBOL(__prom_getchild); -EXPORT_SYMBOL(__prom_getsibling); - -/* sparc library symbols */ -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strnlen); -EXPORT_SYMBOL(__strlen_user); -EXPORT_SYMBOL(__strnlen_user); -EXPORT_SYMBOL(strcpy); -EXPORT_SYMBOL(strncpy); -EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strncat); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(strpbrk); -EXPORT_SYMBOL(strstr); - -#ifdef CONFIG_SOLARIS_EMUL_MODULE -EXPORT_SYMBOL(linux_sparc_syscall); -EXPORT_SYMBOL(rtrap); -EXPORT_SYMBOL(show_regs); -EXPORT_SYMBOL(solaris_syscall); -EXPORT_SYMBOL(syscall_trace); -EXPORT_SYMBOL(sunos_sys_table); -EXPORT_SYMBOL(sys_call_table32); -EXPORT_SYMBOL(tl0_solaris); -EXPORT_SYMBOL(sys_sigsuspend); -EXPORT_SYMBOL(sys_getppid); -EXPORT_SYMBOL(sys_getpid); -EXPORT_SYMBOL(sys_geteuid); -EXPORT_SYMBOL(sys_getuid); -EXPORT_SYMBOL(sys_getegid); -EXPORT_SYMBOL(sys_getgid); -EXPORT_SYMBOL(svr4_getcontext); -EXPORT_SYMBOL(svr4_setcontext); -EXPORT_SYMBOL(compat_sys_ioctl); -EXPORT_SYMBOL(sparc32_open); -EXPORT_SYMBOL(sys_close); -#endif - -/* Special internal versions of library functions. */ -EXPORT_SYMBOL(_clear_page); -EXPORT_SYMBOL(clear_user_page); -EXPORT_SYMBOL(copy_user_page); -EXPORT_SYMBOL(__bzero); -EXPORT_SYMBOL(__memscan_zero); -EXPORT_SYMBOL(__memscan_generic); -EXPORT_SYMBOL(__memcmp); -EXPORT_SYMBOL(__memset); -EXPORT_SYMBOL(memchr); - -EXPORT_SYMBOL(csum_partial); -EXPORT_SYMBOL(csum_partial_copy_nocheck); -EXPORT_SYMBOL(__csum_partial_copy_from_user); -EXPORT_SYMBOL(__csum_partial_copy_to_user); -EXPORT_SYMBOL(ip_fast_csum); - -/* Moving data to/from/in userspace. */ -EXPORT_SYMBOL(___copy_to_user); -EXPORT_SYMBOL(___copy_from_user); -EXPORT_SYMBOL(___copy_in_user); -EXPORT_SYMBOL(copy_to_user_fixup); -EXPORT_SYMBOL(copy_from_user_fixup); -EXPORT_SYMBOL(copy_in_user_fixup); -EXPORT_SYMBOL(__strncpy_from_user); -EXPORT_SYMBOL(__bzero_noasi); - -/* Various address conversion macros use this. */ -EXPORT_SYMBOL(phys_base); -EXPORT_SYMBOL(pfn_base); -EXPORT_SYMBOL(sparc64_valid_addr_bitmap); -EXPORT_SYMBOL(page_to_pfn); -EXPORT_SYMBOL(pfn_to_page); - -/* No version information on this, heavily used in inline asm, - * and will always be 'void __ret_efault(void)'. - */ -EXPORT_SYMBOL(__ret_efault); - -/* No version information on these, as gcc produces such symbols. */ -EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(strncmp); - -/* Delay routines. */ -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__ndelay); -EXPORT_SYMBOL(__const_udelay); -EXPORT_SYMBOL(__delay); - -void VISenter(void); -/* RAID code needs this */ -EXPORT_SYMBOL(VISenter); - -/* for input/keybdev */ -EXPORT_SYMBOL(sun_do_break); -EXPORT_SYMBOL(serial_console); -EXPORT_SYMBOL(stop_a_enabled); - -#ifdef CONFIG_DEBUG_BUGVERBOSE -EXPORT_SYMBOL(do_BUG); -#endif - -/* for ns8703 */ -EXPORT_SYMBOL(ns87303_lock); - -/* for solaris compat module */ -EXPORT_SYMBOL_GPL(sys_call_table); - -EXPORT_SYMBOL(tick_ops); - -EXPORT_SYMBOL(xor_vis_2); -EXPORT_SYMBOL(xor_vis_3); -EXPORT_SYMBOL(xor_vis_4); -EXPORT_SYMBOL(xor_vis_5); - -EXPORT_SYMBOL(prom_palette); diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c deleted file mode 100644 index ae859d40771..00000000000 --- a/arch/sparc64/kernel/starfire.c +++ /dev/null @@ -1,123 +0,0 @@ -/* $Id: starfire.c,v 1.10 2001/04/14 21:13:45 davem Exp $ - * starfire.c: Starfire/E10000 support. - * - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 2000 Anton Blanchard (anton@samba.org) - */ - -#include <linux/kernel.h> -#include <linux/slab.h> - -#include <asm/page.h> -#include <asm/oplib.h> -#include <asm/smp.h> -#include <asm/upa.h> -#include <asm/starfire.h> - -/* - * A few places around the kernel check this to see if - * they need to call us to do things in a Starfire specific - * way. - */ -int this_is_starfire = 0; - -void check_if_starfire(void) -{ - int ssnode = prom_finddevice("/ssp-serial"); - if (ssnode != 0 && ssnode != -1) - this_is_starfire = 1; -} - -void starfire_cpu_setup(void) -{ - /* Currently, nothing to do. */ -} - -int starfire_hard_smp_processor_id(void) -{ - return upa_readl(0x1fff40000d0UL); -} - -/* - * Each Starfire board has 32 registers which perform translation - * and delivery of traditional interrupt packets into the extended - * Starfire hardware format. Essentially UPAID's now have 2 more - * bits than in all previous Sun5 systems. - */ -struct starfire_irqinfo { - unsigned long imap_slots[32]; - unsigned long tregs[32]; - struct starfire_irqinfo *next; - int upaid, hwmid; -}; - -static struct starfire_irqinfo *sflist = NULL; - -/* Beam me up Scott(McNeil)y... */ -void *starfire_hookup(int upaid) -{ - struct starfire_irqinfo *p; - unsigned long treg_base, hwmid, i; - - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) { - prom_printf("starfire_hookup: No memory, this is insane.\n"); - prom_halt(); - } - treg_base = 0x100fc000000UL; - hwmid = ((upaid & 0x3c) << 1) | - ((upaid & 0x40) >> 4) | - (upaid & 0x3); - p->hwmid = hwmid; - treg_base += (hwmid << 33UL); - treg_base += 0x200UL; - for (i = 0; i < 32; i++) { - p->imap_slots[i] = 0UL; - p->tregs[i] = treg_base + (i * 0x10UL); - /* Lets play it safe and not overwrite existing mappings */ - if (upa_readl(p->tregs[i]) != 0) - p->imap_slots[i] = 0xdeadbeaf; - } - p->upaid = upaid; - p->next = sflist; - sflist = p; - - return (void *) p; -} - -unsigned int starfire_translate(unsigned long imap, - unsigned int upaid) -{ - struct starfire_irqinfo *p; - unsigned int bus_hwmid; - unsigned int i; - - bus_hwmid = (((unsigned long)imap) >> 33) & 0x7f; - for (p = sflist; p != NULL; p = p->next) - if (p->hwmid == bus_hwmid) - break; - if (p == NULL) { - prom_printf("XFIRE: Cannot find irqinfo for imap %016lx\n", - ((unsigned long)imap)); - prom_halt(); - } - for (i = 0; i < 32; i++) { - if (p->imap_slots[i] == imap || - p->imap_slots[i] == 0UL) - break; - } - if (i == 32) { - printk("starfire_translate: Are you kidding me?\n"); - panic("Lucy in the sky...."); - } - p->imap_slots[i] = imap; - - /* map to real upaid */ - upaid = (((upaid & 0x3c) << 1) | - ((upaid & 0x40) >> 4) | - (upaid & 0x3)); - - upa_writel(upaid, p->tregs[i]); - - return i; -} diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c deleted file mode 100644 index 3f619ead22c..00000000000 --- a/arch/sparc64/kernel/sunos_ioctl32.c +++ /dev/null @@ -1,275 +0,0 @@ -/* $Id: sunos_ioctl32.c,v 1.11 2000/07/30 23:12:24 davem Exp $ - * sunos_ioctl32.c: SunOS ioctl compatibility on sparc64. - * - * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <asm/uaccess.h> - -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/termios.h> -#include <linux/ioctl.h> -#include <linux/route.h> -#include <linux/sockios.h> -#include <linux/if.h> -#include <linux/netdevice.h> -#include <linux/if_arp.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/syscalls.h> -#include <linux/compat.h> - -#define SUNOS_NR_OPEN 256 - -struct rtentry32 { - u32 rt_pad1; - struct sockaddr rt_dst; /* target address */ - struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ - struct sockaddr rt_genmask; /* target network mask (IP) */ - unsigned short rt_flags; - short rt_pad2; - u32 rt_pad3; - unsigned char rt_tos; - unsigned char rt_class; - short rt_pad4; - short rt_metric; /* +1 for binary compatibility! */ - /* char * */ u32 rt_dev; /* forcing the device at add */ - u32 rt_mtu; /* per route MTU/Window */ - u32 rt_window; /* Window clamping */ - unsigned short rt_irtt; /* Initial RTT */ - -}; - -struct ifmap32 { - u32 mem_start; - u32 mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; -}; - -struct ifreq32 { -#define IFHWADDRLEN 6 -#define IFNAMSIZ 16 - union { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_ivalue; - int ifru_mtu; - struct ifmap32 ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - compat_caddr_t ifru_data; - } ifr_ifru; -}; - -struct ifconf32 { - int ifc_len; /* size of buffer */ - compat_caddr_t ifcbuf; -}; - -extern asmlinkage int compat_sys_ioctl(unsigned int, unsigned int, u32); - -asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg) -{ - int ret = -EBADF; - - if(fd >= SUNOS_NR_OPEN) - goto out; - if(!fcheck(fd)) - goto out; - - if(cmd == TIOCSETD) { - mm_segment_t old_fs = get_fs(); - int __user *p; - int ntty = N_TTY; - int tmp; - - p = (int __user *) (unsigned long) arg; - ret = -EFAULT; - if(get_user(tmp, p)) - goto out; - if(tmp == 2) { - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long) &ntty); - set_fs(old_fs); - ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); - goto out; - } - } - if(cmd == TIOCNOTTY) { - ret = sys_setsid(); - goto out; - } - switch(cmd) { - case _IOW('r', 10, struct rtentry32): - ret = compat_sys_ioctl(fd, SIOCADDRT, arg); - goto out; - case _IOW('r', 11, struct rtentry32): - ret = compat_sys_ioctl(fd, SIOCDELRT, arg); - goto out; - - case _IOW('i', 12, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFADDR, arg); - goto out; - case _IOWR('i', 13, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFADDR, arg); - goto out; - case _IOW('i', 14, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg); - goto out; - case _IOWR('i', 15, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg); - goto out; - case _IOW('i', 16, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFFLAGS, arg); - goto out; - case _IOWR('i', 17, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFFLAGS, arg); - goto out; - case _IOW('i', 18, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFMEM, arg); - goto out; - case _IOWR('i', 19, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFMEM, arg); - goto out; - - case _IOWR('i', 20, struct ifconf32): - ret = compat_sys_ioctl(fd, SIOCGIFCONF, arg); - goto out; - - case _IOW('i', 21, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFMTU, arg); - goto out; - - case _IOWR('i', 22, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFMTU, arg); - goto out; - - case _IOWR('i', 23, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg); - goto out; - case _IOW('i', 24, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg); - goto out; - case _IOWR('i', 25, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFNETMASK, arg); - goto out; - case _IOW('i', 26, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFNETMASK, arg); - goto out; - case _IOWR('i', 27, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFMETRIC, arg); - goto out; - case _IOW('i', 28, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFMETRIC, arg); - goto out; - - case _IOW('i', 30, struct arpreq): - ret = compat_sys_ioctl(fd, SIOCSARP, arg); - goto out; - case _IOWR('i', 31, struct arpreq): - ret = compat_sys_ioctl(fd, SIOCGARP, arg); - goto out; - case _IOW('i', 32, struct arpreq): - ret = compat_sys_ioctl(fd, SIOCDARP, arg); - goto out; - - case _IOW('i', 40, struct ifreq32): /* SIOCUPPER */ - case _IOW('i', 41, struct ifreq32): /* SIOCLOWER */ - case _IOW('i', 44, struct ifreq32): /* SIOCSETSYNC */ - case _IOW('i', 45, struct ifreq32): /* SIOCGETSYNC */ - case _IOW('i', 46, struct ifreq32): /* SIOCSSDSTATS */ - case _IOW('i', 47, struct ifreq32): /* SIOCSSESTATS */ - case _IOW('i', 48, struct ifreq32): /* SIOCSPROMISC */ - ret = -EOPNOTSUPP; - goto out; - - case _IOW('i', 49, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCADDMULTI, arg); - goto out; - case _IOW('i', 50, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCDELMULTI, arg); - goto out; - - /* FDDI interface ioctls, unsupported. */ - - case _IOW('i', 51, struct ifreq32): /* SIOCFDRESET */ - case _IOW('i', 52, struct ifreq32): /* SIOCFDSLEEP */ - case _IOW('i', 53, struct ifreq32): /* SIOCSTRTFMWAR */ - case _IOW('i', 54, struct ifreq32): /* SIOCLDNSTRTFW */ - case _IOW('i', 55, struct ifreq32): /* SIOCGETFDSTAT */ - case _IOW('i', 56, struct ifreq32): /* SIOCFDNMIINT */ - case _IOW('i', 57, struct ifreq32): /* SIOCFDEXUSER */ - case _IOW('i', 58, struct ifreq32): /* SIOCFDGNETMAP */ - case _IOW('i', 59, struct ifreq32): /* SIOCFDGIOCTL */ - printk("FDDI ioctl, returning EOPNOTSUPP\n"); - ret = -EOPNOTSUPP; - goto out; - - case _IOW('t', 125, int): - /* More stupid tty sunos ioctls, just - * say it worked. - */ - ret = 0; - goto out; - - /* Non posix grp */ - case _IOW('t', 118, int): { - int oldval, newval, __user *ptr; - - cmd = TIOCSPGRP; - ptr = (int __user *) (unsigned long) arg; - ret = -EFAULT; - if(get_user(oldval, ptr)) - goto out; - ret = compat_sys_ioctl(fd, cmd, arg); - __get_user(newval, ptr); - if(newval == -1) { - __put_user(oldval, ptr); - ret = -EIO; - } - if(ret == -ENOTTY) - ret = -EIO; - goto out; - } - - case _IOR('t', 119, int): { - int oldval, newval, __user *ptr; - - cmd = TIOCGPGRP; - ptr = (int __user *) (unsigned long) arg; - ret = -EFAULT; - if(get_user(oldval, ptr)) - goto out; - ret = compat_sys_ioctl(fd, cmd, arg); - __get_user(newval, ptr); - if(newval == -1) { - __put_user(oldval, ptr); - ret = -EIO; - } - if(ret == -ENOTTY) - ret = -EIO; - goto out; - } - }; - - ret = compat_sys_ioctl(fd, cmd, arg); - /* so stupid... */ - ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); -out: - return ret; -} diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S deleted file mode 100644 index 9cd272ac3ac..00000000000 --- a/arch/sparc64/kernel/sys32.S +++ /dev/null @@ -1,355 +0,0 @@ -/* $Id: sys32.S,v 1.12 2000/03/24 04:17:37 davem Exp $ - * sys32.S: I-cache tricks for 32-bit compatibility layer simple - * conversions. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <linux/config.h> -#include <asm/errno.h> - -/* NOTE: call as jump breaks return stack, we have to avoid that */ - - .text - -#define SIGN1(STUB,SYSCALL,REG1) \ - .align 32; \ - .globl STUB; \ -STUB: sethi %hi(SYSCALL), %g1; \ - jmpl %g1 + %lo(SYSCALL), %g0; \ - sra REG1, 0, REG1 - -#define SIGN2(STUB,SYSCALL,REG1,REG2) \ - .align 32; \ - .globl STUB; \ -STUB: sethi %hi(SYSCALL), %g1; \ - sra REG1, 0, REG1; \ - jmpl %g1 + %lo(SYSCALL), %g0; \ - sra REG2, 0, REG2 - -#define SIGN3(STUB,SYSCALL,REG1,REG2,REG3) \ - .align 32; \ - .globl STUB; \ -STUB: sra REG1, 0, REG1; \ - sethi %hi(SYSCALL), %g1; \ - sra REG2, 0, REG2; \ - jmpl %g1 + %lo(SYSCALL), %g0; \ - sra REG3, 0, REG3 - -#define SIGN4(STUB,SYSCALL,REG1,REG2,REG3,REG4) \ - .align 32; \ - .globl STUB; \ -STUB: sra REG1, 0, REG1; \ - sethi %hi(SYSCALL), %g1; \ - sra REG2, 0, REG2; \ - sra REG3, 0, REG3; \ - jmpl %g1 + %lo(SYSCALL), %g0; \ - sra REG4, 0, REG4 - -SIGN1(sys32_exit, sparc_exit, %o0) -SIGN1(sys32_exit_group, sys_exit_group, %o0) -SIGN1(sys32_wait4, compat_sys_wait4, %o2) -SIGN1(sys32_creat, sys_creat, %o1) -SIGN1(sys32_mknod, sys_mknod, %o1) -SIGN1(sys32_perfctr, sys_perfctr, %o0) -SIGN1(sys32_umount, sys_umount, %o1) -SIGN1(sys32_signal, sys_signal, %o0) -SIGN1(sys32_access, sys_access, %o1) -SIGN1(sys32_msync, sys_msync, %o2) -SIGN2(sys32_reboot, sys_reboot, %o0, %o1) -SIGN1(sys32_setitimer, compat_sys_setitimer, %o0) -SIGN1(sys32_getitimer, compat_sys_getitimer, %o0) -SIGN1(sys32_sethostname, sys_sethostname, %o1) -SIGN1(sys32_swapon, sys_swapon, %o1) -SIGN1(sys32_sigaction, compat_sys_sigaction, %o0) -SIGN1(sys32_rt_sigaction, compat_sys_rt_sigaction, %o0) -SIGN1(sys32_sigprocmask, compat_sys_sigprocmask, %o0) -SIGN1(sys32_rt_sigprocmask, compat_sys_rt_sigprocmask, %o0) -SIGN2(sys32_rt_sigqueueinfo, compat_sys_rt_sigqueueinfo, %o0, %o1) -SIGN1(sys32_getrusage, compat_sys_getrusage, %o0) -SIGN1(sys32_setxattr, sys_setxattr, %o4) -SIGN1(sys32_lsetxattr, sys_lsetxattr, %o4) -SIGN1(sys32_fsetxattr, sys_fsetxattr, %o4) -SIGN1(sys32_fgetxattr, sys_fgetxattr, %o0) -SIGN1(sys32_flistxattr, sys_flistxattr, %o0) -SIGN1(sys32_fremovexattr, sys_fremovexattr, %o0) -SIGN2(sys32_tkill, sys_tkill, %o0, %o1) -SIGN1(sys32_epoll_create, sys_epoll_create, %o0) -SIGN3(sys32_epoll_ctl, sys_epoll_ctl, %o0, %o1, %o2) -SIGN3(sys32_epoll_wait, sys_epoll_wait, %o0, %o2, %o3) -SIGN1(sys32_readahead, compat_sys_readahead, %o0) -SIGN2(sys32_fadvise64, compat_sys_fadvise64, %o0, %o4) -SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5) -SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1) -SIGN1(sys32_mlockall, sys_mlockall, %o0) -SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0) -SIGN1(sys32_clock_settime, compat_sys_clock_settime, %o1) -SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1) -SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) -SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) -SIGN1(sys32_mq_open, compat_sys_mq_open, %o1) -SIGN1(sys32_select, compat_sys_select, %o0) -SIGN1(sys32_mkdir, sys_mkdir, %o1) -SIGN3(sys32_futex, compat_sys_futex, %o1, %o2, %o5) -SIGN1(sys32_sysfs, compat_sys_sysfs, %o0) -SIGN3(sys32_ipc, compat_sys_ipc, %o1, %o2, %o3) -SIGN2(sys32_sendfile, compat_sys_sendfile, %o0, %o1) -SIGN2(sys32_sendfile64, compat_sys_sendfile64, %o0, %o1) -SIGN1(sys32_prctl, sys_prctl, %o0) -SIGN1(sys32_sched_rr_get_interval, compat_sys_sched_rr_get_interval, %o0) -SIGN2(sys32_waitpid, sys_waitpid, %o0, %o2) -SIGN1(sys32_getgroups, sys_getgroups, %o0) -SIGN1(sys32_getpgid, sys_getpgid, %o0) -SIGN2(sys32_getpriority, sys_getpriority, %o0, %o1) -SIGN1(sys32_getsid, sys_getsid, %o0) -SIGN2(sys32_kill, sys_kill, %o0, %o1) -SIGN1(sys32_nice, sys_nice, %o0) -SIGN1(sys32_lseek, sys_lseek, %o1) -SIGN2(sys32_open, sparc32_open, %o1, %o2) -SIGN1(sys32_readlink, sys_readlink, %o2) -SIGN1(sys32_sched_get_priority_max, sys_sched_get_priority_max, %o0) -SIGN1(sys32_sched_get_priority_min, sys_sched_get_priority_min, %o0) -SIGN1(sys32_sched_getparam, sys_sched_getparam, %o0) -SIGN1(sys32_sched_getscheduler, sys_sched_getscheduler, %o0) -SIGN1(sys32_sched_setparam, sys_sched_setparam, %o0) -SIGN2(sys32_sched_setscheduler, sys_sched_setscheduler, %o0, %o1) -SIGN1(sys32_getdomainname, sys_getdomainname, %o1) -SIGN1(sys32_setdomainname, sys_setdomainname, %o1) -SIGN1(sys32_setgroups, sys_setgroups, %o0) -SIGN2(sys32_setpgid, sys_setpgid, %o0, %o1) -SIGN3(sys32_setpriority, sys_setpriority, %o0, %o1, %o2) -SIGN1(sys32_ssetmask, sys_ssetmask, %o0) -SIGN2(sys32_syslog, sys_syslog, %o0, %o2) -SIGN1(sys32_umask, sys_umask, %o0) -SIGN3(sys32_tgkill, sys_tgkill, %o0, %o1, %o2) -SIGN1(sys32_sendto, sys_sendto, %o0) -SIGN1(sys32_recvfrom, sys_recvfrom, %o0) -SIGN3(sys32_socket, sys_socket, %o0, %o1, %o2) -SIGN2(sys32_connect, sys_connect, %o0, %o2) -SIGN2(sys32_bind, sys_bind, %o0, %o2) -SIGN2(sys32_listen, sys_listen, %o0, %o1) -SIGN1(sys32_recvmsg, compat_sys_recvmsg, %o0) -SIGN1(sys32_sendmsg, compat_sys_sendmsg, %o0) -SIGN2(sys32_shutdown, sys_shutdown, %o0, %o1) -SIGN3(sys32_socketpair, sys_socketpair, %o0, %o1, %o2) -SIGN1(sys32_getpeername, sys_getpeername, %o0) -SIGN1(sys32_getsockname, sys_getsockname, %o0) -SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1) -SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2) - - .globl sys32_mmap2 -sys32_mmap2: - sethi %hi(sys_mmap), %g1 - jmpl %g1 + %lo(sys_mmap), %g0 - sllx %o5, 12, %o5 - - .align 32 - .globl sys32_socketcall -sys32_socketcall: /* %o0=call, %o1=args */ - cmp %o0, 1 - bl,pn %xcc, do_einval - cmp %o0, 17 - bg,pn %xcc, do_einval - sub %o0, 1, %o0 - sllx %o0, 5, %o0 - sethi %hi(__socketcall_table_begin), %g2 - or %g2, %lo(__socketcall_table_begin), %g2 - jmpl %g2 + %o0, %g0 - nop -do_einval: - retl - mov -EINVAL, %o0 - - .align 32 -__socketcall_table_begin: - - /* Each entry is exactly 32 bytes. */ -do_sys_socket: /* sys_socket(int, int, int) */ -1: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_socket), %g1 -2: ldswa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys_socket), %g0 -3: ldswa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ -4: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_bind), %g1 -5: ldswa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys_bind), %g0 -6: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ -7: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_connect), %g1 -8: ldswa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys_connect), %g0 -9: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_listen: /* sys_listen(int, int) */ -10: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_listen), %g1 - jmpl %g1 + %lo(sys_listen), %g0 -11: ldswa [%o1 + 0x4] %asi, %o1 - nop - nop - nop - nop -do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ -12: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_accept), %g1 -13: lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys_accept), %g0 -14: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ -15: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_getsockname), %g1 -16: lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys_getsockname), %g0 -17: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ -18: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_getpeername), %g1 -19: lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys_getpeername), %g0 -20: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ -21: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_socketpair), %g1 -22: ldswa [%o1 + 0x8] %asi, %o2 -23: lduwa [%o1 + 0xc] %asi, %o3 - jmpl %g1 + %lo(sys_socketpair), %g0 -24: ldswa [%o1 + 0x4] %asi, %o1 - nop - nop -do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ -25: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_send), %g1 -26: lduwa [%o1 + 0x8] %asi, %o2 -27: lduwa [%o1 + 0xc] %asi, %o3 - jmpl %g1 + %lo(sys_send), %g0 -28: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop -do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ -29: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_recv), %g1 -30: lduwa [%o1 + 0x8] %asi, %o2 -31: lduwa [%o1 + 0xc] %asi, %o3 - jmpl %g1 + %lo(sys_recv), %g0 -32: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop -do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */ -33: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_sendto), %g1 -34: lduwa [%o1 + 0x8] %asi, %o2 -35: lduwa [%o1 + 0xc] %asi, %o3 -36: lduwa [%o1 + 0x10] %asi, %o4 -37: ldswa [%o1 + 0x14] %asi, %o5 - jmpl %g1 + %lo(sys_sendto), %g0 -38: lduwa [%o1 + 0x4] %asi, %o1 -do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */ -39: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_recvfrom), %g1 -40: lduwa [%o1 + 0x8] %asi, %o2 -41: lduwa [%o1 + 0xc] %asi, %o3 -42: lduwa [%o1 + 0x10] %asi, %o4 -43: lduwa [%o1 + 0x14] %asi, %o5 - jmpl %g1 + %lo(sys_recvfrom), %g0 -44: lduwa [%o1 + 0x4] %asi, %o1 -do_sys_shutdown: /* sys_shutdown(int, int) */ -45: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_shutdown), %g1 - jmpl %g1 + %lo(sys_shutdown), %g0 -46: ldswa [%o1 + 0x4] %asi, %o1 - nop - nop - nop - nop -do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ -47: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(compat_sys_setsockopt), %g1 -48: ldswa [%o1 + 0x8] %asi, %o2 -49: lduwa [%o1 + 0xc] %asi, %o3 -50: ldswa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(compat_sys_setsockopt), %g0 -51: ldswa [%o1 + 0x4] %asi, %o1 - nop -do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ -52: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(compat_sys_getsockopt), %g1 -53: ldswa [%o1 + 0x8] %asi, %o2 -54: lduwa [%o1 + 0xc] %asi, %o3 -55: lduwa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(compat_sys_getsockopt), %g0 -56: ldswa [%o1 + 0x4] %asi, %o1 - nop -do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ -57: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(compat_sys_sendmsg), %g1 -58: lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(compat_sys_sendmsg), %g0 -59: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ -60: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(compat_sys_recvmsg), %g1 -61: lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(compat_sys_recvmsg), %g0 -62: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop - - .section __ex_table - .align 4 - .word 1b, __retl_efault, 2b, __retl_efault - .word 3b, __retl_efault, 4b, __retl_efault - .word 5b, __retl_efault, 6b, __retl_efault - .word 7b, __retl_efault, 8b, __retl_efault - .word 9b, __retl_efault, 10b, __retl_efault - .word 11b, __retl_efault, 12b, __retl_efault - .word 13b, __retl_efault, 14b, __retl_efault - .word 15b, __retl_efault, 16b, __retl_efault - .word 17b, __retl_efault, 18b, __retl_efault - .word 19b, __retl_efault, 20b, __retl_efault - .word 21b, __retl_efault, 22b, __retl_efault - .word 23b, __retl_efault, 24b, __retl_efault - .word 25b, __retl_efault, 26b, __retl_efault - .word 27b, __retl_efault, 28b, __retl_efault - .word 29b, __retl_efault, 30b, __retl_efault - .word 31b, __retl_efault, 32b, __retl_efault - .word 33b, __retl_efault, 34b, __retl_efault - .word 35b, __retl_efault, 36b, __retl_efault - .word 37b, __retl_efault, 38b, __retl_efault - .word 39b, __retl_efault, 40b, __retl_efault - .word 41b, __retl_efault, 42b, __retl_efault - .word 43b, __retl_efault, 44b, __retl_efault - .word 45b, __retl_efault, 46b, __retl_efault - .word 47b, __retl_efault, 48b, __retl_efault - .word 49b, __retl_efault, 50b, __retl_efault - .word 51b, __retl_efault, 52b, __retl_efault - .word 53b, __retl_efault, 54b, __retl_efault - .word 55b, __retl_efault, 56b, __retl_efault - .word 57b, __retl_efault, 58b, __retl_efault - .word 59b, __retl_efault, 60b, __retl_efault - .word 61b, __retl_efault, 62b, __retl_efault - .previous diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c deleted file mode 100644 index 5f8c822a2b4..00000000000 --- a/arch/sparc64/kernel/sys_sparc.c +++ /dev/null @@ -1,731 +0,0 @@ -/* $Id: sys_sparc.c,v 1.57 2002/02/09 19:49:30 davem Exp $ - * linux/arch/sparc64/kernel/sys_sparc.c - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/sparc - * platform. - */ - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/mm.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/stat.h> -#include <linux/mman.h> -#include <linux/utsname.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/slab.h> -#include <linux/syscalls.h> -#include <linux/ipc.h> -#include <linux/personality.h> - -#include <asm/uaccess.h> -#include <asm/ipc.h> -#include <asm/utrap.h> -#include <asm/perfctr.h> - -/* #define DEBUG_UNIMP_SYSCALL */ - -/* XXX Make this per-binary type, this way we can detect the type of - * XXX a binary. Every Sparc executable calls this very early on. - */ -asmlinkage unsigned long sys_getpagesize(void) -{ - return PAGE_SIZE; -} - -#define COLOUR_ALIGN(addr,pgoff) \ - ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ - (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1))) - -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct * vma; - unsigned long task_size = TASK_SIZE; - unsigned long start_addr; - int do_color_align; - - if (flags & MAP_FIXED) { - /* We do not accept a shared mapping if it would violate - * cache aliasing constraints. - */ - if ((flags & MAP_SHARED) && - ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) - return -EINVAL; - return addr; - } - - if (test_thread_flag(TIF_32BIT)) - task_size = 0xf0000000UL; - if (len > task_size || len > -PAGE_OFFSET) - return -ENOMEM; - - do_color_align = 0; - if (filp || (flags & MAP_SHARED)) - do_color_align = 1; - - if (addr) { - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); - else - addr = PAGE_ALIGN(addr); - - vma = find_vma(mm, addr); - if (task_size - len >= addr && - (!vma || addr + len <= vma->vm_start)) - return addr; - } - - if (len <= mm->cached_hole_size) { - mm->cached_hole_size = 0; - mm->free_area_cache = TASK_UNMAPPED_BASE; - } - start_addr = addr = mm->free_area_cache; - - task_size -= len; - -full_search: - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); - else - addr = PAGE_ALIGN(addr); - - for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { - /* At this point: (!vma || addr < vma->vm_end). */ - if (addr < PAGE_OFFSET && -PAGE_OFFSET - len < addr) { - addr = PAGE_OFFSET; - vma = find_vma(mm, PAGE_OFFSET); - } - if (task_size < addr) { - if (start_addr != TASK_UNMAPPED_BASE) { - start_addr = addr = TASK_UNMAPPED_BASE; - mm->cached_hole_size = 0; - goto full_search; - } - return -ENOMEM; - } - if (!vma || addr + len <= vma->vm_start) { - /* - * Remember the place where we stopped the search: - */ - mm->free_area_cache = addr + len; - return addr; - } - if (addr + mm->cached_hole_size < vma->vm_start) - mm->cached_hole_size = vma->vm_start - addr; - - addr = vma->vm_end; - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); - } -} - -/* Try to align mapping such that we align it as much as possible. */ -unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) -{ - unsigned long align_goal, addr = -ENOMEM; - - if (flags & MAP_FIXED) { - /* Ok, don't mess with it. */ - return get_unmapped_area(NULL, addr, len, pgoff, flags); - } - flags &= ~MAP_SHARED; - - align_goal = PAGE_SIZE; - if (len >= (4UL * 1024 * 1024)) - align_goal = (4UL * 1024 * 1024); - else if (len >= (512UL * 1024)) - align_goal = (512UL * 1024); - else if (len >= (64UL * 1024)) - align_goal = (64UL * 1024); - - do { - addr = get_unmapped_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags); - if (!(addr & ~PAGE_MASK)) { - addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL); - break; - } - - if (align_goal == (4UL * 1024 * 1024)) - align_goal = (512UL * 1024); - else if (align_goal == (512UL * 1024)) - align_goal = (64UL * 1024); - else - align_goal = PAGE_SIZE; - } while ((addr & ~PAGE_MASK) && align_goal > PAGE_SIZE); - - /* Mapping is smaller than 64K or larger areas could not - * be obtained. - */ - if (addr & ~PAGE_MASK) - addr = get_unmapped_area(NULL, orig_addr, len, pgoff, flags); - - return addr; -} - -asmlinkage unsigned long sparc_brk(unsigned long brk) -{ - /* People could try to be nasty and use ta 0x6d in 32bit programs */ - if (test_thread_flag(TIF_32BIT) && - brk >= 0xf0000000UL) - return current->mm->brk; - - if ((current->mm->brk & PAGE_OFFSET) != (brk & PAGE_OFFSET)) - return current->mm->brk; - return sys_brk(brk); -} - -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage long sparc_pipe(struct pt_regs *regs) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (error) - goto out; - regs->u_regs[UREG_I1] = fd[1]; - error = fd[0]; -out: - return error; -} - -/* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ - -asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, - unsigned long third, void __user *ptr, long fifth) -{ - int err; - - /* No need for backward compatibility. We can start fresh... */ - if (call <= SEMCTL) { - switch (call) { - case SEMOP: - err = sys_semtimedop(first, ptr, - (unsigned)second, NULL); - goto out; - case SEMTIMEDOP: - err = sys_semtimedop(first, ptr, (unsigned)second, - (const struct timespec __user *) fifth); - goto out; - case SEMGET: - err = sys_semget(first, (int)second, (int)third); - goto out; - case SEMCTL: { - union semun fourth; - err = -EINVAL; - if (!ptr) - goto out; - err = -EFAULT; - if (get_user(fourth.__pad, - (void __user * __user *) ptr)) - goto out; - err = sys_semctl(first, (int)second | IPC_64, - (int)third, fourth); - goto out; - } - default: - err = -ENOSYS; - goto out; - }; - } - if (call <= MSGCTL) { - switch (call) { - case MSGSND: - err = sys_msgsnd(first, ptr, (size_t)second, - (int)third); - goto out; - case MSGRCV: - err = sys_msgrcv(first, ptr, (size_t)second, fifth, - (int)third); - goto out; - case MSGGET: - err = sys_msgget((key_t)first, (int)second); - goto out; - case MSGCTL: - err = sys_msgctl(first, (int)second | IPC_64, ptr); - goto out; - default: - err = -ENOSYS; - goto out; - }; - } - if (call <= SHMCTL) { - switch (call) { - case SHMAT: { - ulong raddr; - err = do_shmat(first, ptr, (int)second, &raddr); - if (!err) { - if (put_user(raddr, - (ulong __user *) third)) - err = -EFAULT; - } - goto out; - } - case SHMDT: - err = sys_shmdt(ptr); - goto out; - case SHMGET: - err = sys_shmget(first, (size_t)second, (int)third); - goto out; - case SHMCTL: - err = sys_shmctl(first, (int)second | IPC_64, ptr); - goto out; - default: - err = -ENOSYS; - goto out; - }; - } else { - err = -ENOSYS; - } -out: - return err; -} - -asmlinkage long sparc64_newuname(struct new_utsname __user *name) -{ - int ret = sys_newuname(name); - - if (current->personality == PER_LINUX32 && !ret) { - ret = (copy_to_user(name->machine, "sparc\0\0", 8) - ? -EFAULT : 0); - } - return ret; -} - -asmlinkage long sparc64_personality(unsigned long personality) -{ - int ret; - - if (current->personality == PER_LINUX32 && - personality == PER_LINUX) - personality = PER_LINUX32; - ret = sys_personality(personality); - if (ret == PER_LINUX32) - ret = PER_LINUX; - - return ret; -} - -/* Linux version of mmap */ -asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long off) -{ - struct file * file = NULL; - unsigned long retval = -EBADF; - - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - len = PAGE_ALIGN(len); - retval = -EINVAL; - - if (test_thread_flag(TIF_32BIT)) { - if (len > 0xf0000000UL || - ((flags & MAP_FIXED) && addr > 0xf0000000UL - len)) - goto out_putf; - } else { - if (len > -PAGE_OFFSET || - ((flags & MAP_FIXED) && - addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET)) - goto out_putf; - } - - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - -out_putf: - if (file) - fput(file); -out: - return retval; -} - -asmlinkage long sys64_munmap(unsigned long addr, size_t len) -{ - long ret; - - if (len > -PAGE_OFFSET || - (addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET)) - return -EINVAL; - down_write(¤t->mm->mmap_sem); - ret = do_munmap(current->mm, addr, len); - up_write(¤t->mm->mmap_sem); - return ret; -} - -extern unsigned long do_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr); - -asmlinkage unsigned long sys64_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr) -{ - struct vm_area_struct *vma; - unsigned long ret = -EINVAL; - if (test_thread_flag(TIF_32BIT)) - goto out; - if (old_len > -PAGE_OFFSET || new_len > -PAGE_OFFSET) - goto out; - if (addr < PAGE_OFFSET && addr + old_len > -PAGE_OFFSET) - goto out; - down_write(¤t->mm->mmap_sem); - if (flags & MREMAP_FIXED) { - if (new_addr < PAGE_OFFSET && - new_addr + new_len > -PAGE_OFFSET) - goto out_sem; - } else if (addr < PAGE_OFFSET && addr + new_len > -PAGE_OFFSET) { - unsigned long map_flags = 0; - struct file *file = NULL; - - ret = -ENOMEM; - if (!(flags & MREMAP_MAYMOVE)) - goto out_sem; - - vma = find_vma(current->mm, addr); - if (vma) { - if (vma->vm_flags & VM_SHARED) - map_flags |= MAP_SHARED; - file = vma->vm_file; - } - - /* MREMAP_FIXED checked above. */ - new_addr = get_unmapped_area(file, addr, new_len, - vma ? vma->vm_pgoff : 0, - map_flags); - ret = new_addr; - if (new_addr & ~PAGE_MASK) - goto out_sem; - flags |= MREMAP_FIXED; - } - ret = do_mremap(addr, old_len, new_len, flags, new_addr); -out_sem: - up_write(¤t->mm->mmap_sem); -out: - return ret; -} - -/* we come to here via sys_nis_syscall so it can setup the regs argument */ -asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs) -{ - static int count; - - /* Don't make the system unusable, if someone goes stuck */ - if (count++ > 5) - return -ENOSYS; - - printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]); -#ifdef DEBUG_UNIMP_SYSCALL - show_regs (regs); -#endif - - return -ENOSYS; -} - -/* #define DEBUG_SPARC_BREAKPOINT */ - -asmlinkage void sparc_breakpoint(struct pt_regs *regs) -{ - siginfo_t info; - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } -#ifdef DEBUG_SPARC_BREAKPOINT - printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc); -#endif - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = 0; - force_sig_info(SIGTRAP, &info, current); -#ifdef DEBUG_SPARC_BREAKPOINT - printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc); -#endif -} - -extern void check_pending(int signum); - -asmlinkage long sys_getdomainname(char __user *name, int len) -{ - int nlen; - int err = -EFAULT; - - down_read(&uts_sem); - - nlen = strlen(system_utsname.domainname) + 1; - - if (nlen < len) - len = nlen; - if (len > __NEW_UTS_LEN) - goto done; - if (copy_to_user(name, system_utsname.domainname, len)) - goto done; - err = 0; -done: - up_read(&uts_sem); - return err; -} - -asmlinkage long solaris_syscall(struct pt_regs *regs) -{ - static int count; - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - if (++count <= 5) { - printk ("For Solaris binary emulation you need solaris module loaded\n"); - show_regs (regs); - } - send_sig(SIGSEGV, current, 1); - - return -ENOSYS; -} - -#ifndef CONFIG_SUNOS_EMUL -asmlinkage long sunos_syscall(struct pt_regs *regs) -{ - static int count; - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - if (++count <= 20) - printk ("SunOS binary emulation not compiled in\n"); - force_sig(SIGSEGV, current); - - return -ENOSYS; -} -#endif - -asmlinkage long sys_utrap_install(utrap_entry_t type, - utrap_handler_t new_p, - utrap_handler_t new_d, - utrap_handler_t __user *old_p, - utrap_handler_t __user *old_d) -{ - if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31) - return -EINVAL; - if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) { - if (old_p) { - if (!current_thread_info()->utraps) { - if (put_user(NULL, old_p)) - return -EFAULT; - } else { - if (put_user((utrap_handler_t)(current_thread_info()->utraps[type]), old_p)) - return -EFAULT; - } - } - if (old_d) { - if (put_user(NULL, old_d)) - return -EFAULT; - } - return 0; - } - if (!current_thread_info()->utraps) { - current_thread_info()->utraps = - kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); - if (!current_thread_info()->utraps) - return -ENOMEM; - current_thread_info()->utraps[0] = 1; - memset(current_thread_info()->utraps+1, 0, - UT_TRAP_INSTRUCTION_31*sizeof(long)); - } else { - if ((utrap_handler_t)current_thread_info()->utraps[type] != new_p && - current_thread_info()->utraps[0] > 1) { - long *p = current_thread_info()->utraps; - - current_thread_info()->utraps = - kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), - GFP_KERNEL); - if (!current_thread_info()->utraps) { - current_thread_info()->utraps = p; - return -ENOMEM; - } - p[0]--; - current_thread_info()->utraps[0] = 1; - memcpy(current_thread_info()->utraps+1, p+1, - UT_TRAP_INSTRUCTION_31*sizeof(long)); - } - } - if (old_p) { - if (put_user((utrap_handler_t)(current_thread_info()->utraps[type]), old_p)) - return -EFAULT; - } - if (old_d) { - if (put_user(NULL, old_d)) - return -EFAULT; - } - current_thread_info()->utraps[type] = (long)new_p; - - return 0; -} - -long sparc_memory_ordering(unsigned long model, struct pt_regs *regs) -{ - if (model >= 3) - return -EINVAL; - regs->tstate = (regs->tstate & ~TSTATE_MM) | (model << 14); - return 0; -} - -asmlinkage long sys_rt_sigaction(int sig, - const struct sigaction __user *act, - struct sigaction __user *oact, - void __user *restorer, - size_t sigsetsize) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (act) { - new_ka.ka_restorer = restorer; - if (copy_from_user(&new_ka.sa, act, sizeof(*act))) - return -EFAULT; - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) - return -EFAULT; - } - - return ret; -} - -/* Invoked by rtrap code to update performance counters in - * user space. - */ -asmlinkage void update_perfctrs(void) -{ - unsigned long pic, tmp; - - read_pic(pic); - tmp = (current_thread_info()->kernel_cntd0 += (unsigned int)pic); - __put_user(tmp, current_thread_info()->user_cntd0); - tmp = (current_thread_info()->kernel_cntd1 += (pic >> 32)); - __put_user(tmp, current_thread_info()->user_cntd1); - reset_pic(); -} - -asmlinkage long sys_perfctr(int opcode, unsigned long arg0, unsigned long arg1, unsigned long arg2) -{ - int err = 0; - - switch(opcode) { - case PERFCTR_ON: - current_thread_info()->pcr_reg = arg2; - current_thread_info()->user_cntd0 = (u64 __user *) arg0; - current_thread_info()->user_cntd1 = (u64 __user *) arg1; - current_thread_info()->kernel_cntd0 = - current_thread_info()->kernel_cntd1 = 0; - write_pcr(arg2); - reset_pic(); - set_thread_flag(TIF_PERFCTR); - break; - - case PERFCTR_OFF: - err = -EINVAL; - if (test_thread_flag(TIF_PERFCTR)) { - current_thread_info()->user_cntd0 = - current_thread_info()->user_cntd1 = NULL; - current_thread_info()->pcr_reg = 0; - write_pcr(0); - clear_thread_flag(TIF_PERFCTR); - err = 0; - } - break; - - case PERFCTR_READ: { - unsigned long pic, tmp; - - if (!test_thread_flag(TIF_PERFCTR)) { - err = -EINVAL; - break; - } - read_pic(pic); - tmp = (current_thread_info()->kernel_cntd0 += (unsigned int)pic); - err |= __put_user(tmp, current_thread_info()->user_cntd0); - tmp = (current_thread_info()->kernel_cntd1 += (pic >> 32)); - err |= __put_user(tmp, current_thread_info()->user_cntd1); - reset_pic(); - break; - } - - case PERFCTR_CLRPIC: - if (!test_thread_flag(TIF_PERFCTR)) { - err = -EINVAL; - break; - } - current_thread_info()->kernel_cntd0 = - current_thread_info()->kernel_cntd1 = 0; - reset_pic(); - break; - - case PERFCTR_SETPCR: { - u64 __user *user_pcr = (u64 __user *)arg0; - - if (!test_thread_flag(TIF_PERFCTR)) { - err = -EINVAL; - break; - } - err |= __get_user(current_thread_info()->pcr_reg, user_pcr); - write_pcr(current_thread_info()->pcr_reg); - current_thread_info()->kernel_cntd0 = - current_thread_info()->kernel_cntd1 = 0; - reset_pic(); - break; - } - - case PERFCTR_GETPCR: { - u64 __user *user_pcr = (u64 __user *)arg0; - - if (!test_thread_flag(TIF_PERFCTR)) { - err = -EINVAL; - break; - } - err |= __put_user(current_thread_info()->pcr_reg, user_pcr); - break; - } - - default: - err = -EINVAL; - break; - }; - return err; -} diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c deleted file mode 100644 index 9264ccbaaaf..00000000000 --- a/arch/sparc64/kernel/sys_sparc32.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* $Id: sys_sparc32.c,v 1.184 2002/02/09 19:49:31 davem Exp $ - * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * - * These routines maintain argument size conversion between 32bit and 64bit - * environment. - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/capability.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/file.h> -#include <linux/signal.h> -#include <linux/resource.h> -#include <linux/times.h> -#include <linux/utsname.h> -#include <linux/timex.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/slab.h> -#include <linux/uio.h> -#include <linux/nfs_fs.h> -#include <linux/quota.h> -#include <linux/module.h> -#include <linux/sunrpc/svc.h> -#include <linux/nfsd/nfsd.h> -#include <linux/nfsd/cache.h> -#include <linux/nfsd/xdr.h> -#include <linux/nfsd/syscall.h> -#include <linux/poll.h> -#include <linux/personality.h> -#include <linux/stat.h> -#include <linux/filter.h> -#include <linux/highmem.h> -#include <linux/highuid.h> -#include <linux/mman.h> -#include <linux/ipv6.h> -#include <linux/in.h> -#include <linux/icmpv6.h> -#include <linux/syscalls.h> -#include <linux/sysctl.h> -#include <linux/binfmts.h> -#include <linux/dnotify.h> -#include <linux/security.h> -#include <linux/compat.h> -#include <linux/vfs.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/ptrace.h> -#include <linux/highuid.h> - -#include <asm/types.h> -#include <asm/ipc.h> -#include <asm/uaccess.h> -#include <asm/fpumacro.h> -#include <asm/semaphore.h> -#include <asm/mmu_context.h> - -asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group) -{ - return sys_chown(filename, low2highuid(user), low2highgid(group)); -} - -asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group) -{ - return sys_lchown(filename, low2highuid(user), low2highgid(group)); -} - -asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group) -{ - return sys_fchown(fd, low2highuid(user), low2highgid(group)); -} - -asmlinkage long sys32_setregid16(u16 rgid, u16 egid) -{ - return sys_setregid(low2highgid(rgid), low2highgid(egid)); -} - -asmlinkage long sys32_setgid16(u16 gid) -{ - return sys_setgid((gid_t)gid); -} - -asmlinkage long sys32_setreuid16(u16 ruid, u16 euid) -{ - return sys_setreuid(low2highuid(ruid), low2highuid(euid)); -} - -asmlinkage long sys32_setuid16(u16 uid) -{ - return sys_setuid((uid_t)uid); -} - -asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) -{ - return sys_setresuid(low2highuid(ruid), low2highuid(euid), - low2highuid(suid)); -} - -asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid) -{ - int retval; - - if (!(retval = put_user(high2lowuid(current->uid), ruid)) && - !(retval = put_user(high2lowuid(current->euid), euid))) - retval = put_user(high2lowuid(current->suid), suid); - - return retval; -} - -asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) -{ - return sys_setresgid(low2highgid(rgid), low2highgid(egid), - low2highgid(sgid)); -} - -asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid) -{ - int retval; - - if (!(retval = put_user(high2lowgid(current->gid), rgid)) && - !(retval = put_user(high2lowgid(current->egid), egid))) - retval = put_user(high2lowgid(current->sgid), sgid); - - return retval; -} - -asmlinkage long sys32_setfsuid16(u16 uid) -{ - return sys_setfsuid((uid_t)uid); -} - -asmlinkage long sys32_setfsgid16(u16 gid) -{ - return sys_setfsgid((gid_t)gid); -} - -static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) -{ - int i; - u16 group; - - for (i = 0; i < group_info->ngroups; i++) { - group = (u16)GROUP_AT(group_info, i); - if (put_user(group, grouplist+i)) - return -EFAULT; - } - - return 0; -} - -static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) -{ - int i; - u16 group; - - for (i = 0; i < group_info->ngroups; i++) { - if (get_user(group, grouplist+i)) - return -EFAULT; - GROUP_AT(group_info, i) = (gid_t)group; - } - - return 0; -} - -asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) -{ - int i; - - if (gidsetsize < 0) - return -EINVAL; - - get_group_info(current->group_info); - i = current->group_info->ngroups; - if (gidsetsize) { - if (i > gidsetsize) { - i = -EINVAL; - goto out; - } - if (groups16_to_user(grouplist, current->group_info)) { - i = -EFAULT; - goto out; - } - } -out: - put_group_info(current->group_info); - return i; -} - -asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) -{ - struct group_info *group_info; - int retval; - - if (!capable(CAP_SETGID)) - return -EPERM; - if ((unsigned)gidsetsize > NGROUPS_MAX) - return -EINVAL; - - group_info = groups_alloc(gidsetsize); - if (!group_info) - return -ENOMEM; - retval = groups16_from_user(group_info, grouplist); - if (retval) { - put_group_info(group_info); - return retval; - } - - retval = set_current_groups(group_info); - put_group_info(group_info); - - return retval; -} - -asmlinkage long sys32_getuid16(void) -{ - return high2lowuid(current->uid); -} - -asmlinkage long sys32_geteuid16(void) -{ - return high2lowuid(current->euid); -} - -asmlinkage long sys32_getgid16(void) -{ - return high2lowgid(current->gid); -} - -asmlinkage long sys32_getegid16(void) -{ - return high2lowgid(current->egid); -} - -/* 32-bit timeval and related flotsam. */ - -static long get_tv32(struct timeval *o, struct compat_timeval __user *i) -{ - return (!access_ok(VERIFY_READ, i, sizeof(*i)) || - (__get_user(o->tv_sec, &i->tv_sec) | - __get_user(o->tv_usec, &i->tv_usec))); -} - -static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) -{ - return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || - (__put_user(i->tv_sec, &o->tv_sec) | - __put_user(i->tv_usec, &o->tv_usec))); -} - -#ifdef CONFIG_SYSVIPC -asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth) -{ - int version; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - - switch (call) { - case SEMTIMEDOP: - if (fifth) - /* sign extend semid */ - return compat_sys_semtimedop((int)first, - compat_ptr(ptr), second, - compat_ptr(fifth)); - /* else fall through for normal semop() */ - case SEMOP: - /* struct sembuf is the same on 32 and 64bit :)) */ - /* sign extend semid */ - return sys_semtimedop((int)first, compat_ptr(ptr), second, - NULL); - case SEMGET: - /* sign extend key, nsems */ - return sys_semget((int)first, (int)second, third); - case SEMCTL: - /* sign extend semid, semnum */ - return compat_sys_semctl((int)first, (int)second, third, - compat_ptr(ptr)); - - case MSGSND: - /* sign extend msqid */ - return compat_sys_msgsnd((int)first, (int)second, third, - compat_ptr(ptr)); - case MSGRCV: - /* sign extend msqid, msgtyp */ - return compat_sys_msgrcv((int)first, second, (int)fifth, - third, version, compat_ptr(ptr)); - case MSGGET: - /* sign extend key */ - return sys_msgget((int)first, second); - case MSGCTL: - /* sign extend msqid */ - return compat_sys_msgctl((int)first, second, compat_ptr(ptr)); - - case SHMAT: - /* sign extend shmid */ - return compat_sys_shmat((int)first, second, third, version, - compat_ptr(ptr)); - case SHMDT: - return sys_shmdt(compat_ptr(ptr)); - case SHMGET: - /* sign extend key_t */ - return sys_shmget((int)first, second, third); - case SHMCTL: - /* sign extend shmid */ - return compat_sys_shmctl((int)first, second, compat_ptr(ptr)); - - default: - return -ENOSYS; - }; - - return -ENOSYS; -} -#endif - -asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) -{ - if ((int)high < 0) - return -EINVAL; - else - return sys_truncate(path, (high << 32) | low); -} - -asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) -{ - if ((int)high < 0) - return -EINVAL; - else - return sys_ftruncate(fd, (high << 32) | low); -} - -int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) -{ - int err; - - if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) || - !old_valid_dev(stat->rdev)) - return -EOVERFLOW; - - err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev); - err |= put_user(stat->ino, &statbuf->st_ino); - err |= put_user(stat->mode, &statbuf->st_mode); - err |= put_user(stat->nlink, &statbuf->st_nlink); - err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid); - err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid); - err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev); - err |= put_user(stat->size, &statbuf->st_size); - err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); - err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); - err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); - err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); - err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); - err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); - err |= put_user(stat->blksize, &statbuf->st_blksize); - err |= put_user(stat->blocks, &statbuf->st_blocks); - err |= put_user(0, &statbuf->__unused4[0]); - err |= put_user(0, &statbuf->__unused4[1]); - - return err; -} - -int cp_compat_stat64(struct kstat *stat, struct compat_stat64 __user *statbuf) -{ - int err; - - err = put_user(huge_encode_dev(stat->dev), &statbuf->st_dev); - err |= put_user(stat->ino, &statbuf->st_ino); - err |= put_user(stat->mode, &statbuf->st_mode); - err |= put_user(stat->nlink, &statbuf->st_nlink); - err |= put_user(stat->uid, &statbuf->st_uid); - err |= put_user(stat->gid, &statbuf->st_gid); - err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev); - err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]); - err |= put_user(stat->size, &statbuf->st_size); - err |= put_user(stat->blksize, &statbuf->st_blksize); - err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[0]); - err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[4]); - err |= put_user(stat->blocks, &statbuf->st_blocks); - err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); - err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); - err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); - err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); - err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); - err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); - err |= put_user(0, &statbuf->__unused4); - err |= put_user(0, &statbuf->__unused5); - - return err; -} - -asmlinkage long compat_sys_stat64(char __user * filename, - struct compat_stat64 __user *statbuf) -{ - struct kstat stat; - int error = vfs_stat(filename, &stat); - - if (!error) - error = cp_compat_stat64(&stat, statbuf); - return error; -} - -asmlinkage long compat_sys_lstat64(char __user * filename, - struct compat_stat64 __user *statbuf) -{ - struct kstat stat; - int error = vfs_lstat(filename, &stat); - - if (!error) - error = cp_compat_stat64(&stat, statbuf); - return error; -} - -asmlinkage long compat_sys_fstat64(unsigned int fd, - struct compat_stat64 __user * statbuf) -{ - struct kstat stat; - int error = vfs_fstat(fd, &stat); - - if (!error) - error = cp_compat_stat64(&stat, statbuf); - return error; -} - -asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2) -{ - return sys_sysfs(option, arg1, arg2); -} - -struct sysinfo32 { - s32 uptime; - u32 loads[3]; - u32 totalram; - u32 freeram; - u32 sharedram; - u32 bufferram; - u32 totalswap; - u32 freeswap; - unsigned short procs; - unsigned short pad; - u32 totalhigh; - u32 freehigh; - u32 mem_unit; - char _f[20-2*sizeof(int)-sizeof(int)]; -}; - -asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info) -{ - struct sysinfo s; - int ret, err; - int bitcount = 0; - mm_segment_t old_fs = get_fs (); - - set_fs(KERNEL_DS); - ret = sys_sysinfo((struct sysinfo __user *) &s); - set_fs(old_fs); - /* Check to see if any memory value is too large for 32-bit and - * scale down if needed. - */ - if ((s.totalram >> 32) || (s.totalswap >> 32)) { - while (s.mem_unit < PAGE_SIZE) { - s.mem_unit <<= 1; - bitcount++; - } - s.totalram >>= bitcount; - s.freeram >>= bitcount; - s.sharedram >>= bitcount; - s.bufferram >>= bitcount; - s.totalswap >>= bitcount; - s.freeswap >>= bitcount; - s.totalhigh >>= bitcount; - s.freehigh >>= bitcount; - } - - err = put_user (s.uptime, &info->uptime); - err |= __put_user (s.loads[0], &info->loads[0]); - err |= __put_user (s.loads[1], &info->loads[1]); - err |= __put_user (s.loads[2], &info->loads[2]); - err |= __put_user (s.totalram, &info->totalram); - err |= __put_user (s.freeram, &info->freeram); - err |= __put_user (s.sharedram, &info->sharedram); - err |= __put_user (s.bufferram, &info->bufferram); - err |= __put_user (s.totalswap, &info->totalswap); - err |= __put_user (s.freeswap, &info->freeswap); - err |= __put_user (s.procs, &info->procs); - err |= __put_user (s.totalhigh, &info->totalhigh); - err |= __put_user (s.freehigh, &info->freehigh); - err |= __put_user (s.mem_unit, &info->mem_unit); - if (err) - return -EFAULT; - return ret; -} - -asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval) -{ - struct timespec t; - int ret; - mm_segment_t old_fs = get_fs (); - - set_fs (KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t); - set_fs (old_fs); - if (put_compat_timespec(&t, interval)) - return -EFAULT; - return ret; -} - -asmlinkage long compat_sys_rt_sigprocmask(int how, - compat_sigset_t __user *set, - compat_sigset_t __user *oset, - compat_size_t sigsetsize) -{ - sigset_t s; - compat_sigset_t s32; - int ret; - mm_segment_t old_fs = get_fs(); - - if (set) { - if (copy_from_user (&s32, set, sizeof(compat_sigset_t))) - return -EFAULT; - switch (_NSIG_WORDS) { - case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); - case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); - case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); - case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); - } - } - set_fs (KERNEL_DS); - ret = sys_rt_sigprocmask(how, - set ? (sigset_t __user *) &s : NULL, - oset ? (sigset_t __user *) &s : NULL, - sigsetsize); - set_fs (old_fs); - if (ret) return ret; - if (oset) { - switch (_NSIG_WORDS) { - case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; - case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; - case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; - case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; - } - if (copy_to_user (oset, &s32, sizeof(compat_sigset_t))) - return -EFAULT; - } - return 0; -} - -asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, - compat_size_t sigsetsize) -{ - sigset_t s; - compat_sigset_t s32; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize); - set_fs (old_fs); - if (!ret) { - switch (_NSIG_WORDS) { - case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; - case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; - case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; - case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; - } - if (copy_to_user (set, &s32, sizeof(compat_sigset_t))) - return -EFAULT; - } - return ret; -} - -asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig, - struct compat_siginfo __user *uinfo) -{ - siginfo_t info; - int ret; - mm_segment_t old_fs = get_fs(); - - if (copy_siginfo_from_user32(&info, uinfo)) - return -EFAULT; - - set_fs (KERNEL_DS); - ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); - set_fs (old_fs); - return ret; -} - -asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act, - struct old_sigaction32 __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (sig < 0) { - set_thread_flag(TIF_NEWSIGNALS); - sig = -sig; - } - - if (act) { - compat_old_sigset_t mask; - u32 u_handler, u_restorer; - - ret = get_user(u_handler, &act->sa_handler); - new_ka.sa.sa_handler = compat_ptr(u_handler); - ret |= __get_user(u_restorer, &act->sa_restorer); - new_ka.sa.sa_restorer = compat_ptr(u_restorer); - ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); - ret |= __get_user(mask, &act->sa_mask); - if (ret) - return ret; - new_ka.ka_restorer = NULL; - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); - ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer); - ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -asmlinkage long compat_sys_rt_sigaction(int sig, - struct sigaction32 __user *act, - struct sigaction32 __user *oact, - void __user *restorer, - compat_size_t sigsetsize) -{ - struct k_sigaction new_ka, old_ka; - int ret; - compat_sigset_t set32; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(compat_sigset_t)) - return -EINVAL; - - /* All tasks which use RT signals (effectively) use - * new style signals. - */ - set_thread_flag(TIF_NEWSIGNALS); - - if (act) { - u32 u_handler, u_restorer; - - new_ka.ka_restorer = restorer; - ret = get_user(u_handler, &act->sa_handler); - new_ka.sa.sa_handler = compat_ptr(u_handler); - ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t)); - switch (_NSIG_WORDS) { - case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32); - case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32); - case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32); - case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32); - } - ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); - ret |= __get_user(u_restorer, &act->sa_restorer); - new_ka.sa.sa_restorer = compat_ptr(u_restorer); - if (ret) - return -EFAULT; - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - switch (_NSIG_WORDS) { - case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3]; - case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2]; - case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1]; - case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0]; - } - ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); - ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t)); - ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer); - if (ret) - ret = -EFAULT; - } - - return ret; -} - -/* - * sparc32_execve() executes a new program after the asm stub has set - * things up for us. This should basically do what I want it to. - */ -asmlinkage long sparc32_execve(struct pt_regs *regs) -{ - int error, base = 0; - char *filename; - - /* User register window flush is done by entry.S */ - - /* Check for indirect call. */ - if ((u32)regs->u_regs[UREG_G1] == 0) - base = 1; - - filename = getname(compat_ptr(regs->u_regs[base + UREG_I0])); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = compat_do_execve(filename, - compat_ptr(regs->u_regs[base + UREG_I1]), - compat_ptr(regs->u_regs[base + UREG_I2]), regs); - - putname(filename); - - if (!error) { - fprs_write(0); - current_thread_info()->xfsr[0] = 0; - current_thread_info()->fpsaved[0] = 0; - regs->tstate &= ~TSTATE_PEF; - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } -out: - return error; -} - -#ifdef CONFIG_MODULES - -asmlinkage long sys32_init_module(void __user *umod, u32 len, - const char __user *uargs) -{ - return sys_init_module(umod, len, uargs); -} - -asmlinkage long sys32_delete_module(const char __user *name_user, - unsigned int flags) -{ - return sys_delete_module(name_user, flags); -} - -#else /* CONFIG_MODULES */ - -asmlinkage long sys32_init_module(const char __user *name_user, - struct module __user *mod_user) -{ - return -ENOSYS; -} - -asmlinkage long sys32_delete_module(const char __user *name_user) -{ - return -ENOSYS; -} - -#endif /* CONFIG_MODULES */ - -/* Translations due to time_t size differences. Which affects all - sorts of things, like timeval and itimerval. */ - -extern struct timezone sys_tz; - -asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, - struct timezone __user *tz) -{ - if (tv) { - struct timeval ktv; - do_gettimeofday(&ktv); - if (put_tv32(tv, &ktv)) - return -EFAULT; - } - if (tz) { - if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) - return -EFAULT; - } - return 0; -} - -static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) -{ - long usec; - - if (!access_ok(VERIFY_READ, i, sizeof(*i))) - return -EFAULT; - if (__get_user(o->tv_sec, &i->tv_sec)) - return -EFAULT; - if (__get_user(usec, &i->tv_usec)) - return -EFAULT; - o->tv_nsec = usec * 1000; - return 0; -} - -asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, - struct timezone __user *tz) -{ - struct timespec kts; - struct timezone ktz; - - if (tv) { - if (get_ts32(&kts, tv)) - return -EFAULT; - } - if (tz) { - if (copy_from_user(&ktz, tz, sizeof(ktz))) - return -EFAULT; - } - - return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); -} - -asmlinkage long sys32_utimes(char __user *filename, - struct compat_timeval __user *tvs) -{ - struct timeval ktvs[2]; - - if (tvs) { - if (get_tv32(&ktvs[0], tvs) || - get_tv32(&ktvs[1], 1+tvs)) - return -EFAULT; - } - - return do_utimes(AT_FDCWD, filename, (tvs ? &ktvs[0] : NULL)); -} - -/* These are here just in case some old sparc32 binary calls it. */ -asmlinkage long sys32_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - -asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, - char __user *ubuf, - compat_size_t count, - unsigned long poshi, - unsigned long poslo) -{ - return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo); -} - -asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd, - char __user *ubuf, - compat_size_t count, - unsigned long poshi, - unsigned long poslo) -{ - return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo); -} - -asmlinkage long compat_sys_readahead(int fd, - unsigned long offhi, - unsigned long offlo, - compat_size_t count) -{ - return sys_readahead(fd, (offhi << 32) | offlo, count); -} - -long compat_sys_fadvise64(int fd, - unsigned long offhi, - unsigned long offlo, - compat_size_t len, int advice) -{ - return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice); -} - -long compat_sys_fadvise64_64(int fd, - unsigned long offhi, unsigned long offlo, - unsigned long lenhi, unsigned long lenlo, - int advice) -{ - return sys_fadvise64_64(fd, - (offhi << 32) | offlo, - (lenhi << 32) | lenlo, - advice); -} - -asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, - compat_off_t __user *offset, - compat_size_t count) -{ - mm_segment_t old_fs = get_fs(); - int ret; - off_t of; - - if (offset && get_user(of, offset)) - return -EFAULT; - - set_fs(KERNEL_DS); - ret = sys_sendfile(out_fd, in_fd, - offset ? (off_t __user *) &of : NULL, - count); - set_fs(old_fs); - - if (offset && put_user(of, offset)) - return -EFAULT; - - return ret; -} - -asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd, - compat_loff_t __user *offset, - compat_size_t count) -{ - mm_segment_t old_fs = get_fs(); - int ret; - loff_t lof; - - if (offset && get_user(lof, offset)) - return -EFAULT; - - set_fs(KERNEL_DS); - ret = sys_sendfile64(out_fd, in_fd, - offset ? (loff_t __user *) &lof : NULL, - count); - set_fs(old_fs); - - if (offset && put_user(lof, offset)) - return -EFAULT; - - return ret; -} - -/* Handle adjtimex compatibility. */ - -struct timex32 { - u32 modes; - s32 offset, freq, maxerror, esterror; - s32 status, constant, precision, tolerance; - struct compat_timeval time; - s32 tick; - s32 ppsfreq, jitter, shift, stabil; - s32 jitcnt, calcnt, errcnt, stbcnt; - s32 :32; s32 :32; s32 :32; s32 :32; - s32 :32; s32 :32; s32 :32; s32 :32; - s32 :32; s32 :32; s32 :32; s32 :32; -}; - -extern int do_adjtimex(struct timex *); - -asmlinkage long sys32_adjtimex(struct timex32 __user *utp) -{ - struct timex txc; - int ret; - - memset(&txc, 0, sizeof(struct timex)); - - if (get_user(txc.modes, &utp->modes) || - __get_user(txc.offset, &utp->offset) || - __get_user(txc.freq, &utp->freq) || - __get_user(txc.maxerror, &utp->maxerror) || - __get_user(txc.esterror, &utp->esterror) || - __get_user(txc.status, &utp->status) || - __get_user(txc.constant, &utp->constant) || - __get_user(txc.precision, &utp->precision) || - __get_user(txc.tolerance, &utp->tolerance) || - __get_user(txc.time.tv_sec, &utp->time.tv_sec) || - __get_user(txc.time.tv_usec, &utp->time.tv_usec) || - __get_user(txc.tick, &utp->tick) || - __get_user(txc.ppsfreq, &utp->ppsfreq) || - __get_user(txc.jitter, &utp->jitter) || - __get_user(txc.shift, &utp->shift) || - __get_user(txc.stabil, &utp->stabil) || - __get_user(txc.jitcnt, &utp->jitcnt) || - __get_user(txc.calcnt, &utp->calcnt) || - __get_user(txc.errcnt, &utp->errcnt) || - __get_user(txc.stbcnt, &utp->stbcnt)) - return -EFAULT; - - ret = do_adjtimex(&txc); - - if (put_user(txc.modes, &utp->modes) || - __put_user(txc.offset, &utp->offset) || - __put_user(txc.freq, &utp->freq) || - __put_user(txc.maxerror, &utp->maxerror) || - __put_user(txc.esterror, &utp->esterror) || - __put_user(txc.status, &utp->status) || - __put_user(txc.constant, &utp->constant) || - __put_user(txc.precision, &utp->precision) || - __put_user(txc.tolerance, &utp->tolerance) || - __put_user(txc.time.tv_sec, &utp->time.tv_sec) || - __put_user(txc.time.tv_usec, &utp->time.tv_usec) || - __put_user(txc.tick, &utp->tick) || - __put_user(txc.ppsfreq, &utp->ppsfreq) || - __put_user(txc.jitter, &utp->jitter) || - __put_user(txc.shift, &utp->shift) || - __put_user(txc.stabil, &utp->stabil) || - __put_user(txc.jitcnt, &utp->jitcnt) || - __put_user(txc.calcnt, &utp->calcnt) || - __put_user(txc.errcnt, &utp->errcnt) || - __put_user(txc.stbcnt, &utp->stbcnt)) - ret = -EFAULT; - - return ret; -} - -/* This is just a version for 32-bit applications which does - * not force O_LARGEFILE on. - */ - -asmlinkage long sparc32_open(const char __user *filename, - int flags, int mode) -{ - return do_sys_open(AT_FDCWD, filename, flags, mode); -} - -extern unsigned long do_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr); - -asmlinkage unsigned long sys32_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, u32 __new_addr) -{ - struct vm_area_struct *vma; - unsigned long ret = -EINVAL; - unsigned long new_addr = __new_addr; - - if (old_len > 0xf0000000UL || new_len > 0xf0000000UL) - goto out; - if (addr > 0xf0000000UL - old_len) - goto out; - down_write(¤t->mm->mmap_sem); - if (flags & MREMAP_FIXED) { - if (new_addr > 0xf0000000UL - new_len) - goto out_sem; - } else if (addr > 0xf0000000UL - new_len) { - unsigned long map_flags = 0; - struct file *file = NULL; - - ret = -ENOMEM; - if (!(flags & MREMAP_MAYMOVE)) - goto out_sem; - - vma = find_vma(current->mm, addr); - if (vma) { - if (vma->vm_flags & VM_SHARED) - map_flags |= MAP_SHARED; - file = vma->vm_file; - } - - /* MREMAP_FIXED checked above. */ - new_addr = get_unmapped_area(file, addr, new_len, - vma ? vma->vm_pgoff : 0, - map_flags); - ret = new_addr; - if (new_addr & ~PAGE_MASK) - goto out_sem; - flags |= MREMAP_FIXED; - } - ret = do_mremap(addr, old_len, new_len, flags, new_addr); -out_sem: - up_write(¤t->mm->mmap_sem); -out: - return ret; -} - -struct __sysctl_args32 { - u32 name; - int nlen; - u32 oldval; - u32 oldlenp; - u32 newval; - u32 newlen; - u32 __unused[4]; -}; - -asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) -{ -#ifndef CONFIG_SYSCTL - return -ENOSYS; -#else - struct __sysctl_args32 tmp; - int error; - size_t oldlen, __user *oldlenp = NULL; - unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL; - - if (copy_from_user(&tmp, args, sizeof(tmp))) - return -EFAULT; - - if (tmp.oldval && tmp.oldlenp) { - /* Duh, this is ugly and might not work if sysctl_args - is in read-only memory, but do_sysctl does indirectly - a lot of uaccess in both directions and we'd have to - basically copy the whole sysctl.c here, and - glibc's __sysctl uses rw memory for the structure - anyway. */ - if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) || - put_user(oldlen, (size_t __user *)addr)) - return -EFAULT; - oldlenp = (size_t __user *)addr; - } - - lock_kernel(); - error = do_sysctl((int __user *)(unsigned long) tmp.name, - tmp.nlen, - (void __user *)(unsigned long) tmp.oldval, - oldlenp, - (void __user *)(unsigned long) tmp.newval, - tmp.newlen); - unlock_kernel(); - if (oldlenp) { - if (!error) { - if (get_user(oldlen, (size_t __user *)addr) || - put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp)) - error = -EFAULT; - } - if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused))) - error = -EFAULT; - } - return error; -#endif -} - -long sys32_lookup_dcookie(unsigned long cookie_high, - unsigned long cookie_low, - char __user *buf, size_t len) -{ - return sys_lookup_dcookie((cookie_high << 32) | cookie_low, - buf, len); -} diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c deleted file mode 100644 index ae5b32f817f..00000000000 --- a/arch/sparc64/kernel/sys_sunos32.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* $Id: sys_sunos32.c,v 1.64 2002/02/09 19:49:31 davem Exp $ - * sys_sunos32.c: SunOS binary compatibility layer on sparc64. - * - * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * Based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/capability.h> -#include <linux/compat.h> -#include <linux/mman.h> -#include <linux/mm.h> -#include <linux/swap.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/resource.h> -#include <linux/ipc.h> -#include <linux/shm.h> -#include <linux/msg.h> -#include <linux/sem.h> -#include <linux/signal.h> -#include <linux/uio.h> -#include <linux/utsname.h> -#include <linux/major.h> -#include <linux/stat.h> -#include <linux/slab.h> -#include <linux/pagemap.h> -#include <linux/errno.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/syscalls.h> - -#include <asm/uaccess.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/pconf.h> -#include <asm/idprom.h> /* for gethostid() */ -#include <asm/unistd.h> -#include <asm/system.h> - -/* For the nfs mount emulation */ -#include <linux/socket.h> -#include <linux/in.h> -#include <linux/nfs.h> -#include <linux/nfs2.h> -#include <linux/nfs_mount.h> - -/* for sunos_select */ -#include <linux/time.h> -#include <linux/personality.h> - -/* For SOCKET_I */ -#include <linux/socket.h> -#include <net/sock.h> -#include <net/compat.h> - -#define SUNOS_NR_OPEN 256 - -asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off) -{ - struct file *file = NULL; - unsigned long retval, ret_type; - - if (flags & MAP_NORESERVE) { - static int cnt; - if (cnt++ < 10) - printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n", - current->comm); - flags &= ~MAP_NORESERVE; - } - retval = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - struct inode * inode; - if (fd >= SUNOS_NR_OPEN) - goto out; - file = fget(fd); - if (!file) - goto out; - inode = file->f_dentry->d_inode; - if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } - } - - retval = -EINVAL; - if (!(flags & MAP_FIXED)) - addr = 0; - else if (len > 0xf0000000 || addr > 0xf0000000 - len) - goto out_putf; - ret_type = flags & _MAP_NEW; - flags &= ~_MAP_NEW; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, - (unsigned long) addr, (unsigned long) len, - (unsigned long) prot, (unsigned long) flags, - (unsigned long) off); - up_write(¤t->mm->mmap_sem); - if (!ret_type) - retval = ((retval < 0xf0000000) ? 0 : retval); -out_putf: - if (file) - fput(file); -out: - return (u32) retval; -} - -asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg) -{ - return 0; -} - -asmlinkage int sunos_brk(u32 baddr) -{ - int freepages, retval = -ENOMEM; - unsigned long rlim; - unsigned long newbrk, oldbrk, brk = (unsigned long) baddr; - - down_write(¤t->mm->mmap_sem); - if (brk < current->mm->end_code) - goto out; - newbrk = PAGE_ALIGN(brk); - oldbrk = PAGE_ALIGN(current->mm->brk); - retval = 0; - if (oldbrk == newbrk) { - current->mm->brk = brk; - goto out; - } - /* Always allow shrinking brk. */ - if (brk <= current->mm->brk) { - current->mm->brk = brk; - do_munmap(current->mm, newbrk, oldbrk-newbrk); - goto out; - } - /* Check against rlimit and stack.. */ - retval = -ENOMEM; - rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; - if (rlim >= RLIM_INFINITY) - rlim = ~0; - if (brk - current->mm->end_code > rlim) - goto out; - /* Check against existing mmap mappings. */ - if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE)) - goto out; - /* stupid algorithm to decide if we have enough memory: while - * simple, it hopefully works in most obvious cases.. Easy to - * fool it, but this should catch most mistakes. - */ - freepages = get_page_cache_size(); - freepages >>= 1; - freepages += nr_free_pages(); - freepages += nr_swap_pages; - freepages -= num_physpages >> 4; - freepages -= (newbrk-oldbrk) >> PAGE_SHIFT; - if (freepages < 0) - goto out; - /* Ok, we have probably got enough memory - let it rip. */ - current->mm->brk = brk; - do_brk(oldbrk, newbrk-oldbrk); - retval = 0; -out: - up_write(¤t->mm->mmap_sem); - return retval; -} - -asmlinkage u32 sunos_sbrk(int increment) -{ - int error, oldbrk; - - /* This should do it hopefully... */ - oldbrk = (int)current->mm->brk; - error = sunos_brk(((int) current->mm->brk) + increment); - if (!error) - error = oldbrk; - return error; -} - -asmlinkage u32 sunos_sstk(int increment) -{ - printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n", - current->comm, increment); - - return (u32)-1; -} - -/* Give hints to the kernel as to what paging strategy to use... - * Completely bogus, don't remind me. - */ -#define VA_NORMAL 0 /* Normal vm usage expected */ -#define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */ -#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */ -#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */ -static char *vstrings[] = { - "VA_NORMAL", - "VA_ABNORMAL", - "VA_SEQUENTIAL", - "VA_INVALIDATE", -}; - -asmlinkage void sunos_vadvise(u32 strategy) -{ - static int count; - - /* I wanna see who uses this... */ - if (count++ < 5) - printk("%s: Advises us to use %s paging strategy\n", - current->comm, - strategy <= 3 ? vstrings[strategy] : "BOGUS"); -} - -/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE - * resource limit and is for backwards compatibility with older sunos - * revs. - */ -asmlinkage int sunos_getdtablesize(void) -{ - return SUNOS_NR_OPEN; -} - - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -asmlinkage u32 sunos_sigblock(u32 blk_mask) -{ - u32 old; - - spin_lock_irq(¤t->sighand->siglock); - old = (u32) current->blocked.sig[0]; - current->blocked.sig[0] |= (blk_mask & _BLOCKABLE); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return old; -} - -asmlinkage u32 sunos_sigsetmask(u32 newmask) -{ - u32 retval; - - spin_lock_irq(¤t->sighand->siglock); - retval = (u32) current->blocked.sig[0]; - current->blocked.sig[0] = (newmask & _BLOCKABLE); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return retval; -} - -/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */ -/* getdents system call, the format of the structure just has a different */ -/* layout (d_off+d_ino instead of d_ino+d_off) */ -struct sunos_dirent { - s32 d_off; - u32 d_ino; - u16 d_reclen; - u16 d_namlen; - char d_name[1]; -}; - -struct sunos_dirent_callback { - struct sunos_dirent __user *curr; - struct sunos_dirent __user *previous; - int count; - int error; -}; - -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) -#define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1)) - -static int sunos_filldir(void * __buf, const char * name, int namlen, - loff_t offset, ino_t ino, unsigned int d_type) -{ - struct sunos_dirent __user *dirent; - struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); - - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; - dirent = buf->previous; - if (dirent) - put_user(offset, &dirent->d_off); - dirent = buf->curr; - buf->previous = dirent; - put_user(ino, &dirent->d_ino); - put_user(namlen, &dirent->d_namlen); - put_user(reclen, &dirent->d_reclen); - if (copy_to_user(dirent->d_name, name, namlen)) - return -EFAULT; - put_user(0, dirent->d_name + namlen); - dirent = (void __user *) dirent + reclen; - buf->curr = dirent; - buf->count -= reclen; - return 0; -} - -asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt) -{ - struct file * file; - struct sunos_dirent __user *lastdirent; - struct sunos_dirent_callback buf; - int error = -EBADF; - - if (fd >= SUNOS_NR_OPEN) - goto out; - - file = fget(fd); - if (!file) - goto out; - - error = -EINVAL; - if (cnt < (sizeof(struct sunos_dirent) + 255)) - goto out_putf; - - buf.curr = (struct sunos_dirent __user *) dirent; - buf.previous = NULL; - buf.count = cnt; - buf.error = 0; - - error = vfs_readdir(file, sunos_filldir, &buf); - if (error < 0) - goto out_putf; - - lastdirent = buf.previous; - error = buf.error; - if (lastdirent) { - put_user(file->f_pos, &lastdirent->d_off); - error = cnt - buf.count; - } - -out_putf: - fput(file); -out: - return error; -} - -/* Old sunos getdirentries, severely broken compatibility stuff here. */ -struct sunos_direntry { - u32 d_ino; - u16 d_reclen; - u16 d_namlen; - char d_name[1]; -}; - -struct sunos_direntry_callback { - struct sunos_direntry __user *curr; - struct sunos_direntry __user *previous; - int count; - int error; -}; - -static int sunos_filldirentry(void * __buf, const char * name, int namlen, - loff_t offset, ino_t ino, unsigned int d_type) -{ - struct sunos_direntry __user *dirent; - struct sunos_direntry_callback * buf = - (struct sunos_direntry_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); - - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; - dirent = buf->previous; - dirent = buf->curr; - buf->previous = dirent; - put_user(ino, &dirent->d_ino); - put_user(namlen, &dirent->d_namlen); - put_user(reclen, &dirent->d_reclen); - if (copy_to_user(dirent->d_name, name, namlen)) - return -EFAULT; - put_user(0, dirent->d_name + namlen); - dirent = (void __user *) dirent + reclen; - buf->curr = dirent; - buf->count -= reclen; - return 0; -} - -asmlinkage int sunos_getdirentries(unsigned int fd, - void __user *dirent, - int cnt, - unsigned int __user *basep) -{ - struct file * file; - struct sunos_direntry __user *lastdirent; - int error = -EBADF; - struct sunos_direntry_callback buf; - - if (fd >= SUNOS_NR_OPEN) - goto out; - - file = fget(fd); - if (!file) - goto out; - - error = -EINVAL; - if (cnt < (sizeof(struct sunos_direntry) + 255)) - goto out_putf; - - buf.curr = (struct sunos_direntry __user *) dirent; - buf.previous = NULL; - buf.count = cnt; - buf.error = 0; - - error = vfs_readdir(file, sunos_filldirentry, &buf); - if (error < 0) - goto out_putf; - - lastdirent = buf.previous; - error = buf.error; - if (lastdirent) { - put_user(file->f_pos, basep); - error = cnt - buf.count; - } - -out_putf: - fput(file); -out: - return error; -} - -struct sunos_utsname { - char sname[9]; - char nname[9]; - char nnext[56]; - char rel[9]; - char ver[9]; - char mach[9]; -}; - -asmlinkage int sunos_uname(struct sunos_utsname __user *name) -{ - int ret; - - down_read(&uts_sem); - ret = copy_to_user(&name->sname[0], &system_utsname.sysname[0], - sizeof(name->sname) - 1); - ret |= copy_to_user(&name->nname[0], &system_utsname.nodename[0], - sizeof(name->nname) - 1); - ret |= put_user('\0', &name->nname[8]); - ret |= copy_to_user(&name->rel[0], &system_utsname.release[0], - sizeof(name->rel) - 1); - ret |= copy_to_user(&name->ver[0], &system_utsname.version[0], - sizeof(name->ver) - 1); - ret |= copy_to_user(&name->mach[0], &system_utsname.machine[0], - sizeof(name->mach) - 1); - up_read(&uts_sem); - return (ret ? -EFAULT : 0); -} - -asmlinkage int sunos_nosys(void) -{ - struct pt_regs *regs; - siginfo_t info; - static int cnt; - - regs = current_thread_info()->kregs; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGSYS; - info.si_errno = 0; - info.si_code = __SI_FAULT|0x100; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = regs->u_regs[UREG_G1]; - send_sig_info(SIGSYS, &info, current); - if (cnt++ < 4) { - printk("Process makes ni_syscall number %d, register dump:\n", - (int) regs->u_regs[UREG_G1]); - show_regs(regs); - } - return -ENOSYS; -} - -/* This is not a real and complete implementation yet, just to keep - * the easy SunOS binaries happy. - */ -asmlinkage int sunos_fpathconf(int fd, int name) -{ - int ret; - - switch(name) { - case _PCONF_LINK: - ret = LINK_MAX; - break; - case _PCONF_CANON: - ret = MAX_CANON; - break; - case _PCONF_INPUT: - ret = MAX_INPUT; - break; - case _PCONF_NAME: - ret = NAME_MAX; - break; - case _PCONF_PATH: - ret = PATH_MAX; - break; - case _PCONF_PIPE: - ret = PIPE_BUF; - break; - case _PCONF_CHRESTRICT: /* XXX Investigate XXX */ - ret = 1; - break; - case _PCONF_NOTRUNC: /* XXX Investigate XXX */ - case _PCONF_VDISABLE: - ret = 0; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -asmlinkage int sunos_pathconf(u32 u_path, int name) -{ - int ret; - - ret = sunos_fpathconf(0, name); /* XXX cheese XXX */ - return ret; -} - -asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x) -{ - int ret; - - /* SunOS binaries expect that select won't change the tvp contents */ - ret = compat_sys_select(width, compat_ptr(inp), compat_ptr(outp), - compat_ptr(exp), compat_ptr(tvp_x)); - if (ret == -EINTR && tvp_x) { - struct compat_timeval __user *tvp = compat_ptr(tvp_x); - time_t sec, usec; - - __get_user(sec, &tvp->tv_sec); - __get_user(usec, &tvp->tv_usec); - if (sec == 0 && usec == 0) - ret = 0; - } - return ret; -} - -asmlinkage void sunos_nop(void) -{ - return; -} - -#if 0 /* This code doesn't translate user pointers correctly, - * disable for now. -DaveM - */ - -/* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */ -#define SMNT_RDONLY 1 -#define SMNT_NOSUID 2 -#define SMNT_NEWTYPE 4 -#define SMNT_GRPID 8 -#define SMNT_REMOUNT 16 -#define SMNT_NOSUB 32 -#define SMNT_MULTI 64 -#define SMNT_SYS5 128 - -struct sunos_fh_t { - char fh_data [NFS_FHSIZE]; -}; - -struct sunos_nfs_mount_args { - struct sockaddr_in *addr; /* file server address */ - struct nfs_fh *fh; /* File handle to be mounted */ - int flags; /* flags */ - int wsize; /* write size in bytes */ - int rsize; /* read size in bytes */ - int timeo; /* initial timeout in .1 secs */ - int retrans; /* times to retry send */ - char *hostname; /* server's hostname */ - int acregmin; /* attr cache file min secs */ - int acregmax; /* attr cache file max secs */ - int acdirmin; /* attr cache dir min secs */ - int acdirmax; /* attr cache dir max secs */ - char *netname; /* server's netname */ -}; - - -/* Bind the socket on a local reserved port and connect it to the - * remote server. This on Linux/i386 is done by the mount program, - * not by the kernel. - */ -/* XXXXXXXXXXXXXXXXXXXX */ -static int -sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) -{ - struct sockaddr_in local; - struct sockaddr_in server; - int try_port; - int ret; - struct socket *socket; - struct inode *inode; - struct file *file; - - file = fget(fd); - if (!file) - return 0; - - inode = file->f_dentry->d_inode; - - socket = SOCKET_I(inode); - local.sin_family = AF_INET; - local.sin_addr.s_addr = INADDR_ANY; - - /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */ - try_port = 1024; - do { - local.sin_port = htons (--try_port); - ret = socket->ops->bind(socket, (struct sockaddr*)&local, - sizeof(local)); - } while (ret && try_port > (1024 / 2)); - - if (ret) { - fput(file); - return 0; - } - - server.sin_family = AF_INET; - server.sin_addr = addr->sin_addr; - server.sin_port = NFS_PORT; - - /* Call sys_connect */ - ret = socket->ops->connect (socket, (struct sockaddr *) &server, - sizeof (server), file->f_flags); - fput(file); - if (ret < 0) - return 0; - return 1; -} - -/* XXXXXXXXXXXXXXXXXXXX */ -static int get_default (int value, int def_value) -{ - if (value) - return value; - else - return def_value; -} - -/* XXXXXXXXXXXXXXXXXXXX */ -static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data) -{ - int server_fd, err; - char *the_name, *mount_page; - struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args sunos_mount; - - /* Ok, here comes the fun part: Linux's nfs mount needs a - * socket connection to the server, but SunOS mount does not - * require this, so we use the information on the destination - * address to create a socket and bind it to a reserved - * port on this system - */ - if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount))) - return -EFAULT; - - server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (server_fd < 0) - return -ENXIO; - - if (copy_from_user(&linux_nfs_mount.addr, sunos_mount.addr, - sizeof(*sunos_mount.addr)) || - copy_from_user(&linux_nfs_mount.root, sunos_mount.fh, - sizeof(*sunos_mount.fh))) { - sys_close (server_fd); - return -EFAULT; - } - - if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ - sys_close (server_fd); - return -ENXIO; - } - - /* Now, bind it to a locally reserved port */ - linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount.flags; - linux_nfs_mount.fd = server_fd; - - linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); - linux_nfs_mount.retrans = sunos_mount.retrans; - - linux_nfs_mount.acregmin = sunos_mount.acregmin; - linux_nfs_mount.acregmax = sunos_mount.acregmax; - linux_nfs_mount.acdirmin = sunos_mount.acdirmin; - linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - - the_name = getname(sunos_mount.hostname); - if (IS_ERR(the_name)) - return PTR_ERR(the_name); - - strlcpy(linux_nfs_mount.hostname, the_name, - sizeof(linux_nfs_mount.hostname)); - putname (the_name); - - mount_page = (char *) get_zeroed_page(GFP_KERNEL); - if (!mount_page) - return -ENOMEM; - - memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount)); - - err = do_mount("", dir_name, "nfs", linux_flags, mount_page); - - free_page((unsigned long) mount_page); - return err; -} - -/* XXXXXXXXXXXXXXXXXXXX */ -asmlinkage int -sunos_mount(char *type, char *dir, int flags, void *data) -{ - int linux_flags = 0; - int ret = -EINVAL; - char *dev_fname = 0; - char *dir_page, *type_page; - - if (!capable (CAP_SYS_ADMIN)) - return -EPERM; - - /* We don't handle the integer fs type */ - if ((flags & SMNT_NEWTYPE) == 0) - goto out; - - /* Do not allow for those flags we don't support */ - if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5)) - goto out; - - if (flags & SMNT_REMOUNT) - linux_flags |= MS_REMOUNT; - if (flags & SMNT_RDONLY) - linux_flags |= MS_RDONLY; - if (flags & SMNT_NOSUID) - linux_flags |= MS_NOSUID; - - dir_page = getname(dir); - ret = PTR_ERR(dir_page); - if (IS_ERR(dir_page)) - goto out; - - type_page = getname(type); - ret = PTR_ERR(type_page); - if (IS_ERR(type_page)) - goto out1; - - if (strcmp(type_page, "ext2") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "iso9660") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "minix") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "nfs") == 0) { - ret = sunos_nfs_mount (dir_page, flags, data); - goto out2; - } else if (strcmp(type_page, "ufs") == 0) { - printk("Warning: UFS filesystem mounts unsupported.\n"); - ret = -ENODEV; - goto out2; - } else if (strcmp(type_page, "proc")) { - ret = -ENODEV; - goto out2; - } - ret = PTR_ERR(dev_fname); - if (IS_ERR(dev_fname)) - goto out2; - lock_kernel(); - ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); - unlock_kernel(); - if (dev_fname) - putname(dev_fname); -out2: - putname(type_page); -out1: - putname(dir_page); -out: - return ret; -} -#endif - -asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid) -{ - int ret; - - /* So stupid... */ - if ((!pid || pid == current->pid) && - !pgid) { - sys_setsid(); - ret = 0; - } else { - ret = sys_setpgid(pid, pgid); - } - return ret; -} - -/* So stupid... */ -extern long compat_sys_wait4(compat_pid_t, compat_uint_t __user *, int, - struct compat_rusage __user *); - -asmlinkage int sunos_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru) -{ - int ret; - - ret = compat_sys_wait4((pid ? pid : ((compat_pid_t)-1)), - stat_addr, options, ru); - return ret; -} - -extern int kill_pg(int, int, int); -asmlinkage int sunos_killpg(int pgrp, int sig) -{ - return kill_pg(pgrp, sig, 0); -} - -asmlinkage int sunos_audit(void) -{ - printk ("sys_audit\n"); - return -1; -} - -asmlinkage u32 sunos_gethostid(void) -{ - u32 ret; - - ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum)); - - return ret; -} - -/* sysconf options, for SunOS compatibility */ -#define _SC_ARG_MAX 1 -#define _SC_CHILD_MAX 2 -#define _SC_CLK_TCK 3 -#define _SC_NGROUPS_MAX 4 -#define _SC_OPEN_MAX 5 -#define _SC_JOB_CONTROL 6 -#define _SC_SAVED_IDS 7 -#define _SC_VERSION 8 - -asmlinkage s32 sunos_sysconf (int name) -{ - s32 ret; - - switch (name){ - case _SC_ARG_MAX: - ret = ARG_MAX; - break; - case _SC_CHILD_MAX: - ret = -1; /* no limit */ - break; - case _SC_CLK_TCK: - ret = HZ; - break; - case _SC_NGROUPS_MAX: - ret = NGROUPS_MAX; - break; - case _SC_OPEN_MAX: - ret = OPEN_MAX; - break; - case _SC_JOB_CONTROL: - ret = 1; /* yes, we do support job control */ - break; - case _SC_SAVED_IDS: - ret = 1; /* yes, we do support saved uids */ - break; - case _SC_VERSION: - /* mhm, POSIX_VERSION is in /usr/include/unistd.h - * should it go on /usr/include/linux? - */ - ret = 199009; - break; - default: - ret = -1; - break; - }; - return ret; -} - -asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, void __user *ptr) -{ - union semun arg4; - int ret; - - switch (op) { - case 0: - /* Most arguments match on a 1:1 basis but cmd doesn't */ - switch(arg3) { - case 4: - arg3=GETPID; break; - case 5: - arg3=GETVAL; break; - case 6: - arg3=GETALL; break; - case 3: - arg3=GETNCNT; break; - case 7: - arg3=GETZCNT; break; - case 8: - arg3=SETVAL; break; - case 9: - arg3=SETALL; break; - } - /* sys_semctl(): */ - /* value to modify semaphore to */ - arg4.__pad = ptr; - ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4); - break; - case 1: - /* sys_semget(): */ - ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3); - break; - case 2: - /* sys_semop(): */ - ret = sys_semop((int)arg1, (struct sembuf __user *)(unsigned long)arg2, - (unsigned int) arg3); - break; - default: - ret = -EINVAL; - break; - }; - return ret; -} - -struct msgbuf32 { - s32 mtype; - char mtext[1]; -}; - -struct ipc_perm32 -{ - key_t key; - compat_uid_t uid; - compat_gid_t gid; - compat_uid_t cuid; - compat_gid_t cgid; - compat_mode_t mode; - unsigned short seq; -}; - -struct msqid_ds32 -{ - struct ipc_perm32 msg_perm; - u32 msg_first; - u32 msg_last; - compat_time_t msg_stime; - compat_time_t msg_rtime; - compat_time_t msg_ctime; - u32 wwait; - u32 rwait; - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - compat_ipc_pid_t msg_lspid; - compat_ipc_pid_t msg_lrpid; -}; - -static inline int sunos_msqid_get(struct msqid_ds32 __user *user, - struct msqid_ds *kern) -{ - if (get_user(kern->msg_perm.key, &user->msg_perm.key) || - __get_user(kern->msg_perm.uid, &user->msg_perm.uid) || - __get_user(kern->msg_perm.gid, &user->msg_perm.gid) || - __get_user(kern->msg_perm.cuid, &user->msg_perm.cuid) || - __get_user(kern->msg_perm.cgid, &user->msg_perm.cgid) || - __get_user(kern->msg_stime, &user->msg_stime) || - __get_user(kern->msg_rtime, &user->msg_rtime) || - __get_user(kern->msg_ctime, &user->msg_ctime) || - __get_user(kern->msg_ctime, &user->msg_cbytes) || - __get_user(kern->msg_ctime, &user->msg_qnum) || - __get_user(kern->msg_ctime, &user->msg_qbytes) || - __get_user(kern->msg_ctime, &user->msg_lspid) || - __get_user(kern->msg_ctime, &user->msg_lrpid)) - return -EFAULT; - return 0; -} - -static inline int sunos_msqid_put(struct msqid_ds32 __user *user, - struct msqid_ds *kern) -{ - if (put_user(kern->msg_perm.key, &user->msg_perm.key) || - __put_user(kern->msg_perm.uid, &user->msg_perm.uid) || - __put_user(kern->msg_perm.gid, &user->msg_perm.gid) || - __put_user(kern->msg_perm.cuid, &user->msg_perm.cuid) || - __put_user(kern->msg_perm.cgid, &user->msg_perm.cgid) || - __put_user(kern->msg_stime, &user->msg_stime) || - __put_user(kern->msg_rtime, &user->msg_rtime) || - __put_user(kern->msg_ctime, &user->msg_ctime) || - __put_user(kern->msg_ctime, &user->msg_cbytes) || - __put_user(kern->msg_ctime, &user->msg_qnum) || - __put_user(kern->msg_ctime, &user->msg_qbytes) || - __put_user(kern->msg_ctime, &user->msg_lspid) || - __put_user(kern->msg_ctime, &user->msg_lrpid)) - return -EFAULT; - return 0; -} - -static inline int sunos_msgbuf_get(struct msgbuf32 __user *user, struct msgbuf *kern, int len) -{ - if (get_user(kern->mtype, &user->mtype) || - __copy_from_user(kern->mtext, &user->mtext, len)) - return -EFAULT; - return 0; -} - -static inline int sunos_msgbuf_put(struct msgbuf32 __user *user, struct msgbuf *kern, int len) -{ - if (put_user(kern->mtype, &user->mtype) || - __copy_to_user(user->mtext, kern->mtext, len)) - return -EFAULT; - return 0; -} - -asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4) -{ - struct sparc_stackf32 __user *sp; - struct msqid_ds kds; - struct msgbuf *kmbuf; - mm_segment_t old_fs = get_fs(); - u32 arg5; - int rval; - - switch(op) { - case 0: - rval = sys_msgget((key_t)arg1, (int)arg2); - break; - case 1: - if (!sunos_msqid_get((struct msqid_ds32 __user *)(unsigned long)arg3, &kds)) { - set_fs(KERNEL_DS); - rval = sys_msgctl((int)arg1, (int)arg2, - (struct msqid_ds __user *)(unsigned long)arg3); - set_fs(old_fs); - if (!rval) - rval = sunos_msqid_put((struct msqid_ds32 __user *)(unsigned long)arg3, - &kds); - } else - rval = -EFAULT; - break; - case 2: - rval = -EFAULT; - kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3, - GFP_KERNEL); - if (!kmbuf) - break; - sp = (struct sparc_stackf32 __user *) - (current_thread_info()->kregs->u_regs[UREG_FP] & 0xffffffffUL); - if (get_user(arg5, &sp->xxargs[0])) { - rval = -EFAULT; - kfree(kmbuf); - break; - } - set_fs(KERNEL_DS); - rval = sys_msgrcv((int)arg1, (struct msgbuf __user *) kmbuf, - (size_t)arg3, - (long)arg4, (int)arg5); - set_fs(old_fs); - if (!rval) - rval = sunos_msgbuf_put((struct msgbuf32 __user *)(unsigned long)arg2, - kmbuf, arg3); - kfree(kmbuf); - break; - case 3: - rval = -EFAULT; - kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3, - GFP_KERNEL); - if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2, - kmbuf, arg3)) - break; - set_fs(KERNEL_DS); - rval = sys_msgsnd((int)arg1, (struct msgbuf __user *) kmbuf, - (size_t)arg3, (int)arg4); - set_fs(old_fs); - kfree(kmbuf); - break; - default: - rval = -EINVAL; - break; - } - return rval; -} - -struct shmid_ds32 { - struct ipc_perm32 shm_perm; - int shm_segsz; - compat_time_t shm_atime; - compat_time_t shm_dtime; - compat_time_t shm_ctime; - compat_ipc_pid_t shm_cpid; - compat_ipc_pid_t shm_lpid; - unsigned short shm_nattch; -}; - -static inline int sunos_shmid_get(struct shmid_ds32 __user *user, - struct shmid_ds *kern) -{ - if (get_user(kern->shm_perm.key, &user->shm_perm.key) || - __get_user(kern->shm_perm.uid, &user->shm_perm.uid) || - __get_user(kern->shm_perm.gid, &user->shm_perm.gid) || - __get_user(kern->shm_perm.cuid, &user->shm_perm.cuid) || - __get_user(kern->shm_perm.cgid, &user->shm_perm.cgid) || - __get_user(kern->shm_segsz, &user->shm_segsz) || - __get_user(kern->shm_atime, &user->shm_atime) || - __get_user(kern->shm_dtime, &user->shm_dtime) || - __get_user(kern->shm_ctime, &user->shm_ctime) || - __get_user(kern->shm_cpid, &user->shm_cpid) || - __get_user(kern->shm_lpid, &user->shm_lpid) || - __get_user(kern->shm_nattch, &user->shm_nattch)) - return -EFAULT; - return 0; -} - -static inline int sunos_shmid_put(struct shmid_ds32 __user *user, - struct shmid_ds *kern) -{ - if (put_user(kern->shm_perm.key, &user->shm_perm.key) || - __put_user(kern->shm_perm.uid, &user->shm_perm.uid) || - __put_user(kern->shm_perm.gid, &user->shm_perm.gid) || - __put_user(kern->shm_perm.cuid, &user->shm_perm.cuid) || - __put_user(kern->shm_perm.cgid, &user->shm_perm.cgid) || - __put_user(kern->shm_segsz, &user->shm_segsz) || - __put_user(kern->shm_atime, &user->shm_atime) || - __put_user(kern->shm_dtime, &user->shm_dtime) || - __put_user(kern->shm_ctime, &user->shm_ctime) || - __put_user(kern->shm_cpid, &user->shm_cpid) || - __put_user(kern->shm_lpid, &user->shm_lpid) || - __put_user(kern->shm_nattch, &user->shm_nattch)) - return -EFAULT; - return 0; -} - -asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3) -{ - struct shmid_ds ksds; - unsigned long raddr; - mm_segment_t old_fs = get_fs(); - int rval; - - switch(op) { - case 0: - /* do_shmat(): attach a shared memory area */ - rval = do_shmat((int)arg1,(char __user *)(unsigned long)arg2,(int)arg3,&raddr); - if (!rval) - rval = (int) raddr; - break; - case 1: - /* sys_shmctl(): modify shared memory area attr. */ - if (!sunos_shmid_get((struct shmid_ds32 __user *)(unsigned long)arg3, &ksds)) { - set_fs(KERNEL_DS); - rval = sys_shmctl((int) arg1,(int) arg2, - (struct shmid_ds __user *) &ksds); - set_fs(old_fs); - if (!rval) - rval = sunos_shmid_put((struct shmid_ds32 __user *)(unsigned long)arg3, - &ksds); - } else - rval = -EFAULT; - break; - case 2: - /* sys_shmdt(): detach a shared memory area */ - rval = sys_shmdt((char __user *)(unsigned long)arg1); - break; - case 3: - /* sys_shmget(): get a shared memory area */ - rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3); - break; - default: - rval = -EINVAL; - break; - }; - return rval; -} - -extern asmlinkage long sparc32_open(const char __user * filename, int flags, int mode); - -asmlinkage int sunos_open(u32 fname, int flags, int mode) -{ - const char __user *filename = compat_ptr(fname); - - return sparc32_open(filename, flags, mode); -} - -#define SUNOS_EWOULDBLOCK 35 - -/* see the sunos man page read(2v) for an explanation - of this garbage. We use O_NDELAY to mark - file descriptors that have been set non-blocking - using 4.2BSD style calls. (tridge) */ - -static inline int check_nonblock(int ret, int fd) -{ - if (ret == -EAGAIN) { - struct file * file = fget(fd); - if (file) { - if (file->f_flags & O_NDELAY) - ret = -SUNOS_EWOULDBLOCK; - fput(file); - } - } - return ret; -} - -asmlinkage int sunos_read(unsigned int fd, char __user *buf, u32 count) -{ - int ret; - - ret = check_nonblock(sys_read(fd, buf, count), fd); - return ret; -} - -asmlinkage int sunos_readv(u32 fd, void __user *vector, s32 count) -{ - int ret; - - ret = check_nonblock(compat_sys_readv(fd, vector, count), fd); - return ret; -} - -asmlinkage int sunos_write(unsigned int fd, char __user *buf, u32 count) -{ - int ret; - - ret = check_nonblock(sys_write(fd, buf, count), fd); - return ret; -} - -asmlinkage int sunos_writev(u32 fd, void __user *vector, s32 count) -{ - int ret; - - ret = check_nonblock(compat_sys_writev(fd, vector, count), fd); - return ret; -} - -asmlinkage int sunos_recv(u32 __fd, void __user *ubuf, int size, unsigned flags) -{ - int ret, fd = (int) __fd; - - ret = check_nonblock(sys_recv(fd, ubuf, size, flags), fd); - return ret; -} - -asmlinkage int sunos_send(u32 __fd, void __user *buff, int len, unsigned flags) -{ - int ret, fd = (int) __fd; - - ret = check_nonblock(sys_send(fd, buff, len, flags), fd); - return ret; -} - -asmlinkage int sunos_accept(u32 __fd, struct sockaddr __user *sa, int __user *addrlen) -{ - int ret, fd = (int) __fd; - - while (1) { - ret = check_nonblock(sys_accept(fd, sa, addrlen), fd); - if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) - break; - } - return ret; -} - -#define SUNOS_SV_INTERRUPT 2 - -asmlinkage int sunos_sigaction (int sig, - struct old_sigaction32 __user *act, - struct old_sigaction32 __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - compat_old_sigset_t mask; - u32 u_handler; - - if (get_user(u_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags)) - return -EFAULT; - new_ka.sa.sa_handler = compat_ptr(u_handler); - __get_user(mask, &act->sa_mask); - new_ka.sa.sa_restorer = NULL; - new_ka.ka_restorer = NULL; - siginitset(&new_ka.sa.sa_mask, mask); - new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; - if (put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) - return -EFAULT; - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -asmlinkage int sunos_setsockopt(u32 __fd, u32 __level, u32 __optname, - char __user *optval, u32 __optlen) -{ - int fd = (int) __fd; - int level = (int) __level; - int optname = (int) __optname; - int optlen = (int) __optlen; - int tr_opt = optname; - int ret; - - if (level == SOL_IP) { - /* Multicast socketopts (ttl, membership) */ - if (tr_opt >=2 && tr_opt <= 6) - tr_opt += 30; - } - ret = sys_setsockopt(fd, level, tr_opt, - optval, optlen); - return ret; -} - -asmlinkage int sunos_getsockopt(u32 __fd, u32 __level, u32 __optname, - char __user *optval, int __user *optlen) -{ - int fd = (int) __fd; - int level = (int) __level; - int optname = (int) __optname; - int tr_opt = optname; - int ret; - - if (level == SOL_IP) { - /* Multicast socketopts (ttl, membership) */ - if (tr_opt >=2 && tr_opt <= 6) - tr_opt += 30; - } - ret = compat_sys_getsockopt(fd, level, tr_opt, - optval, optlen); - return ret; -} diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S deleted file mode 100644 index bf0fc5bfbfb..00000000000 --- a/arch/sparc64/kernel/systbls.S +++ /dev/null @@ -1,264 +0,0 @@ -/* $Id: systbls.S,v 1.81 2002/02/08 03:57:14 davem Exp $ - * systbls.S: System call entry point tables for OS compatibility. - * The native Linux system call table lives here also. - * - * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * Based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - */ - -#include <linux/config.h> - - .text - .align 4 - -#ifdef CONFIG_COMPAT - /* First, the 32-bit Linux native syscall table. */ - - .globl sys_call_table32 -sys_call_table32: -/*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write -/*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link -/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod -/*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek -/*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16 -/*25*/ .word compat_sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause -/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice - .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile -/*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid - .word sys32_umount, sys32_setgid16, sys32_getgid16, sys32_signal, sys32_geteuid16 -/*50*/ .word sys32_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl - .word sys32_reboot, sys32_mmap2, sys_symlink, sys32_readlink, sys32_execve -/*60*/ .word sys32_umask, sys_chroot, compat_sys_newfstat, compat_sys_fstat64, sys_getpagesize - .word sys32_msync, sys_vfork, sys32_pread64, sys32_pwrite64, sys_geteuid -/*70*/ .word sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect - .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16 -/*80*/ .word sys32_setgroups16, sys_getpgrp, sys32_setgroups, sys32_setitimer, sys32_ftruncate64 - .word sys32_swapon, sys32_getitimer, sys_setuid, sys32_sethostname, sys_setgid -/*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid - .word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending - .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid -/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall - .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd -/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod - .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate -/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys32_mkdir, sys_rmdir, sys32_utimes, compat_sys_stat64 -/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit - .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write -/*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 - .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount -/*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys32_getdomainname, sys32_setdomainname, sys_nis_syscall - .word sys_quotactl, sys_set_tid_address, compat_sys_mount, sys_ustat, sys32_setxattr -/*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents - .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr -/*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall - .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sparc64_newuname -/*190*/ .word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl - .word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask -/*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir - .word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64 -/*210*/ .word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, sys32_sysinfo - .word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, sys32_adjtimex -/*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid - .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16 -/*230*/ .word sys32_select, compat_sys_time, sys_nis_syscall, compat_sys_stime, compat_sys_statfs64 - .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall -/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler - .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep -/*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl - .word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep -/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun - .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy -/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink - .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid -/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat - .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat -/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat - .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll - -#endif /* CONFIG_COMPAT */ - - /* Now the 64-bit native Linux syscall table. */ - - .align 4 - .globl sys_call_table64, sys_call_table -sys_call_table64: -sys_call_table: -/*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write -/*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link -/*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod -/*15*/ .word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek -/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid -/*25*/ .word sys_nis_syscall, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall -/*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice - .word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile64 -/*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall - .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid -/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl - .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve -/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize - .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall -/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect - .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups -/*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall - .word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall -/*90*/ .word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall - .word sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept -/*100*/ .word sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending - .word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_setresuid, sys_getresuid -/*110*/ .word sys_setresgid, sys_getresgid, sys_nis_syscall, sys_recvmsg, sys_sendmsg - .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd -/*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod - .word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate -/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_sendto, sys_shutdown - .word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64 -/*140*/ .word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit - .word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write -/*150*/ .word sys_getsockname, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 - .word sys_nis_syscall, sys_inotify_rm_watch, sys_statfs, sys_fstatfs, sys_oldumount -/*160*/ .word sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_utrap_install - .word sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr -/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents - .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr -/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall - .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sparc64_newuname -/*190*/ .word sys_init_module, sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl - .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask -/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall - .word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64 -/*210*/ .word sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo - .word sys_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex -/*220*/ .word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid - .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid -/*230*/ .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_statfs64 - .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall -/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler - .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep -/*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl - .word sys_ni_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep -/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun - .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy -/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink - .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid -/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat - .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat -/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat - .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll - -#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ - defined(CONFIG_SOLARIS_EMUL_MODULE) - /* Now the 32-bit SunOS syscall table. */ - - .align 4 - .globl sunos_sys_table -sunos_sys_table: -/*0*/ .word sunos_indir, sys32_exit, sys_fork - .word sunos_read, sunos_write, sunos_open - .word sys_close, sunos_wait4, sys_creat - .word sys_link, sys_unlink, sunos_execv - .word sys_chdir, sunos_nosys, sys32_mknod - .word sys_chmod, sys32_lchown16, sunos_brk - .word sunos_nosys, sys32_lseek, sunos_getpid - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_getuid, sunos_nosys, sys_ptrace - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sys_access, sunos_nosys, sunos_nosys - .word sys_sync, sys_kill, compat_sys_newstat - .word sunos_nosys, compat_sys_newlstat, sys_dup - .word sys_pipe, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_getgid - .word sunos_nosys, sunos_nosys -/*50*/ .word sunos_nosys, sys_acct, sunos_nosys - .word sunos_mctl, sunos_ioctl, sys_reboot - .word sunos_nosys, sys_symlink, sys_readlink - .word sys32_execve, sys_umask, sys_chroot - .word compat_sys_newfstat, sunos_nosys, sys_getpagesize - .word sys_msync, sys_vfork, sunos_nosys - .word sunos_nosys, sunos_sbrk, sunos_sstk - .word sunos_mmap, sunos_vadvise, sys_munmap - .word sys_mprotect, sys_madvise, sys_vhangup - .word sunos_nosys, sys_mincore, sys32_getgroups16 - .word sys32_setgroups16, sys_getpgrp, sunos_setpgrp - .word compat_sys_setitimer, sunos_nosys, sys_swapon - .word compat_sys_getitimer, sys_gethostname, sys_sethostname - .word sunos_getdtablesize, sys_dup2, sunos_nop - .word compat_sys_fcntl, sunos_select, sunos_nop - .word sys_fsync, sys32_setpriority, sys32_socket - .word sys32_connect, sunos_accept -/*100*/ .word sys_getpriority, sunos_send, sunos_recv - .word sunos_nosys, sys32_bind, sunos_setsockopt - .word sys32_listen, sunos_nosys, sunos_sigaction - .word sunos_sigblock, sunos_sigsetmask, sys_sigpause - .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg - .word sunos_nosys, sys32_gettimeofday, compat_sys_getrusage - .word sunos_getsockopt, sunos_nosys, sunos_readv - .word sunos_writev, sys32_settimeofday, sys32_fchown16 - .word sys_fchmod, sys32_recvfrom, sys32_setreuid16 - .word sys32_setregid16, sys_rename, sys_truncate - .word sys_ftruncate, sys_flock, sunos_nosys - .word sys32_sendto, sys32_shutdown, sys32_socketpair - .word sys_mkdir, sys_rmdir, sys32_utimes - .word sys32_sigreturn, sunos_nosys, sys32_getpeername - .word sunos_gethostid, sunos_nosys, compat_sys_getrlimit - .word compat_sys_setrlimit, sunos_killpg, sunos_nosys - .word sunos_nosys, sunos_nosys -/*150*/ .word sys32_getsockname, sunos_nosys, sunos_nosys - .word sys_poll, sunos_nosys, sunos_nosys - .word sunos_getdirentries, compat_sys_statfs, compat_sys_fstatfs - .word sys_oldumount, sunos_nosys, sunos_nosys - .word sys_getdomainname, sys_setdomainname - .word sunos_nosys, sys_quotactl, sunos_nosys - .word sunos_nosys, sys_ustat, sunos_semsys - .word sunos_nosys, sunos_shmsys, sunos_audit - .word sunos_nosys, sunos_getdents, sys_setsid - .word sys_fchdir, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, compat_sys_sigpending, sunos_nosys - .word sys_setpgid, sunos_pathconf, sunos_fpathconf - .word sunos_sysconf, sunos_uname, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys -/*200*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys -/*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*260*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*270*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*280*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys -#endif diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c deleted file mode 100644 index a22930d62ad..00000000000 --- a/arch/sparc64/kernel/time.c +++ /dev/null @@ -1,1181 +0,0 @@ -/* $Id: time.c,v 1.42 2002/01/23 14:33:55 davem Exp $ - * time.c: UltraSparc timer and TOD clock support. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * - * Based largely on code which is: - * - * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) - */ - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/mc146818rtc.h> -#include <linux/delay.h> -#include <linux/profile.h> -#include <linux/bcd.h> -#include <linux/jiffies.h> -#include <linux/cpufreq.h> -#include <linux/percpu.h> -#include <linux/profile.h> - -#include <asm/oplib.h> -#include <asm/mostek.h> -#include <asm/timer.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/sbus.h> -#include <asm/fhc.h> -#include <asm/pbm.h> -#include <asm/ebus.h> -#include <asm/isa.h> -#include <asm/starfire.h> -#include <asm/smp.h> -#include <asm/sections.h> -#include <asm/cpudata.h> - -DEFINE_SPINLOCK(mostek_lock); -DEFINE_SPINLOCK(rtc_lock); -void __iomem *mstk48t02_regs = NULL; -#ifdef CONFIG_PCI -unsigned long ds1287_regs = 0UL; -#endif - -extern unsigned long wall_jiffies; - -static void __iomem *mstk48t08_regs; -static void __iomem *mstk48t59_regs; - -static int set_rtc_mmss(unsigned long); - -#define TICK_PRIV_BIT (1UL << 63) - -#ifdef CONFIG_SMP -unsigned long profile_pc(struct pt_regs *regs) -{ - unsigned long pc = instruction_pointer(regs); - - if (in_lock_functions(pc)) - return regs->u_regs[UREG_RETPC]; - return pc; -} -EXPORT_SYMBOL(profile_pc); -#endif - -static void tick_disable_protection(void) -{ - /* Set things up so user can access tick register for profiling - * purposes. Also workaround BB_ERRATA_1 by doing a dummy - * read back of %tick after writing it. - */ - __asm__ __volatile__( - " ba,pt %%xcc, 1f\n" - " nop\n" - " .align 64\n" - "1: rd %%tick, %%g2\n" - " add %%g2, 6, %%g2\n" - " andn %%g2, %0, %%g2\n" - " wrpr %%g2, 0, %%tick\n" - " rdpr %%tick, %%g0" - : /* no outputs */ - : "r" (TICK_PRIV_BIT) - : "g2"); -} - -static void tick_init_tick(unsigned long offset) -{ - tick_disable_protection(); - - __asm__ __volatile__( - " rd %%tick, %%g1\n" - " andn %%g1, %1, %%g1\n" - " ba,pt %%xcc, 1f\n" - " add %%g1, %0, %%g1\n" - " .align 64\n" - "1: wr %%g1, 0x0, %%tick_cmpr\n" - " rd %%tick_cmpr, %%g0" - : /* no outputs */ - : "r" (offset), "r" (TICK_PRIV_BIT) - : "g1"); -} - -static unsigned long tick_get_tick(void) -{ - unsigned long ret; - - __asm__ __volatile__("rd %%tick, %0\n\t" - "mov %0, %0" - : "=r" (ret)); - - return ret & ~TICK_PRIV_BIT; -} - -static unsigned long tick_get_compare(void) -{ - unsigned long ret; - - __asm__ __volatile__("rd %%tick_cmpr, %0\n\t" - "mov %0, %0" - : "=r" (ret)); - - return ret; -} - -static unsigned long tick_add_compare(unsigned long adj) -{ - unsigned long new_compare; - - /* Workaround for Spitfire Errata (#54 I think??), I discovered - * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch - * number 103640. - * - * On Blackbird writes to %tick_cmpr can fail, the - * workaround seems to be to execute the wr instruction - * at the start of an I-cache line, and perform a dummy - * read back from %tick_cmpr right after writing to it. -DaveM - */ - __asm__ __volatile__("rd %%tick_cmpr, %0\n\t" - "ba,pt %%xcc, 1f\n\t" - " add %0, %1, %0\n\t" - ".align 64\n" - "1:\n\t" - "wr %0, 0, %%tick_cmpr\n\t" - "rd %%tick_cmpr, %%g0" - : "=&r" (new_compare) - : "r" (adj)); - - return new_compare; -} - -static unsigned long tick_add_tick(unsigned long adj, unsigned long offset) -{ - unsigned long new_tick, tmp; - - /* Also need to handle Blackbird bug here too. */ - __asm__ __volatile__("rd %%tick, %0\n\t" - "add %0, %2, %0\n\t" - "wrpr %0, 0, %%tick\n\t" - "andn %0, %4, %1\n\t" - "ba,pt %%xcc, 1f\n\t" - " add %1, %3, %1\n\t" - ".align 64\n" - "1:\n\t" - "wr %1, 0, %%tick_cmpr\n\t" - "rd %%tick_cmpr, %%g0" - : "=&r" (new_tick), "=&r" (tmp) - : "r" (adj), "r" (offset), "r" (TICK_PRIV_BIT)); - - return new_tick; -} - -static struct sparc64_tick_ops tick_operations __read_mostly = { - .init_tick = tick_init_tick, - .get_tick = tick_get_tick, - .get_compare = tick_get_compare, - .add_tick = tick_add_tick, - .add_compare = tick_add_compare, - .softint_mask = 1UL << 0, -}; - -struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations; - -static void stick_init_tick(unsigned long offset) -{ - tick_disable_protection(); - - /* Let the user get at STICK too. */ - __asm__ __volatile__( - " rd %%asr24, %%g2\n" - " andn %%g2, %0, %%g2\n" - " wr %%g2, 0, %%asr24" - : /* no outputs */ - : "r" (TICK_PRIV_BIT) - : "g1", "g2"); - - __asm__ __volatile__( - " rd %%asr24, %%g1\n" - " andn %%g1, %1, %%g1\n" - " add %%g1, %0, %%g1\n" - " wr %%g1, 0x0, %%asr25" - : /* no outputs */ - : "r" (offset), "r" (TICK_PRIV_BIT) - : "g1"); -} - -static unsigned long stick_get_tick(void) -{ - unsigned long ret; - - __asm__ __volatile__("rd %%asr24, %0" - : "=r" (ret)); - - return ret & ~TICK_PRIV_BIT; -} - -static unsigned long stick_get_compare(void) -{ - unsigned long ret; - - __asm__ __volatile__("rd %%asr25, %0" - : "=r" (ret)); - - return ret; -} - -static unsigned long stick_add_tick(unsigned long adj, unsigned long offset) -{ - unsigned long new_tick, tmp; - - __asm__ __volatile__("rd %%asr24, %0\n\t" - "add %0, %2, %0\n\t" - "wr %0, 0, %%asr24\n\t" - "andn %0, %4, %1\n\t" - "add %1, %3, %1\n\t" - "wr %1, 0, %%asr25" - : "=&r" (new_tick), "=&r" (tmp) - : "r" (adj), "r" (offset), "r" (TICK_PRIV_BIT)); - - return new_tick; -} - -static unsigned long stick_add_compare(unsigned long adj) -{ - unsigned long new_compare; - - __asm__ __volatile__("rd %%asr25, %0\n\t" - "add %0, %1, %0\n\t" - "wr %0, 0, %%asr25" - : "=&r" (new_compare) - : "r" (adj)); - - return new_compare; -} - -static struct sparc64_tick_ops stick_operations __read_mostly = { - .init_tick = stick_init_tick, - .get_tick = stick_get_tick, - .get_compare = stick_get_compare, - .add_tick = stick_add_tick, - .add_compare = stick_add_compare, - .softint_mask = 1UL << 16, -}; - -/* On Hummingbird the STICK/STICK_CMPR register is implemented - * in I/O space. There are two 64-bit registers each, the - * first holds the low 32-bits of the value and the second holds - * the high 32-bits. - * - * Since STICK is constantly updating, we have to access it carefully. - * - * The sequence we use to read is: - * 1) read high - * 2) read low - * 3) read high again, if it rolled re-read both low and high again. - * - * Writing STICK safely is also tricky: - * 1) write low to zero - * 2) write high - * 3) write low - */ -#define HBIRD_STICKCMP_ADDR 0x1fe0000f060UL -#define HBIRD_STICK_ADDR 0x1fe0000f070UL - -static unsigned long __hbird_read_stick(void) -{ - unsigned long ret, tmp1, tmp2, tmp3; - unsigned long addr = HBIRD_STICK_ADDR+8; - - __asm__ __volatile__("ldxa [%1] %5, %2\n" - "1:\n\t" - "sub %1, 0x8, %1\n\t" - "ldxa [%1] %5, %3\n\t" - "add %1, 0x8, %1\n\t" - "ldxa [%1] %5, %4\n\t" - "cmp %4, %2\n\t" - "bne,a,pn %%xcc, 1b\n\t" - " mov %4, %2\n\t" - "sllx %4, 32, %4\n\t" - "or %3, %4, %0\n\t" - : "=&r" (ret), "=&r" (addr), - "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3) - : "i" (ASI_PHYS_BYPASS_EC_E), "1" (addr)); - - return ret; -} - -static unsigned long __hbird_read_compare(void) -{ - unsigned long low, high; - unsigned long addr = HBIRD_STICKCMP_ADDR; - - __asm__ __volatile__("ldxa [%2] %3, %0\n\t" - "add %2, 0x8, %2\n\t" - "ldxa [%2] %3, %1" - : "=&r" (low), "=&r" (high), "=&r" (addr) - : "i" (ASI_PHYS_BYPASS_EC_E), "2" (addr)); - - return (high << 32UL) | low; -} - -static void __hbird_write_stick(unsigned long val) -{ - unsigned long low = (val & 0xffffffffUL); - unsigned long high = (val >> 32UL); - unsigned long addr = HBIRD_STICK_ADDR; - - __asm__ __volatile__("stxa %%g0, [%0] %4\n\t" - "add %0, 0x8, %0\n\t" - "stxa %3, [%0] %4\n\t" - "sub %0, 0x8, %0\n\t" - "stxa %2, [%0] %4" - : "=&r" (addr) - : "0" (addr), "r" (low), "r" (high), - "i" (ASI_PHYS_BYPASS_EC_E)); -} - -static void __hbird_write_compare(unsigned long val) -{ - unsigned long low = (val & 0xffffffffUL); - unsigned long high = (val >> 32UL); - unsigned long addr = HBIRD_STICKCMP_ADDR + 0x8UL; - - __asm__ __volatile__("stxa %3, [%0] %4\n\t" - "sub %0, 0x8, %0\n\t" - "stxa %2, [%0] %4" - : "=&r" (addr) - : "0" (addr), "r" (low), "r" (high), - "i" (ASI_PHYS_BYPASS_EC_E)); -} - -static void hbtick_init_tick(unsigned long offset) -{ - unsigned long val; - - tick_disable_protection(); - - /* XXX This seems to be necessary to 'jumpstart' Hummingbird - * XXX into actually sending STICK interrupts. I think because - * XXX of how we store %tick_cmpr in head.S this somehow resets the - * XXX {TICK + STICK} interrupt mux. -DaveM - */ - __hbird_write_stick(__hbird_read_stick()); - - val = __hbird_read_stick() & ~TICK_PRIV_BIT; - __hbird_write_compare(val + offset); -} - -static unsigned long hbtick_get_tick(void) -{ - return __hbird_read_stick() & ~TICK_PRIV_BIT; -} - -static unsigned long hbtick_get_compare(void) -{ - return __hbird_read_compare(); -} - -static unsigned long hbtick_add_tick(unsigned long adj, unsigned long offset) -{ - unsigned long val; - - val = __hbird_read_stick() + adj; - __hbird_write_stick(val); - - val &= ~TICK_PRIV_BIT; - __hbird_write_compare(val + offset); - - return val; -} - -static unsigned long hbtick_add_compare(unsigned long adj) -{ - unsigned long val = __hbird_read_compare() + adj; - - val &= ~TICK_PRIV_BIT; - __hbird_write_compare(val); - - return val; -} - -static struct sparc64_tick_ops hbtick_operations __read_mostly = { - .init_tick = hbtick_init_tick, - .get_tick = hbtick_get_tick, - .get_compare = hbtick_get_compare, - .add_tick = hbtick_add_tick, - .add_compare = hbtick_add_compare, - .softint_mask = 1UL << 0, -}; - -/* timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - * - * NOTE: On SUN5 systems the ticker interrupt comes in using 2 - * interrupts, one at level14 and one with softint bit 0. - */ -unsigned long timer_tick_offset __read_mostly; - -static unsigned long timer_ticks_per_nsec_quotient __read_mostly; - -#define TICK_SIZE (tick_nsec / 1000) - -static inline void timer_check_rtc(void) -{ - /* last time the cmos clock got updated */ - static long last_rtc_update; - - /* Determine when to update the Mostek clock. */ - if (ntp_synced() && - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && - (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; - /* do it again in 60 s */ - } -} - -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - unsigned long ticks, compare, pstate; - - write_seqlock(&xtime_lock); - - do { -#ifndef CONFIG_SMP - profile_tick(CPU_PROFILING, regs); - update_process_times(user_mode(regs)); -#endif - do_timer(regs); - - /* Guarantee that the following sequences execute - * uninterrupted. - */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - compare = tick_ops->add_compare(timer_tick_offset); - ticks = tick_ops->get_tick(); - - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); - } while (time_after_eq(ticks, compare)); - - timer_check_rtc(); - - write_sequnlock(&xtime_lock); - - return IRQ_HANDLED; -} - -#ifdef CONFIG_SMP -void timer_tick_interrupt(struct pt_regs *regs) -{ - write_seqlock(&xtime_lock); - - do_timer(regs); - - timer_check_rtc(); - - write_sequnlock(&xtime_lock); -} -#endif - -/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ -static void __init kick_start_clock(void) -{ - void __iomem *regs = mstk48t02_regs; - u8 sec, tmp; - int i, count; - - prom_printf("CLOCK: Clock was stopped. Kick start "); - - spin_lock_irq(&mostek_lock); - - /* Turn on the kick start bit to start the oscillator. */ - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - tmp = mostek_read(regs + MOSTEK_SEC); - tmp &= ~MSTK_STOP; - mostek_write(regs + MOSTEK_SEC, tmp); - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp |= MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - /* Delay to allow the clock oscillator to start. */ - sec = MSTK_REG_SEC(regs); - for (i = 0; i < 3; i++) { - while (sec == MSTK_REG_SEC(regs)) - for (count = 0; count < 100000; count++) - /* nothing */ ; - prom_printf("."); - sec = MSTK_REG_SEC(regs); - } - prom_printf("\n"); - - spin_lock_irq(&mostek_lock); - - /* Turn off kick start and set a "valid" time and date. */ - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp &= ~MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - MSTK_SET_REG_SEC(regs,0); - MSTK_SET_REG_MIN(regs,0); - MSTK_SET_REG_HOUR(regs,0); - MSTK_SET_REG_DOW(regs,5); - MSTK_SET_REG_DOM(regs,1); - MSTK_SET_REG_MONTH(regs,8); - MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - /* Ensure the kick start bit is off. If it isn't, turn it off. */ - while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) { - prom_printf("CLOCK: Kick start still on!\n"); - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp &= ~MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - } - - prom_printf("CLOCK: Kick start procedure successful.\n"); -} - -/* Return nonzero if the clock chip battery is low. */ -static int __init has_low_battery(void) -{ - void __iomem *regs = mstk48t02_regs; - u8 data1, data2; - - spin_lock_irq(&mostek_lock); - - data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */ - mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */ - data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */ - mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */ - - spin_unlock_irq(&mostek_lock); - - return (data1 == data2); /* Was the write blocked? */ -} - -/* Probe for the real time clock chip. */ -static void __init set_system_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - void __iomem *mregs = mstk48t02_regs; -#ifdef CONFIG_PCI - unsigned long dregs = ds1287_regs; -#else - unsigned long dregs = 0UL; -#endif - u8 tmp; - - if (!mregs && !dregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - if (mregs) { - spin_lock_irq(&mostek_lock); - - /* Traditional Mostek chip. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - } else { - int i; - - /* Dallas 12887 RTC chip. */ - - /* Stolen from arch/i386/kernel/time.c, see there for - * credits and descriptive comments. - */ - for (i = 0; i < 1000000; i++) { - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - udelay(10); - } - for (i = 0; i < 1000000; i++) { - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - udelay(10); - } - do { - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - if ((year += 1900) < 1970) - year += 100; - } - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - - if (mregs) { - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - } -} - -void __init clock_probe(void) -{ - struct linux_prom_registers clk_reg[2]; - char model[128]; - int node, busnd = -1, err; - unsigned long flags; - struct linux_central *cbus; -#ifdef CONFIG_PCI - struct linux_ebus *ebus = NULL; - struct sparc_isa_bridge *isa_br = NULL; -#endif - static int invoked; - - if (invoked) - return; - invoked = 1; - - - if (this_is_starfire) { - /* davem suggests we keep this within the 4M locked kernel image */ - static char obp_gettod[256]; - static u32 unix_tod; - - sprintf(obp_gettod, "h# %08x unix-gettod", - (unsigned int) (long) &unix_tod); - prom_feval(obp_gettod); - xtime.tv_sec = unix_tod; - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - return; - } - - local_irq_save(flags); - - cbus = central_bus; - if (cbus != NULL) - busnd = central_bus->child->prom_node; - - /* Check FHC Central then EBUSs then ISA bridges then SBUSs. - * That way we handle the presence of multiple properly. - * - * As a special case, machines with Central must provide the - * timer chip there. - */ -#ifdef CONFIG_PCI - if (ebus_chain != NULL) { - ebus = ebus_chain; - if (busnd == -1) - busnd = ebus->prom_node; - } - if (isa_chain != NULL) { - isa_br = isa_chain; - if (busnd == -1) - busnd = isa_br->prom_node; - } -#endif - if (sbus_root != NULL && busnd == -1) - busnd = sbus_root->prom_node; - - if (busnd == -1) { - prom_printf("clock_probe: problem, cannot find bus to search.\n"); - prom_halt(); - } - - node = prom_getchild(busnd); - - while (1) { - if (!node) - model[0] = 0; - else - prom_getstring(node, "model", model, sizeof(model)); - if (strcmp(model, "mk48t02") && - strcmp(model, "mk48t08") && - strcmp(model, "mk48t59") && - strcmp(model, "m5819") && - strcmp(model, "m5819p") && - strcmp(model, "m5823") && - strcmp(model, "ds1287")) { - if (cbus != NULL) { - prom_printf("clock_probe: Central bus lacks timer chip.\n"); - prom_halt(); - } - - if (node != 0) - node = prom_getsibling(node); -#ifdef CONFIG_PCI - while ((node == 0) && ebus != NULL) { - ebus = ebus->next; - if (ebus != NULL) { - busnd = ebus->prom_node; - node = prom_getchild(busnd); - } - } - while ((node == 0) && isa_br != NULL) { - isa_br = isa_br->next; - if (isa_br != NULL) { - busnd = isa_br->prom_node; - node = prom_getchild(busnd); - } - } -#endif - if (node == 0) { - prom_printf("clock_probe: Cannot find timer chip\n"); - prom_halt(); - } - continue; - } - - err = prom_getproperty(node, "reg", (char *)clk_reg, - sizeof(clk_reg)); - if(err == -1) { - prom_printf("clock_probe: Cannot get Mostek reg property\n"); - prom_halt(); - } - - if (cbus != NULL) { - apply_fhc_ranges(central_bus->child, clk_reg, 1); - apply_central_ranges(central_bus, clk_reg, 1); - } -#ifdef CONFIG_PCI - else if (ebus != NULL) { - struct linux_ebus_device *edev; - - for_each_ebusdev(edev, ebus) - if (edev->prom_node == node) - break; - if (edev == NULL) { - if (isa_chain != NULL) - goto try_isa_clock; - prom_printf("%s: Mostek not probed by EBUS\n", - __FUNCTION__); - prom_halt(); - } - - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = edev->resource[0].start; - } else { - mstk48t59_regs = (void __iomem *) - edev->resource[0].start; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; - } - else if (isa_br != NULL) { - struct sparc_isa_device *isadev; - -try_isa_clock: - for_each_isadev(isadev, isa_br) - if (isadev->prom_node == node) - break; - if (isadev == NULL) { - prom_printf("%s: Mostek not probed by ISA\n"); - prom_halt(); - } - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = isadev->resource.start; - } else { - mstk48t59_regs = (void __iomem *) - isadev->resource.start; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; - } -#endif - else { - if (sbus_root->num_sbus_ranges) { - int nranges = sbus_root->num_sbus_ranges; - int rngc; - - for (rngc = 0; rngc < nranges; rngc++) - if (clk_reg[0].which_io == - sbus_root->sbus_ranges[rngc].ot_child_space) - break; - if (rngc == nranges) { - prom_printf("clock_probe: Cannot find ranges for " - "clock regs.\n"); - prom_halt(); - } - clk_reg[0].which_io = - sbus_root->sbus_ranges[rngc].ot_parent_space; - clk_reg[0].phys_addr += - sbus_root->sbus_ranges[rngc].ot_parent_base; - } - } - - if(model[5] == '0' && model[6] == '2') { - mstk48t02_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; - } else { - mstk48t59_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; - } - - if (mstk48t02_regs != NULL) { - /* Report a low battery voltage condition. */ - if (has_low_battery()) - prom_printf("NVRAM: Low battery voltage!\n"); - - /* Kick start the clock if it is completely stopped. */ - if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) - kick_start_clock(); - } - - set_system_time(); - - local_irq_restore(flags); -} - -/* This is gets the master TICK_INT timer going. */ -static unsigned long sparc64_init_timers(void) -{ - unsigned long clock; - int node; -#ifdef CONFIG_SMP - extern void smp_tick_init(void); -#endif - - if (tlb_type == spitfire) { - unsigned long ver, manuf, impl; - - __asm__ __volatile__ ("rdpr %%ver, %0" - : "=&r" (ver)); - manuf = ((ver >> 48) & 0xffff); - impl = ((ver >> 32) & 0xffff); - if (manuf == 0x17 && impl == 0x13) { - /* Hummingbird, aka Ultra-IIe */ - tick_ops = &hbtick_operations; - node = prom_root_node; - clock = prom_getint(node, "stick-frequency"); - } else { - tick_ops = &tick_operations; - cpu_find_by_instance(0, &node, NULL); - clock = prom_getint(node, "clock-frequency"); - } - } else { - tick_ops = &stick_operations; - node = prom_root_node; - clock = prom_getint(node, "stick-frequency"); - } - timer_tick_offset = clock / HZ; - -#ifdef CONFIG_SMP - smp_tick_init(); -#endif - - return clock; -} - -static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *)) -{ - unsigned long pstate; - int err; - - /* Register IRQ handler. */ - err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, 0, - "timer", NULL); - - if (err) { - prom_printf("Serious problem, cannot register TICK_INT\n"); - prom_halt(); - } - - /* Guarantee that the following sequences execute - * uninterrupted. - */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - tick_ops->init_tick(timer_tick_offset); - - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); - - local_irq_enable(); -} - -struct freq_table { - unsigned long udelay_val_ref; - unsigned long clock_tick_ref; - unsigned int ref_freq; -}; -static DEFINE_PER_CPU(struct freq_table, sparc64_freq_table) = { 0, 0, 0 }; - -unsigned long sparc64_get_clock_tick(unsigned int cpu) -{ - struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); - - if (ft->clock_tick_ref) - return ft->clock_tick_ref; - return cpu_data(cpu).clock_tick; -} - -#ifdef CONFIG_CPU_FREQ - -static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct cpufreq_freqs *freq = data; - unsigned int cpu = freq->cpu; - struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); - - if (!ft->ref_freq) { - ft->ref_freq = freq->old; - ft->udelay_val_ref = cpu_data(cpu).udelay_val; - ft->clock_tick_ref = cpu_data(cpu).clock_tick; - } - if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || - (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || - (val == CPUFREQ_RESUMECHANGE)) { - cpu_data(cpu).udelay_val = - cpufreq_scale(ft->udelay_val_ref, - ft->ref_freq, - freq->new); - cpu_data(cpu).clock_tick = - cpufreq_scale(ft->clock_tick_ref, - ft->ref_freq, - freq->new); - } - - return 0; -} - -static struct notifier_block sparc64_cpufreq_notifier_block = { - .notifier_call = sparc64_cpufreq_notifier -}; - -#endif /* CONFIG_CPU_FREQ */ - -static struct time_interpolator sparc64_cpu_interpolator = { - .source = TIME_SOURCE_CPU, - .shift = 16, - .mask = 0xffffffffffffffffLL -}; - -/* The quotient formula is taken from the IA64 port. */ -#define SPARC64_NSEC_PER_CYC_SHIFT 30UL -void __init time_init(void) -{ - unsigned long clock = sparc64_init_timers(); - - sparc64_cpu_interpolator.frequency = clock; - register_time_interpolator(&sparc64_cpu_interpolator); - - /* Now that the interpolator is registered, it is - * safe to start the timer ticking. - */ - sparc64_start_timers(timer_interrupt); - - timer_ticks_per_nsec_quotient = - (((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) + - (clock / 2)) / clock); - -#ifdef CONFIG_CPU_FREQ - cpufreq_register_notifier(&sparc64_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); -#endif -} - -unsigned long long sched_clock(void) -{ - unsigned long ticks = tick_ops->get_tick(); - - return (ticks * timer_ticks_per_nsec_quotient) - >> SPARC64_NSEC_PER_CYC_SHIFT; -} - -static int set_rtc_mmss(unsigned long nowtime) -{ - int real_seconds, real_minutes, chip_minutes; - void __iomem *mregs = mstk48t02_regs; -#ifdef CONFIG_PCI - unsigned long dregs = ds1287_regs; -#else - unsigned long dregs = 0UL; -#endif - unsigned long flags; - u8 tmp; - - /* - * Not having a register set can lead to trouble. - * Also starfire doesn't have a tod clock. - */ - if (!mregs && !dregs) - return -1; - - if (mregs) { - spin_lock_irqsave(&mostek_lock, flags); - - /* Read the current RTC minutes. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - chip_minutes = MSTK_REG_MIN(mregs); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(mregs + MOSTEK_CREG, tmp); - - MSTK_SET_REG_SEC(mregs,real_seconds); - MSTK_SET_REG_MIN(mregs,real_minutes); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irqrestore(&mostek_lock, flags); - - return 0; - } else { - spin_unlock_irqrestore(&mostek_lock, flags); - - return -1; - } - } else { - int retval = 0; - unsigned char save_control, save_freq_select; - - /* Stolen from arch/i386/kernel/time.c, see there for - * credits and descriptive comments. - */ - spin_lock_irqsave(&rtc_lock, flags); - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - chip_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(chip_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - chip_minutes, real_minutes); - retval = -1; - } - - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock_irqrestore(&rtc_lock, flags); - - return retval; - } -} diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S deleted file mode 100644 index 9478551cb02..00000000000 --- a/arch/sparc64/kernel/trampoline.S +++ /dev/null @@ -1,362 +0,0 @@ -/* $Id: trampoline.S,v 1.26 2002/02/09 19:49:30 davem Exp $ - * trampoline.S: Jump start slave processors on sparc64. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <asm/head.h> -#include <asm/asi.h> -#include <asm/lsu.h> -#include <asm/dcr.h> -#include <asm/dcu.h> -#include <asm/pstate.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/spitfire.h> -#include <asm/processor.h> -#include <asm/thread_info.h> -#include <asm/mmu.h> - - .data - .align 8 -call_method: - .asciz "call-method" - .align 8 -itlb_load: - .asciz "SUNW,itlb-load" - .align 8 -dtlb_load: - .asciz "SUNW,dtlb-load" - - .text - .align 8 - .globl sparc64_cpu_startup, sparc64_cpu_startup_end -sparc64_cpu_startup: - flushw - - BRANCH_IF_CHEETAH_BASE(g1,g5,cheetah_startup) - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g5,cheetah_plus_startup) - - ba,pt %xcc, spitfire_startup - nop - -cheetah_plus_startup: - /* Preserve OBP chosen DCU and DCR register settings. */ - ba,pt %xcc, cheetah_generic_startup - nop - -cheetah_startup: - mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1 - wr %g1, %asr18 - - sethi %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5 - or %g5, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5 - sllx %g5, 32, %g5 - or %g5, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g5 - stxa %g5, [%g0] ASI_DCU_CONTROL_REG - membar #Sync - -cheetah_generic_startup: - mov TSB_EXTENSION_P, %g3 - stxa %g0, [%g3] ASI_DMMU - stxa %g0, [%g3] ASI_IMMU - membar #Sync - - mov TSB_EXTENSION_S, %g3 - stxa %g0, [%g3] ASI_DMMU - membar #Sync - - mov TSB_EXTENSION_N, %g3 - stxa %g0, [%g3] ASI_DMMU - stxa %g0, [%g3] ASI_IMMU - membar #Sync - - /* Disable STICK_INT interrupts. */ - sethi %hi(0x80000000), %g5 - sllx %g5, 32, %g5 - wr %g5, %asr25 - - ba,pt %xcc, startup_continue - nop - -spitfire_startup: - mov (LSU_CONTROL_IC | LSU_CONTROL_DC | LSU_CONTROL_IM | LSU_CONTROL_DM), %g1 - stxa %g1, [%g0] ASI_LSU_CONTROL - membar #Sync - -startup_continue: - wrpr %g0, 15, %pil - - sethi %hi(0x80000000), %g2 - sllx %g2, 32, %g2 - wr %g2, 0, %tick_cmpr - - /* Call OBP by hand to lock KERNBASE into i/d tlbs. - * We lock 2 consequetive entries if we are 'bigkernel'. - */ - mov %o0, %l0 - - sethi %hi(prom_entry_lock), %g2 -1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 - membar #StoreLoad | #StoreStore - brnz,pn %g1, 1b - nop - - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x10], %l2 - mov %sp, %l1 - add %l2, -(192 + 128), %sp - flushw - - sethi %hi(call_method), %g2 - or %g2, %lo(call_method), %g2 - stx %g2, [%sp + 2047 + 128 + 0x00] - mov 5, %g2 - stx %g2, [%sp + 2047 + 128 + 0x08] - mov 1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x10] - sethi %hi(itlb_load), %g2 - or %g2, %lo(itlb_load), %g2 - stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(prom_mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - - mov 15, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) - - mov 63, %g2 -1: - stx %g2, [%sp + 2047 + 128 + 0x38] - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x08], %o1 - call %o1 - add %sp, (2047 + 128), %o0 - - sethi %hi(bigkernel), %g2 - lduw [%g2 + %lo(bigkernel)], %g2 - cmp %g2, 0 - be,pt %icc, do_dtlb - nop - - sethi %hi(call_method), %g2 - or %g2, %lo(call_method), %g2 - stx %g2, [%sp + 2047 + 128 + 0x00] - mov 5, %g2 - stx %g2, [%sp + 2047 + 128 + 0x08] - mov 1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x10] - sethi %hi(itlb_load), %g2 - or %g2, %lo(itlb_load), %g2 - stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(prom_mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE + 0x400000), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - sethi %hi(0x400000), %g1 - add %g2, %g1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - - mov 14, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) - - mov 62, %g2 -1: - stx %g2, [%sp + 2047 + 128 + 0x38] - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x08], %o1 - call %o1 - add %sp, (2047 + 128), %o0 - -do_dtlb: - sethi %hi(call_method), %g2 - or %g2, %lo(call_method), %g2 - stx %g2, [%sp + 2047 + 128 + 0x00] - mov 5, %g2 - stx %g2, [%sp + 2047 + 128 + 0x08] - mov 1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x10] - sethi %hi(dtlb_load), %g2 - or %g2, %lo(dtlb_load), %g2 - stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(prom_mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - - mov 15, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) - - mov 63, %g2 -1: - - stx %g2, [%sp + 2047 + 128 + 0x38] - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x08], %o1 - call %o1 - add %sp, (2047 + 128), %o0 - - sethi %hi(bigkernel), %g2 - lduw [%g2 + %lo(bigkernel)], %g2 - cmp %g2, 0 - be,pt %icc, do_unlock - nop - - sethi %hi(call_method), %g2 - or %g2, %lo(call_method), %g2 - stx %g2, [%sp + 2047 + 128 + 0x00] - mov 5, %g2 - stx %g2, [%sp + 2047 + 128 + 0x08] - mov 1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x10] - sethi %hi(dtlb_load), %g2 - or %g2, %lo(dtlb_load), %g2 - stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(prom_mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE + 0x400000), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - sethi %hi(0x400000), %g1 - add %g2, %g1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - - mov 14, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) - - mov 62, %g2 -1: - - stx %g2, [%sp + 2047 + 128 + 0x38] - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x08], %o1 - call %o1 - add %sp, (2047 + 128), %o0 - -do_unlock: - sethi %hi(prom_entry_lock), %g2 - stb %g0, [%g2 + %lo(prom_entry_lock)] - membar #StoreStore | #StoreLoad - - mov %l1, %sp - flushw - - mov %l0, %o0 - - wrpr %g0, (PSTATE_PRIV | PSTATE_PEF), %pstate - wr %g0, 0, %fprs - - /* XXX Buggy PROM... */ - srl %o0, 0, %o0 - ldx [%o0], %g6 - - wr %g0, ASI_P, %asi - - mov PRIMARY_CONTEXT, %g7 - stxa %g0, [%g7] ASI_DMMU - membar #Sync - mov SECONDARY_CONTEXT, %g7 - stxa %g0, [%g7] ASI_DMMU - membar #Sync - - mov 1, %g5 - sllx %g5, THREAD_SHIFT, %g5 - sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5 - add %g6, %g5, %sp - mov 0, %fp - - wrpr %g0, 0, %wstate - wrpr %g0, 0, %tl - - /* Setup the trap globals, then we can resurface. */ - rdpr %pstate, %o1 - mov %g6, %o2 - wrpr %o1, PSTATE_AG, %pstate - sethi %hi(sparc64_ttable_tl0), %g5 - wrpr %g5, %tba - mov %o2, %g6 - - wrpr %o1, PSTATE_MG, %pstate -#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) -#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) - - mov TSB_REG, %g1 - stxa %g0, [%g1] ASI_DMMU - membar #Sync - mov TLB_SFSR, %g1 - sethi %uhi(KERN_HIGHBITS), %g2 - or %g2, %ulo(KERN_HIGHBITS), %g2 - sllx %g2, 32, %g2 - or %g2, KERN_LOWBITS, %g2 - - BRANCH_IF_ANY_CHEETAH(g3,g7,9f) - - ba,pt %xcc, 1f - nop - -9: - sethi %uhi(VPTE_BASE_CHEETAH), %g3 - or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 - ba,pt %xcc, 2f - sllx %g3, 32, %g3 -1: - sethi %uhi(VPTE_BASE_SPITFIRE), %g3 - or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 - sllx %g3, 32, %g3 - -2: - clr %g7 -#undef KERN_HIGHBITS -#undef KERN_LOWBITS - - wrpr %o1, 0x0, %pstate - ldx [%g6 + TI_TASK], %g4 - - wrpr %g0, 0, %wstate - - call init_irqwork_curcpu - nop - - /* Start using proper page size encodings in ctx register. */ - sethi %hi(sparc64_kern_pri_context), %g3 - ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 - mov PRIMARY_CONTEXT, %g1 - stxa %g2, [%g1] ASI_DMMU - membar #Sync - - rdpr %pstate, %o1 - or %o1, PSTATE_IE, %o1 - wrpr %o1, 0, %pstate - - call prom_set_trap_table - sethi %hi(sparc64_ttable_tl0), %o0 - - call smp_callin - nop - call cpu_idle - mov 0, %o0 - call cpu_panic - nop -1: b,a,pt %xcc, 1b - - .align 8 -sparc64_cpu_startup_end: diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c deleted file mode 100644 index 8d44ae5a15e..00000000000 --- a/arch/sparc64/kernel/traps.c +++ /dev/null @@ -1,2173 +0,0 @@ -/* $Id: traps.c,v 1.85 2002/02/09 19:49:31 davem Exp $ - * arch/sparc64/kernel/traps.c - * - * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com) - */ - -/* - * I like traps on v9, :)))) - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/sched.h> /* for jiffies */ -#include <linux/kernel.h> -#include <linux/kallsyms.h> -#include <linux/signal.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/mm.h> -#include <linux/init.h> - -#include <asm/delay.h> -#include <asm/system.h> -#include <asm/ptrace.h> -#include <asm/oplib.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/unistd.h> -#include <asm/uaccess.h> -#include <asm/fpumacro.h> -#include <asm/lsu.h> -#include <asm/dcu.h> -#include <asm/estate.h> -#include <asm/chafsr.h> -#include <asm/sfafsr.h> -#include <asm/psrcompat.h> -#include <asm/processor.h> -#include <asm/timer.h> -#include <asm/kdebug.h> -#ifdef CONFIG_KMOD -#include <linux/kmod.h> -#endif - -struct notifier_block *sparc64die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); - -int register_die_notifier(struct notifier_block *nb) -{ - int err = 0; - unsigned long flags; - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&sparc64die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; -} - -/* When an irrecoverable trap occurs at tl > 0, the trap entry - * code logs the trap state registers at every level in the trap - * stack. It is found at (pt_regs + sizeof(pt_regs)) and the layout - * is as follows: - */ -struct tl1_traplog { - struct { - unsigned long tstate; - unsigned long tpc; - unsigned long tnpc; - unsigned long tt; - } trapstack[4]; - unsigned long tl; -}; - -static void dump_tl1_traplog(struct tl1_traplog *p) -{ - int i; - - printk("TRAPLOG: Error at trap level 0x%lx, dumping track stack.\n", - p->tl); - for (i = 0; i < 4; i++) { - printk(KERN_CRIT - "TRAPLOG: Trap level %d TSTATE[%016lx] TPC[%016lx] " - "TNPC[%016lx] TT[%lx]\n", - i + 1, - p->trapstack[i].tstate, p->trapstack[i].tpc, - p->trapstack[i].tnpc, p->trapstack[i].tt); - } -} - -void do_call_debug(struct pt_regs *regs) -{ - notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); -} - -void bad_trap(struct pt_regs *regs, long lvl) -{ - char buffer[32]; - siginfo_t info; - - if (notify_die(DIE_TRAP, "bad trap", regs, - 0, lvl, SIGTRAP) == NOTIFY_STOP) - return; - - if (lvl < 0x100) { - sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl); - die_if_kernel(buffer, regs); - } - - lvl -= 0x100; - if (regs->tstate & TSTATE_PRIV) { - sprintf(buffer, "Kernel bad sw trap %lx", lvl); - die_if_kernel(buffer, regs); - } - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = lvl; - force_sig_info(SIGILL, &info, current); -} - -void bad_trap_tl1(struct pt_regs *regs, long lvl) -{ - char buffer[32]; - - if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs, - 0, lvl, SIGTRAP) == NOTIFY_STOP) - return; - - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - - sprintf (buffer, "Bad trap %lx at tl>0", lvl); - die_if_kernel (buffer, regs); -} - -#ifdef CONFIG_DEBUG_BUGVERBOSE -void do_BUG(const char *file, int line) -{ - bust_spinlocks(1); - printk("kernel BUG at %s:%d!\n", file, line); -} -#endif - -void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) -{ - siginfo_t info; - - if (notify_die(DIE_TRAP, "instruction access exception", regs, - 0, 0x8, SIGTRAP) == NOTIFY_STOP) - return; - - if (regs->tstate & TSTATE_PRIV) { - printk("spitfire_insn_access_exception: SFSR[%016lx] " - "SFAR[%016lx], going.\n", sfsr, sfar); - die_if_kernel("Iax", regs); - } - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_MAPERR; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = 0; - force_sig_info(SIGSEGV, &info, current); -} - -void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) -{ - if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs, - 0, 0x8, SIGTRAP) == NOTIFY_STOP) - return; - - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - spitfire_insn_access_exception(regs, sfsr, sfar); -} - -void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) -{ - siginfo_t info; - - if (notify_die(DIE_TRAP, "data access exception", regs, - 0, 0x30, SIGTRAP) == NOTIFY_STOP) - return; - - if (regs->tstate & TSTATE_PRIV) { - /* Test if this comes from uaccess places. */ - const struct exception_table_entry *entry; - - entry = search_exception_tables(regs->tpc); - if (entry) { - /* Ouch, somebody is trying VM hole tricks on us... */ -#ifdef DEBUG_EXCEPTIONS - printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); - printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n", - regs->tpc, entry->fixup); -#endif - regs->tpc = entry->fixup; - regs->tnpc = regs->tpc + 4; - return; - } - /* Shit... */ - printk("spitfire_data_access_exception: SFSR[%016lx] " - "SFAR[%016lx], going.\n", sfsr, sfar); - die_if_kernel("Dax", regs); - } - - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_MAPERR; - info.si_addr = (void __user *)sfar; - info.si_trapno = 0; - force_sig_info(SIGSEGV, &info, current); -} - -void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) -{ - if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs, - 0, 0x30, SIGTRAP) == NOTIFY_STOP) - return; - - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - spitfire_data_access_exception(regs, sfsr, sfar); -} - -#ifdef CONFIG_PCI -/* This is really pathetic... */ -extern volatile int pci_poke_in_progress; -extern volatile int pci_poke_cpu; -extern volatile int pci_poke_faulted; -#endif - -/* When access exceptions happen, we must do this. */ -static void spitfire_clean_and_reenable_l1_caches(void) -{ - unsigned long va; - - if (tlb_type != spitfire) - BUG(); - - /* Clean 'em. */ - for (va = 0; va < (PAGE_SIZE << 1); va += 32) { - spitfire_put_icache_tag(va, 0x0); - spitfire_put_dcache_tag(va, 0x0); - } - - /* Re-enable in LSU. */ - __asm__ __volatile__("flush %%g6\n\t" - "membar #Sync\n\t" - "stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC | - LSU_CONTROL_IM | LSU_CONTROL_DM), - "i" (ASI_LSU_CONTROL) - : "memory"); -} - -static void spitfire_enable_estate_errors(void) -{ - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (ESTATE_ERR_ALL), - "i" (ASI_ESTATE_ERROR_EN)); -} - -static char ecc_syndrome_table[] = { - 0x4c, 0x40, 0x41, 0x48, 0x42, 0x48, 0x48, 0x49, - 0x43, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4a, - 0x44, 0x48, 0x48, 0x20, 0x48, 0x39, 0x4b, 0x48, - 0x48, 0x25, 0x31, 0x48, 0x28, 0x48, 0x48, 0x2c, - 0x45, 0x48, 0x48, 0x21, 0x48, 0x3d, 0x04, 0x48, - 0x48, 0x4b, 0x35, 0x48, 0x2d, 0x48, 0x48, 0x29, - 0x48, 0x00, 0x01, 0x48, 0x0a, 0x48, 0x48, 0x4b, - 0x0f, 0x48, 0x48, 0x4b, 0x48, 0x49, 0x49, 0x48, - 0x46, 0x48, 0x48, 0x2a, 0x48, 0x3b, 0x27, 0x48, - 0x48, 0x4b, 0x33, 0x48, 0x22, 0x48, 0x48, 0x2e, - 0x48, 0x19, 0x1d, 0x48, 0x1b, 0x4a, 0x48, 0x4b, - 0x1f, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48, - 0x48, 0x4b, 0x24, 0x48, 0x07, 0x48, 0x48, 0x36, - 0x4b, 0x48, 0x48, 0x3e, 0x48, 0x30, 0x38, 0x48, - 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x16, 0x48, - 0x48, 0x12, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b, - 0x47, 0x48, 0x48, 0x2f, 0x48, 0x3f, 0x4b, 0x48, - 0x48, 0x06, 0x37, 0x48, 0x23, 0x48, 0x48, 0x2b, - 0x48, 0x05, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x32, - 0x26, 0x48, 0x48, 0x3a, 0x48, 0x34, 0x3c, 0x48, - 0x48, 0x11, 0x15, 0x48, 0x13, 0x4a, 0x48, 0x4b, - 0x17, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48, - 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x1e, 0x48, - 0x48, 0x1a, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b, - 0x48, 0x08, 0x0d, 0x48, 0x02, 0x48, 0x48, 0x49, - 0x03, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x4b, 0x48, - 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x10, 0x48, - 0x48, 0x14, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b, - 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x18, 0x48, - 0x48, 0x1c, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b, - 0x4a, 0x0c, 0x09, 0x48, 0x0e, 0x48, 0x48, 0x4b, - 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a -}; - -static char *syndrome_unknown = "<Unknown>"; - -static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long bit) -{ - unsigned short scode; - char memmod_str[64], *p; - - if (udbl & bit) { - scode = ecc_syndrome_table[udbl & 0xff]; - if (prom_getunumber(scode, afar, - memmod_str, sizeof(memmod_str)) == -1) - p = syndrome_unknown; - else - p = memmod_str; - printk(KERN_WARNING "CPU[%d]: UDBL Syndrome[%x] " - "Memory Module \"%s\"\n", - smp_processor_id(), scode, p); - } - - if (udbh & bit) { - scode = ecc_syndrome_table[udbh & 0xff]; - if (prom_getunumber(scode, afar, - memmod_str, sizeof(memmod_str)) == -1) - p = syndrome_unknown; - else - p = memmod_str; - printk(KERN_WARNING "CPU[%d]: UDBH Syndrome[%x] " - "Memory Module \"%s\"\n", - smp_processor_id(), scode, p); - } - -} - -static void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, int tl1, struct pt_regs *regs) -{ - - printk(KERN_WARNING "CPU[%d]: Correctable ECC Error " - "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx] TL>1[%d]\n", - smp_processor_id(), afsr, afar, udbl, udbh, tl1); - - spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_CE); - - /* We always log it, even if someone is listening for this - * trap. - */ - notify_die(DIE_TRAP, "Correctable ECC Error", regs, - 0, TRAP_TYPE_CEE, SIGTRAP); - - /* The Correctable ECC Error trap does not disable I/D caches. So - * we only have to restore the ESTATE Error Enable register. - */ - spitfire_enable_estate_errors(); -} - -static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs) -{ - siginfo_t info; - - printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] " - "AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n", - smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1); - - /* XXX add more human friendly logging of the error status - * XXX as is implemented for cheetah - */ - - spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_UE); - - /* We always log it, even if someone is listening for this - * trap. - */ - notify_die(DIE_TRAP, "Uncorrectable Error", regs, - 0, tt, SIGTRAP); - - if (regs->tstate & TSTATE_PRIV) { - if (tl1) - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("UE", regs); - } - - /* XXX need more intelligent processing here, such as is implemented - * XXX for cheetah errors, in fact if the E-cache still holds the - * XXX line with bad parity this will loop - */ - - spitfire_clean_and_reenable_l1_caches(); - spitfire_enable_estate_errors(); - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_OBJERR; - info.si_addr = (void *)0; - info.si_trapno = 0; - force_sig_info(SIGBUS, &info, current); -} - -void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar) -{ - unsigned long afsr, tt, udbh, udbl; - int tl1; - - afsr = (status_encoded & SFSTAT_AFSR_MASK) >> SFSTAT_AFSR_SHIFT; - tt = (status_encoded & SFSTAT_TRAP_TYPE) >> SFSTAT_TRAP_TYPE_SHIFT; - tl1 = (status_encoded & SFSTAT_TL_GT_ONE) ? 1 : 0; - udbl = (status_encoded & SFSTAT_UDBL_MASK) >> SFSTAT_UDBL_SHIFT; - udbh = (status_encoded & SFSTAT_UDBH_MASK) >> SFSTAT_UDBH_SHIFT; - -#ifdef CONFIG_PCI - if (tt == TRAP_TYPE_DAE && - pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) { - spitfire_clean_and_reenable_l1_caches(); - spitfire_enable_estate_errors(); - - pci_poke_faulted = 1; - regs->tnpc = regs->tpc + 4; - return; - } -#endif - - if (afsr & SFAFSR_UE) - spitfire_ue_log(afsr, afar, udbh, udbl, tt, tl1, regs); - - if (tt == TRAP_TYPE_CEE) { - /* Handle the case where we took a CEE trap, but ACK'd - * only the UE state in the UDB error registers. - */ - if (afsr & SFAFSR_UE) { - if (udbh & UDBE_CE) { - __asm__ __volatile__( - "stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (udbh & UDBE_CE), - "r" (0x0), "i" (ASI_UDB_ERROR_W)); - } - if (udbl & UDBE_CE) { - __asm__ __volatile__( - "stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (udbl & UDBE_CE), - "r" (0x18), "i" (ASI_UDB_ERROR_W)); - } - } - - spitfire_cee_log(afsr, afar, udbh, udbl, tl1, regs); - } -} - -int cheetah_pcache_forced_on; - -void cheetah_enable_pcache(void) -{ - unsigned long dcr; - - printk("CHEETAH: Enabling P-Cache on cpu %d.\n", - smp_processor_id()); - - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (dcr) - : "i" (ASI_DCU_CONTROL_REG)); - dcr |= (DCU_PE | DCU_HPE | DCU_SPE | DCU_SL); - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (dcr), "i" (ASI_DCU_CONTROL_REG)); -} - -/* Cheetah error trap handling. */ -static unsigned long ecache_flush_physbase; -static unsigned long ecache_flush_linesize; -static unsigned long ecache_flush_size; - -/* WARNING: The error trap handlers in assembly know the precise - * layout of the following structure. - * - * C-level handlers below use this information to log the error - * and then determine how to recover (if possible). - */ -struct cheetah_err_info { -/*0x00*/u64 afsr; -/*0x08*/u64 afar; - - /* D-cache state */ -/*0x10*/u64 dcache_data[4]; /* The actual data */ -/*0x30*/u64 dcache_index; /* D-cache index */ -/*0x38*/u64 dcache_tag; /* D-cache tag/valid */ -/*0x40*/u64 dcache_utag; /* D-cache microtag */ -/*0x48*/u64 dcache_stag; /* D-cache snooptag */ - - /* I-cache state */ -/*0x50*/u64 icache_data[8]; /* The actual insns + predecode */ -/*0x90*/u64 icache_index; /* I-cache index */ -/*0x98*/u64 icache_tag; /* I-cache phys tag */ -/*0xa0*/u64 icache_utag; /* I-cache microtag */ -/*0xa8*/u64 icache_stag; /* I-cache snooptag */ -/*0xb0*/u64 icache_upper; /* I-cache upper-tag */ -/*0xb8*/u64 icache_lower; /* I-cache lower-tag */ - - /* E-cache state */ -/*0xc0*/u64 ecache_data[4]; /* 32 bytes from staging registers */ -/*0xe0*/u64 ecache_index; /* E-cache index */ -/*0xe8*/u64 ecache_tag; /* E-cache tag/state */ - -/*0xf0*/u64 __pad[32 - 30]; -}; -#define CHAFSR_INVALID ((u64)-1L) - -/* This table is ordered in priority of errors and matches the - * AFAR overwrite policy as well. - */ - -struct afsr_error_table { - unsigned long mask; - const char *name; -}; - -static const char CHAFSR_PERR_msg[] = - "System interface protocol error"; -static const char CHAFSR_IERR_msg[] = - "Internal processor error"; -static const char CHAFSR_ISAP_msg[] = - "System request parity error on incoming addresss"; -static const char CHAFSR_UCU_msg[] = - "Uncorrectable E-cache ECC error for ifetch/data"; -static const char CHAFSR_UCC_msg[] = - "SW Correctable E-cache ECC error for ifetch/data"; -static const char CHAFSR_UE_msg[] = - "Uncorrectable system bus data ECC error for read"; -static const char CHAFSR_EDU_msg[] = - "Uncorrectable E-cache ECC error for stmerge/blkld"; -static const char CHAFSR_EMU_msg[] = - "Uncorrectable system bus MTAG error"; -static const char CHAFSR_WDU_msg[] = - "Uncorrectable E-cache ECC error for writeback"; -static const char CHAFSR_CPU_msg[] = - "Uncorrectable ECC error for copyout"; -static const char CHAFSR_CE_msg[] = - "HW corrected system bus data ECC error for read"; -static const char CHAFSR_EDC_msg[] = - "HW corrected E-cache ECC error for stmerge/blkld"; -static const char CHAFSR_EMC_msg[] = - "HW corrected system bus MTAG ECC error"; -static const char CHAFSR_WDC_msg[] = - "HW corrected E-cache ECC error for writeback"; -static const char CHAFSR_CPC_msg[] = - "HW corrected ECC error for copyout"; -static const char CHAFSR_TO_msg[] = - "Unmapped error from system bus"; -static const char CHAFSR_BERR_msg[] = - "Bus error response from system bus"; -static const char CHAFSR_IVC_msg[] = - "HW corrected system bus data ECC error for ivec read"; -static const char CHAFSR_IVU_msg[] = - "Uncorrectable system bus data ECC error for ivec read"; -static struct afsr_error_table __cheetah_error_table[] = { - { CHAFSR_PERR, CHAFSR_PERR_msg }, - { CHAFSR_IERR, CHAFSR_IERR_msg }, - { CHAFSR_ISAP, CHAFSR_ISAP_msg }, - { CHAFSR_UCU, CHAFSR_UCU_msg }, - { CHAFSR_UCC, CHAFSR_UCC_msg }, - { CHAFSR_UE, CHAFSR_UE_msg }, - { CHAFSR_EDU, CHAFSR_EDU_msg }, - { CHAFSR_EMU, CHAFSR_EMU_msg }, - { CHAFSR_WDU, CHAFSR_WDU_msg }, - { CHAFSR_CPU, CHAFSR_CPU_msg }, - { CHAFSR_CE, CHAFSR_CE_msg }, - { CHAFSR_EDC, CHAFSR_EDC_msg }, - { CHAFSR_EMC, CHAFSR_EMC_msg }, - { CHAFSR_WDC, CHAFSR_WDC_msg }, - { CHAFSR_CPC, CHAFSR_CPC_msg }, - { CHAFSR_TO, CHAFSR_TO_msg }, - { CHAFSR_BERR, CHAFSR_BERR_msg }, - /* These two do not update the AFAR. */ - { CHAFSR_IVC, CHAFSR_IVC_msg }, - { CHAFSR_IVU, CHAFSR_IVU_msg }, - { 0, NULL }, -}; -static const char CHPAFSR_DTO_msg[] = - "System bus unmapped error for prefetch/storequeue-read"; -static const char CHPAFSR_DBERR_msg[] = - "System bus error for prefetch/storequeue-read"; -static const char CHPAFSR_THCE_msg[] = - "Hardware corrected E-cache Tag ECC error"; -static const char CHPAFSR_TSCE_msg[] = - "SW handled correctable E-cache Tag ECC error"; -static const char CHPAFSR_TUE_msg[] = - "Uncorrectable E-cache Tag ECC error"; -static const char CHPAFSR_DUE_msg[] = - "System bus uncorrectable data ECC error due to prefetch/store-fill"; -static struct afsr_error_table __cheetah_plus_error_table[] = { - { CHAFSR_PERR, CHAFSR_PERR_msg }, - { CHAFSR_IERR, CHAFSR_IERR_msg }, - { CHAFSR_ISAP, CHAFSR_ISAP_msg }, - { CHAFSR_UCU, CHAFSR_UCU_msg }, - { CHAFSR_UCC, CHAFSR_UCC_msg }, - { CHAFSR_UE, CHAFSR_UE_msg }, - { CHAFSR_EDU, CHAFSR_EDU_msg }, - { CHAFSR_EMU, CHAFSR_EMU_msg }, - { CHAFSR_WDU, CHAFSR_WDU_msg }, - { CHAFSR_CPU, CHAFSR_CPU_msg }, - { CHAFSR_CE, CHAFSR_CE_msg }, - { CHAFSR_EDC, CHAFSR_EDC_msg }, - { CHAFSR_EMC, CHAFSR_EMC_msg }, - { CHAFSR_WDC, CHAFSR_WDC_msg }, - { CHAFSR_CPC, CHAFSR_CPC_msg }, - { CHAFSR_TO, CHAFSR_TO_msg }, - { CHAFSR_BERR, CHAFSR_BERR_msg }, - { CHPAFSR_DTO, CHPAFSR_DTO_msg }, - { CHPAFSR_DBERR, CHPAFSR_DBERR_msg }, - { CHPAFSR_THCE, CHPAFSR_THCE_msg }, - { CHPAFSR_TSCE, CHPAFSR_TSCE_msg }, - { CHPAFSR_TUE, CHPAFSR_TUE_msg }, - { CHPAFSR_DUE, CHPAFSR_DUE_msg }, - /* These two do not update the AFAR. */ - { CHAFSR_IVC, CHAFSR_IVC_msg }, - { CHAFSR_IVU, CHAFSR_IVU_msg }, - { 0, NULL }, -}; -static const char JPAFSR_JETO_msg[] = - "System interface protocol error, hw timeout caused"; -static const char JPAFSR_SCE_msg[] = - "Parity error on system snoop results"; -static const char JPAFSR_JEIC_msg[] = - "System interface protocol error, illegal command detected"; -static const char JPAFSR_JEIT_msg[] = - "System interface protocol error, illegal ADTYPE detected"; -static const char JPAFSR_OM_msg[] = - "Out of range memory error has occurred"; -static const char JPAFSR_ETP_msg[] = - "Parity error on L2 cache tag SRAM"; -static const char JPAFSR_UMS_msg[] = - "Error due to unsupported store"; -static const char JPAFSR_RUE_msg[] = - "Uncorrectable ECC error from remote cache/memory"; -static const char JPAFSR_RCE_msg[] = - "Correctable ECC error from remote cache/memory"; -static const char JPAFSR_BP_msg[] = - "JBUS parity error on returned read data"; -static const char JPAFSR_WBP_msg[] = - "JBUS parity error on data for writeback or block store"; -static const char JPAFSR_FRC_msg[] = - "Foreign read to DRAM incurring correctable ECC error"; -static const char JPAFSR_FRU_msg[] = - "Foreign read to DRAM incurring uncorrectable ECC error"; -static struct afsr_error_table __jalapeno_error_table[] = { - { JPAFSR_JETO, JPAFSR_JETO_msg }, - { JPAFSR_SCE, JPAFSR_SCE_msg }, - { JPAFSR_JEIC, JPAFSR_JEIC_msg }, - { JPAFSR_JEIT, JPAFSR_JEIT_msg }, - { CHAFSR_PERR, CHAFSR_PERR_msg }, - { CHAFSR_IERR, CHAFSR_IERR_msg }, - { CHAFSR_ISAP, CHAFSR_ISAP_msg }, - { CHAFSR_UCU, CHAFSR_UCU_msg }, - { CHAFSR_UCC, CHAFSR_UCC_msg }, - { CHAFSR_UE, CHAFSR_UE_msg }, - { CHAFSR_EDU, CHAFSR_EDU_msg }, - { JPAFSR_OM, JPAFSR_OM_msg }, - { CHAFSR_WDU, CHAFSR_WDU_msg }, - { CHAFSR_CPU, CHAFSR_CPU_msg }, - { CHAFSR_CE, CHAFSR_CE_msg }, - { CHAFSR_EDC, CHAFSR_EDC_msg }, - { JPAFSR_ETP, JPAFSR_ETP_msg }, - { CHAFSR_WDC, CHAFSR_WDC_msg }, - { CHAFSR_CPC, CHAFSR_CPC_msg }, - { CHAFSR_TO, CHAFSR_TO_msg }, - { CHAFSR_BERR, CHAFSR_BERR_msg }, - { JPAFSR_UMS, JPAFSR_UMS_msg }, - { JPAFSR_RUE, JPAFSR_RUE_msg }, - { JPAFSR_RCE, JPAFSR_RCE_msg }, - { JPAFSR_BP, JPAFSR_BP_msg }, - { JPAFSR_WBP, JPAFSR_WBP_msg }, - { JPAFSR_FRC, JPAFSR_FRC_msg }, - { JPAFSR_FRU, JPAFSR_FRU_msg }, - /* These two do not update the AFAR. */ - { CHAFSR_IVU, CHAFSR_IVU_msg }, - { 0, NULL }, -}; -static struct afsr_error_table *cheetah_error_table; -static unsigned long cheetah_afsr_errors; - -/* This is allocated at boot time based upon the largest hardware - * cpu ID in the system. We allocate two entries per cpu, one for - * TL==0 logging and one for TL >= 1 logging. - */ -struct cheetah_err_info *cheetah_error_log; - -static __inline__ struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr) -{ - struct cheetah_err_info *p; - int cpu = smp_processor_id(); - - if (!cheetah_error_log) - return NULL; - - p = cheetah_error_log + (cpu * 2); - if ((afsr & CHAFSR_TL1) != 0UL) - p++; - - return p; -} - -extern unsigned int tl0_icpe[], tl1_icpe[]; -extern unsigned int tl0_dcpe[], tl1_dcpe[]; -extern unsigned int tl0_fecc[], tl1_fecc[]; -extern unsigned int tl0_cee[], tl1_cee[]; -extern unsigned int tl0_iae[], tl1_iae[]; -extern unsigned int tl0_dae[], tl1_dae[]; -extern unsigned int cheetah_plus_icpe_trap_vector[], cheetah_plus_icpe_trap_vector_tl1[]; -extern unsigned int cheetah_plus_dcpe_trap_vector[], cheetah_plus_dcpe_trap_vector_tl1[]; -extern unsigned int cheetah_fecc_trap_vector[], cheetah_fecc_trap_vector_tl1[]; -extern unsigned int cheetah_cee_trap_vector[], cheetah_cee_trap_vector_tl1[]; -extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector_tl1[]; - -void __init cheetah_ecache_flush_init(void) -{ - unsigned long largest_size, smallest_linesize, order, ver; - int node, i, instance; - - /* Scan all cpu device tree nodes, note two values: - * 1) largest E-cache size - * 2) smallest E-cache line size - */ - largest_size = 0UL; - smallest_linesize = ~0UL; - - instance = 0; - while (!cpu_find_by_instance(instance, &node, NULL)) { - unsigned long val; - - val = prom_getintdefault(node, "ecache-size", - (2 * 1024 * 1024)); - if (val > largest_size) - largest_size = val; - val = prom_getintdefault(node, "ecache-line-size", 64); - if (val < smallest_linesize) - smallest_linesize = val; - instance++; - } - - if (largest_size == 0UL || smallest_linesize == ~0UL) { - prom_printf("cheetah_ecache_flush_init: Cannot probe cpu E-cache " - "parameters.\n"); - prom_halt(); - } - - ecache_flush_size = (2 * largest_size); - ecache_flush_linesize = smallest_linesize; - - ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size); - - if (ecache_flush_physbase == ~0UL) { - prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " - "contiguous physical memory.\n", - ecache_flush_size); - prom_halt(); - } - - /* Now allocate error trap reporting scoreboard. */ - node = NR_CPUS * (2 * sizeof(struct cheetah_err_info)); - for (order = 0; order < MAX_ORDER; order++) { - if ((PAGE_SIZE << order) >= node) - break; - } - cheetah_error_log = (struct cheetah_err_info *) - __get_free_pages(GFP_KERNEL, order); - if (!cheetah_error_log) { - prom_printf("cheetah_ecache_flush_init: Failed to allocate " - "error logging scoreboard (%d bytes).\n", node); - prom_halt(); - } - memset(cheetah_error_log, 0, PAGE_SIZE << order); - - /* Mark all AFSRs as invalid so that the trap handler will - * log new new information there. - */ - for (i = 0; i < 2 * NR_CPUS; i++) - cheetah_error_log[i].afsr = CHAFSR_INVALID; - - __asm__ ("rdpr %%ver, %0" : "=r" (ver)); - if ((ver >> 32) == 0x003e0016) { - cheetah_error_table = &__jalapeno_error_table[0]; - cheetah_afsr_errors = JPAFSR_ERRORS; - } else if ((ver >> 32) == 0x003e0015) { - cheetah_error_table = &__cheetah_plus_error_table[0]; - cheetah_afsr_errors = CHPAFSR_ERRORS; - } else { - cheetah_error_table = &__cheetah_error_table[0]; - cheetah_afsr_errors = CHAFSR_ERRORS; - } - - /* Now patch trap tables. */ - memcpy(tl0_fecc, cheetah_fecc_trap_vector, (8 * 4)); - memcpy(tl1_fecc, cheetah_fecc_trap_vector_tl1, (8 * 4)); - memcpy(tl0_cee, cheetah_cee_trap_vector, (8 * 4)); - memcpy(tl1_cee, cheetah_cee_trap_vector_tl1, (8 * 4)); - memcpy(tl0_iae, cheetah_deferred_trap_vector, (8 * 4)); - memcpy(tl1_iae, cheetah_deferred_trap_vector_tl1, (8 * 4)); - memcpy(tl0_dae, cheetah_deferred_trap_vector, (8 * 4)); - memcpy(tl1_dae, cheetah_deferred_trap_vector_tl1, (8 * 4)); - if (tlb_type == cheetah_plus) { - memcpy(tl0_dcpe, cheetah_plus_dcpe_trap_vector, (8 * 4)); - memcpy(tl1_dcpe, cheetah_plus_dcpe_trap_vector_tl1, (8 * 4)); - memcpy(tl0_icpe, cheetah_plus_icpe_trap_vector, (8 * 4)); - memcpy(tl1_icpe, cheetah_plus_icpe_trap_vector_tl1, (8 * 4)); - } - flushi(PAGE_OFFSET); -} - -static void cheetah_flush_ecache(void) -{ - unsigned long flush_base = ecache_flush_physbase; - unsigned long flush_linesize = ecache_flush_linesize; - unsigned long flush_size = ecache_flush_size; - - __asm__ __volatile__("1: subcc %0, %4, %0\n\t" - " bne,pt %%xcc, 1b\n\t" - " ldxa [%2 + %0] %3, %%g0\n\t" - : "=&r" (flush_size) - : "0" (flush_size), "r" (flush_base), - "i" (ASI_PHYS_USE_EC), "r" (flush_linesize)); -} - -static void cheetah_flush_ecache_line(unsigned long physaddr) -{ - unsigned long alias; - - physaddr &= ~(8UL - 1UL); - physaddr = (ecache_flush_physbase + - (physaddr & ((ecache_flush_size>>1UL) - 1UL))); - alias = physaddr + (ecache_flush_size >> 1UL); - __asm__ __volatile__("ldxa [%0] %2, %%g0\n\t" - "ldxa [%1] %2, %%g0\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (physaddr), "r" (alias), - "i" (ASI_PHYS_USE_EC)); -} - -/* Unfortunately, the diagnostic access to the I-cache tags we need to - * use to clear the thing interferes with I-cache coherency transactions. - * - * So we must only flush the I-cache when it is disabled. - */ -static void __cheetah_flush_icache(void) -{ - unsigned int icache_size, icache_line_size; - unsigned long addr; - - icache_size = local_cpu_data().icache_size; - icache_line_size = local_cpu_data().icache_line_size; - - /* Clear the valid bits in all the tags. */ - for (addr = 0; addr < icache_size; addr += icache_line_size) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (addr | (2 << 3)), - "i" (ASI_IC_TAG)); - } -} - -static void cheetah_flush_icache(void) -{ - unsigned long dcu_save; - - /* Save current DCU, disable I-cache. */ - __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t" - "or %0, %2, %%g1\n\t" - "stxa %%g1, [%%g0] %1\n\t" - "membar #Sync" - : "=r" (dcu_save) - : "i" (ASI_DCU_CONTROL_REG), "i" (DCU_IC) - : "g1"); - - __cheetah_flush_icache(); - - /* Restore DCU register */ - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (dcu_save), "i" (ASI_DCU_CONTROL_REG)); -} - -static void cheetah_flush_dcache(void) -{ - unsigned int dcache_size, dcache_line_size; - unsigned long addr; - - dcache_size = local_cpu_data().dcache_size; - dcache_line_size = local_cpu_data().dcache_line_size; - - for (addr = 0; addr < dcache_size; addr += dcache_line_size) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (addr), "i" (ASI_DCACHE_TAG)); - } -} - -/* In order to make the even parity correct we must do two things. - * First, we clear DC_data_parity and set DC_utag to an appropriate value. - * Next, we clear out all 32-bytes of data for that line. Data of - * all-zero + tag parity value of zero == correct parity. - */ -static void cheetah_plus_zap_dcache_parity(void) -{ - unsigned int dcache_size, dcache_line_size; - unsigned long addr; - - dcache_size = local_cpu_data().dcache_size; - dcache_line_size = local_cpu_data().dcache_line_size; - - for (addr = 0; addr < dcache_size; addr += dcache_line_size) { - unsigned long tag = (addr >> 14); - unsigned long line; - - __asm__ __volatile__("membar #Sync\n\t" - "stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (tag), "r" (addr), - "i" (ASI_DCACHE_UTAG)); - for (line = addr; line < addr + dcache_line_size; line += 8) - __asm__ __volatile__("membar #Sync\n\t" - "stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (line), - "i" (ASI_DCACHE_DATA)); - } -} - -/* Conversion tables used to frob Cheetah AFSR syndrome values into - * something palatable to the memory controller driver get_unumber - * routine. - */ -#define MT0 137 -#define MT1 138 -#define MT2 139 -#define NONE 254 -#define MTC0 140 -#define MTC1 141 -#define MTC2 142 -#define MTC3 143 -#define C0 128 -#define C1 129 -#define C2 130 -#define C3 131 -#define C4 132 -#define C5 133 -#define C6 134 -#define C7 135 -#define C8 136 -#define M2 144 -#define M3 145 -#define M4 146 -#define M 147 -static unsigned char cheetah_ecc_syntab[] = { -/*00*/NONE, C0, C1, M2, C2, M2, M3, 47, C3, M2, M2, 53, M2, 41, 29, M, -/*01*/C4, M, M, 50, M2, 38, 25, M2, M2, 33, 24, M2, 11, M, M2, 16, -/*02*/C5, M, M, 46, M2, 37, 19, M2, M, 31, 32, M, 7, M2, M2, 10, -/*03*/M2, 40, 13, M2, 59, M, M2, 66, M, M2, M2, 0, M2, 67, 71, M, -/*04*/C6, M, M, 43, M, 36, 18, M, M2, 49, 15, M, 63, M2, M2, 6, -/*05*/M2, 44, 28, M2, M, M2, M2, 52, 68, M2, M2, 62, M2, M3, M3, M4, -/*06*/M2, 26, 106, M2, 64, M, M2, 2, 120, M, M2, M3, M, M3, M3, M4, -/*07*/116, M2, M2, M3, M2, M3, M, M4, M2, 58, 54, M2, M, M4, M4, M3, -/*08*/C7, M2, M, 42, M, 35, 17, M2, M, 45, 14, M2, 21, M2, M2, 5, -/*09*/M, 27, M, M, 99, M, M, 3, 114, M2, M2, 20, M2, M3, M3, M, -/*0a*/M2, 23, 113, M2, 112, M2, M, 51, 95, M, M2, M3, M2, M3, M3, M2, -/*0b*/103, M, M2, M3, M2, M3, M3, M4, M2, 48, M, M, 73, M2, M, M3, -/*0c*/M2, 22, 110, M2, 109, M2, M, 9, 108, M2, M, M3, M2, M3, M3, M, -/*0d*/102, M2, M, M, M2, M3, M3, M, M2, M3, M3, M2, M, M4, M, M3, -/*0e*/98, M, M2, M3, M2, M, M3, M4, M2, M3, M3, M4, M3, M, M, M, -/*0f*/M2, M3, M3, M, M3, M, M, M, 56, M4, M, M3, M4, M, M, M, -/*10*/C8, M, M2, 39, M, 34, 105, M2, M, 30, 104, M, 101, M, M, 4, -/*11*/M, M, 100, M, 83, M, M2, 12, 87, M, M, 57, M2, M, M3, M, -/*12*/M2, 97, 82, M2, 78, M2, M2, 1, 96, M, M, M, M, M, M3, M2, -/*13*/94, M, M2, M3, M2, M, M3, M, M2, M, 79, M, 69, M, M4, M, -/*14*/M2, 93, 92, M, 91, M, M2, 8, 90, M2, M2, M, M, M, M, M4, -/*15*/89, M, M, M3, M2, M3, M3, M, M, M, M3, M2, M3, M2, M, M3, -/*16*/86, M, M2, M3, M2, M, M3, M, M2, M, M3, M, M3, M, M, M3, -/*17*/M, M, M3, M2, M3, M2, M4, M, 60, M, M2, M3, M4, M, M, M2, -/*18*/M2, 88, 85, M2, 84, M, M2, 55, 81, M2, M2, M3, M2, M3, M3, M4, -/*19*/77, M, M, M, M2, M3, M, M, M2, M3, M3, M4, M3, M2, M, M, -/*1a*/74, M, M2, M3, M, M, M3, M, M, M, M3, M, M3, M, M4, M3, -/*1b*/M2, 70, 107, M4, 65, M2, M2, M, 127, M, M, M, M2, M3, M3, M, -/*1c*/80, M2, M2, 72, M, 119, 118, M, M2, 126, 76, M, 125, M, M4, M3, -/*1d*/M2, 115, 124, M, 75, M, M, M3, 61, M, M4, M, M4, M, M, M, -/*1e*/M, 123, 122, M4, 121, M4, M, M3, 117, M2, M2, M3, M4, M3, M, M, -/*1f*/111, M, M, M, M4, M3, M3, M, M, M, M3, M, M3, M2, M, M -}; -static unsigned char cheetah_mtag_syntab[] = { - NONE, MTC0, - MTC1, NONE, - MTC2, NONE, - NONE, MT0, - MTC3, NONE, - NONE, MT1, - NONE, MT2, - NONE, NONE -}; - -/* Return the highest priority error conditon mentioned. */ -static __inline__ unsigned long cheetah_get_hipri(unsigned long afsr) -{ - unsigned long tmp = 0; - int i; - - for (i = 0; cheetah_error_table[i].mask; i++) { - if ((tmp = (afsr & cheetah_error_table[i].mask)) != 0UL) - return tmp; - } - return tmp; -} - -static const char *cheetah_get_string(unsigned long bit) -{ - int i; - - for (i = 0; cheetah_error_table[i].mask; i++) { - if ((bit & cheetah_error_table[i].mask) != 0UL) - return cheetah_error_table[i].name; - } - return "???"; -} - -extern int chmc_getunumber(int, unsigned long, char *, int); - -static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, - unsigned long afsr, unsigned long afar, int recoverable) -{ - unsigned long hipri; - char unum[256]; - - printk("%s" "ERROR(%d): Cheetah error trap taken afsr[%016lx] afar[%016lx] TL1(%d)\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - afsr, afar, - (afsr & CHAFSR_TL1) ? 1 : 0); - printk("%s" "ERROR(%d): TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - regs->tpc, regs->tnpc, regs->tstate); - printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, - (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT, - (afsr & CHAFSR_ME) ? ", Multiple Errors" : "", - (afsr & CHAFSR_PRIV) ? ", Privileged" : ""); - hipri = cheetah_get_hipri(afsr); - printk("%s" "ERROR(%d): Highest priority error (%016lx) \"%s\"\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - hipri, cheetah_get_string(hipri)); - - /* Try to get unumber if relevant. */ -#define ESYND_ERRORS (CHAFSR_IVC | CHAFSR_IVU | \ - CHAFSR_CPC | CHAFSR_CPU | \ - CHAFSR_UE | CHAFSR_CE | \ - CHAFSR_EDC | CHAFSR_EDU | \ - CHAFSR_UCC | CHAFSR_UCU | \ - CHAFSR_WDU | CHAFSR_WDC) -#define MSYND_ERRORS (CHAFSR_EMC | CHAFSR_EMU) - if (afsr & ESYND_ERRORS) { - int syndrome; - int ret; - - syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; - syndrome = cheetah_ecc_syntab[syndrome]; - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); - if (ret != -1) - printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), - smp_processor_id(), unum); - } else if (afsr & MSYND_ERRORS) { - int syndrome; - int ret; - - syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; - syndrome = cheetah_mtag_syntab[syndrome]; - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); - if (ret != -1) - printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), - smp_processor_id(), unum); - } - - /* Now dump the cache snapshots. */ - printk("%s" "ERROR(%d): D-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - (int) info->dcache_index, - info->dcache_tag, - info->dcache_utag, - info->dcache_stag); - printk("%s" "ERROR(%d): D-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - info->dcache_data[0], - info->dcache_data[1], - info->dcache_data[2], - info->dcache_data[3]); - printk("%s" "ERROR(%d): I-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx] " - "u[%016lx] l[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - (int) info->icache_index, - info->icache_tag, - info->icache_utag, - info->icache_stag, - info->icache_upper, - info->icache_lower); - printk("%s" "ERROR(%d): I-cache INSN0[%016lx] INSN1[%016lx] INSN2[%016lx] INSN3[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - info->icache_data[0], - info->icache_data[1], - info->icache_data[2], - info->icache_data[3]); - printk("%s" "ERROR(%d): I-cache INSN4[%016lx] INSN5[%016lx] INSN6[%016lx] INSN7[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - info->icache_data[4], - info->icache_data[5], - info->icache_data[6], - info->icache_data[7]); - printk("%s" "ERROR(%d): E-cache idx[%x] tag[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - (int) info->ecache_index, info->ecache_tag); - printk("%s" "ERROR(%d): E-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), - info->ecache_data[0], - info->ecache_data[1], - info->ecache_data[2], - info->ecache_data[3]); - - afsr = (afsr & ~hipri) & cheetah_afsr_errors; - while (afsr != 0UL) { - unsigned long bit = cheetah_get_hipri(afsr); - - printk("%s" "ERROR: Multiple-error (%016lx) \"%s\"\n", - (recoverable ? KERN_WARNING : KERN_CRIT), - bit, cheetah_get_string(bit)); - - afsr &= ~bit; - } - - if (!recoverable) - printk(KERN_CRIT "ERROR: This condition is not recoverable.\n"); -} - -static int cheetah_recheck_errors(struct cheetah_err_info *logp) -{ - unsigned long afsr, afar; - int ret = 0; - - __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t" - : "=r" (afsr) - : "i" (ASI_AFSR)); - if ((afsr & cheetah_afsr_errors) != 0) { - if (logp != NULL) { - __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t" - : "=r" (afar) - : "i" (ASI_AFAR)); - logp->afsr = afsr; - logp->afar = afar; - } - ret = 1; - } - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync\n\t" - : : "r" (afsr), "i" (ASI_AFSR)); - - return ret; -} - -void cheetah_fecc_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) -{ - struct cheetah_err_info local_snapshot, *p; - int recoverable; - - /* Flush E-cache */ - cheetah_flush_ecache(); - - p = cheetah_get_error_log(afsr); - if (!p) { - prom_printf("ERROR: Early Fast-ECC error afsr[%016lx] afar[%016lx]\n", - afsr, afar); - prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n", - smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate); - prom_halt(); - } - - /* Grab snapshot of logged error. */ - memcpy(&local_snapshot, p, sizeof(local_snapshot)); - - /* If the current trap snapshot does not match what the - * trap handler passed along into our args, big trouble. - * In such a case, mark the local copy as invalid. - * - * Else, it matches and we mark the afsr in the non-local - * copy as invalid so we may log new error traps there. - */ - if (p->afsr != afsr || p->afar != afar) - local_snapshot.afsr = CHAFSR_INVALID; - else - p->afsr = CHAFSR_INVALID; - - cheetah_flush_icache(); - cheetah_flush_dcache(); - - /* Re-enable I-cache/D-cache */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_DCU_CONTROL_REG), - "i" (DCU_DC | DCU_IC) - : "g1"); - - /* Re-enable error reporting */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_ESTATE_ERROR_EN), - "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN) - : "g1"); - - /* Decide if we can continue after handling this trap and - * logging the error. - */ - recoverable = 1; - if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP)) - recoverable = 0; - - /* Re-check AFSR/AFAR. What we are looking for here is whether a new - * error was logged while we had error reporting traps disabled. - */ - if (cheetah_recheck_errors(&local_snapshot)) { - unsigned long new_afsr = local_snapshot.afsr; - - /* If we got a new asynchronous error, die... */ - if (new_afsr & (CHAFSR_EMU | CHAFSR_EDU | - CHAFSR_WDU | CHAFSR_CPU | - CHAFSR_IVU | CHAFSR_UE | - CHAFSR_BERR | CHAFSR_TO)) - recoverable = 0; - } - - /* Log errors. */ - cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable); - - if (!recoverable) - panic("Irrecoverable Fast-ECC error trap.\n"); - - /* Flush E-cache to kick the error trap handlers out. */ - cheetah_flush_ecache(); -} - -/* Try to fix a correctable error by pushing the line out from - * the E-cache. Recheck error reporting registers to see if the - * problem is intermittent. - */ -static int cheetah_fix_ce(unsigned long physaddr) -{ - unsigned long orig_estate; - unsigned long alias1, alias2; - int ret; - - /* Make sure correctable error traps are disabled. */ - __asm__ __volatile__("ldxa [%%g0] %2, %0\n\t" - "andn %0, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %2\n\t" - "membar #Sync" - : "=&r" (orig_estate) - : "i" (ESTATE_ERROR_CEEN), - "i" (ASI_ESTATE_ERROR_EN) - : "g1"); - - /* We calculate alias addresses that will force the - * cache line in question out of the E-cache. Then - * we bring it back in with an atomic instruction so - * that we get it in some modified/exclusive state, - * then we displace it again to try and get proper ECC - * pushed back into the system. - */ - physaddr &= ~(8UL - 1UL); - alias1 = (ecache_flush_physbase + - (physaddr & ((ecache_flush_size >> 1) - 1))); - alias2 = alias1 + (ecache_flush_size >> 1); - __asm__ __volatile__("ldxa [%0] %3, %%g0\n\t" - "ldxa [%1] %3, %%g0\n\t" - "casxa [%2] %3, %%g0, %%g0\n\t" - "membar #StoreLoad | #StoreStore\n\t" - "ldxa [%0] %3, %%g0\n\t" - "ldxa [%1] %3, %%g0\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (alias1), "r" (alias2), - "r" (physaddr), "i" (ASI_PHYS_USE_EC)); - - /* Did that trigger another error? */ - if (cheetah_recheck_errors(NULL)) { - /* Try one more time. */ - __asm__ __volatile__("ldxa [%0] %1, %%g0\n\t" - "membar #Sync" - : : "r" (physaddr), "i" (ASI_PHYS_USE_EC)); - if (cheetah_recheck_errors(NULL)) - ret = 2; - else - ret = 1; - } else { - /* No new error, intermittent problem. */ - ret = 0; - } - - /* Restore error enables. */ - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : : "r" (orig_estate), "i" (ASI_ESTATE_ERROR_EN)); - - return ret; -} - -/* Return non-zero if PADDR is a valid physical memory address. */ -static int cheetah_check_main_memory(unsigned long paddr) -{ - unsigned long vaddr = PAGE_OFFSET + paddr; - - if (vaddr > (unsigned long) high_memory) - return 0; - - return kern_addr_valid(vaddr); -} - -void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) -{ - struct cheetah_err_info local_snapshot, *p; - int recoverable, is_memory; - - p = cheetah_get_error_log(afsr); - if (!p) { - prom_printf("ERROR: Early CEE error afsr[%016lx] afar[%016lx]\n", - afsr, afar); - prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n", - smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate); - prom_halt(); - } - - /* Grab snapshot of logged error. */ - memcpy(&local_snapshot, p, sizeof(local_snapshot)); - - /* If the current trap snapshot does not match what the - * trap handler passed along into our args, big trouble. - * In such a case, mark the local copy as invalid. - * - * Else, it matches and we mark the afsr in the non-local - * copy as invalid so we may log new error traps there. - */ - if (p->afsr != afsr || p->afar != afar) - local_snapshot.afsr = CHAFSR_INVALID; - else - p->afsr = CHAFSR_INVALID; - - is_memory = cheetah_check_main_memory(afar); - - if (is_memory && (afsr & CHAFSR_CE) != 0UL) { - /* XXX Might want to log the results of this operation - * XXX somewhere... -DaveM - */ - cheetah_fix_ce(afar); - } - - { - int flush_all, flush_line; - - flush_all = flush_line = 0; - if ((afsr & CHAFSR_EDC) != 0UL) { - if ((afsr & cheetah_afsr_errors) == CHAFSR_EDC) - flush_line = 1; - else - flush_all = 1; - } else if ((afsr & CHAFSR_CPC) != 0UL) { - if ((afsr & cheetah_afsr_errors) == CHAFSR_CPC) - flush_line = 1; - else - flush_all = 1; - } - - /* Trap handler only disabled I-cache, flush it. */ - cheetah_flush_icache(); - - /* Re-enable I-cache */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_DCU_CONTROL_REG), - "i" (DCU_IC) - : "g1"); - - if (flush_all) - cheetah_flush_ecache(); - else if (flush_line) - cheetah_flush_ecache_line(afar); - } - - /* Re-enable error reporting */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_ESTATE_ERROR_EN), - "i" (ESTATE_ERROR_CEEN) - : "g1"); - - /* Decide if we can continue after handling this trap and - * logging the error. - */ - recoverable = 1; - if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP)) - recoverable = 0; - - /* Re-check AFSR/AFAR */ - (void) cheetah_recheck_errors(&local_snapshot); - - /* Log errors. */ - cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable); - - if (!recoverable) - panic("Irrecoverable Correctable-ECC error trap.\n"); -} - -void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) -{ - struct cheetah_err_info local_snapshot, *p; - int recoverable, is_memory; - -#ifdef CONFIG_PCI - /* Check for the special PCI poke sequence. */ - if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) { - cheetah_flush_icache(); - cheetah_flush_dcache(); - - /* Re-enable I-cache/D-cache */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_DCU_CONTROL_REG), - "i" (DCU_DC | DCU_IC) - : "g1"); - - /* Re-enable error reporting */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_ESTATE_ERROR_EN), - "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN) - : "g1"); - - (void) cheetah_recheck_errors(NULL); - - pci_poke_faulted = 1; - regs->tpc += 4; - regs->tnpc = regs->tpc + 4; - return; - } -#endif - - p = cheetah_get_error_log(afsr); - if (!p) { - prom_printf("ERROR: Early deferred error afsr[%016lx] afar[%016lx]\n", - afsr, afar); - prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n", - smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate); - prom_halt(); - } - - /* Grab snapshot of logged error. */ - memcpy(&local_snapshot, p, sizeof(local_snapshot)); - - /* If the current trap snapshot does not match what the - * trap handler passed along into our args, big trouble. - * In such a case, mark the local copy as invalid. - * - * Else, it matches and we mark the afsr in the non-local - * copy as invalid so we may log new error traps there. - */ - if (p->afsr != afsr || p->afar != afar) - local_snapshot.afsr = CHAFSR_INVALID; - else - p->afsr = CHAFSR_INVALID; - - is_memory = cheetah_check_main_memory(afar); - - { - int flush_all, flush_line; - - flush_all = flush_line = 0; - if ((afsr & CHAFSR_EDU) != 0UL) { - if ((afsr & cheetah_afsr_errors) == CHAFSR_EDU) - flush_line = 1; - else - flush_all = 1; - } else if ((afsr & CHAFSR_BERR) != 0UL) { - if ((afsr & cheetah_afsr_errors) == CHAFSR_BERR) - flush_line = 1; - else - flush_all = 1; - } - - cheetah_flush_icache(); - cheetah_flush_dcache(); - - /* Re-enable I/D caches */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_DCU_CONTROL_REG), - "i" (DCU_IC | DCU_DC) - : "g1"); - - if (flush_all) - cheetah_flush_ecache(); - else if (flush_line) - cheetah_flush_ecache_line(afar); - } - - /* Re-enable error reporting */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_ESTATE_ERROR_EN), - "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN) - : "g1"); - - /* Decide if we can continue after handling this trap and - * logging the error. - */ - recoverable = 1; - if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP)) - recoverable = 0; - - /* Re-check AFSR/AFAR. What we are looking for here is whether a new - * error was logged while we had error reporting traps disabled. - */ - if (cheetah_recheck_errors(&local_snapshot)) { - unsigned long new_afsr = local_snapshot.afsr; - - /* If we got a new asynchronous error, die... */ - if (new_afsr & (CHAFSR_EMU | CHAFSR_EDU | - CHAFSR_WDU | CHAFSR_CPU | - CHAFSR_IVU | CHAFSR_UE | - CHAFSR_BERR | CHAFSR_TO)) - recoverable = 0; - } - - /* Log errors. */ - cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable); - - /* "Recoverable" here means we try to yank the page from ever - * being newly used again. This depends upon a few things: - * 1) Must be main memory, and AFAR must be valid. - * 2) If we trapped from user, OK. - * 3) Else, if we trapped from kernel we must find exception - * table entry (ie. we have to have been accessing user - * space). - * - * If AFAR is not in main memory, or we trapped from kernel - * and cannot find an exception table entry, it is unacceptable - * to try and continue. - */ - if (recoverable && is_memory) { - if ((regs->tstate & TSTATE_PRIV) == 0UL) { - /* OK, usermode access. */ - recoverable = 1; - } else { - const struct exception_table_entry *entry; - - entry = search_exception_tables(regs->tpc); - if (entry) { - /* OK, kernel access to userspace. */ - recoverable = 1; - - } else { - /* BAD, privileged state is corrupted. */ - recoverable = 0; - } - - if (recoverable) { - if (pfn_valid(afar >> PAGE_SHIFT)) - get_page(pfn_to_page(afar >> PAGE_SHIFT)); - else - recoverable = 0; - - /* Only perform fixup if we still have a - * recoverable condition. - */ - if (recoverable) { - regs->tpc = entry->fixup; - regs->tnpc = regs->tpc + 4; - } - } - } - } else { - recoverable = 0; - } - - if (!recoverable) - panic("Irrecoverable deferred error trap.\n"); -} - -/* Handle a D/I cache parity error trap. TYPE is encoded as: - * - * Bit0: 0=dcache,1=icache - * Bit1: 0=recoverable,1=unrecoverable - * - * The hardware has disabled both the I-cache and D-cache in - * the %dcr register. - */ -void cheetah_plus_parity_error(int type, struct pt_regs *regs) -{ - if (type & 0x1) - __cheetah_flush_icache(); - else - cheetah_plus_zap_dcache_parity(); - cheetah_flush_dcache(); - - /* Re-enable I-cache/D-cache */ - __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t" - "or %%g1, %1, %%g1\n\t" - "stxa %%g1, [%%g0] %0\n\t" - "membar #Sync" - : /* no outputs */ - : "i" (ASI_DCU_CONTROL_REG), - "i" (DCU_DC | DCU_IC) - : "g1"); - - if (type & 0x2) { - printk(KERN_EMERG "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n", - smp_processor_id(), - (type & 0x1) ? 'I' : 'D', - regs->tpc); - panic("Irrecoverable Cheetah+ parity error."); - } - - printk(KERN_WARNING "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n", - smp_processor_id(), - (type & 0x1) ? 'I' : 'D', - regs->tpc); -} - -void do_fpe_common(struct pt_regs *regs) -{ - if (regs->tstate & TSTATE_PRIV) { - regs->tpc = regs->tnpc; - regs->tnpc += 4; - } else { - unsigned long fsr = current_thread_info()->xfsr[0]; - siginfo_t info; - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = 0; - info.si_code = __SI_FAULT; - if ((fsr & 0x1c000) == (1 << 14)) { - if (fsr & 0x10) - info.si_code = FPE_FLTINV; - else if (fsr & 0x08) - info.si_code = FPE_FLTOVF; - else if (fsr & 0x04) - info.si_code = FPE_FLTUND; - else if (fsr & 0x02) - info.si_code = FPE_FLTDIV; - else if (fsr & 0x01) - info.si_code = FPE_FLTRES; - } - force_sig_info(SIGFPE, &info, current); - } -} - -void do_fpieee(struct pt_regs *regs) -{ - if (notify_die(DIE_TRAP, "fpu exception ieee", regs, - 0, 0x24, SIGFPE) == NOTIFY_STOP) - return; - - do_fpe_common(regs); -} - -extern int do_mathemu(struct pt_regs *, struct fpustate *); - -void do_fpother(struct pt_regs *regs) -{ - struct fpustate *f = FPUSTATE; - int ret = 0; - - if (notify_die(DIE_TRAP, "fpu exception other", regs, - 0, 0x25, SIGFPE) == NOTIFY_STOP) - return; - - switch ((current_thread_info()->xfsr[0] & 0x1c000)) { - case (2 << 14): /* unfinished_FPop */ - case (3 << 14): /* unimplemented_FPop */ - ret = do_mathemu(regs, f); - break; - } - if (ret) - return; - do_fpe_common(regs); -} - -void do_tof(struct pt_regs *regs) -{ - siginfo_t info; - - if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs, - 0, 0x26, SIGEMT) == NOTIFY_STOP) - return; - - if (regs->tstate & TSTATE_PRIV) - die_if_kernel("Penguin overflow trap from kernel mode", regs); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGEMT; - info.si_errno = 0; - info.si_code = EMT_TAGOVF; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = 0; - force_sig_info(SIGEMT, &info, current); -} - -void do_div0(struct pt_regs *regs) -{ - siginfo_t info; - - if (notify_die(DIE_TRAP, "integer division by zero", regs, - 0, 0x28, SIGFPE) == NOTIFY_STOP) - return; - - if (regs->tstate & TSTATE_PRIV) - die_if_kernel("TL0: Kernel divide by zero.", regs); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_code = FPE_INTDIV; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = 0; - force_sig_info(SIGFPE, &info, current); -} - -void instruction_dump (unsigned int *pc) -{ - int i; - - if ((((unsigned long) pc) & 3)) - return; - - printk("Instruction DUMP:"); - for (i = -3; i < 6; i++) - printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>'); - printk("\n"); -} - -static void user_instruction_dump (unsigned int __user *pc) -{ - int i; - unsigned int buf[9]; - - if ((((unsigned long) pc) & 3)) - return; - - if (copy_from_user(buf, pc - 3, sizeof(buf))) - return; - - printk("Instruction DUMP:"); - for (i = 0; i < 9; i++) - printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>'); - printk("\n"); -} - -void show_stack(struct task_struct *tsk, unsigned long *_ksp) -{ - unsigned long pc, fp, thread_base, ksp; - void *tp = task_stack_page(tsk); - struct reg_window *rw; - int count = 0; - - ksp = (unsigned long) _ksp; - - if (tp == current_thread_info()) - flushw_all(); - - fp = ksp + STACK_BIAS; - thread_base = (unsigned long) tp; - - printk("Call Trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif - do { - /* Bogus frame pointer? */ - if (fp < (thread_base + sizeof(struct thread_info)) || - fp >= (thread_base + THREAD_SIZE)) - break; - rw = (struct reg_window *)fp; - pc = rw->ins[7]; - printk(" [%016lx] ", pc); - print_symbol("%s\n", pc); - fp = rw->ins[6] + STACK_BIAS; - } while (++count < 16); -#ifndef CONFIG_KALLSYMS - printk("\n"); -#endif -} - -void dump_stack(void) -{ - unsigned long *ksp; - - __asm__ __volatile__("mov %%fp, %0" - : "=r" (ksp)); - show_stack(current, ksp); -} - -EXPORT_SYMBOL(dump_stack); - -static inline int is_kernel_stack(struct task_struct *task, - struct reg_window *rw) -{ - unsigned long rw_addr = (unsigned long) rw; - unsigned long thread_base, thread_end; - - if (rw_addr < PAGE_OFFSET) { - if (task != &init_task) - return 0; - } - - thread_base = (unsigned long) task_stack_page(task); - thread_end = thread_base + sizeof(union thread_union); - if (rw_addr >= thread_base && - rw_addr < thread_end && - !(rw_addr & 0x7UL)) - return 1; - - return 0; -} - -static inline struct reg_window *kernel_stack_up(struct reg_window *rw) -{ - unsigned long fp = rw->ins[6]; - - if (!fp) - return NULL; - - return (struct reg_window *) (fp + STACK_BIAS); -} - -void die_if_kernel(char *str, struct pt_regs *regs) -{ - static int die_counter; - extern void __show_regs(struct pt_regs * regs); - extern void smp_report_regs(void); - int count = 0; - - /* Amuse the user. */ - printk( -" \\|/ ____ \\|/\n" -" \"@'/ .. \\`@\"\n" -" /_| \\__/ |_\\\n" -" \\__U_/\n"); - - printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); - notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); - __asm__ __volatile__("flushw"); - __show_regs(regs); - if (regs->tstate & TSTATE_PRIV) { - struct reg_window *rw = (struct reg_window *) - (regs->u_regs[UREG_FP] + STACK_BIAS); - - /* Stop the back trace when we hit userland or we - * find some badly aligned kernel stack. - */ - while (rw && - count++ < 30&& - is_kernel_stack(current, rw)) { - printk("Caller[%016lx]", rw->ins[7]); - print_symbol(": %s", rw->ins[7]); - printk("\n"); - - rw = kernel_stack_up(rw); - } - instruction_dump ((unsigned int *) regs->tpc); - } else { - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - user_instruction_dump ((unsigned int __user *) regs->tpc); - } -#ifdef CONFIG_SMP - smp_report_regs(); -#endif - - if (regs->tstate & TSTATE_PRIV) - do_exit(SIGKILL); - do_exit(SIGSEGV); -} - -extern int handle_popc(u32 insn, struct pt_regs *regs); -extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); - -void do_illegal_instruction(struct pt_regs *regs) -{ - unsigned long pc = regs->tpc; - unsigned long tstate = regs->tstate; - u32 insn; - siginfo_t info; - - if (notify_die(DIE_TRAP, "illegal instruction", regs, - 0, 0x10, SIGILL) == NOTIFY_STOP) - return; - - if (tstate & TSTATE_PRIV) - die_if_kernel("Kernel illegal instruction", regs); - if (test_thread_flag(TIF_32BIT)) - pc = (u32)pc; - if (get_user(insn, (u32 __user *) pc) != -EFAULT) { - if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ { - if (handle_popc(insn, regs)) - return; - } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ { - if (handle_ldf_stq(insn, regs)) - return; - } - } - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPC; - info.si_addr = (void __user *)pc; - info.si_trapno = 0; - force_sig_info(SIGILL, &info, current); -} - -void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) -{ - siginfo_t info; - - if (notify_die(DIE_TRAP, "memory address unaligned", regs, - 0, 0x34, SIGSEGV) == NOTIFY_STOP) - return; - - if (regs->tstate & TSTATE_PRIV) { - extern void kernel_unaligned_trap(struct pt_regs *regs, - unsigned int insn, - unsigned long sfar, - unsigned long sfsr); - - kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), - sfar, sfsr); - return; - } - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRALN; - info.si_addr = (void __user *)sfar; - info.si_trapno = 0; - force_sig_info(SIGBUS, &info, current); -} - -void do_privop(struct pt_regs *regs) -{ - siginfo_t info; - - if (notify_die(DIE_TRAP, "privileged operation", regs, - 0, 0x11, SIGILL) == NOTIFY_STOP) - return; - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_PRVOPC; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = 0; - force_sig_info(SIGILL, &info, current); -} - -void do_privact(struct pt_regs *regs) -{ - do_privop(regs); -} - -/* Trap level 1 stuff or other traps we should never see... */ -void do_cee(struct pt_regs *regs) -{ - die_if_kernel("TL0: Cache Error Exception", regs); -} - -void do_cee_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: Cache Error Exception", regs); -} - -void do_dae_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: Data Access Exception", regs); -} - -void do_iae_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: Instruction Access Exception", regs); -} - -void do_div0_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: DIV0 Exception", regs); -} - -void do_fpdis_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: FPU Disabled", regs); -} - -void do_fpieee_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: FPU IEEE Exception", regs); -} - -void do_fpother_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: FPU Other Exception", regs); -} - -void do_ill_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: Illegal Instruction Exception", regs); -} - -void do_irq_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: IRQ Exception", regs); -} - -void do_lddfmna_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: LDDF Exception", regs); -} - -void do_stdfmna_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: STDF Exception", regs); -} - -void do_paw(struct pt_regs *regs) -{ - die_if_kernel("TL0: Phys Watchpoint Exception", regs); -} - -void do_paw_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: Phys Watchpoint Exception", regs); -} - -void do_vaw(struct pt_regs *regs) -{ - die_if_kernel("TL0: Virt Watchpoint Exception", regs); -} - -void do_vaw_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: Virt Watchpoint Exception", regs); -} - -void do_tof_tl1(struct pt_regs *regs) -{ - dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); - die_if_kernel("TL1: Tag Overflow Exception", regs); -} - -void do_getpsr(struct pt_regs *regs) -{ - regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate); - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } -} - -extern void thread_info_offsets_are_bolixed_dave(void); - -/* Only invoked on boot processor. */ -void __init trap_init(void) -{ - /* Compile time sanity check. */ - if (TI_TASK != offsetof(struct thread_info, task) || - TI_FLAGS != offsetof(struct thread_info, flags) || - TI_CPU != offsetof(struct thread_info, cpu) || - TI_FPSAVED != offsetof(struct thread_info, fpsaved) || - TI_KSP != offsetof(struct thread_info, ksp) || - TI_FAULT_ADDR != offsetof(struct thread_info, fault_address) || - TI_KREGS != offsetof(struct thread_info, kregs) || - TI_UTRAPS != offsetof(struct thread_info, utraps) || - TI_EXEC_DOMAIN != offsetof(struct thread_info, exec_domain) || - TI_REG_WINDOW != offsetof(struct thread_info, reg_window) || - TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) || - TI_GSR != offsetof(struct thread_info, gsr) || - TI_XFSR != offsetof(struct thread_info, xfsr) || - TI_USER_CNTD0 != offsetof(struct thread_info, user_cntd0) || - TI_USER_CNTD1 != offsetof(struct thread_info, user_cntd1) || - TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) || - TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) || - TI_PCR != offsetof(struct thread_info, pcr_reg) || - TI_CEE_STUFF != offsetof(struct thread_info, cee_stuff) || - TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) || - TI_NEW_CHILD != offsetof(struct thread_info, new_child) || - TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) || - TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) || - TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) || - TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) || - TI_FPREGS != offsetof(struct thread_info, fpregs) || - (TI_FPREGS & (64 - 1))) - thread_info_offsets_are_bolixed_dave(); - - /* Attach to the address space of init_task. On SMP we - * do this in smp.c:smp_callin for other cpus. - */ - atomic_inc(&init_mm.mm_count); - current->active_mm = &init_mm; -} diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S deleted file mode 100644 index 8365bc1f81f..00000000000 --- a/arch/sparc64/kernel/ttable.S +++ /dev/null @@ -1,285 +0,0 @@ -/* $Id: ttable.S,v 1.38 2002/02/09 19:49:30 davem Exp $ - * ttable.S: Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions. - * - * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/config.h> - - .globl sparc64_ttable_tl0, sparc64_ttable_tl1 - .globl tl0_icpe, tl1_icpe - .globl tl0_dcpe, tl1_dcpe - .globl tl0_fecc, tl1_fecc - .globl tl0_cee, tl1_cee - .globl tl0_iae, tl1_iae - .globl tl0_dae, tl1_dae - -sparc64_ttable_tl0: -tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) -tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7) -tl0_iax: membar #Sync - TRAP_NOSAVE_7INSNS(__spitfire_insn_access_exception) -tl0_resv009: BTRAP(0x9) -tl0_iae: membar #Sync - TRAP_NOSAVE_7INSNS(__spitfire_access_error) -tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) -tl0_ill: membar #Sync - TRAP_7INSNS(do_illegal_instruction) -tl0_privop: TRAP(do_privop) -tl0_resv012: BTRAP(0x12) BTRAP(0x13) BTRAP(0x14) BTRAP(0x15) BTRAP(0x16) BTRAP(0x17) -tl0_resv018: BTRAP(0x18) BTRAP(0x19) BTRAP(0x1a) BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d) -tl0_resv01e: BTRAP(0x1e) BTRAP(0x1f) -tl0_fpdis: TRAP_NOSAVE(do_fpdis) -tl0_fpieee: TRAP_SAVEFPU(do_fpieee) -tl0_fpother: TRAP_NOSAVE(do_fpother_check_fitos) -tl0_tof: TRAP(do_tof) -tl0_cwin: CLEAN_WINDOW -tl0_div0: TRAP(do_div0) -tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) -tl0_resv02f: BTRAP(0x2f) -tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception) -tl0_resv031: BTRAP(0x31) -tl0_dae: membar #Sync - TRAP_NOSAVE_7INSNS(__spitfire_access_error) -tl0_resv033: BTRAP(0x33) -tl0_mna: TRAP_NOSAVE(do_mna) -tl0_lddfmna: TRAP_NOSAVE(do_lddfmna) -tl0_stdfmna: TRAP_NOSAVE(do_stdfmna) -tl0_privact: TRAP_NOSAVE(__do_privact) -tl0_resv038: BTRAP(0x38) BTRAP(0x39) BTRAP(0x3a) BTRAP(0x3b) BTRAP(0x3c) BTRAP(0x3d) -tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40) -#ifdef CONFIG_SMP -tl0_irq1: TRAP_IRQ(smp_call_function_client, 1) -tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2) -tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3) -#else -tl0_irq1: BTRAP(0x41) -tl0_irq2: BTRAP(0x42) -tl0_irq3: BTRAP(0x43) -#endif -tl0_irq4: TRAP_IRQ(handler_irq, 4) -tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) -tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) -tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) -tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) -tl0_irq13: TRAP_IRQ(handler_irq, 13) -#ifndef CONFIG_SMP -tl0_irq14: TRAP_IRQ(handler_irq, 14) -#else -tl0_irq14: TICK_SMP_IRQ -#endif -tl0_irq15: TRAP_IRQ(handler_irq, 15) -tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) -tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) -tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f) -tl0_ivec: TRAP_IVEC -tl0_paw: TRAP(do_paw) -tl0_vaw: TRAP(do_vaw) -tl0_cee: membar #Sync - TRAP_NOSAVE_7INSNS(__spitfire_cee_trap) -tl0_iamiss: -#include "itlb_base.S" -tl0_damiss: -#include "dtlb_base.S" -tl0_daprot: -#include "dtlb_prot.S" -tl0_fecc: BTRAP(0x70) /* Fast-ECC on Cheetah */ -tl0_dcpe: BTRAP(0x71) /* D-cache Parity Error on Cheetah+ */ -tl0_icpe: BTRAP(0x72) /* I-cache Parity Error on Cheetah+ */ -tl0_resv073: BTRAP(0x73) BTRAP(0x74) BTRAP(0x75) -tl0_resv076: BTRAP(0x76) BTRAP(0x77) BTRAP(0x78) BTRAP(0x79) BTRAP(0x7a) BTRAP(0x7b) -tl0_resv07c: BTRAP(0x7c) BTRAP(0x7d) BTRAP(0x7e) BTRAP(0x7f) -tl0_s0n: SPILL_0_NORMAL -tl0_s1n: SPILL_1_NORMAL -tl0_s2n: SPILL_2_NORMAL -tl0_s3n: SPILL_3_NORMAL -tl0_s4n: SPILL_4_NORMAL -tl0_s5n: SPILL_5_NORMAL -tl0_s6n: SPILL_6_NORMAL -tl0_s7n: SPILL_7_NORMAL -tl0_s0o: SPILL_0_OTHER -tl0_s1o: SPILL_1_OTHER -tl0_s2o: SPILL_2_OTHER -tl0_s3o: SPILL_3_OTHER -tl0_s4o: SPILL_4_OTHER -tl0_s5o: SPILL_5_OTHER -tl0_s6o: SPILL_6_OTHER -tl0_s7o: SPILL_7_OTHER -tl0_f0n: FILL_0_NORMAL -tl0_f1n: FILL_1_NORMAL -tl0_f2n: FILL_2_NORMAL -tl0_f3n: FILL_3_NORMAL -tl0_f4n: FILL_4_NORMAL -tl0_f5n: FILL_5_NORMAL -tl0_f6n: FILL_6_NORMAL -tl0_f7n: FILL_7_NORMAL -tl0_f0o: FILL_0_OTHER -tl0_f1o: FILL_1_OTHER -tl0_f2o: FILL_2_OTHER -tl0_f3o: FILL_3_OTHER -tl0_f4o: FILL_4_OTHER -tl0_f5o: FILL_5_OTHER -tl0_f6o: FILL_6_OTHER -tl0_f7o: FILL_7_OTHER -tl0_sunos: SUNOS_SYSCALL_TRAP -tl0_bkpt: BREAKPOINT_TRAP -tl0_divz: TRAP(do_div0) -tl0_flushw: FLUSH_WINDOW_TRAP -tl0_resv104: BTRAP(0x104) BTRAP(0x105) BTRAP(0x106) BTRAP(0x107) - .globl tl0_solaris -tl0_solaris: SOLARIS_SYSCALL_TRAP -tl0_netbsd: NETBSD_SYSCALL_TRAP -tl0_resv10a: BTRAP(0x10a) BTRAP(0x10b) BTRAP(0x10c) BTRAP(0x10d) BTRAP(0x10e) -tl0_resv10f: BTRAP(0x10f) -tl0_linux32: LINUX_32BIT_SYSCALL_TRAP -tl0_oldlinux64: LINUX_64BIT_SYSCALL_TRAP -tl0_resv112: TRAP_UTRAP(UT_TRAP_INSTRUCTION_18,0x112) TRAP_UTRAP(UT_TRAP_INSTRUCTION_19,0x113) -tl0_resv114: TRAP_UTRAP(UT_TRAP_INSTRUCTION_20,0x114) TRAP_UTRAP(UT_TRAP_INSTRUCTION_21,0x115) -tl0_resv116: TRAP_UTRAP(UT_TRAP_INSTRUCTION_22,0x116) TRAP_UTRAP(UT_TRAP_INSTRUCTION_23,0x117) -tl0_resv118: TRAP_UTRAP(UT_TRAP_INSTRUCTION_24,0x118) TRAP_UTRAP(UT_TRAP_INSTRUCTION_25,0x119) -tl0_resv11a: TRAP_UTRAP(UT_TRAP_INSTRUCTION_26,0x11a) TRAP_UTRAP(UT_TRAP_INSTRUCTION_27,0x11b) -tl0_resv11c: TRAP_UTRAP(UT_TRAP_INSTRUCTION_28,0x11c) TRAP_UTRAP(UT_TRAP_INSTRUCTION_29,0x11d) -tl0_resv11e: TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUCTION_31,0x11f) -tl0_getcc: GETCC_TRAP -tl0_setcc: SETCC_TRAP -tl0_getpsr: TRAP(do_getpsr) -tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) -tl0_solindir: INDIRECT_SOLARIS_SYSCALL(156) -tl0_resv128: BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c) -tl0_resv12d: BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131) -tl0_resv132: BTRAP(0x132) BTRAP(0x133) BTRAP(0x134) BTRAP(0x135) BTRAP(0x136) -tl0_resv137: BTRAP(0x137) BTRAP(0x138) BTRAP(0x139) BTRAP(0x13a) BTRAP(0x13b) -tl0_resv13c: BTRAP(0x13c) BTRAP(0x13d) BTRAP(0x13e) BTRAP(0x13f) BTRAP(0x140) -tl0_resv141: BTRAP(0x141) BTRAP(0x142) BTRAP(0x143) BTRAP(0x144) BTRAP(0x145) -tl0_resv146: BTRAP(0x146) BTRAP(0x147) BTRAP(0x148) BTRAP(0x149) BTRAP(0x14a) -tl0_resv14b: BTRAP(0x14b) BTRAP(0x14c) BTRAP(0x14d) BTRAP(0x14e) BTRAP(0x14f) -tl0_resv150: BTRAP(0x150) BTRAP(0x151) BTRAP(0x152) BTRAP(0x153) BTRAP(0x154) -tl0_resv155: BTRAP(0x155) BTRAP(0x156) BTRAP(0x157) BTRAP(0x158) BTRAP(0x159) -tl0_resv15a: BTRAP(0x15a) BTRAP(0x15b) BTRAP(0x15c) BTRAP(0x15d) BTRAP(0x15e) -tl0_resv15f: BTRAP(0x15f) BTRAP(0x160) BTRAP(0x161) BTRAP(0x162) BTRAP(0x163) -tl0_resv164: BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168) -tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c) -tl0_linux64: LINUX_64BIT_SYSCALL_TRAP -tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context) -tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172) -tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177) -tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c) -tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f) -#define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7) -tl0_resv180: BTRAPS(0x180) BTRAPS(0x188) -tl0_resv190: BTRAPS(0x190) BTRAPS(0x198) -tl0_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8) -tl0_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8) -tl0_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8) -tl0_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8) -tl0_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8) -tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) - -sparc64_ttable_tl1: -tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3) -tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7) -tl1_iax: TRAP_NOSAVE(__spitfire_insn_access_exception_tl1) -tl1_resv009: BTRAPTL1(0x9) -tl1_iae: membar #Sync - TRAP_NOSAVE_7INSNS(__spitfire_access_error) -tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf) -tl1_ill: TRAPTL1(do_ill_tl1) -tl1_privop: BTRAPTL1(0x11) -tl1_resv012: BTRAPTL1(0x12) BTRAPTL1(0x13) BTRAPTL1(0x14) BTRAPTL1(0x15) -tl1_resv016: BTRAPTL1(0x16) BTRAPTL1(0x17) BTRAPTL1(0x18) BTRAPTL1(0x19) -tl1_resv01a: BTRAPTL1(0x1a) BTRAPTL1(0x1b) BTRAPTL1(0x1c) BTRAPTL1(0x1d) -tl1_resv01e: BTRAPTL1(0x1e) BTRAPTL1(0x1f) -tl1_fpdis: TRAP_NOSAVE(do_fpdis) -tl1_fpieee: TRAPTL1(do_fpieee_tl1) -tl1_fpother: TRAPTL1(do_fpother_tl1) -tl1_tof: TRAPTL1(do_tof_tl1) -tl1_cwin: CLEAN_WINDOW -tl1_div0: TRAPTL1(do_div0_tl1) -tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c) -tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f) -tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1) -tl1_resv031: BTRAPTL1(0x31) -tl1_dae: membar #Sync - TRAP_NOSAVE_7INSNS(__spitfire_access_error) -tl1_resv033: BTRAPTL1(0x33) -tl1_mna: TRAP_NOSAVE(do_mna) -tl1_lddfmna: TRAPTL1(do_lddfmna_tl1) -tl1_stdfmna: TRAPTL1(do_stdfmna_tl1) -tl1_privact: BTRAPTL1(0x37) -tl1_resv038: BTRAPTL1(0x38) BTRAPTL1(0x39) BTRAPTL1(0x3a) BTRAPTL1(0x3b) -tl1_resv03c: BTRAPTL1(0x3c) BTRAPTL1(0x3d) BTRAPTL1(0x3e) BTRAPTL1(0x3f) -tl1_resv040: BTRAPTL1(0x40) -tl1_irq1: TRAP_IRQ(do_irq_tl1, 1) TRAP_IRQ(do_irq_tl1, 2) TRAP_IRQ(do_irq_tl1, 3) -tl1_irq4: TRAP_IRQ(do_irq_tl1, 4) TRAP_IRQ(do_irq_tl1, 5) TRAP_IRQ(do_irq_tl1, 6) -tl1_irq7: TRAP_IRQ(do_irq_tl1, 7) TRAP_IRQ(do_irq_tl1, 8) TRAP_IRQ(do_irq_tl1, 9) -tl1_irq10: TRAP_IRQ(do_irq_tl1, 10) TRAP_IRQ(do_irq_tl1, 11) -tl1_irq12: TRAP_IRQ(do_irq_tl1, 12) TRAP_IRQ(do_irq_tl1, 13) -tl1_irq14: TRAP_IRQ(do_irq_tl1, 14) TRAP_IRQ(do_irq_tl1, 15) -tl1_resv050: BTRAPTL1(0x50) BTRAPTL1(0x51) BTRAPTL1(0x52) BTRAPTL1(0x53) -tl1_resv054: BTRAPTL1(0x54) BTRAPTL1(0x55) BTRAPTL1(0x56) BTRAPTL1(0x57) -tl1_resv058: BTRAPTL1(0x58) BTRAPTL1(0x59) BTRAPTL1(0x5a) BTRAPTL1(0x5b) -tl1_resv05c: BTRAPTL1(0x5c) BTRAPTL1(0x5d) BTRAPTL1(0x5e) BTRAPTL1(0x5f) -tl1_ivec: TRAP_IVEC -tl1_paw: TRAPTL1(do_paw_tl1) -tl1_vaw: TRAPTL1(do_vaw_tl1) - - /* The grotty trick to save %g1 into current->thread.cee_stuff - * is because when we take this trap we could be interrupting - * trap code already using the trap alternate global registers. - * - * We cross our fingers and pray that this store/load does - * not cause yet another CEE trap. - */ -tl1_cee: membar #Sync - stx %g1, [%g6 + TI_CEE_STUFF] - ldxa [%g0] ASI_AFSR, %g1 - membar #Sync - stxa %g1, [%g0] ASI_AFSR - membar #Sync - ldx [%g6 + TI_CEE_STUFF], %g1 - retry - -tl1_iamiss: BTRAPTL1(0x64) BTRAPTL1(0x65) BTRAPTL1(0x66) BTRAPTL1(0x67) -tl1_damiss: -#include "dtlb_backend.S" -tl1_daprot: -#include "dtlb_prot.S" -tl1_fecc: BTRAPTL1(0x70) /* Fast-ECC on Cheetah */ -tl1_dcpe: BTRAPTL1(0x71) /* D-cache Parity Error on Cheetah+ */ -tl1_icpe: BTRAPTL1(0x72) /* I-cache Parity Error on Cheetah+ */ -tl1_resv073: BTRAPTL1(0x73) -tl1_resv074: BTRAPTL1(0x74) BTRAPTL1(0x75) BTRAPTL1(0x76) BTRAPTL1(0x77) -tl1_resv078: BTRAPTL1(0x78) BTRAPTL1(0x79) BTRAPTL1(0x7a) BTRAPTL1(0x7b) -tl1_resv07c: BTRAPTL1(0x7c) BTRAPTL1(0x7d) BTRAPTL1(0x7e) BTRAPTL1(0x7f) -tl1_s0n: SPILL_0_NORMAL -tl1_s1n: SPILL_1_NORMAL -tl1_s2n: SPILL_2_NORMAL -tl1_s3n: SPILL_3_NORMAL -tl1_s4n: SPILL_4_NORMAL -tl1_s5n: SPILL_5_NORMAL -tl1_s6n: SPILL_6_NORMAL -tl1_s7n: SPILL_7_NORMAL -tl1_s0o: SPILL_0_OTHER -tl1_s1o: SPILL_1_OTHER -tl1_s2o: SPILL_2_OTHER -tl1_s3o: SPILL_3_OTHER -tl1_s4o: SPILL_4_OTHER -tl1_s5o: SPILL_5_OTHER -tl1_s6o: SPILL_6_OTHER -tl1_s7o: SPILL_7_OTHER -tl1_f0n: FILL_0_NORMAL -tl1_f1n: FILL_1_NORMAL -tl1_f2n: FILL_2_NORMAL -tl1_f3n: FILL_3_NORMAL -tl1_f4n: FILL_4_NORMAL -tl1_f5n: FILL_5_NORMAL -tl1_f6n: FILL_6_NORMAL -tl1_f7n: FILL_7_NORMAL -tl1_f0o: FILL_0_OTHER -tl1_f1o: FILL_1_OTHER -tl1_f2o: FILL_2_OTHER -tl1_f3o: FILL_3_OTHER -tl1_f4o: FILL_4_OTHER -tl1_f5o: FILL_5_OTHER -tl1_f6o: FILL_6_OTHER -tl1_f7o: FILL_7_OTHER diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S deleted file mode 100644 index 1f5b5b708ce..00000000000 --- a/arch/sparc64/kernel/una_asm.S +++ /dev/null @@ -1,146 +0,0 @@ -/* una_asm.S: Kernel unaligned trap assembler helpers. - * - * Copyright (C) 1996,2005 David S. Miller (davem@davemloft.net) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - - .text - - .globl __do_int_store -__do_int_store: - rd %asi, %o4 - wr %o3, 0, %asi - mov %o2, %g3 - cmp %o1, 2 - be,pn %icc, 2f - cmp %o1, 4 - be,pt %icc, 1f - srlx %g3, 24, %g2 - srlx %g3, 56, %g1 - srlx %g3, 48, %g7 -4: stba %g1, [%o0] %asi - srlx %g3, 40, %g1 -5: stba %g7, [%o0 + 1] %asi - srlx %g3, 32, %g7 -6: stba %g1, [%o0 + 2] %asi -7: stba %g7, [%o0 + 3] %asi - srlx %g3, 16, %g1 -8: stba %g2, [%o0 + 4] %asi - srlx %g3, 8, %g7 -9: stba %g1, [%o0 + 5] %asi -10: stba %g7, [%o0 + 6] %asi - ba,pt %xcc, 0f -11: stba %g3, [%o0 + 7] %asi -1: srl %g3, 16, %g7 -12: stba %g2, [%o0] %asi - srl %g3, 8, %g2 -13: stba %g7, [%o0 + 1] %asi -14: stba %g2, [%o0 + 2] %asi - ba,pt %xcc, 0f -15: stba %g3, [%o0 + 3] %asi -2: srl %g3, 8, %g2 -16: stba %g2, [%o0] %asi -17: stba %g3, [%o0 + 1] %asi -0: - wr %o4, 0x0, %asi - retl - mov 0, %o0 - .size __do_int_store, .-__do_int_store - - .section __ex_table - .word 4b, __retl_efault - .word 5b, __retl_efault - .word 6b, __retl_efault - .word 7b, __retl_efault - .word 8b, __retl_efault - .word 9b, __retl_efault - .word 10b, __retl_efault - .word 11b, __retl_efault - .word 12b, __retl_efault - .word 13b, __retl_efault - .word 14b, __retl_efault - .word 15b, __retl_efault - .word 16b, __retl_efault - .word 17b, __retl_efault - .previous - - .globl do_int_load -do_int_load: - rd %asi, %o5 - wr %o4, 0, %asi - cmp %o1, 8 - bge,pn %icc, 9f - cmp %o1, 4 - be,pt %icc, 6f -4: lduba [%o2] %asi, %g2 -5: lduba [%o2 + 1] %asi, %g3 - sll %g2, 8, %g2 - brz,pt %o3, 3f - add %g2, %g3, %g2 - sllx %g2, 48, %g2 - srax %g2, 48, %g2 -3: ba,pt %xcc, 0f - stx %g2, [%o0] -6: lduba [%o2 + 1] %asi, %g3 - sll %g2, 24, %g2 -7: lduba [%o2 + 2] %asi, %g7 - sll %g3, 16, %g3 -8: lduba [%o2 + 3] %asi, %g1 - sll %g7, 8, %g7 - or %g2, %g3, %g2 - or %g7, %g1, %g7 - or %g2, %g7, %g2 - brnz,a,pt %o3, 3f - sra %g2, 0, %g2 -3: ba,pt %xcc, 0f - stx %g2, [%o0] -9: lduba [%o2] %asi, %g2 -10: lduba [%o2 + 1] %asi, %g3 - sllx %g2, 56, %g2 -11: lduba [%o2 + 2] %asi, %g7 - sllx %g3, 48, %g3 -12: lduba [%o2 + 3] %asi, %g1 - sllx %g7, 40, %g7 - sllx %g1, 32, %g1 - or %g2, %g3, %g2 - or %g7, %g1, %g7 -13: lduba [%o2 + 4] %asi, %g3 - or %g2, %g7, %g7 -14: lduba [%o2 + 5] %asi, %g1 - sllx %g3, 24, %g3 -15: lduba [%o2 + 6] %asi, %g2 - sllx %g1, 16, %g1 - or %g7, %g3, %g7 -16: lduba [%o2 + 7] %asi, %g3 - sllx %g2, 8, %g2 - or %g7, %g1, %g7 - or %g2, %g3, %g2 - or %g7, %g2, %g7 - cmp %o1, 8 - be,a,pt %icc, 0f - stx %g7, [%o0] - srlx %g7, 32, %g2 - sra %g7, 0, %g7 - stx %g2, [%o0] - stx %g7, [%o0 + 8] -0: - wr %o5, 0x0, %asi - retl - mov 0, %o0 - .size __do_int_load, .-__do_int_load - - .section __ex_table - .word 4b, __retl_efault - .word 5b, __retl_efault - .word 6b, __retl_efault - .word 7b, __retl_efault - .word 8b, __retl_efault - .word 9b, __retl_efault - .word 10b, __retl_efault - .word 11b, __retl_efault - .word 12b, __retl_efault - .word 13b, __retl_efault - .word 14b, __retl_efault - .word 15b, __retl_efault - .word 16b, __retl_efault - .previous diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c deleted file mode 100644 index 70faf630603..00000000000 --- a/arch/sparc64/kernel/unaligned.c +++ /dev/null @@ -1,639 +0,0 @@ -/* $Id: unaligned.c,v 1.24 2002/02/09 19:49:31 davem Exp $ - * unaligned.c: Unaligned load/store trap handling with special - * cases for the kernel to do them more quickly. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <asm/asi.h> -#include <asm/ptrace.h> -#include <asm/pstate.h> -#include <asm/processor.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/bitops.h> -#include <asm/fpumacro.h> - -/* #define DEBUG_MNA */ - -enum direction { - load, /* ld, ldd, ldh, ldsh */ - store, /* st, std, sth, stsh */ - both, /* Swap, ldstub, cas, ... */ - fpld, - fpst, - invalid, -}; - -#ifdef DEBUG_MNA -static char *dirstrings[] = { - "load", "store", "both", "fpload", "fpstore", "invalid" -}; -#endif - -static inline enum direction decode_direction(unsigned int insn) -{ - unsigned long tmp = (insn >> 21) & 1; - - if (!tmp) - return load; - else { - switch ((insn>>19)&0xf) { - case 15: /* swap* */ - return both; - default: - return store; - } - } -} - -/* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */ -static inline int decode_access_size(unsigned int insn) -{ - unsigned int tmp; - - tmp = ((insn >> 19) & 0xf); - if (tmp == 11 || tmp == 14) /* ldx/stx */ - return 8; - tmp &= 3; - if (!tmp) - return 4; - else if (tmp == 3) - return 16; /* ldd/std - Although it is actually 8 */ - else if (tmp == 2) - return 2; - else { - printk("Impossible unaligned trap. insn=%08x\n", insn); - die_if_kernel("Byte sized unaligned access?!?!", current_thread_info()->kregs); - - /* GCC should never warn that control reaches the end - * of this function without returning a value because - * die_if_kernel() is marked with attribute 'noreturn'. - * Alas, some versions do... - */ - - return 0; - } -} - -static inline int decode_asi(unsigned int insn, struct pt_regs *regs) -{ - if (insn & 0x800000) { - if (insn & 0x2000) - return (unsigned char)(regs->tstate >> 24); /* %asi */ - else - return (unsigned char)(insn >> 5); /* imm_asi */ - } else - return ASI_P; -} - -/* 0x400000 = signed, 0 = unsigned */ -static inline int decode_signedness(unsigned int insn) -{ - return (insn & 0x400000); -} - -static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, - unsigned int rd, int from_kernel) -{ - if (rs2 >= 16 || rs1 >= 16 || rd >= 16) { - if (from_kernel != 0) - __asm__ __volatile__("flushw"); - else - flushw_user(); - } -} - -static inline long sign_extend_imm13(long imm) -{ - return imm << 51 >> 51; -} - -static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) -{ - unsigned long value; - - if (reg < 16) - return (!reg ? 0 : regs->u_regs[reg]); - if (regs->tstate & TSTATE_PRIV) { - struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); - value = win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { - struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); - get_user(value, &win32->locals[reg - 16]); - } else { - struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); - get_user(value, &win->locals[reg - 16]); - } - return value; -} - -static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) -{ - if (reg < 16) - return ®s->u_regs[reg]; - if (regs->tstate & TSTATE_PRIV) { - struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); - return &win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { - struct reg_window32 *win32; - win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); - return (unsigned long *)&win32->locals[reg - 16]; - } else { - struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); - return &win->locals[reg - 16]; - } -} - -unsigned long compute_effective_address(struct pt_regs *regs, - unsigned int insn, unsigned int rd) -{ - unsigned int rs1 = (insn >> 14) & 0x1f; - unsigned int rs2 = insn & 0x1f; - int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; - - if (insn & 0x2000) { - maybe_flush_windows(rs1, 0, rd, from_kernel); - return (fetch_reg(rs1, regs) + sign_extend_imm13(insn)); - } else { - maybe_flush_windows(rs1, rs2, rd, from_kernel); - return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs)); - } -} - -/* This is just to make gcc think die_if_kernel does return... */ -static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs) -{ - die_if_kernel(str, regs); -} - -extern int do_int_load(unsigned long *dest_reg, int size, - unsigned long *saddr, int is_signed, int asi); - -extern int __do_int_store(unsigned long *dst_addr, int size, - unsigned long src_val, int asi); - -static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr, - struct pt_regs *regs, int asi, int orig_asi) -{ - unsigned long zero = 0; - unsigned long *src_val_p = &zero; - unsigned long src_val; - - if (size == 16) { - size = 8; - zero = (((long)(reg_num ? - (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | - (unsigned)fetch_reg(reg_num + 1, regs); - } else if (reg_num) { - src_val_p = fetch_reg_addr(reg_num, regs); - } - src_val = *src_val_p; - if (unlikely(asi != orig_asi)) { - switch (size) { - case 2: - src_val = swab16(src_val); - break; - case 4: - src_val = swab32(src_val); - break; - case 8: - src_val = swab64(src_val); - break; - case 16: - default: - BUG(); - break; - }; - } - return __do_int_store(dst_addr, size, src_val, asi); -} - -static inline void advance(struct pt_regs *regs) -{ - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } -} - -static inline int floating_point_load_or_store_p(unsigned int insn) -{ - return (insn >> 24) & 1; -} - -static inline int ok_for_kernel(unsigned int insn) -{ - return !floating_point_load_or_store_p(insn); -} - -static void kernel_mna_trap_fault(void) -{ - struct pt_regs *regs = current_thread_info()->kern_una_regs; - unsigned int insn = current_thread_info()->kern_una_insn; - const struct exception_table_entry *entry; - - entry = search_exception_tables(regs->tpc); - if (!entry) { - unsigned long address; - - address = compute_effective_address(regs, insn, - ((insn >> 25) & 0x1f)); - if (address < PAGE_SIZE) { - printk(KERN_ALERT "Unable to handle kernel NULL " - "pointer dereference in mna handler"); - } else - printk(KERN_ALERT "Unable to handle kernel paging " - "request in mna handler"); - printk(KERN_ALERT " at virtual address %016lx\n",address); - printk(KERN_ALERT "current->{active_,}mm->context = %016lx\n", - (current->mm ? CTX_HWBITS(current->mm->context) : - CTX_HWBITS(current->active_mm->context))); - printk(KERN_ALERT "current->{active_,}mm->pgd = %016lx\n", - (current->mm ? (unsigned long) current->mm->pgd : - (unsigned long) current->active_mm->pgd)); - die_if_kernel("Oops", regs); - /* Not reached */ - } - regs->tpc = entry->fixup; - regs->tnpc = regs->tpc + 4; - - regs->tstate &= ~TSTATE_ASI; - regs->tstate |= (ASI_AIUS << 24UL); -} - -asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, unsigned long sfar, unsigned long sfsr) -{ - enum direction dir = decode_direction(insn); - int size = decode_access_size(insn); - - current_thread_info()->kern_una_regs = regs; - current_thread_info()->kern_una_insn = insn; - - if (!ok_for_kernel(insn) || dir == both) { - printk("Unsupported unaligned load/store trap for kernel " - "at <%016lx>.\n", regs->tpc); - unaligned_panic("Kernel does fpu/atomic " - "unaligned load/store.", regs); - - kernel_mna_trap_fault(); - } else { - unsigned long addr, *reg_addr; - int orig_asi, asi, err; - - addr = compute_effective_address(regs, insn, - ((insn >> 25) & 0x1f)); -#ifdef DEBUG_MNA - printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] " - "retpc[%016lx]\n", - regs->tpc, dirstrings[dir], addr, size, - regs->u_regs[UREG_RETPC]); -#endif - orig_asi = asi = decode_asi(insn, regs); - switch (asi) { - case ASI_NL: - case ASI_AIUPL: - case ASI_AIUSL: - case ASI_PL: - case ASI_SL: - case ASI_PNFL: - case ASI_SNFL: - asi &= ~0x08; - break; - }; - switch (dir) { - case load: - reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); - err = do_int_load(reg_addr, size, - (unsigned long *) addr, - decode_signedness(insn), asi); - if (likely(!err) && unlikely(asi != orig_asi)) { - unsigned long val_in = *reg_addr; - switch (size) { - case 2: - val_in = swab16(val_in); - break; - case 4: - val_in = swab32(val_in); - break; - case 8: - val_in = swab64(val_in); - break; - case 16: - default: - BUG(); - break; - }; - *reg_addr = val_in; - } - break; - - case store: - err = do_int_store(((insn>>25)&0x1f), size, - (unsigned long *) addr, regs, - asi, orig_asi); - break; - - default: - panic("Impossible kernel unaligned trap."); - /* Not reached... */ - } - if (unlikely(err)) - kernel_mna_trap_fault(); - else - advance(regs); - } -} - -static char popc_helper[] = { -0, 1, 1, 2, 1, 2, 2, 3, -1, 2, 2, 3, 2, 3, 3, 4, -}; - -int handle_popc(u32 insn, struct pt_regs *regs) -{ - u64 value; - int ret, i, rd = ((insn >> 25) & 0x1f); - int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; - - if (insn & 0x2000) { - maybe_flush_windows(0, 0, rd, from_kernel); - value = sign_extend_imm13(insn); - } else { - maybe_flush_windows(0, insn & 0x1f, rd, from_kernel); - value = fetch_reg(insn & 0x1f, regs); - } - for (ret = 0, i = 0; i < 16; i++) { - ret += popc_helper[value & 0xf]; - value >>= 4; - } - if (rd < 16) { - if (rd) - regs->u_regs[rd] = ret; - } else { - if (test_thread_flag(TIF_32BIT)) { - struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); - put_user(ret, &win32->locals[rd - 16]); - } else { - struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); - put_user(ret, &win->locals[rd - 16]); - } - } - advance(regs); - return 1; -} - -extern void do_fpother(struct pt_regs *regs); -extern void do_privact(struct pt_regs *regs); -extern void spitfire_data_access_exception(struct pt_regs *regs, - unsigned long sfsr, - unsigned long sfar); - -int handle_ldf_stq(u32 insn, struct pt_regs *regs) -{ - unsigned long addr = compute_effective_address(regs, insn, 0); - int freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20); - struct fpustate *f = FPUSTATE; - int asi = decode_asi(insn, regs); - int flag = (freg < 32) ? FPRS_DL : FPRS_DU; - - save_and_clear_fpu(); - current_thread_info()->xfsr[0] &= ~0x1c000; - if (freg & 3) { - current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */; - do_fpother(regs); - return 0; - } - if (insn & 0x200000) { - /* STQ */ - u64 first = 0, second = 0; - - if (current_thread_info()->fpsaved[0] & flag) { - first = *(u64 *)&f->regs[freg]; - second = *(u64 *)&f->regs[freg+2]; - } - if (asi < 0x80) { - do_privact(regs); - return 1; - } - switch (asi) { - case ASI_P: - case ASI_S: break; - case ASI_PL: - case ASI_SL: - { - /* Need to convert endians */ - u64 tmp = __swab64p(&first); - - first = __swab64p(&second); - second = tmp; - break; - } - default: - spitfire_data_access_exception(regs, 0, addr); - return 1; - } - if (put_user (first >> 32, (u32 __user *)addr) || - __put_user ((u32)first, (u32 __user *)(addr + 4)) || - __put_user (second >> 32, (u32 __user *)(addr + 8)) || - __put_user ((u32)second, (u32 __user *)(addr + 12))) { - spitfire_data_access_exception(regs, 0, addr); - return 1; - } - } else { - /* LDF, LDDF, LDQF */ - u32 data[4] __attribute__ ((aligned(8))); - int size, i; - int err; - - if (asi < 0x80) { - do_privact(regs); - return 1; - } else if (asi > ASI_SNFL) { - spitfire_data_access_exception(regs, 0, addr); - return 1; - } - switch (insn & 0x180000) { - case 0x000000: size = 1; break; - case 0x100000: size = 4; break; - default: size = 2; break; - } - for (i = 0; i < size; i++) - data[i] = 0; - - err = get_user (data[0], (u32 __user *) addr); - if (!err) { - for (i = 1; i < size; i++) - err |= __get_user (data[i], (u32 __user *)(addr + 4*i)); - } - if (err && !(asi & 0x2 /* NF */)) { - spitfire_data_access_exception(regs, 0, addr); - return 1; - } - if (asi & 0x8) /* Little */ { - u64 tmp; - - switch (size) { - case 1: data[0] = le32_to_cpup(data + 0); break; - default:*(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 0)); - break; - case 4: tmp = le64_to_cpup((u64 *)(data + 0)); - *(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 2)); - *(u64 *)(data + 2) = tmp; - break; - } - } - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) { - current_thread_info()->fpsaved[0] = FPRS_FEF; - current_thread_info()->gsr[0] = 0; - } - if (!(current_thread_info()->fpsaved[0] & flag)) { - if (freg < 32) - memset(f->regs, 0, 32*sizeof(u32)); - else - memset(f->regs+32, 0, 32*sizeof(u32)); - } - memcpy(f->regs + freg, data, size * 4); - current_thread_info()->fpsaved[0] |= flag; - } - advance(regs); - return 1; -} - -void handle_ld_nf(u32 insn, struct pt_regs *regs) -{ - int rd = ((insn >> 25) & 0x1f); - int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; - unsigned long *reg; - - maybe_flush_windows(0, 0, rd, from_kernel); - reg = fetch_reg_addr(rd, regs); - if (from_kernel || rd < 16) { - reg[0] = 0; - if ((insn & 0x780000) == 0x180000) - reg[1] = 0; - } else if (test_thread_flag(TIF_32BIT)) { - put_user(0, (int __user *) reg); - if ((insn & 0x780000) == 0x180000) - put_user(0, ((int __user *) reg) + 1); - } else { - put_user(0, (unsigned long __user *) reg); - if ((insn & 0x780000) == 0x180000) - put_user(0, (unsigned long __user *) reg + 1); - } - advance(regs); -} - -void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) -{ - unsigned long pc = regs->tpc; - unsigned long tstate = regs->tstate; - u32 insn; - u32 first, second; - u64 value; - u8 asi, freg; - int flag; - struct fpustate *f = FPUSTATE; - - if (tstate & TSTATE_PRIV) - die_if_kernel("lddfmna from kernel", regs); - if (test_thread_flag(TIF_32BIT)) - pc = (u32)pc; - if (get_user(insn, (u32 __user *) pc) != -EFAULT) { - asi = sfsr >> 16; - if ((asi > ASI_SNFL) || - (asi < ASI_P)) - goto daex; - if (get_user(first, (u32 __user *)sfar) || - get_user(second, (u32 __user *)(sfar + 4))) { - if (asi & 0x2) /* NF */ { - first = 0; second = 0; - } else - goto daex; - } - save_and_clear_fpu(); - freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20); - value = (((u64)first) << 32) | second; - if (asi & 0x8) /* Little */ - value = __swab64p(&value); - flag = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) { - current_thread_info()->fpsaved[0] = FPRS_FEF; - current_thread_info()->gsr[0] = 0; - } - if (!(current_thread_info()->fpsaved[0] & flag)) { - if (freg < 32) - memset(f->regs, 0, 32*sizeof(u32)); - else - memset(f->regs+32, 0, 32*sizeof(u32)); - } - *(u64 *)(f->regs + freg) = value; - current_thread_info()->fpsaved[0] |= flag; - } else { -daex: spitfire_data_access_exception(regs, sfsr, sfar); - return; - } - advance(regs); - return; -} - -void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) -{ - unsigned long pc = regs->tpc; - unsigned long tstate = regs->tstate; - u32 insn; - u64 value; - u8 asi, freg; - int flag; - struct fpustate *f = FPUSTATE; - - if (tstate & TSTATE_PRIV) - die_if_kernel("stdfmna from kernel", regs); - if (test_thread_flag(TIF_32BIT)) - pc = (u32)pc; - if (get_user(insn, (u32 __user *) pc) != -EFAULT) { - freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20); - asi = sfsr >> 16; - value = 0; - flag = (freg < 32) ? FPRS_DL : FPRS_DU; - if ((asi > ASI_SNFL) || - (asi < ASI_P)) - goto daex; - save_and_clear_fpu(); - if (current_thread_info()->fpsaved[0] & flag) - value = *(u64 *)&f->regs[freg]; - switch (asi) { - case ASI_P: - case ASI_S: break; - case ASI_PL: - case ASI_SL: - value = __swab64p(&value); break; - default: goto daex; - } - if (put_user (value >> 32, (u32 __user *) sfar) || - __put_user ((u32)value, (u32 __user *)(sfar + 4))) - goto daex; - } else { -daex: spitfire_data_access_exception(regs, sfsr, sfar); - return; - } - advance(regs); - return; -} diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c deleted file mode 100644 index b35dc8dc995..00000000000 --- a/arch/sparc64/kernel/us2e_cpufreq.c +++ /dev/null @@ -1,415 +0,0 @@ -/* us2e_cpufreq.c: UltraSPARC-IIe cpu frequency support - * - * Copyright (C) 2003 David S. Miller (davem@redhat.com) - * - * Many thanks to Dominik Brodowski for fixing up the cpufreq - * infrastructure in order to make this driver easier to implement. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/cpufreq.h> -#include <linux/threads.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/init.h> - -#include <asm/asi.h> -#include <asm/timer.h> - -static struct cpufreq_driver *cpufreq_us2e_driver; - -struct us2e_freq_percpu_info { - struct cpufreq_frequency_table table[6]; -}; - -/* Indexed by cpu number. */ -static struct us2e_freq_percpu_info *us2e_freq_table; - -#define HBIRD_MEM_CNTL0_ADDR 0x1fe0000f010UL -#define HBIRD_ESTAR_MODE_ADDR 0x1fe0000f080UL - -/* UltraSPARC-IIe has five dividers: 1, 2, 4, 6, and 8. These are controlled - * in the ESTAR mode control register. - */ -#define ESTAR_MODE_DIV_1 0x0000000000000000UL -#define ESTAR_MODE_DIV_2 0x0000000000000001UL -#define ESTAR_MODE_DIV_4 0x0000000000000003UL -#define ESTAR_MODE_DIV_6 0x0000000000000002UL -#define ESTAR_MODE_DIV_8 0x0000000000000004UL -#define ESTAR_MODE_DIV_MASK 0x0000000000000007UL - -#define MCTRL0_SREFRESH_ENAB 0x0000000000010000UL -#define MCTRL0_REFR_COUNT_MASK 0x0000000000007f00UL -#define MCTRL0_REFR_COUNT_SHIFT 8 -#define MCTRL0_REFR_INTERVAL 7800 -#define MCTRL0_REFR_CLKS_P_CNT 64 - -static unsigned long read_hbreg(unsigned long addr) -{ - unsigned long ret; - - __asm__ __volatile__("ldxa [%1] %2, %0" - : "=&r" (ret) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)); - return ret; -} - -static void write_hbreg(unsigned long addr, unsigned long val) -{ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E) - : "memory"); - if (addr == HBIRD_ESTAR_MODE_ADDR) { - /* Need to wait 16 clock cycles for the PLL to lock. */ - udelay(1); - } -} - -static void self_refresh_ctl(int enable) -{ - unsigned long mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); - - if (enable) - mctrl |= MCTRL0_SREFRESH_ENAB; - else - mctrl &= ~MCTRL0_SREFRESH_ENAB; - write_hbreg(HBIRD_MEM_CNTL0_ADDR, mctrl); - (void) read_hbreg(HBIRD_MEM_CNTL0_ADDR); -} - -static void frob_mem_refresh(int cpu_slowing_down, - unsigned long clock_tick, - unsigned long old_divisor, unsigned long divisor) -{ - unsigned long old_refr_count, refr_count, mctrl; - - refr_count = (clock_tick * MCTRL0_REFR_INTERVAL); - refr_count /= (MCTRL0_REFR_CLKS_P_CNT * divisor * 1000000000UL); - - mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); - old_refr_count = (mctrl & MCTRL0_REFR_COUNT_MASK) - >> MCTRL0_REFR_COUNT_SHIFT; - - mctrl &= ~MCTRL0_REFR_COUNT_MASK; - mctrl |= refr_count << MCTRL0_REFR_COUNT_SHIFT; - write_hbreg(HBIRD_MEM_CNTL0_ADDR, mctrl); - mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); - - if (cpu_slowing_down && !(mctrl & MCTRL0_SREFRESH_ENAB)) { - unsigned long usecs; - - /* We have to wait for both refresh counts (old - * and new) to go to zero. - */ - usecs = (MCTRL0_REFR_CLKS_P_CNT * - (refr_count + old_refr_count) * - 1000000UL * - old_divisor) / clock_tick; - udelay(usecs + 1UL); - } -} - -static void us2e_transition(unsigned long estar, unsigned long new_bits, - unsigned long clock_tick, - unsigned long old_divisor, unsigned long divisor) -{ - unsigned long flags; - - local_irq_save(flags); - - estar &= ~ESTAR_MODE_DIV_MASK; - - /* This is based upon the state transition diagram in the IIe manual. */ - if (old_divisor == 2 && divisor == 1) { - self_refresh_ctl(0); - write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); - frob_mem_refresh(0, clock_tick, old_divisor, divisor); - } else if (old_divisor == 1 && divisor == 2) { - frob_mem_refresh(1, clock_tick, old_divisor, divisor); - write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); - self_refresh_ctl(1); - } else if (old_divisor == 1 && divisor > 2) { - us2e_transition(estar, ESTAR_MODE_DIV_2, clock_tick, - 1, 2); - us2e_transition(estar, new_bits, clock_tick, - 2, divisor); - } else if (old_divisor > 2 && divisor == 1) { - us2e_transition(estar, ESTAR_MODE_DIV_2, clock_tick, - old_divisor, 2); - us2e_transition(estar, new_bits, clock_tick, - 2, divisor); - } else if (old_divisor < divisor) { - frob_mem_refresh(0, clock_tick, old_divisor, divisor); - write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); - } else if (old_divisor > divisor) { - write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); - frob_mem_refresh(1, clock_tick, old_divisor, divisor); - } else { - BUG(); - } - - local_irq_restore(flags); -} - -static unsigned long index_to_estar_mode(unsigned int index) -{ - switch (index) { - case 0: - return ESTAR_MODE_DIV_1; - - case 1: - return ESTAR_MODE_DIV_2; - - case 2: - return ESTAR_MODE_DIV_4; - - case 3: - return ESTAR_MODE_DIV_6; - - case 4: - return ESTAR_MODE_DIV_8; - - default: - BUG(); - }; -} - -static unsigned long index_to_divisor(unsigned int index) -{ - switch (index) { - case 0: - return 1; - - case 1: - return 2; - - case 2: - return 4; - - case 3: - return 6; - - case 4: - return 8; - - default: - BUG(); - }; -} - -static unsigned long estar_to_divisor(unsigned long estar) -{ - unsigned long ret; - - switch (estar & ESTAR_MODE_DIV_MASK) { - case ESTAR_MODE_DIV_1: - ret = 1; - break; - case ESTAR_MODE_DIV_2: - ret = 2; - break; - case ESTAR_MODE_DIV_4: - ret = 4; - break; - case ESTAR_MODE_DIV_6: - ret = 6; - break; - case ESTAR_MODE_DIV_8: - ret = 8; - break; - default: - BUG(); - }; - - return ret; -} - -static unsigned int us2e_freq_get(unsigned int cpu) -{ - cpumask_t cpus_allowed; - unsigned long clock_tick, estar; - - if (!cpu_online(cpu)) - return 0; - - cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - - clock_tick = sparc64_get_clock_tick(cpu) / 1000; - estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR); - - set_cpus_allowed(current, cpus_allowed); - - return clock_tick / estar_to_divisor(estar); -} - -static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index) -{ - unsigned long new_bits, new_freq; - unsigned long clock_tick, divisor, old_divisor, estar; - cpumask_t cpus_allowed; - struct cpufreq_freqs freqs; - - if (!cpu_online(cpu)) - return; - - cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - - new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000; - new_bits = index_to_estar_mode(index); - divisor = index_to_divisor(index); - new_freq /= divisor; - - estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR); - - old_divisor = estar_to_divisor(estar); - - freqs.old = clock_tick / old_divisor; - freqs.new = new_freq; - freqs.cpu = cpu; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - if (old_divisor != divisor) - us2e_transition(estar, new_bits, clock_tick * 1000, - old_divisor, divisor); - - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - set_cpus_allowed(current, cpus_allowed); -} - -static int us2e_freq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int new_index = 0; - - if (cpufreq_frequency_table_target(policy, - &us2e_freq_table[policy->cpu].table[0], - target_freq, relation, &new_index)) - return -EINVAL; - - us2e_set_cpu_divider_index(policy->cpu, new_index); - - return 0; -} - -static int us2e_freq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - &us2e_freq_table[policy->cpu].table[0]); -} - -static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) -{ - unsigned int cpu = policy->cpu; - unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; - struct cpufreq_frequency_table *table = - &us2e_freq_table[cpu].table[0]; - - table[0].index = 0; - table[0].frequency = clock_tick / 1; - table[1].index = 1; - table[1].frequency = clock_tick / 2; - table[2].index = 2; - table[2].frequency = clock_tick / 4; - table[2].index = 3; - table[2].frequency = clock_tick / 6; - table[2].index = 4; - table[2].frequency = clock_tick / 8; - table[2].index = 5; - table[3].frequency = CPUFREQ_TABLE_END; - - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = 0; - policy->cur = clock_tick; - - return cpufreq_frequency_table_cpuinfo(policy, table); -} - -static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) -{ - if (cpufreq_us2e_driver) - us2e_set_cpu_divider_index(policy->cpu, 0); - - return 0; -} - -static int __init us2e_freq_init(void) -{ - unsigned long manuf, impl, ver; - int ret; - - __asm__("rdpr %%ver, %0" : "=r" (ver)); - manuf = ((ver >> 48) & 0xffff); - impl = ((ver >> 32) & 0xffff); - - if (manuf == 0x17 && impl == 0x13) { - struct cpufreq_driver *driver; - - ret = -ENOMEM; - driver = kmalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); - if (!driver) - goto err_out; - memset(driver, 0, sizeof(*driver)); - - us2e_freq_table = kmalloc( - (NR_CPUS * sizeof(struct us2e_freq_percpu_info)), - GFP_KERNEL); - if (!us2e_freq_table) - goto err_out; - - memset(us2e_freq_table, 0, - (NR_CPUS * sizeof(struct us2e_freq_percpu_info))); - - driver->init = us2e_freq_cpu_init; - driver->verify = us2e_freq_verify; - driver->target = us2e_freq_target; - driver->get = us2e_freq_get; - driver->exit = us2e_freq_cpu_exit; - driver->owner = THIS_MODULE, - strcpy(driver->name, "UltraSPARC-IIe"); - - cpufreq_us2e_driver = driver; - ret = cpufreq_register_driver(driver); - if (ret) - goto err_out; - - return 0; - -err_out: - if (driver) { - kfree(driver); - cpufreq_us2e_driver = NULL; - } - kfree(us2e_freq_table); - us2e_freq_table = NULL; - return ret; - } - - return -ENODEV; -} - -static void __exit us2e_freq_exit(void) -{ - if (cpufreq_us2e_driver) { - cpufreq_unregister_driver(cpufreq_us2e_driver); - kfree(cpufreq_us2e_driver); - cpufreq_us2e_driver = NULL; - kfree(us2e_freq_table); - us2e_freq_table = NULL; - } -} - -MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); -MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-IIe"); -MODULE_LICENSE("GPL"); - -module_init(us2e_freq_init); -module_exit(us2e_freq_exit); diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c deleted file mode 100644 index 6d1f9a3c464..00000000000 --- a/arch/sparc64/kernel/us3_cpufreq.c +++ /dev/null @@ -1,276 +0,0 @@ -/* us3_cpufreq.c: UltraSPARC-III cpu frequency support - * - * Copyright (C) 2003 David S. Miller (davem@redhat.com) - * - * Many thanks to Dominik Brodowski for fixing up the cpufreq - * infrastructure in order to make this driver easier to implement. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/cpufreq.h> -#include <linux/threads.h> -#include <linux/slab.h> -#include <linux/init.h> - -#include <asm/head.h> -#include <asm/timer.h> - -static struct cpufreq_driver *cpufreq_us3_driver; - -struct us3_freq_percpu_info { - struct cpufreq_frequency_table table[4]; -}; - -/* Indexed by cpu number. */ -static struct us3_freq_percpu_info *us3_freq_table; - -/* UltraSPARC-III has three dividers: 1, 2, and 32. These are controlled - * in the Safari config register. - */ -#define SAFARI_CFG_DIV_1 0x0000000000000000UL -#define SAFARI_CFG_DIV_2 0x0000000040000000UL -#define SAFARI_CFG_DIV_32 0x0000000080000000UL -#define SAFARI_CFG_DIV_MASK 0x00000000C0000000UL - -static unsigned long read_safari_cfg(void) -{ - unsigned long ret; - - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=&r" (ret) - : "i" (ASI_SAFARI_CONFIG)); - return ret; -} - -static void write_safari_cfg(unsigned long val) -{ - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "i" (ASI_SAFARI_CONFIG) - : "memory"); -} - -static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg) -{ - unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; - unsigned long ret; - - switch (safari_cfg & SAFARI_CFG_DIV_MASK) { - case SAFARI_CFG_DIV_1: - ret = clock_tick / 1; - break; - case SAFARI_CFG_DIV_2: - ret = clock_tick / 2; - break; - case SAFARI_CFG_DIV_32: - ret = clock_tick / 32; - break; - default: - BUG(); - }; - - return ret; -} - -static unsigned int us3_freq_get(unsigned int cpu) -{ - cpumask_t cpus_allowed; - unsigned long reg; - unsigned int ret; - - if (!cpu_online(cpu)) - return 0; - - cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - - reg = read_safari_cfg(); - ret = get_current_freq(cpu, reg); - - set_cpus_allowed(current, cpus_allowed); - - return ret; -} - -static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) -{ - unsigned long new_bits, new_freq, reg; - cpumask_t cpus_allowed; - struct cpufreq_freqs freqs; - - if (!cpu_online(cpu)) - return; - - cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - - new_freq = sparc64_get_clock_tick(cpu) / 1000; - switch (index) { - case 0: - new_bits = SAFARI_CFG_DIV_1; - new_freq /= 1; - break; - case 1: - new_bits = SAFARI_CFG_DIV_2; - new_freq /= 2; - break; - case 2: - new_bits = SAFARI_CFG_DIV_32; - new_freq /= 32; - break; - - default: - BUG(); - }; - - reg = read_safari_cfg(); - - freqs.old = get_current_freq(cpu, reg); - freqs.new = new_freq; - freqs.cpu = cpu; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - reg &= ~SAFARI_CFG_DIV_MASK; - reg |= new_bits; - write_safari_cfg(reg); - - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - set_cpus_allowed(current, cpus_allowed); -} - -static int us3_freq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int new_index = 0; - - if (cpufreq_frequency_table_target(policy, - &us3_freq_table[policy->cpu].table[0], - target_freq, - relation, - &new_index)) - return -EINVAL; - - us3_set_cpu_divider_index(policy->cpu, new_index); - - return 0; -} - -static int us3_freq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - &us3_freq_table[policy->cpu].table[0]); -} - -static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) -{ - unsigned int cpu = policy->cpu; - unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; - struct cpufreq_frequency_table *table = - &us3_freq_table[cpu].table[0]; - - table[0].index = 0; - table[0].frequency = clock_tick / 1; - table[1].index = 1; - table[1].frequency = clock_tick / 2; - table[2].index = 2; - table[2].frequency = clock_tick / 32; - table[3].index = 0; - table[3].frequency = CPUFREQ_TABLE_END; - - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = 0; - policy->cur = clock_tick; - - return cpufreq_frequency_table_cpuinfo(policy, table); -} - -static int us3_freq_cpu_exit(struct cpufreq_policy *policy) -{ - if (cpufreq_us3_driver) - us3_set_cpu_divider_index(policy->cpu, 0); - - return 0; -} - -static int __init us3_freq_init(void) -{ - unsigned long manuf, impl, ver; - int ret; - - __asm__("rdpr %%ver, %0" : "=r" (ver)); - manuf = ((ver >> 48) & 0xffff); - impl = ((ver >> 32) & 0xffff); - - if (manuf == CHEETAH_MANUF && - (impl == CHEETAH_IMPL || - impl == CHEETAH_PLUS_IMPL || - impl == JAGUAR_IMPL || - impl == PANTHER_IMPL)) { - struct cpufreq_driver *driver; - - ret = -ENOMEM; - driver = kmalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); - if (!driver) - goto err_out; - memset(driver, 0, sizeof(*driver)); - - us3_freq_table = kmalloc( - (NR_CPUS * sizeof(struct us3_freq_percpu_info)), - GFP_KERNEL); - if (!us3_freq_table) - goto err_out; - - memset(us3_freq_table, 0, - (NR_CPUS * sizeof(struct us3_freq_percpu_info))); - - driver->init = us3_freq_cpu_init; - driver->verify = us3_freq_verify; - driver->target = us3_freq_target; - driver->get = us3_freq_get; - driver->exit = us3_freq_cpu_exit; - driver->owner = THIS_MODULE, - strcpy(driver->name, "UltraSPARC-III"); - - cpufreq_us3_driver = driver; - ret = cpufreq_register_driver(driver); - if (ret) - goto err_out; - - return 0; - -err_out: - if (driver) { - kfree(driver); - cpufreq_us3_driver = NULL; - } - kfree(us3_freq_table); - us3_freq_table = NULL; - return ret; - } - - return -ENODEV; -} - -static void __exit us3_freq_exit(void) -{ - if (cpufreq_us3_driver) { - cpufreq_unregister_driver(cpufreq_us3_driver); - kfree(cpufreq_us3_driver); - cpufreq_us3_driver = NULL; - kfree(us3_freq_table); - us3_freq_table = NULL; - } -} - -MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); -MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-III"); -MODULE_LICENSE("GPL"); - -module_init(us3_freq_init); -module_exit(us3_freq_exit); diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S deleted file mode 100644 index 467d13a0d5c..00000000000 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ /dev/null @@ -1,98 +0,0 @@ -/* ld script to make UltraLinux kernel */ - -#include <asm-generic/vmlinux.lds.h> - -OUTPUT_FORMAT("elf64-sparc", "elf64-sparc", "elf64-sparc") -OUTPUT_ARCH(sparc:v9a) -ENTRY(_start) - -jiffies = jiffies_64; -SECTIONS -{ - swapper_low_pmd_dir = 0x0000000000402000; - . = 0x4000; - .text 0x0000000000404000 : - { - *(.text) - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - *(.gnu.warning) - } =0 - _etext = .; - PROVIDE (etext = .); - - RODATA - - .data : - { - *(.data) - CONSTRUCTORS - } - .data1 : { *(.data1) } - . = ALIGN(64); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - . = ALIGN(64); - .data.read_mostly : { *(.data.read_mostly) } - _edata = .; - PROVIDE (edata = .); - .fixup : { *(.fixup) } - - . = ALIGN(16); - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - . = ALIGN(8192); - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } - .init.data : { *(.init.data) } - . = ALIGN(16); - __setup_start = .; - .init.setup : { *(.init.setup) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : { *(.con_initcall.init) } - __con_initcall_end = .; - SECURITY_INIT - . = ALIGN(8192); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; - . = ALIGN(8192); - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } - __per_cpu_end = .; - . = ALIGN(8192); - __init_end = .; - __bss_start = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); - /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) } - - STABS_DEBUG - - DWARF_DEBUG -} diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S deleted file mode 100644 index 39160926267..00000000000 --- a/arch/sparc64/kernel/winfixup.S +++ /dev/null @@ -1,388 +0,0 @@ -/* $Id: winfixup.S,v 1.30 2002/02/09 19:49:30 davem Exp $ - * - * winfixup.S: Handle cases where user stack pointer is found to be bogus. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <asm/asi.h> -#include <asm/head.h> -#include <asm/page.h> -#include <asm/ptrace.h> -#include <asm/processor.h> -#include <asm/spitfire.h> -#include <asm/thread_info.h> - - .text - -set_pcontext: - sethi %hi(sparc64_kern_pri_context), %l1 - ldx [%l1 + %lo(sparc64_kern_pri_context)], %l1 - mov PRIMARY_CONTEXT, %g1 - stxa %l1, [%g1] ASI_DMMU - flush %g6 - retl - nop - - .align 32 - - /* Here are the rules, pay attention. - * - * The kernel is disallowed from touching user space while - * the trap level is greater than zero, except for from within - * the window spill/fill handlers. This must be followed - * so that we can easily detect the case where we tried to - * spill/fill with a bogus (or unmapped) user stack pointer. - * - * These are layed out in a special way for cache reasons, - * don't touch... - */ - .globl fill_fixup, spill_fixup -fill_fixup: - rdpr %tstate, %g1 - andcc %g1, TSTATE_PRIV, %g0 - or %g4, FAULT_CODE_WINFIXUP, %g4 - be,pt %xcc, window_scheisse_from_user_common - and %g1, TSTATE_CWP, %g1 - - /* This is the extremely complex case, but it does happen from - * time to time if things are just right. Essentially the restore - * done in rtrap right before going back to user mode, with tl=1 - * and that levels trap stack registers all setup, took a fill trap, - * the user stack was not mapped in the tlb, and tlb miss occurred, - * the pte found was not valid, and a simple ref bit watch update - * could not satisfy the miss, so we got here. - * - * We must carefully unwind the state so we get back to tl=0, preserve - * all the register values we were going to give to the user. Luckily - * most things are where they need to be, we also have the address - * which triggered the fault handy as well. - * - * Also note that we must preserve %l5 and %l6. If the user was - * returning from a system call, we must make it look this way - * after we process the fill fault on the users stack. - * - * First, get into the window where the original restore was executed. - */ - - rdpr %wstate, %g2 ! Grab user mode wstate. - wrpr %g1, %cwp ! Get into the right window. - sll %g2, 3, %g2 ! NORMAL-->OTHER - - wrpr %g0, 0x0, %canrestore ! Standard etrap stuff. - wrpr %g2, 0x0, %wstate ! This must be consistent. - wrpr %g0, 0x0, %otherwin ! We know this. - call set_pcontext ! Change contexts... - nop - rdpr %pstate, %l1 ! Prepare to change globals. - mov %g6, %o7 ! Get current. - - andn %l1, PSTATE_MM, %l1 ! We want to be in RMO - stb %g4, [%g6 + TI_FAULT_CODE] - stx %g5, [%g6 + TI_FAULT_ADDR] - wrpr %g0, 0x0, %tl ! Out of trap levels. - wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate - mov %o7, %g6 - ldx [%g6 + TI_TASK], %g4 -#ifdef CONFIG_SMP - mov TSB_REG, %g1 - ldxa [%g1] ASI_IMMU, %g5 -#endif - - /* This is the same as below, except we handle this a bit special - * since we must preserve %l5 and %l6, see comment above. - */ - call do_sparc64_fault - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - nop ! yes, nop is correct - - /* Be very careful about usage of the alternate globals here. - * You cannot touch %g4/%g5 as that has the fault information - * should this be from usermode. Also be careful for the case - * where we get here from the save instruction in etrap.S when - * coming from either user or kernel (does not matter which, it - * is the same problem in both cases). Essentially this means - * do not touch %g7 or %g2 so we handle the two cases fine. - */ -spill_fixup: - ldx [%g6 + TI_FLAGS], %g1 - andcc %g1, _TIF_32BIT, %g0 - ldub [%g6 + TI_WSAVED], %g1 - - sll %g1, 3, %g3 - add %g6, %g3, %g3 - stx %sp, [%g3 + TI_RWIN_SPTRS] - sll %g1, 7, %g3 - bne,pt %xcc, 1f - add %g6, %g3, %g3 - stx %l0, [%g3 + TI_REG_WINDOW + 0x00] - stx %l1, [%g3 + TI_REG_WINDOW + 0x08] - - stx %l2, [%g3 + TI_REG_WINDOW + 0x10] - stx %l3, [%g3 + TI_REG_WINDOW + 0x18] - stx %l4, [%g3 + TI_REG_WINDOW + 0x20] - stx %l5, [%g3 + TI_REG_WINDOW + 0x28] - stx %l6, [%g3 + TI_REG_WINDOW + 0x30] - stx %l7, [%g3 + TI_REG_WINDOW + 0x38] - stx %i0, [%g3 + TI_REG_WINDOW + 0x40] - stx %i1, [%g3 + TI_REG_WINDOW + 0x48] - - stx %i2, [%g3 + TI_REG_WINDOW + 0x50] - stx %i3, [%g3 + TI_REG_WINDOW + 0x58] - stx %i4, [%g3 + TI_REG_WINDOW + 0x60] - stx %i5, [%g3 + TI_REG_WINDOW + 0x68] - stx %i6, [%g3 + TI_REG_WINDOW + 0x70] - b,pt %xcc, 2f - stx %i7, [%g3 + TI_REG_WINDOW + 0x78] -1: stw %l0, [%g3 + TI_REG_WINDOW + 0x00] - - stw %l1, [%g3 + TI_REG_WINDOW + 0x04] - stw %l2, [%g3 + TI_REG_WINDOW + 0x08] - stw %l3, [%g3 + TI_REG_WINDOW + 0x0c] - stw %l4, [%g3 + TI_REG_WINDOW + 0x10] - stw %l5, [%g3 + TI_REG_WINDOW + 0x14] - stw %l6, [%g3 + TI_REG_WINDOW + 0x18] - stw %l7, [%g3 + TI_REG_WINDOW + 0x1c] - stw %i0, [%g3 + TI_REG_WINDOW + 0x20] - - stw %i1, [%g3 + TI_REG_WINDOW + 0x24] - stw %i2, [%g3 + TI_REG_WINDOW + 0x28] - stw %i3, [%g3 + TI_REG_WINDOW + 0x2c] - stw %i4, [%g3 + TI_REG_WINDOW + 0x30] - stw %i5, [%g3 + TI_REG_WINDOW + 0x34] - stw %i6, [%g3 + TI_REG_WINDOW + 0x38] - stw %i7, [%g3 + TI_REG_WINDOW + 0x3c] -2: add %g1, 1, %g1 - - stb %g1, [%g6 + TI_WSAVED] - rdpr %tstate, %g1 - andcc %g1, TSTATE_PRIV, %g0 - saved - and %g1, TSTATE_CWP, %g1 - be,pn %xcc, window_scheisse_from_user_common - mov FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4 - retry - -window_scheisse_from_user_common: - stb %g4, [%g6 + TI_FAULT_CODE] - stx %g5, [%g6 + TI_FAULT_ADDR] - wrpr %g1, %cwp - ba,pt %xcc, etrap - rd %pc, %g7 - call do_sparc64_fault - add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 - - .globl winfix_mna, fill_fixup_mna, spill_fixup_mna -winfix_mna: - andn %g3, 0x7f, %g3 - add %g3, 0x78, %g3 - wrpr %g3, %tnpc - done -fill_fixup_mna: - rdpr %tstate, %g1 - andcc %g1, TSTATE_PRIV, %g0 - be,pt %xcc, window_mna_from_user_common - and %g1, TSTATE_CWP, %g1 - - /* Please, see fill_fixup commentary about why we must preserve - * %l5 and %l6 to preserve absolute correct semantics. - */ - rdpr %wstate, %g2 ! Grab user mode wstate. - wrpr %g1, %cwp ! Get into the right window. - sll %g2, 3, %g2 ! NORMAL-->OTHER - wrpr %g0, 0x0, %canrestore ! Standard etrap stuff. - - wrpr %g2, 0x0, %wstate ! This must be consistent. - wrpr %g0, 0x0, %otherwin ! We know this. - call set_pcontext ! Change contexts... - nop - rdpr %pstate, %l1 ! Prepare to change globals. - mov %g4, %o2 ! Setup args for - mov %g5, %o1 ! final call to mem_address_unaligned. - andn %l1, PSTATE_MM, %l1 ! We want to be in RMO - - mov %g6, %o7 ! Stash away current. - wrpr %g0, 0x0, %tl ! Out of trap levels. - wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate - mov %o7, %g6 ! Get current back. - ldx [%g6 + TI_TASK], %g4 ! Finish it. -#ifdef CONFIG_SMP - mov TSB_REG, %g1 - ldxa [%g1] ASI_IMMU, %g5 -#endif - call mem_address_unaligned - add %sp, PTREGS_OFF, %o0 - - b,pt %xcc, rtrap - nop ! yes, the nop is correct -spill_fixup_mna: - ldx [%g6 + TI_FLAGS], %g1 - andcc %g1, _TIF_32BIT, %g0 - ldub [%g6 + TI_WSAVED], %g1 - sll %g1, 3, %g3 - add %g6, %g3, %g3 - stx %sp, [%g3 + TI_RWIN_SPTRS] - - sll %g1, 7, %g3 - bne,pt %xcc, 1f - add %g6, %g3, %g3 - stx %l0, [%g3 + TI_REG_WINDOW + 0x00] - stx %l1, [%g3 + TI_REG_WINDOW + 0x08] - stx %l2, [%g3 + TI_REG_WINDOW + 0x10] - stx %l3, [%g3 + TI_REG_WINDOW + 0x18] - stx %l4, [%g3 + TI_REG_WINDOW + 0x20] - - stx %l5, [%g3 + TI_REG_WINDOW + 0x28] - stx %l6, [%g3 + TI_REG_WINDOW + 0x30] - stx %l7, [%g3 + TI_REG_WINDOW + 0x38] - stx %i0, [%g3 + TI_REG_WINDOW + 0x40] - stx %i1, [%g3 + TI_REG_WINDOW + 0x48] - stx %i2, [%g3 + TI_REG_WINDOW + 0x50] - stx %i3, [%g3 + TI_REG_WINDOW + 0x58] - stx %i4, [%g3 + TI_REG_WINDOW + 0x60] - - stx %i5, [%g3 + TI_REG_WINDOW + 0x68] - stx %i6, [%g3 + TI_REG_WINDOW + 0x70] - stx %i7, [%g3 + TI_REG_WINDOW + 0x78] - b,pt %xcc, 2f - add %g1, 1, %g1 -1: std %l0, [%g3 + TI_REG_WINDOW + 0x00] - std %l2, [%g3 + TI_REG_WINDOW + 0x08] - std %l4, [%g3 + TI_REG_WINDOW + 0x10] - - std %l6, [%g3 + TI_REG_WINDOW + 0x18] - std %i0, [%g3 + TI_REG_WINDOW + 0x20] - std %i2, [%g3 + TI_REG_WINDOW + 0x28] - std %i4, [%g3 + TI_REG_WINDOW + 0x30] - std %i6, [%g3 + TI_REG_WINDOW + 0x38] - add %g1, 1, %g1 -2: stb %g1, [%g6 + TI_WSAVED] - rdpr %tstate, %g1 - - andcc %g1, TSTATE_PRIV, %g0 - saved - be,pn %xcc, window_mna_from_user_common - and %g1, TSTATE_CWP, %g1 - retry -window_mna_from_user_common: - wrpr %g1, %cwp - sethi %hi(109f), %g7 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - mov %l4, %o2 - mov %l5, %o1 - call mem_address_unaligned - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 - - /* These are only needed for 64-bit mode processes which - * put their stack pointer into the VPTE area and there - * happens to be a VPTE tlb entry mapped there during - * a spill/fill trap to that stack frame. - */ - .globl winfix_dax, fill_fixup_dax, spill_fixup_dax -winfix_dax: - andn %g3, 0x7f, %g3 - add %g3, 0x74, %g3 - wrpr %g3, %tnpc - done -fill_fixup_dax: - rdpr %tstate, %g1 - andcc %g1, TSTATE_PRIV, %g0 - be,pt %xcc, window_dax_from_user_common - and %g1, TSTATE_CWP, %g1 - - /* Please, see fill_fixup commentary about why we must preserve - * %l5 and %l6 to preserve absolute correct semantics. - */ - rdpr %wstate, %g2 ! Grab user mode wstate. - wrpr %g1, %cwp ! Get into the right window. - sll %g2, 3, %g2 ! NORMAL-->OTHER - wrpr %g0, 0x0, %canrestore ! Standard etrap stuff. - - wrpr %g2, 0x0, %wstate ! This must be consistent. - wrpr %g0, 0x0, %otherwin ! We know this. - call set_pcontext ! Change contexts... - nop - rdpr %pstate, %l1 ! Prepare to change globals. - mov %g4, %o1 ! Setup args for - mov %g5, %o2 ! final call to spitfire_data_access_exception. - andn %l1, PSTATE_MM, %l1 ! We want to be in RMO - - mov %g6, %o7 ! Stash away current. - wrpr %g0, 0x0, %tl ! Out of trap levels. - wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate - mov %o7, %g6 ! Get current back. - ldx [%g6 + TI_TASK], %g4 ! Finish it. -#ifdef CONFIG_SMP - mov TSB_REG, %g1 - ldxa [%g1] ASI_IMMU, %g5 -#endif - call spitfire_data_access_exception - add %sp, PTREGS_OFF, %o0 - - b,pt %xcc, rtrap - nop ! yes, the nop is correct -spill_fixup_dax: - ldx [%g6 + TI_FLAGS], %g1 - andcc %g1, _TIF_32BIT, %g0 - ldub [%g6 + TI_WSAVED], %g1 - sll %g1, 3, %g3 - add %g6, %g3, %g3 - stx %sp, [%g3 + TI_RWIN_SPTRS] - - sll %g1, 7, %g3 - bne,pt %xcc, 1f - add %g6, %g3, %g3 - stx %l0, [%g3 + TI_REG_WINDOW + 0x00] - stx %l1, [%g3 + TI_REG_WINDOW + 0x08] - stx %l2, [%g3 + TI_REG_WINDOW + 0x10] - stx %l3, [%g3 + TI_REG_WINDOW + 0x18] - stx %l4, [%g3 + TI_REG_WINDOW + 0x20] - - stx %l5, [%g3 + TI_REG_WINDOW + 0x28] - stx %l6, [%g3 + TI_REG_WINDOW + 0x30] - stx %l7, [%g3 + TI_REG_WINDOW + 0x38] - stx %i0, [%g3 + TI_REG_WINDOW + 0x40] - stx %i1, [%g3 + TI_REG_WINDOW + 0x48] - stx %i2, [%g3 + TI_REG_WINDOW + 0x50] - stx %i3, [%g3 + TI_REG_WINDOW + 0x58] - stx %i4, [%g3 + TI_REG_WINDOW + 0x60] - - stx %i5, [%g3 + TI_REG_WINDOW + 0x68] - stx %i6, [%g3 + TI_REG_WINDOW + 0x70] - stx %i7, [%g3 + TI_REG_WINDOW + 0x78] - b,pt %xcc, 2f - add %g1, 1, %g1 -1: std %l0, [%g3 + TI_REG_WINDOW + 0x00] - std %l2, [%g3 + TI_REG_WINDOW + 0x08] - std %l4, [%g3 + TI_REG_WINDOW + 0x10] - - std %l6, [%g3 + TI_REG_WINDOW + 0x18] - std %i0, [%g3 + TI_REG_WINDOW + 0x20] - std %i2, [%g3 + TI_REG_WINDOW + 0x28] - std %i4, [%g3 + TI_REG_WINDOW + 0x30] - std %i6, [%g3 + TI_REG_WINDOW + 0x38] - add %g1, 1, %g1 -2: stb %g1, [%g6 + TI_WSAVED] - rdpr %tstate, %g1 - - andcc %g1, TSTATE_PRIV, %g0 - saved - be,pn %xcc, window_dax_from_user_common - and %g1, TSTATE_CWP, %g1 - retry -window_dax_from_user_common: - wrpr %g1, %cwp - sethi %hi(109f), %g7 - ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - mov %l4, %o1 - mov %l5, %o2 - call spitfire_data_access_exception - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap - clr %l6 diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile deleted file mode 100644 index c295806500f..00000000000 --- a/arch/sparc64/lib/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $Id: Makefile,v 1.25 2000/12/14 22:57:25 davem Exp $ -# Makefile for Sparc64 library files.. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \ - memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ - bzero.o csum_copy.o csum_copy_from_user.o csum_copy_to_user.o \ - VISsave.o atomic.o bitops.o \ - U1memcpy.o U1copy_from_user.o U1copy_to_user.o \ - U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ - copy_in_user.o user_fixup.o memmove.o \ - mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o - -obj-y += iomap.o diff --git a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc64/lib/PeeCeeI.c deleted file mode 100644 index 3c6cfbb2036..00000000000 --- a/arch/sparc64/lib/PeeCeeI.c +++ /dev/null @@ -1,248 +0,0 @@ -/* $Id: PeeCeeI.c,v 1.4 1999/09/06 01:17:35 davem Exp $ - * PeeCeeI.c: The emerging standard... - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <asm/io.h> -#include <asm/byteorder.h> - -void outsb(unsigned long __addr, const void *src, unsigned long count) -{ - void __iomem *addr = (void __iomem *) __addr; - const u8 *p = src; - - while (count--) - outb(*p++, addr); -} - -void outsw(unsigned long __addr, const void *src, unsigned long count) -{ - void __iomem *addr = (void __iomem *) __addr; - - if (count) { - u16 *ps = (u16 *)src; - u32 *pi; - - if (((u64)src) & 0x2) { - u16 val = le16_to_cpup(ps); - outw(val, addr); - ps++; - count--; - } - pi = (u32 *)ps; - while (count >= 2) { - u32 w = le32_to_cpup(pi); - - pi++; - outw(w >> 0, addr); - outw(w >> 16, addr); - count -= 2; - } - ps = (u16 *)pi; - if (count) { - u16 val = le16_to_cpup(ps); - outw(val, addr); - } - } -} - -void outsl(unsigned long __addr, const void *src, unsigned long count) -{ - void __iomem *addr = (void __iomem *) __addr; - - if (count) { - if ((((u64)src) & 0x3) == 0) { - u32 *p = (u32 *)src; - while (count--) { - u32 val = cpu_to_le32p(p); - outl(val, addr); - p++; - } - } else { - u8 *pb; - u16 *ps = (u16 *)src; - u32 l = 0, l2; - u32 *pi; - - switch (((u64)src) & 0x3) { - case 0x2: - count -= 1; - l = cpu_to_le16p(ps) << 16; - ps++; - pi = (u32 *)ps; - while (count--) { - l2 = cpu_to_le32p(pi); - pi++; - outl(((l >> 16) | (l2 << 16)), addr); - l = l2; - } - ps = (u16 *)pi; - l2 = cpu_to_le16p(ps); - outl(((l >> 16) | (l2 << 16)), addr); - break; - - case 0x1: - count -= 1; - pb = (u8 *)src; - l = (*pb++ << 8); - ps = (u16 *)pb; - l2 = cpu_to_le16p(ps); - ps++; - l |= (l2 << 16); - pi = (u32 *)ps; - while (count--) { - l2 = cpu_to_le32p(pi); - pi++; - outl(((l >> 8) | (l2 << 24)), addr); - l = l2; - } - pb = (u8 *)pi; - outl(((l >> 8) | (*pb << 24)), addr); - break; - - case 0x3: - count -= 1; - pb = (u8 *)src; - l = (*pb++ << 24); - pi = (u32 *)pb; - while (count--) { - l2 = cpu_to_le32p(pi); - pi++; - outl(((l >> 24) | (l2 << 8)), addr); - l = l2; - } - ps = (u16 *)pi; - l2 = cpu_to_le16p(ps); - ps++; - pb = (u8 *)ps; - l2 |= (*pb << 16); - outl(((l >> 24) | (l2 << 8)), addr); - break; - } - } - } -} - -void insb(unsigned long __addr, void *dst, unsigned long count) -{ - void __iomem *addr = (void __iomem *) __addr; - - if (count) { - u32 *pi; - u8 *pb = dst; - - while ((((unsigned long)pb) & 0x3) && count--) - *pb++ = inb(addr); - pi = (u32 *)pb; - while (count >= 4) { - u32 w; - - w = (inb(addr) << 24); - w |= (inb(addr) << 16); - w |= (inb(addr) << 8); - w |= (inb(addr) << 0); - *pi++ = w; - count -= 4; - } - pb = (u8 *)pi; - while (count--) - *pb++ = inb(addr); - } -} - -void insw(unsigned long __addr, void *dst, unsigned long count) -{ - void __iomem *addr = (void __iomem *) __addr; - - if (count) { - u16 *ps = dst; - u32 *pi; - - if (((unsigned long)ps) & 0x2) { - *ps++ = le16_to_cpu(inw(addr)); - count--; - } - pi = (u32 *)ps; - while (count >= 2) { - u32 w; - - w = (le16_to_cpu(inw(addr)) << 16); - w |= (le16_to_cpu(inw(addr)) << 0); - *pi++ = w; - count -= 2; - } - ps = (u16 *)pi; - if (count) - *ps = le16_to_cpu(inw(addr)); - } -} - -void insl(unsigned long __addr, void *dst, unsigned long count) -{ - void __iomem *addr = (void __iomem *) __addr; - - if (count) { - if ((((unsigned long)dst) & 0x3) == 0) { - u32 *pi = dst; - while (count--) - *pi++ = le32_to_cpu(inl(addr)); - } else { - u32 l = 0, l2, *pi; - u16 *ps; - u8 *pb; - - switch (((unsigned long)dst) & 3) { - case 0x2: - ps = dst; - count -= 1; - l = le32_to_cpu(inl(addr)); - *ps++ = l; - pi = (u32 *)ps; - while (count--) { - l2 = le32_to_cpu(inl(addr)); - *pi++ = (l << 16) | (l2 >> 16); - l = l2; - } - ps = (u16 *)pi; - *ps = l; - break; - - case 0x1: - pb = dst; - count -= 1; - l = le32_to_cpu(inl(addr)); - *pb++ = l >> 24; - ps = (u16 *)pb; - *ps++ = ((l >> 8) & 0xffff); - pi = (u32 *)ps; - while (count--) { - l2 = le32_to_cpu(inl(addr)); - *pi++ = (l << 24) | (l2 >> 8); - l = l2; - } - pb = (u8 *)pi; - *pb = l; - break; - - case 0x3: - pb = (u8 *)dst; - count -= 1; - l = le32_to_cpu(inl(addr)); - *pb++ = l >> 24; - pi = (u32 *)pb; - while (count--) { - l2 = le32_to_cpu(inl(addr)); - *pi++ = (l << 8) | (l2 >> 24); - l = l2; - } - ps = (u16 *)pi; - *ps++ = ((l >> 8) & 0xffff); - pb = (u8 *)ps; - *pb = l; - break; - } - } - } -} - diff --git a/arch/sparc64/lib/U1copy_from_user.S b/arch/sparc64/lib/U1copy_from_user.S deleted file mode 100644 index 93146a81e2d..00000000000 --- a/arch/sparc64/lib/U1copy_from_user.S +++ /dev/null @@ -1,33 +0,0 @@ -/* U1copy_from_user.S: UltraSparc-I/II/IIi/IIe optimized copy from userspace. - * - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - -#define EX_LD(x) \ -98: x; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - -#define FUNC_NAME ___copy_from_user -#define LOAD(type,addr,dest) type##a [addr] %asi, dest -#define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_AIUS, dest -#define EX_RETVAL(x) 0 - - /* Writing to %asi is _expensive_ so we hardcode it. - * Reading %asi to check for KERNEL_DS is comparatively - * cheap. - */ -#define PREAMBLE \ - rd %asi, %g1; \ - cmp %g1, ASI_AIUS; \ - bne,pn %icc, memcpy_user_stub; \ - nop; \ - -#include "U1memcpy.S" diff --git a/arch/sparc64/lib/U1copy_to_user.S b/arch/sparc64/lib/U1copy_to_user.S deleted file mode 100644 index 1fccc521e2b..00000000000 --- a/arch/sparc64/lib/U1copy_to_user.S +++ /dev/null @@ -1,33 +0,0 @@ -/* U1copy_to_user.S: UltraSparc-I/II/IIi/IIe optimized copy to userspace. - * - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - -#define EX_ST(x) \ -98: x; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - -#define FUNC_NAME ___copy_to_user -#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS -#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS -#define EX_RETVAL(x) 0 - - /* Writing to %asi is _expensive_ so we hardcode it. - * Reading %asi to check for KERNEL_DS is comparatively - * cheap. - */ -#define PREAMBLE \ - rd %asi, %g1; \ - cmp %g1, ASI_AIUS; \ - bne,pn %icc, memcpy_user_stub; \ - nop; \ - -#include "U1memcpy.S" diff --git a/arch/sparc64/lib/U1memcpy.S b/arch/sparc64/lib/U1memcpy.S deleted file mode 100644 index bafd2fc07ac..00000000000 --- a/arch/sparc64/lib/U1memcpy.S +++ /dev/null @@ -1,563 +0,0 @@ -/* U1memcpy.S: UltraSPARC-I/II/IIi/IIe optimized memcpy. - * - * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com) - * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#ifdef __KERNEL__ -#include <asm/visasm.h> -#include <asm/asi.h> -#define GLOBAL_SPARE g7 -#else -#define GLOBAL_SPARE g5 -#define ASI_BLK_P 0xf0 -#define FPRS_FEF 0x04 -#ifdef MEMCPY_DEBUG -#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \ - clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0; -#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#else -#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs -#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#endif -#endif - -#ifndef EX_LD -#define EX_LD(x) x -#endif - -#ifndef EX_ST -#define EX_ST(x) x -#endif - -#ifndef EX_RETVAL -#define EX_RETVAL(x) x -#endif - -#ifndef LOAD -#define LOAD(type,addr,dest) type [addr], dest -#endif - -#ifndef LOAD_BLK -#define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_P, dest -#endif - -#ifndef STORE -#define STORE(type,src,addr) type src, [addr] -#endif - -#ifndef STORE_BLK -#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P -#endif - -#ifndef FUNC_NAME -#define FUNC_NAME memcpy -#endif - -#ifndef PREAMBLE -#define PREAMBLE -#endif - -#ifndef XCC -#define XCC xcc -#endif - -#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9) \ - faligndata %f1, %f2, %f48; \ - faligndata %f2, %f3, %f50; \ - faligndata %f3, %f4, %f52; \ - faligndata %f4, %f5, %f54; \ - faligndata %f5, %f6, %f56; \ - faligndata %f6, %f7, %f58; \ - faligndata %f7, %f8, %f60; \ - faligndata %f8, %f9, %f62; - -#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ - EX_LD(LOAD_BLK(%src, %fdest)); \ - EX_ST(STORE_BLK(%fsrc, %dest)); \ - add %src, 0x40, %src; \ - subcc %len, 0x40, %len; \ - be,pn %xcc, jmptgt; \ - add %dest, 0x40, %dest; \ - -#define LOOP_CHUNK1(src, dest, len, branch_dest) \ - MAIN_LOOP_CHUNK(src, dest, f0, f48, len, branch_dest) -#define LOOP_CHUNK2(src, dest, len, branch_dest) \ - MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest) -#define LOOP_CHUNK3(src, dest, len, branch_dest) \ - MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) - -#define DO_SYNC membar #Sync; -#define STORE_SYNC(dest, fsrc) \ - EX_ST(STORE_BLK(%fsrc, %dest)); \ - add %dest, 0x40, %dest; \ - DO_SYNC - -#define STORE_JUMP(dest, fsrc, target) \ - EX_ST(STORE_BLK(%fsrc, %dest)); \ - add %dest, 0x40, %dest; \ - ba,pt %xcc, target; \ - nop; - -#define FINISH_VISCHUNK(dest, f0, f1, left) \ - subcc %left, 8, %left;\ - bl,pn %xcc, 95f; \ - faligndata %f0, %f1, %f48; \ - EX_ST(STORE(std, %f48, %dest)); \ - add %dest, 8, %dest; - -#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ - subcc %left, 8, %left; \ - bl,pn %xcc, 95f; \ - fsrc1 %f0, %f1; - -#define UNEVEN_VISCHUNK(dest, f0, f1, left) \ - UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ - ba,a,pt %xcc, 93f; - - .register %g2,#scratch - .register %g3,#scratch - - .text - .align 64 - - .globl FUNC_NAME - .type FUNC_NAME,#function -FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - srlx %o2, 31, %g2 - cmp %g2, 0 - tne %xcc, 5 - PREAMBLE - mov %o0, %o4 - cmp %o2, 0 - be,pn %XCC, 85f - or %o0, %o1, %o3 - cmp %o2, 16 - blu,a,pn %XCC, 80f - or %o3, %o2, %o3 - - cmp %o2, (5 * 64) - blu,pt %XCC, 70f - andcc %o3, 0x7, %g0 - - /* Clobbers o5/g1/g2/g3/g7/icc/xcc. */ - VISEntry - - /* Is 'dst' already aligned on an 64-byte boundary? */ - andcc %o0, 0x3f, %g2 - be,pt %XCC, 2f - - /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number - * of bytes to copy to make 'dst' 64-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %o0, %o1, %GLOBAL_SPARE - sub %g2, 0x40, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 - andcc %g2, 0x7, %g1 - be,pt %icc, 2f - and %g2, 0x38, %g2 - -1: subcc %g1, 0x1, %g1 - EX_LD(LOAD(ldub, %o1 + 0x00, %o3)) - EX_ST(STORE(stb, %o3, %o1 + %GLOBAL_SPARE)) - bgu,pt %XCC, 1b - add %o1, 0x1, %o1 - - add %o1, %GLOBAL_SPARE, %o0 - -2: cmp %g2, 0x0 - and %o1, 0x7, %g1 - be,pt %icc, 3f - alignaddr %o1, %g0, %o1 - - EX_LD(LOAD(ldd, %o1, %f4)) -1: EX_LD(LOAD(ldd, %o1 + 0x8, %f6)) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f4, %f6, %f0 - EX_ST(STORE(std, %f0, %o0)) - be,pn %icc, 3f - add %o0, 0x8, %o0 - - EX_LD(LOAD(ldd, %o1 + 0x8, %f4)) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f6, %f4, %f0 - EX_ST(STORE(std, %f0, %o0)) - bne,pt %icc, 1b - add %o0, 0x8, %o0 - - /* Destination is 64-byte aligned. */ -3: - membar #LoadStore | #StoreStore | #StoreLoad - - subcc %o2, 0x40, %GLOBAL_SPARE - add %o1, %g1, %g1 - andncc %GLOBAL_SPARE, (0x40 - 1), %GLOBAL_SPARE - srl %g1, 3, %g2 - sub %o2, %GLOBAL_SPARE, %g3 - andn %o1, (0x40 - 1), %o1 - and %g2, 7, %g2 - andncc %g3, 0x7, %g3 - fmovd %f0, %f2 - sub %g3, 0x8, %g3 - sub %o2, %GLOBAL_SPARE, %o2 - - add %g1, %GLOBAL_SPARE, %g1 - subcc %o2, %g3, %o2 - - EX_LD(LOAD_BLK(%o1, %f0)) - add %o1, 0x40, %o1 - add %g1, %g3, %g1 - EX_LD(LOAD_BLK(%o1, %f16)) - add %o1, 0x40, %o1 - sub %GLOBAL_SPARE, 0x80, %GLOBAL_SPARE - EX_LD(LOAD_BLK(%o1, %f32)) - add %o1, 0x40, %o1 - - /* There are 8 instances of the unrolled loop, - * one for each possible alignment of the - * source buffer. Each loop instance is 452 - * bytes. - */ - sll %g2, 3, %o3 - sub %o3, %g2, %o3 - sllx %o3, 4, %o3 - add %o3, %g2, %o3 - sllx %o3, 2, %g2 -1: rd %pc, %o3 - add %o3, %lo(1f - 1b), %o3 - jmpl %o3 + %g2, %g0 - nop - - .align 64 -1: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f0, %f2, %f48 -1: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) - STORE_SYNC(o0, f48) - FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) - STORE_JUMP(o0, f48, 40f) -2: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) - STORE_SYNC(o0, f48) - FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) - STORE_JUMP(o0, f48, 48f) -3: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) - STORE_SYNC(o0, f48) - FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) - STORE_JUMP(o0, f48, 56f) - -1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f2, %f4, %f48 -1: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) - STORE_SYNC(o0, f48) - FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) - STORE_JUMP(o0, f48, 41f) -2: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) - STORE_SYNC(o0, f48) - FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) - STORE_JUMP(o0, f48, 49f) -3: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) - STORE_SYNC(o0, f48) - FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) - STORE_JUMP(o0, f48, 57f) - -1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f4, %f6, %f48 -1: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) - STORE_SYNC(o0, f48) - FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) - STORE_JUMP(o0, f48, 42f) -2: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) - STORE_SYNC(o0, f48) - FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) - STORE_JUMP(o0, f48, 50f) -3: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) - STORE_SYNC(o0, f48) - FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) - STORE_JUMP(o0, f48, 58f) - -1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f6, %f8, %f48 -1: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) - STORE_SYNC(o0, f48) - FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) - STORE_JUMP(o0, f48, 43f) -2: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) - STORE_SYNC(o0, f48) - FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) - STORE_JUMP(o0, f48, 51f) -3: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) - STORE_SYNC(o0, f48) - FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) - STORE_JUMP(o0, f48, 59f) - -1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f8, %f10, %f48 -1: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) - STORE_SYNC(o0, f48) - FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) - STORE_JUMP(o0, f48, 44f) -2: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) - STORE_SYNC(o0, f48) - FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) - STORE_JUMP(o0, f48, 52f) -3: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) - STORE_SYNC(o0, f48) - FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) - STORE_JUMP(o0, f48, 60f) - -1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f10, %f12, %f48 -1: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) - STORE_SYNC(o0, f48) - FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) - STORE_JUMP(o0, f48, 45f) -2: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) - STORE_SYNC(o0, f48) - FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) - STORE_JUMP(o0, f48, 53f) -3: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) - STORE_SYNC(o0, f48) - FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) - STORE_JUMP(o0, f48, 61f) - -1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f12, %f14, %f48 -1: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) - STORE_SYNC(o0, f48) - FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) - STORE_JUMP(o0, f48, 46f) -2: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) - STORE_SYNC(o0, f48) - FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) - STORE_JUMP(o0, f48, 54f) -3: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) - STORE_SYNC(o0, f48) - FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) - STORE_JUMP(o0, f48, 62f) - -1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) - LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) - FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) - LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) - FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) - LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) - ba,pt %xcc, 1b+4 - faligndata %f14, %f16, %f48 -1: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) - STORE_SYNC(o0, f48) - FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) - STORE_JUMP(o0, f48, 47f) -2: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) - STORE_SYNC(o0, f48) - FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) - STORE_JUMP(o0, f48, 55f) -3: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) - STORE_SYNC(o0, f48) - FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) - STORE_JUMP(o0, f48, 63f) - -40: FINISH_VISCHUNK(o0, f0, f2, g3) -41: FINISH_VISCHUNK(o0, f2, f4, g3) -42: FINISH_VISCHUNK(o0, f4, f6, g3) -43: FINISH_VISCHUNK(o0, f6, f8, g3) -44: FINISH_VISCHUNK(o0, f8, f10, g3) -45: FINISH_VISCHUNK(o0, f10, f12, g3) -46: FINISH_VISCHUNK(o0, f12, f14, g3) -47: UNEVEN_VISCHUNK(o0, f14, f0, g3) -48: FINISH_VISCHUNK(o0, f16, f18, g3) -49: FINISH_VISCHUNK(o0, f18, f20, g3) -50: FINISH_VISCHUNK(o0, f20, f22, g3) -51: FINISH_VISCHUNK(o0, f22, f24, g3) -52: FINISH_VISCHUNK(o0, f24, f26, g3) -53: FINISH_VISCHUNK(o0, f26, f28, g3) -54: FINISH_VISCHUNK(o0, f28, f30, g3) -55: UNEVEN_VISCHUNK(o0, f30, f0, g3) -56: FINISH_VISCHUNK(o0, f32, f34, g3) -57: FINISH_VISCHUNK(o0, f34, f36, g3) -58: FINISH_VISCHUNK(o0, f36, f38, g3) -59: FINISH_VISCHUNK(o0, f38, f40, g3) -60: FINISH_VISCHUNK(o0, f40, f42, g3) -61: FINISH_VISCHUNK(o0, f42, f44, g3) -62: FINISH_VISCHUNK(o0, f44, f46, g3) -63: UNEVEN_VISCHUNK_LAST(o0, f46, f0, g3) - -93: EX_LD(LOAD(ldd, %o1, %f2)) - add %o1, 8, %o1 - subcc %g3, 8, %g3 - faligndata %f0, %f2, %f8 - EX_ST(STORE(std, %f8, %o0)) - bl,pn %xcc, 95f - add %o0, 8, %o0 - EX_LD(LOAD(ldd, %o1, %f0)) - add %o1, 8, %o1 - subcc %g3, 8, %g3 - faligndata %f2, %f0, %f8 - EX_ST(STORE(std, %f8, %o0)) - bge,pt %xcc, 93b - add %o0, 8, %o0 - -95: brz,pt %o2, 2f - mov %g1, %o1 - -1: EX_LD(LOAD(ldub, %o1, %o3)) - add %o1, 1, %o1 - subcc %o2, 1, %o2 - EX_ST(STORE(stb, %o3, %o0)) - bne,pt %xcc, 1b - add %o0, 1, %o0 - -2: membar #StoreLoad | #StoreStore - VISExit - retl - mov EX_RETVAL(%o4), %o0 - - .align 64 -70: /* 16 < len <= (5 * 64) */ - bne,pn %XCC, 75f - sub %o0, %o1, %o3 - -72: andn %o2, 0xf, %GLOBAL_SPARE - and %o2, 0xf, %o2 -1: EX_LD(LOAD(ldx, %o1 + 0x00, %o5)) - EX_LD(LOAD(ldx, %o1 + 0x08, %g1)) - subcc %GLOBAL_SPARE, 0x10, %GLOBAL_SPARE - EX_ST(STORE(stx, %o5, %o1 + %o3)) - add %o1, 0x8, %o1 - EX_ST(STORE(stx, %g1, %o1 + %o3)) - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 -73: andcc %o2, 0x8, %g0 - be,pt %XCC, 1f - nop - EX_LD(LOAD(ldx, %o1, %o5)) - sub %o2, 0x8, %o2 - EX_ST(STORE(stx, %o5, %o1 + %o3)) - add %o1, 0x8, %o1 -1: andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop - EX_LD(LOAD(lduw, %o1, %o5)) - sub %o2, 0x4, %o2 - EX_ST(STORE(stw, %o5, %o1 + %o3)) - add %o1, 0x4, %o1 -1: cmp %o2, 0 - be,pt %XCC, 85f - nop - ba,pt %xcc, 90f - nop - -75: andcc %o0, 0x7, %g1 - sub %g1, 0x8, %g1 - be,pn %icc, 2f - sub %g0, %g1, %g1 - sub %o2, %g1, %o2 - -1: EX_LD(LOAD(ldub, %o1, %o5)) - subcc %g1, 1, %g1 - EX_ST(STORE(stb, %o5, %o1 + %o3)) - bgu,pt %icc, 1b - add %o1, 1, %o1 - -2: add %o1, %o3, %o0 - andcc %o1, 0x7, %g1 - bne,pt %icc, 8f - sll %g1, 3, %g1 - - cmp %o2, 16 - bgeu,pt %icc, 72b - nop - ba,a,pt %xcc, 73b - -8: mov 64, %o3 - andn %o1, 0x7, %o1 - EX_LD(LOAD(ldx, %o1, %g2)) - sub %o3, %g1, %o3 - andn %o2, 0x7, %GLOBAL_SPARE - sllx %g2, %g1, %g2 -1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3)) - subcc %GLOBAL_SPARE, 0x8, %GLOBAL_SPARE - add %o1, 0x8, %o1 - srlx %g3, %o3, %o5 - or %o5, %g2, %o5 - EX_ST(STORE(stx, %o5, %o0)) - add %o0, 0x8, %o0 - bgu,pt %icc, 1b - sllx %g3, %g1, %g2 - - srl %g1, 3, %g1 - andcc %o2, 0x7, %o2 - be,pn %icc, 85f - add %o1, %g1, %o1 - ba,pt %xcc, 90f - sub %o0, %o1, %o3 - - .align 64 -80: /* 0 < len <= 16 */ - andcc %o3, 0x3, %g0 - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - -1: EX_LD(LOAD(lduw, %o1, %g1)) - subcc %o2, 4, %o2 - EX_ST(STORE(stw, %g1, %o1 + %o3)) - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -85: retl - mov EX_RETVAL(%o4), %o0 - - .align 32 -90: EX_LD(LOAD(ldub, %o1, %g1)) - subcc %o2, 1, %o2 - EX_ST(STORE(stb, %g1, %o1 + %o3)) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl - mov EX_RETVAL(%o4), %o0 - - .size FUNC_NAME, .-FUNC_NAME diff --git a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc64/lib/U3copy_from_user.S deleted file mode 100644 index df600b667e4..00000000000 --- a/arch/sparc64/lib/U3copy_from_user.S +++ /dev/null @@ -1,22 +0,0 @@ -/* U3copy_from_user.S: UltraSparc-III optimized copy from userspace. - * - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - -#define EX_LD(x) \ -98: x; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - -#define FUNC_NAME U3copy_from_user -#define LOAD(type,addr,dest) type##a [addr] %asi, dest -#define EX_RETVAL(x) 0 - -#include "U3memcpy.S" diff --git a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc64/lib/U3copy_to_user.S deleted file mode 100644 index f337f22ed82..00000000000 --- a/arch/sparc64/lib/U3copy_to_user.S +++ /dev/null @@ -1,33 +0,0 @@ -/* U3copy_to_user.S: UltraSparc-III optimized copy to userspace. - * - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - -#define EX_ST(x) \ -98: x; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - -#define FUNC_NAME U3copy_to_user -#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS -#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS -#define EX_RETVAL(x) 0 - - /* Writing to %asi is _expensive_ so we hardcode it. - * Reading %asi to check for KERNEL_DS is comparatively - * cheap. - */ -#define PREAMBLE \ - rd %asi, %g1; \ - cmp %g1, ASI_AIUS; \ - bne,pn %icc, memcpy_user_stub; \ - nop; \ - -#include "U3memcpy.S" diff --git a/arch/sparc64/lib/U3memcpy.S b/arch/sparc64/lib/U3memcpy.S deleted file mode 100644 index 7cae9cc6a20..00000000000 --- a/arch/sparc64/lib/U3memcpy.S +++ /dev/null @@ -1,422 +0,0 @@ -/* U3memcpy.S: UltraSparc-III optimized memcpy. - * - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - -#ifdef __KERNEL__ -#include <asm/visasm.h> -#include <asm/asi.h> -#define GLOBAL_SPARE %g7 -#else -#define ASI_BLK_P 0xf0 -#define FPRS_FEF 0x04 -#ifdef MEMCPY_DEBUG -#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \ - clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0; -#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#else -#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs -#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#endif -#define GLOBAL_SPARE %g5 -#endif - -#ifndef EX_LD -#define EX_LD(x) x -#endif - -#ifndef EX_ST -#define EX_ST(x) x -#endif - -#ifndef EX_RETVAL -#define EX_RETVAL(x) x -#endif - -#ifndef LOAD -#define LOAD(type,addr,dest) type [addr], dest -#endif - -#ifndef STORE -#define STORE(type,src,addr) type src, [addr] -#endif - -#ifndef STORE_BLK -#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P -#endif - -#ifndef FUNC_NAME -#define FUNC_NAME U3memcpy -#endif - -#ifndef PREAMBLE -#define PREAMBLE -#endif - -#ifndef XCC -#define XCC xcc -#endif - - .register %g2,#scratch - .register %g3,#scratch - - /* Special/non-trivial issues of this code: - * - * 1) %o5 is preserved from VISEntryHalf to VISExitHalf - * 2) Only low 32 FPU registers are used so that only the - * lower half of the FPU register set is dirtied by this - * code. This is especially important in the kernel. - * 3) This code never prefetches cachelines past the end - * of the source buffer. - */ - - .text - .align 64 - - /* The cheetah's flexible spine, oversized liver, enlarged heart, - * slender muscular body, and claws make it the swiftest hunter - * in Africa and the fastest animal on land. Can reach speeds - * of up to 2.4GB per second. - */ - - .globl FUNC_NAME - .type FUNC_NAME,#function -FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - srlx %o2, 31, %g2 - cmp %g2, 0 - tne %xcc, 5 - PREAMBLE - mov %o0, %o4 - cmp %o2, 0 - be,pn %XCC, 85f - or %o0, %o1, %o3 - cmp %o2, 16 - blu,a,pn %XCC, 80f - or %o3, %o2, %o3 - - cmp %o2, (3 * 64) - blu,pt %XCC, 70f - andcc %o3, 0x7, %g0 - - /* Clobbers o5/g1/g2/g3/g7/icc/xcc. We must preserve - * o5 from here until we hit VISExitHalf. - */ - VISEntryHalf - - /* Is 'dst' already aligned on an 64-byte boundary? */ - andcc %o0, 0x3f, %g2 - be,pt %XCC, 2f - - /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number - * of bytes to copy to make 'dst' 64-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %o0, %o1, GLOBAL_SPARE - sub %g2, 0x40, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 - andcc %g2, 0x7, %g1 - be,pt %icc, 2f - and %g2, 0x38, %g2 - -1: subcc %g1, 0x1, %g1 - EX_LD(LOAD(ldub, %o1 + 0x00, %o3)) - EX_ST(STORE(stb, %o3, %o1 + GLOBAL_SPARE)) - bgu,pt %XCC, 1b - add %o1, 0x1, %o1 - - add %o1, GLOBAL_SPARE, %o0 - -2: cmp %g2, 0x0 - and %o1, 0x7, %g1 - be,pt %icc, 3f - alignaddr %o1, %g0, %o1 - - EX_LD(LOAD(ldd, %o1, %f4)) -1: EX_LD(LOAD(ldd, %o1 + 0x8, %f6)) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f4, %f6, %f0 - EX_ST(STORE(std, %f0, %o0)) - be,pn %icc, 3f - add %o0, 0x8, %o0 - - EX_LD(LOAD(ldd, %o1 + 0x8, %f4)) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f6, %f4, %f2 - EX_ST(STORE(std, %f2, %o0)) - bne,pt %icc, 1b - add %o0, 0x8, %o0 - -3: LOAD(prefetch, %o1 + 0x000, #one_read) - LOAD(prefetch, %o1 + 0x040, #one_read) - andn %o2, (0x40 - 1), GLOBAL_SPARE - LOAD(prefetch, %o1 + 0x080, #one_read) - LOAD(prefetch, %o1 + 0x0c0, #one_read) - LOAD(prefetch, %o1 + 0x100, #one_read) - EX_LD(LOAD(ldd, %o1 + 0x000, %f0)) - LOAD(prefetch, %o1 + 0x140, #one_read) - EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) - LOAD(prefetch, %o1 + 0x180, #one_read) - EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) - LOAD(prefetch, %o1 + 0x1c0, #one_read) - faligndata %f0, %f2, %f16 - EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) - faligndata %f2, %f4, %f18 - EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) - faligndata %f4, %f6, %f20 - EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) - faligndata %f6, %f8, %f22 - - EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) - faligndata %f8, %f10, %f24 - EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) - faligndata %f10, %f12, %f26 - EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) - - subcc GLOBAL_SPARE, 0x80, GLOBAL_SPARE - add %o1, 0x40, %o1 - bgu,pt %XCC, 1f - srl GLOBAL_SPARE, 6, %o3 - ba,pt %xcc, 2f - nop - - .align 64 -1: - EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) - faligndata %f12, %f14, %f28 - EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) - faligndata %f14, %f0, %f30 - EX_ST(STORE_BLK(%f16, %o0)) - EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) - faligndata %f0, %f2, %f16 - add %o0, 0x40, %o0 - - EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) - faligndata %f2, %f4, %f18 - EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) - faligndata %f4, %f6, %f20 - EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) - subcc %o3, 0x01, %o3 - faligndata %f6, %f8, %f22 - EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) - - faligndata %f8, %f10, %f24 - EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) - LOAD(prefetch, %o1 + 0x1c0, #one_read) - faligndata %f10, %f12, %f26 - bg,pt %XCC, 1b - add %o1, 0x40, %o1 - - /* Finally we copy the last full 64-byte block. */ -2: - EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) - faligndata %f12, %f14, %f28 - EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) - faligndata %f14, %f0, %f30 - EX_ST(STORE_BLK(%f16, %o0)) - EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) - faligndata %f0, %f2, %f16 - EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) - faligndata %f2, %f4, %f18 - EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) - faligndata %f4, %f6, %f20 - EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) - faligndata %f6, %f8, %f22 - EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) - faligndata %f8, %f10, %f24 - cmp %g1, 0 - be,pt %XCC, 1f - add %o0, 0x40, %o0 - EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) -1: faligndata %f10, %f12, %f26 - faligndata %f12, %f14, %f28 - faligndata %f14, %f0, %f30 - EX_ST(STORE_BLK(%f16, %o0)) - add %o0, 0x40, %o0 - add %o1, 0x40, %o1 - membar #Sync - - /* Now we copy the (len modulo 64) bytes at the end. - * Note how we borrow the %f0 loaded above. - * - * Also notice how this code is careful not to perform a - * load past the end of the src buffer. - */ - and %o2, 0x3f, %o2 - andcc %o2, 0x38, %g2 - be,pn %XCC, 2f - subcc %g2, 0x8, %g2 - be,pn %XCC, 2f - cmp %g1, 0 - - sub %o2, %g2, %o2 - be,a,pt %XCC, 1f - EX_LD(LOAD(ldd, %o1 + 0x00, %f0)) - -1: EX_LD(LOAD(ldd, %o1 + 0x08, %f2)) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f0, %f2, %f8 - EX_ST(STORE(std, %f8, %o0)) - be,pn %XCC, 2f - add %o0, 0x8, %o0 - EX_LD(LOAD(ldd, %o1 + 0x08, %f0)) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f2, %f0, %f8 - EX_ST(STORE(std, %f8, %o0)) - bne,pn %XCC, 1b - add %o0, 0x8, %o0 - - /* If anything is left, we copy it one byte at a time. - * Note that %g1 is (src & 0x3) saved above before the - * alignaddr was performed. - */ -2: - cmp %o2, 0 - add %o1, %g1, %o1 - VISExitHalf - be,pn %XCC, 85f - sub %o0, %o1, %o3 - - andcc %g1, 0x7, %g0 - bne,pn %icc, 90f - andcc %o2, 0x8, %g0 - be,pt %icc, 1f - nop - EX_LD(LOAD(ldx, %o1, %o5)) - EX_ST(STORE(stx, %o5, %o1 + %o3)) - add %o1, 0x8, %o1 - -1: andcc %o2, 0x4, %g0 - be,pt %icc, 1f - nop - EX_LD(LOAD(lduw, %o1, %o5)) - EX_ST(STORE(stw, %o5, %o1 + %o3)) - add %o1, 0x4, %o1 - -1: andcc %o2, 0x2, %g0 - be,pt %icc, 1f - nop - EX_LD(LOAD(lduh, %o1, %o5)) - EX_ST(STORE(sth, %o5, %o1 + %o3)) - add %o1, 0x2, %o1 - -1: andcc %o2, 0x1, %g0 - be,pt %icc, 85f - nop - EX_LD(LOAD(ldub, %o1, %o5)) - ba,pt %xcc, 85f - EX_ST(STORE(stb, %o5, %o1 + %o3)) - - .align 64 -70: /* 16 < len <= 64 */ - bne,pn %XCC, 75f - sub %o0, %o1, %o3 - -72: - andn %o2, 0xf, GLOBAL_SPARE - and %o2, 0xf, %o2 -1: subcc GLOBAL_SPARE, 0x10, GLOBAL_SPARE - EX_LD(LOAD(ldx, %o1 + 0x00, %o5)) - EX_LD(LOAD(ldx, %o1 + 0x08, %g1)) - EX_ST(STORE(stx, %o5, %o1 + %o3)) - add %o1, 0x8, %o1 - EX_ST(STORE(stx, %g1, %o1 + %o3)) - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 -73: andcc %o2, 0x8, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x8, %o2 - EX_LD(LOAD(ldx, %o1, %o5)) - EX_ST(STORE(stx, %o5, %o1 + %o3)) - add %o1, 0x8, %o1 -1: andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x4, %o2 - EX_LD(LOAD(lduw, %o1, %o5)) - EX_ST(STORE(stw, %o5, %o1 + %o3)) - add %o1, 0x4, %o1 -1: cmp %o2, 0 - be,pt %XCC, 85f - nop - ba,pt %xcc, 90f - nop - -75: - andcc %o0, 0x7, %g1 - sub %g1, 0x8, %g1 - be,pn %icc, 2f - sub %g0, %g1, %g1 - sub %o2, %g1, %o2 - -1: subcc %g1, 1, %g1 - EX_LD(LOAD(ldub, %o1, %o5)) - EX_ST(STORE(stb, %o5, %o1 + %o3)) - bgu,pt %icc, 1b - add %o1, 1, %o1 - -2: add %o1, %o3, %o0 - andcc %o1, 0x7, %g1 - bne,pt %icc, 8f - sll %g1, 3, %g1 - - cmp %o2, 16 - bgeu,pt %icc, 72b - nop - ba,a,pt %xcc, 73b - -8: mov 64, %o3 - andn %o1, 0x7, %o1 - EX_LD(LOAD(ldx, %o1, %g2)) - sub %o3, %g1, %o3 - andn %o2, 0x7, GLOBAL_SPARE - sllx %g2, %g1, %g2 -1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3)) - subcc GLOBAL_SPARE, 0x8, GLOBAL_SPARE - add %o1, 0x8, %o1 - srlx %g3, %o3, %o5 - or %o5, %g2, %o5 - EX_ST(STORE(stx, %o5, %o0)) - add %o0, 0x8, %o0 - bgu,pt %icc, 1b - sllx %g3, %g1, %g2 - - srl %g1, 3, %g1 - andcc %o2, 0x7, %o2 - be,pn %icc, 85f - add %o1, %g1, %o1 - ba,pt %xcc, 90f - sub %o0, %o1, %o3 - - .align 64 -80: /* 0 < len <= 16 */ - andcc %o3, 0x3, %g0 - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - -1: - subcc %o2, 4, %o2 - EX_LD(LOAD(lduw, %o1, %g1)) - EX_ST(STORE(stw, %g1, %o1 + %o3)) - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -85: retl - mov EX_RETVAL(%o4), %o0 - - .align 32 -90: - subcc %o2, 1, %o2 - EX_LD(LOAD(ldub, %o1, %g1)) - EX_ST(STORE(stb, %g1, %o1 + %o3)) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl - mov EX_RETVAL(%o4), %o0 - - .size FUNC_NAME, .-FUNC_NAME diff --git a/arch/sparc64/lib/U3patch.S b/arch/sparc64/lib/U3patch.S deleted file mode 100644 index e2b6c5e4b95..00000000000 --- a/arch/sparc64/lib/U3patch.S +++ /dev/null @@ -1,32 +0,0 @@ -/* U3patch.S: Patch Ultra-I routines with Ultra-III variant. - * - * Copyright (C) 2004 David S. Miller <davem@redhat.com> - */ - -#define BRANCH_ALWAYS 0x10680000 -#define NOP 0x01000000 -#define ULTRA3_DO_PATCH(OLD, NEW) \ - sethi %hi(NEW), %g1; \ - or %g1, %lo(NEW), %g1; \ - sethi %hi(OLD), %g2; \ - or %g2, %lo(OLD), %g2; \ - sub %g1, %g2, %g1; \ - sethi %hi(BRANCH_ALWAYS), %g3; \ - srl %g1, 2, %g1; \ - or %g3, %lo(BRANCH_ALWAYS), %g3; \ - or %g3, %g1, %g3; \ - stw %g3, [%g2]; \ - sethi %hi(NOP), %g3; \ - or %g3, %lo(NOP), %g3; \ - stw %g3, [%g2 + 0x4]; \ - flush %g2; - - .globl cheetah_patch_copyops - .type cheetah_patch_copyops,#function -cheetah_patch_copyops: - ULTRA3_DO_PATCH(memcpy, U3memcpy) - ULTRA3_DO_PATCH(___copy_from_user, U3copy_from_user) - ULTRA3_DO_PATCH(___copy_to_user, U3copy_to_user) - retl - nop - .size cheetah_patch_copyops,.-cheetah_patch_copyops diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S deleted file mode 100644 index a0ded5c5aa5..00000000000 --- a/arch/sparc64/lib/VISsave.S +++ /dev/null @@ -1,144 +0,0 @@ -/* $Id: VISsave.S,v 1.6 2002/02/09 19:49:30 davem Exp $ - * VISsave.S: Code for saving FPU register state for - * VIS routines. One should not call this directly, - * but use macros provided in <asm/visasm.h>. - * - * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <asm/asi.h> -#include <asm/page.h> -#include <asm/ptrace.h> -#include <asm/visasm.h> -#include <asm/thread_info.h> - - .text - .globl VISenter, VISenterhalf - - /* On entry: %o5=current FPRS value, %g7 is callers address */ - /* May clobber %o5, %g1, %g2, %g3, %g7, %icc, %xcc */ - - /* Nothing special need be done here to handle pre-emption, this - * FPU save/restore mechanism is already preemption safe. - */ - - .align 32 -VISenter: - ldub [%g6 + TI_FPDEPTH], %g1 - brnz,a,pn %g1, 1f - cmp %g1, 1 - stb %g0, [%g6 + TI_FPSAVED] - stx %fsr, [%g6 + TI_XFSR] -9: jmpl %g7 + %g0, %g0 - nop -1: bne,pn %icc, 2f - - srl %g1, 1, %g1 -vis1: ldub [%g6 + TI_FPSAVED], %g3 - stx %fsr, [%g6 + TI_XFSR] - or %g3, %o5, %g3 - stb %g3, [%g6 + TI_FPSAVED] - rd %gsr, %g3 - clr %g1 - ba,pt %xcc, 3f - - stx %g3, [%g6 + TI_GSR] -2: add %g6, %g1, %g3 - cmp %o5, FPRS_DU - be,pn %icc, 6f - sll %g1, 3, %g1 - stb %o5, [%g3 + TI_FPSAVED] - rd %gsr, %g2 - add %g6, %g1, %g3 - stx %g2, [%g3 + TI_GSR] - - add %g6, %g1, %g2 - stx %fsr, [%g2 + TI_XFSR] - sll %g1, 5, %g1 -3: andcc %o5, FPRS_DL|FPRS_DU, %g0 - be,pn %icc, 9b - add %g6, TI_FPREGS, %g2 - andcc %o5, FPRS_DL, %g0 - - be,pn %icc, 4f - add %g6, TI_FPREGS+0x40, %g3 - membar #Sync - stda %f0, [%g2 + %g1] ASI_BLK_P - stda %f16, [%g3 + %g1] ASI_BLK_P - membar #Sync - andcc %o5, FPRS_DU, %g0 - be,pn %icc, 5f -4: add %g1, 128, %g1 - membar #Sync - stda %f32, [%g2 + %g1] ASI_BLK_P - - stda %f48, [%g3 + %g1] ASI_BLK_P -5: membar #Sync - ba,pt %xcc, 80f - nop - - .align 32 -80: jmpl %g7 + %g0, %g0 - nop - -6: ldub [%g3 + TI_FPSAVED], %o5 - or %o5, FPRS_DU, %o5 - add %g6, TI_FPREGS+0x80, %g2 - stb %o5, [%g3 + TI_FPSAVED] - - sll %g1, 5, %g1 - add %g6, TI_FPREGS+0xc0, %g3 - wr %g0, FPRS_FEF, %fprs - membar #Sync - stda %f32, [%g2 + %g1] ASI_BLK_P - stda %f48, [%g3 + %g1] ASI_BLK_P - membar #Sync - ba,pt %xcc, 80f - nop - - .align 32 -80: jmpl %g7 + %g0, %g0 - nop - - .align 32 -VISenterhalf: - ldub [%g6 + TI_FPDEPTH], %g1 - brnz,a,pn %g1, 1f - cmp %g1, 1 - stb %g0, [%g6 + TI_FPSAVED] - stx %fsr, [%g6 + TI_XFSR] - clr %o5 - jmpl %g7 + %g0, %g0 - wr %g0, FPRS_FEF, %fprs - -1: bne,pn %icc, 2f - srl %g1, 1, %g1 - ba,pt %xcc, vis1 - sub %g7, 8, %g7 -2: addcc %g6, %g1, %g3 - sll %g1, 3, %g1 - andn %o5, FPRS_DU, %g2 - stb %g2, [%g3 + TI_FPSAVED] - - rd %gsr, %g2 - add %g6, %g1, %g3 - stx %g2, [%g3 + TI_GSR] - add %g6, %g1, %g2 - stx %fsr, [%g2 + TI_XFSR] - sll %g1, 5, %g1 -3: andcc %o5, FPRS_DL, %g0 - be,pn %icc, 4f - add %g6, TI_FPREGS, %g2 - - add %g6, TI_FPREGS+0x40, %g3 - membar #Sync - stda %f0, [%g2 + %g1] ASI_BLK_P - stda %f16, [%g3 + %g1] ASI_BLK_P - membar #Sync - ba,pt %xcc, 4f - nop - - .align 32 -4: and %o5, FPRS_DU, %o5 - jmpl %g7 + %g0, %g0 - wr %o5, FPRS_FEF, %fprs diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S deleted file mode 100644 index faf87c31598..00000000000 --- a/arch/sparc64/lib/atomic.S +++ /dev/null @@ -1,149 +0,0 @@ -/* $Id: atomic.S,v 1.4 2001/11/18 00:12:56 davem Exp $ - * atomic.S: These things are too big to do inline. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#include <linux/config.h> -#include <asm/asi.h> - - .text - - /* Two versions of the atomic routines, one that - * does not return a value and does not perform - * memory barriers, and a second which returns - * a value and does the barriers. - */ - .globl atomic_add - .type atomic_add,#function -atomic_add: /* %o0 = increment, %o1 = atomic_ptr */ -1: lduw [%o1], %g1 - add %g1, %o0, %g7 - cas [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - nop - retl - nop - .size atomic_add, .-atomic_add - - .globl atomic_sub - .type atomic_sub,#function -atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ -1: lduw [%o1], %g1 - sub %g1, %o0, %g7 - cas [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - nop - retl - nop - .size atomic_sub, .-atomic_sub - - /* On SMP we need to use memory barriers to ensure - * correct memory operation ordering, nop these out - * for uniprocessor. - */ -#ifdef CONFIG_SMP - -#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad; -#define ATOMIC_POST_BARRIER \ - ba,pt %xcc, 80b; \ - membar #StoreLoad | #StoreStore - -80: retl - nop -#else -#define ATOMIC_PRE_BARRIER -#define ATOMIC_POST_BARRIER -#endif - - .globl atomic_add_ret - .type atomic_add_ret,#function -atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ - ATOMIC_PRE_BARRIER -1: lduw [%o1], %g1 - add %g1, %o0, %g7 - cas [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - add %g7, %o0, %g7 - sra %g7, 0, %o0 - ATOMIC_POST_BARRIER - retl - nop - .size atomic_add_ret, .-atomic_add_ret - - .globl atomic_sub_ret - .type atomic_sub_ret,#function -atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ - ATOMIC_PRE_BARRIER -1: lduw [%o1], %g1 - sub %g1, %o0, %g7 - cas [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - sub %g7, %o0, %g7 - sra %g7, 0, %o0 - ATOMIC_POST_BARRIER - retl - nop - .size atomic_sub_ret, .-atomic_sub_ret - - .globl atomic64_add - .type atomic64_add,#function -atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */ -1: ldx [%o1], %g1 - add %g1, %o0, %g7 - casx [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %xcc, 1b - nop - retl - nop - .size atomic64_add, .-atomic64_add - - .globl atomic64_sub - .type atomic64_sub,#function -atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */ -1: ldx [%o1], %g1 - sub %g1, %o0, %g7 - casx [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %xcc, 1b - nop - retl - nop - .size atomic64_sub, .-atomic64_sub - - .globl atomic64_add_ret - .type atomic64_add_ret,#function -atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ - ATOMIC_PRE_BARRIER -1: ldx [%o1], %g1 - add %g1, %o0, %g7 - casx [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %xcc, 1b - add %g7, %o0, %g7 - mov %g7, %o0 - ATOMIC_POST_BARRIER - retl - nop - .size atomic64_add_ret, .-atomic64_add_ret - - .globl atomic64_sub_ret - .type atomic64_sub_ret,#function -atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ - ATOMIC_PRE_BARRIER -1: ldx [%o1], %g1 - sub %g1, %o0, %g7 - casx [%o1], %g1, %g7 - cmp %g1, %g7 - bne,pn %xcc, 1b - sub %g7, %o0, %g7 - mov %g7, %o0 - ATOMIC_POST_BARRIER - retl - nop - .size atomic64_sub_ret, .-atomic64_sub_ret diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S deleted file mode 100644 index 31afbfe6c1e..00000000000 --- a/arch/sparc64/lib/bitops.S +++ /dev/null @@ -1,154 +0,0 @@ -/* $Id: bitops.S,v 1.3 2001/11/18 00:12:56 davem Exp $ - * bitops.S: Sparc64 atomic bit operations. - * - * Copyright (C) 2000 David S. Miller (davem@redhat.com) - */ - -#include <linux/config.h> -#include <asm/asi.h> - - .text - - /* On SMP we need to use memory barriers to ensure - * correct memory operation ordering, nop these out - * for uniprocessor. - */ - -#ifdef CONFIG_SMP -#define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad -#define BITOP_POST_BARRIER \ - ba,pt %xcc, 80b; \ - membar #StoreLoad | #StoreStore - -80: retl - nop -#else -#define BITOP_PRE_BARRIER -#define BITOP_POST_BARRIER -#endif - - .globl test_and_set_bit - .type test_and_set_bit,#function -test_and_set_bit: /* %o0=nr, %o1=addr */ - BITOP_PRE_BARRIER - srlx %o0, 6, %g1 - mov 1, %o2 - sllx %g1, 3, %g3 - and %o0, 63, %g2 - sllx %o2, %g2, %o2 - add %o1, %g3, %o1 -1: ldx [%o1], %g7 - or %g7, %o2, %g1 - casx [%o1], %g7, %g1 - cmp %g7, %g1 - bne,pn %xcc, 1b - and %g7, %o2, %g2 - clr %o0 - movrne %g2, 1, %o0 - BITOP_POST_BARRIER - retl - nop - .size test_and_set_bit, .-test_and_set_bit - - .globl test_and_clear_bit - .type test_and_clear_bit,#function -test_and_clear_bit: /* %o0=nr, %o1=addr */ - BITOP_PRE_BARRIER - srlx %o0, 6, %g1 - mov 1, %o2 - sllx %g1, 3, %g3 - and %o0, 63, %g2 - sllx %o2, %g2, %o2 - add %o1, %g3, %o1 -1: ldx [%o1], %g7 - andn %g7, %o2, %g1 - casx [%o1], %g7, %g1 - cmp %g7, %g1 - bne,pn %xcc, 1b - and %g7, %o2, %g2 - clr %o0 - movrne %g2, 1, %o0 - BITOP_POST_BARRIER - retl - nop - .size test_and_clear_bit, .-test_and_clear_bit - - .globl test_and_change_bit - .type test_and_change_bit,#function -test_and_change_bit: /* %o0=nr, %o1=addr */ - BITOP_PRE_BARRIER - srlx %o0, 6, %g1 - mov 1, %o2 - sllx %g1, 3, %g3 - and %o0, 63, %g2 - sllx %o2, %g2, %o2 - add %o1, %g3, %o1 -1: ldx [%o1], %g7 - xor %g7, %o2, %g1 - casx [%o1], %g7, %g1 - cmp %g7, %g1 - bne,pn %xcc, 1b - and %g7, %o2, %g2 - clr %o0 - movrne %g2, 1, %o0 - BITOP_POST_BARRIER - retl - nop - .size test_and_change_bit, .-test_and_change_bit - - .globl set_bit - .type set_bit,#function -set_bit: /* %o0=nr, %o1=addr */ - srlx %o0, 6, %g1 - mov 1, %o2 - sllx %g1, 3, %g3 - and %o0, 63, %g2 - sllx %o2, %g2, %o2 - add %o1, %g3, %o1 -1: ldx [%o1], %g7 - or %g7, %o2, %g1 - casx [%o1], %g7, %g1 - cmp %g7, %g1 - bne,pn %xcc, 1b - nop - retl - nop - .size set_bit, .-set_bit - - .globl clear_bit - .type clear_bit,#function -clear_bit: /* %o0=nr, %o1=addr */ - srlx %o0, 6, %g1 - mov 1, %o2 - sllx %g1, 3, %g3 - and %o0, 63, %g2 - sllx %o2, %g2, %o2 - add %o1, %g3, %o1 -1: ldx [%o1], %g7 - andn %g7, %o2, %g1 - casx [%o1], %g7, %g1 - cmp %g7, %g1 - bne,pn %xcc, 1b - nop - retl - nop - .size clear_bit, .-clear_bit - - .globl change_bit - .type change_bit,#function -change_bit: /* %o0=nr, %o1=addr */ - srlx %o0, 6, %g1 - mov 1, %o2 - sllx %g1, 3, %g3 - and %o0, 63, %g2 - sllx %o2, %g2, %o2 - add %o1, %g3, %o1 -1: ldx [%o1], %g7 - xor %g7, %o2, %g1 - casx [%o1], %g7, %g1 - cmp %g7, %g1 - bne,pn %xcc, 1b - nop - retl - nop - .size change_bit, .-change_bit diff --git a/arch/sparc64/lib/bzero.S b/arch/sparc64/lib/bzero.S deleted file mode 100644 index 21a933ffb7c..00000000000 --- a/arch/sparc64/lib/bzero.S +++ /dev/null @@ -1,158 +0,0 @@ -/* bzero.S: Simple prefetching memset, bzero, and clear_user - * implementations. - * - * Copyright (C) 2005 David S. Miller <davem@davemloft.net> - */ - - .text - - .globl __memset - .type __memset, #function -__memset: /* %o0=buf, %o1=pat, %o2=len */ - - .globl memset - .type memset, #function -memset: /* %o0=buf, %o1=pat, %o2=len */ - and %o1, 0xff, %o3 - mov %o2, %o1 - sllx %o3, 8, %g1 - or %g1, %o3, %o2 - sllx %o2, 16, %g1 - or %g1, %o2, %o2 - sllx %o2, 32, %g1 - ba,pt %xcc, 1f - or %g1, %o2, %o2 - - .globl __bzero - .type __bzero, #function -__bzero: /* %o0=buf, %o1=len */ - clr %o2 -1: mov %o0, %o3 - brz,pn %o1, __bzero_done - cmp %o1, 16 - bl,pn %icc, __bzero_tiny - prefetch [%o0 + 0x000], #n_writes - andcc %o0, 0x3, %g0 - be,pt %icc, 2f -1: stb %o2, [%o0 + 0x00] - add %o0, 1, %o0 - andcc %o0, 0x3, %g0 - bne,pn %icc, 1b - sub %o1, 1, %o1 -2: andcc %o0, 0x7, %g0 - be,pt %icc, 3f - stw %o2, [%o0 + 0x00] - sub %o1, 4, %o1 - add %o0, 4, %o0 -3: and %o1, 0x38, %g1 - cmp %o1, 0x40 - andn %o1, 0x3f, %o4 - bl,pn %icc, 5f - and %o1, 0x7, %o1 - prefetch [%o0 + 0x040], #n_writes - prefetch [%o0 + 0x080], #n_writes - prefetch [%o0 + 0x0c0], #n_writes - prefetch [%o0 + 0x100], #n_writes - prefetch [%o0 + 0x140], #n_writes -4: prefetch [%o0 + 0x180], #n_writes - stx %o2, [%o0 + 0x00] - stx %o2, [%o0 + 0x08] - stx %o2, [%o0 + 0x10] - stx %o2, [%o0 + 0x18] - stx %o2, [%o0 + 0x20] - stx %o2, [%o0 + 0x28] - stx %o2, [%o0 + 0x30] - stx %o2, [%o0 + 0x38] - subcc %o4, 0x40, %o4 - bne,pt %icc, 4b - add %o0, 0x40, %o0 - brz,pn %g1, 6f - nop -5: stx %o2, [%o0 + 0x00] - subcc %g1, 8, %g1 - bne,pt %icc, 5b - add %o0, 0x8, %o0 -6: brz,pt %o1, __bzero_done - nop -__bzero_tiny: -1: stb %o2, [%o0 + 0x00] - subcc %o1, 1, %o1 - bne,pt %icc, 1b - add %o0, 1, %o0 -__bzero_done: - retl - mov %o3, %o0 - .size __bzero, .-__bzero - .size __memset, .-__memset - .size memset, .-memset - -#define EX_ST(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov %o1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - - .globl __bzero_noasi - .type __bzero_noasi, #function -__bzero_noasi: /* %o0=buf, %o1=len */ - brz,pn %o1, __bzero_noasi_done - cmp %o1, 16 - bl,pn %icc, __bzero_noasi_tiny - EX_ST(prefetcha [%o0 + 0x00] %asi, #n_writes) - andcc %o0, 0x3, %g0 - be,pt %icc, 2f -1: EX_ST(stba %g0, [%o0 + 0x00] %asi) - add %o0, 1, %o0 - andcc %o0, 0x3, %g0 - bne,pn %icc, 1b - sub %o1, 1, %o1 -2: andcc %o0, 0x7, %g0 - be,pt %icc, 3f - EX_ST(stwa %g0, [%o0 + 0x00] %asi) - sub %o1, 4, %o1 - add %o0, 4, %o0 -3: and %o1, 0x38, %g1 - cmp %o1, 0x40 - andn %o1, 0x3f, %o4 - bl,pn %icc, 5f - and %o1, 0x7, %o1 - EX_ST(prefetcha [%o0 + 0x040] %asi, #n_writes) - EX_ST(prefetcha [%o0 + 0x080] %asi, #n_writes) - EX_ST(prefetcha [%o0 + 0x0c0] %asi, #n_writes) - EX_ST(prefetcha [%o0 + 0x100] %asi, #n_writes) - EX_ST(prefetcha [%o0 + 0x140] %asi, #n_writes) -4: EX_ST(prefetcha [%o0 + 0x180] %asi, #n_writes) - EX_ST(stxa %g0, [%o0 + 0x00] %asi) - EX_ST(stxa %g0, [%o0 + 0x08] %asi) - EX_ST(stxa %g0, [%o0 + 0x10] %asi) - EX_ST(stxa %g0, [%o0 + 0x18] %asi) - EX_ST(stxa %g0, [%o0 + 0x20] %asi) - EX_ST(stxa %g0, [%o0 + 0x28] %asi) - EX_ST(stxa %g0, [%o0 + 0x30] %asi) - EX_ST(stxa %g0, [%o0 + 0x38] %asi) - subcc %o4, 0x40, %o4 - bne,pt %icc, 4b - add %o0, 0x40, %o0 - brz,pn %g1, 6f - nop -5: EX_ST(stxa %g0, [%o0 + 0x00] %asi) - subcc %g1, 8, %g1 - bne,pt %icc, 5b - add %o0, 0x8, %o0 -6: brz,pt %o1, __bzero_noasi_done - nop -__bzero_noasi_tiny: -1: EX_ST(stba %g0, [%o0 + 0x00] %asi) - subcc %o1, 1, %o1 - bne,pt %icc, 1b - add %o0, 1, %o0 -__bzero_noasi_done: - retl - clr %o0 - .size __bzero_noasi, .-__bzero_noasi diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S deleted file mode 100644 index ba9cd3ccc2b..00000000000 --- a/arch/sparc64/lib/checksum.S +++ /dev/null @@ -1,172 +0,0 @@ -/* checksum.S: Sparc V9 optimized checksum code. - * - * Copyright(C) 1995 Linus Torvalds - * Copyright(C) 1995 Miguel de Icaza - * Copyright(C) 1996, 2000 David S. Miller - * Copyright(C) 1997 Jakub Jelinek - * - * derived from: - * Linux/Alpha checksum c-code - * Linux/ix86 inline checksum assembly - * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code) - * David Mosberger-Tang for optimized reference c-code - * BSD4.4 portable checksum routine - */ - - .text - -csum_partial_fix_alignment: - /* We checked for zero length already, so there must be - * at least one byte. - */ - be,pt %icc, 1f - nop - ldub [%o0 + 0x00], %o4 - add %o0, 1, %o0 - sub %o1, 1, %o1 -1: andcc %o0, 0x2, %g0 - be,pn %icc, csum_partial_post_align - cmp %o1, 2 - blu,pn %icc, csum_partial_end_cruft - nop - lduh [%o0 + 0x00], %o5 - add %o0, 2, %o0 - sub %o1, 2, %o1 - ba,pt %xcc, csum_partial_post_align - add %o5, %o4, %o4 - - .align 32 - .globl csum_partial -csum_partial: /* %o0=buff, %o1=len, %o2=sum */ - prefetch [%o0 + 0x000], #n_reads - clr %o4 - prefetch [%o0 + 0x040], #n_reads - brz,pn %o1, csum_partial_finish - andcc %o0, 0x3, %g0 - - /* We "remember" whether the lowest bit in the address - * was set in %g7. Because if it is, we have to swap - * upper and lower 8 bit fields of the sum we calculate. - */ - bne,pn %icc, csum_partial_fix_alignment - andcc %o0, 0x1, %g7 - -csum_partial_post_align: - prefetch [%o0 + 0x080], #n_reads - andncc %o1, 0x3f, %o3 - - prefetch [%o0 + 0x0c0], #n_reads - sub %o1, %o3, %o1 - brz,pn %o3, 2f - prefetch [%o0 + 0x100], #n_reads - - /* So that we don't need to use the non-pairing - * add-with-carry instructions we accumulate 32-bit - * values into a 64-bit register. At the end of the - * loop we fold it down to 32-bits and so on. - */ - prefetch [%o0 + 0x140], #n_reads -1: lduw [%o0 + 0x00], %o5 - lduw [%o0 + 0x04], %g1 - lduw [%o0 + 0x08], %g2 - add %o4, %o5, %o4 - lduw [%o0 + 0x0c], %g3 - add %o4, %g1, %o4 - lduw [%o0 + 0x10], %o5 - add %o4, %g2, %o4 - lduw [%o0 + 0x14], %g1 - add %o4, %g3, %o4 - lduw [%o0 + 0x18], %g2 - add %o4, %o5, %o4 - lduw [%o0 + 0x1c], %g3 - add %o4, %g1, %o4 - lduw [%o0 + 0x20], %o5 - add %o4, %g2, %o4 - lduw [%o0 + 0x24], %g1 - add %o4, %g3, %o4 - lduw [%o0 + 0x28], %g2 - add %o4, %o5, %o4 - lduw [%o0 + 0x2c], %g3 - add %o4, %g1, %o4 - lduw [%o0 + 0x30], %o5 - add %o4, %g2, %o4 - lduw [%o0 + 0x34], %g1 - add %o4, %g3, %o4 - lduw [%o0 + 0x38], %g2 - add %o4, %o5, %o4 - lduw [%o0 + 0x3c], %g3 - add %o4, %g1, %o4 - prefetch [%o0 + 0x180], #n_reads - add %o4, %g2, %o4 - subcc %o3, 0x40, %o3 - add %o0, 0x40, %o0 - bne,pt %icc, 1b - add %o4, %g3, %o4 - -2: and %o1, 0x3c, %o3 - brz,pn %o3, 2f - sub %o1, %o3, %o1 -1: lduw [%o0 + 0x00], %o5 - subcc %o3, 0x4, %o3 - add %o0, 0x4, %o0 - bne,pt %icc, 1b - add %o4, %o5, %o4 - -2: - /* fold 64-->32 */ - srlx %o4, 32, %o5 - srl %o4, 0, %o4 - add %o4, %o5, %o4 - srlx %o4, 32, %o5 - srl %o4, 0, %o4 - add %o4, %o5, %o4 - - /* fold 32-->16 */ - sethi %hi(0xffff0000), %g1 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - -csum_partial_end_cruft: - /* %o4 has the 16-bit sum we have calculated so-far. */ - cmp %o1, 2 - blu,pt %icc, 1f - nop - lduh [%o0 + 0x00], %o5 - sub %o1, 2, %o1 - add %o0, 2, %o0 - add %o4, %o5, %o4 -1: brz,pt %o1, 1f - nop - ldub [%o0 + 0x00], %o5 - sub %o1, 1, %o1 - add %o0, 1, %o0 - sllx %o5, 8, %o5 - add %o4, %o5, %o4 -1: - /* fold 32-->16 */ - sethi %hi(0xffff0000), %g1 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - -1: brz,pt %g7, 1f - nop - - /* We started with an odd byte, byte-swap the result. */ - srl %o4, 8, %o5 - and %o4, 0xff, %g1 - sll %g1, 8, %g1 - or %o5, %g1, %o4 - -1: add %o2, %o4, %o2 - -csum_partial_finish: - retl - mov %o2, %o0 diff --git a/arch/sparc64/lib/clear_page.S b/arch/sparc64/lib/clear_page.S deleted file mode 100644 index b59884ef051..00000000000 --- a/arch/sparc64/lib/clear_page.S +++ /dev/null @@ -1,105 +0,0 @@ -/* clear_page.S: UltraSparc optimized clear page. - * - * Copyright (C) 1996, 1998, 1999, 2000, 2004 David S. Miller (davem@redhat.com) - * Copyright (C) 1997 Jakub Jelinek (jakub@redhat.com) - */ - -#include <asm/visasm.h> -#include <asm/thread_info.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/spitfire.h> - - /* What we used to do was lock a TLB entry into a specific - * TLB slot, clear the page with interrupts disabled, then - * restore the original TLB entry. This was great for - * disturbing the TLB as little as possible, but it meant - * we had to keep interrupts disabled for a long time. - * - * Now, we simply use the normal TLB loading mechanism, - * and this makes the cpu choose a slot all by itself. - * Then we do a normal TLB flush on exit. We need only - * disable preemption during the clear. - */ - -#define TTE_BITS_TOP (_PAGE_VALID | _PAGE_SZBITS) -#define TTE_BITS_BOTTOM (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W) - - .text - - .globl _clear_page -_clear_page: /* %o0=dest */ - ba,pt %xcc, clear_page_common - clr %o4 - - /* This thing is pretty important, it shows up - * on the profiles via do_anonymous_page(). - */ - .align 32 - .globl clear_user_page -clear_user_page: /* %o0=dest, %o1=vaddr */ - lduw [%g6 + TI_PRE_COUNT], %o2 - sethi %uhi(PAGE_OFFSET), %g2 - sethi %hi(PAGE_SIZE), %o4 - - sllx %g2, 32, %g2 - sethi %uhi(TTE_BITS_TOP), %g3 - - sllx %g3, 32, %g3 - sub %o0, %g2, %g1 ! paddr - - or %g3, TTE_BITS_BOTTOM, %g3 - and %o1, %o4, %o0 ! vaddr D-cache alias bit - - or %g1, %g3, %g1 ! TTE data - sethi %hi(TLBTEMP_BASE), %o3 - - add %o2, 1, %o4 - add %o0, %o3, %o0 ! TTE vaddr - - /* Disable preemption. */ - mov TLB_TAG_ACCESS, %g3 - stw %o4, [%g6 + TI_PRE_COUNT] - - /* Load TLB entry. */ - rdpr %pstate, %o4 - wrpr %o4, PSTATE_IE, %pstate - stxa %o0, [%g3] ASI_DMMU - stxa %g1, [%g0] ASI_DTLB_DATA_IN - flush %g6 - wrpr %o4, 0x0, %pstate - - mov 1, %o4 - -clear_page_common: - VISEntryHalf - membar #StoreLoad | #StoreStore | #LoadStore - fzero %f0 - sethi %hi(PAGE_SIZE/64), %o1 - mov %o0, %g1 ! remember vaddr for tlbflush - fzero %f2 - or %o1, %lo(PAGE_SIZE/64), %o1 - faddd %f0, %f2, %f4 - fmuld %f0, %f2, %f6 - faddd %f0, %f2, %f8 - fmuld %f0, %f2, %f10 - - faddd %f0, %f2, %f12 - fmuld %f0, %f2, %f14 -1: stda %f0, [%o0 + %g0] ASI_BLK_P - subcc %o1, 1, %o1 - bne,pt %icc, 1b - add %o0, 0x40, %o0 - membar #Sync - VISExitHalf - - brz,pn %o4, out - nop - - stxa %g0, [%g1] ASI_DMMU_DEMAP - membar #Sync - stw %o2, [%g6 + TI_PRE_COUNT] - -out: retl - nop - diff --git a/arch/sparc64/lib/copy_in_user.S b/arch/sparc64/lib/copy_in_user.S deleted file mode 100644 index 816076c0bc0..00000000000 --- a/arch/sparc64/lib/copy_in_user.S +++ /dev/null @@ -1,119 +0,0 @@ -/* copy_in_user.S: Copy from userspace to userspace. - * - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - -#include <asm/asi.h> - -#define XCC xcc - -#define EX(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - - .register %g2,#scratch - .register %g3,#scratch - - .text - .align 32 - - /* Don't try to get too fancy here, just nice and - * simple. This is predominantly used for well aligned - * small copies in the compat layer. It is also used - * to copy register windows around during thread cloning. - */ - - .globl ___copy_in_user - .type ___copy_in_user,#function -___copy_in_user: /* %o0=dst, %o1=src, %o2=len */ - /* Writing to %asi is _expensive_ so we hardcode it. - * Reading %asi to check for KERNEL_DS is comparatively - * cheap. - */ - rd %asi, %g1 - cmp %g1, ASI_AIUS - bne,pn %icc, memcpy_user_stub - nop - - cmp %o2, 0 - be,pn %XCC, 85f - or %o0, %o1, %o3 - cmp %o2, 16 - bleu,a,pn %XCC, 80f - or %o3, %o2, %o3 - - /* 16 < len <= 64 */ - andcc %o3, 0x7, %g0 - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - - andn %o2, 0x7, %o4 - and %o2, 0x7, %o2 -1: subcc %o4, 0x8, %o4 - EX(ldxa [%o1] %asi, %o5) - EX(stxa %o5, [%o1 + %o3] ASI_AIUS) - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 - andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x4, %o2 - EX(lduwa [%o1] %asi, %o5) - EX(stwa %o5, [%o1 + %o3] ASI_AIUS) - add %o1, 0x4, %o1 -1: cmp %o2, 0 - be,pt %XCC, 85f - nop - ba,pt %xcc, 90f - nop - -80: /* 0 < len <= 16 */ - andcc %o3, 0x3, %g0 - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - -82: - subcc %o2, 4, %o2 - EX(lduwa [%o1] %asi, %g1) - EX(stwa %g1, [%o1 + %o3] ASI_AIUS) - bgu,pt %XCC, 82b - add %o1, 4, %o1 - -85: retl - clr %o0 - - .align 32 -90: - subcc %o2, 1, %o2 - EX(lduba [%o1] %asi, %g1) - EX(stba %g1, [%o1 + %o3] ASI_AIUS) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl - clr %o0 - - .size ___copy_in_user, .-___copy_in_user - - /* Act like copy_{to,in}_user(), ie. return zero instead - * of original destination pointer. This is invoked when - * copy_{to,in}_user() finds that %asi is kernel space. - */ - .globl memcpy_user_stub - .type memcpy_user_stub,#function -memcpy_user_stub: - save %sp, -192, %sp - mov %i0, %o0 - mov %i1, %o1 - call memcpy - mov %i2, %o2 - ret - restore %g0, %g0, %o0 - .size memcpy_user_stub, .-memcpy_user_stub diff --git a/arch/sparc64/lib/copy_page.S b/arch/sparc64/lib/copy_page.S deleted file mode 100644 index feebb14fd27..00000000000 --- a/arch/sparc64/lib/copy_page.S +++ /dev/null @@ -1,253 +0,0 @@ -/* clear_page.S: UltraSparc optimized copy page. - * - * Copyright (C) 1996, 1998, 1999, 2000, 2004 David S. Miller (davem@redhat.com) - * Copyright (C) 1997 Jakub Jelinek (jakub@redhat.com) - */ - -#include <asm/visasm.h> -#include <asm/thread_info.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/spitfire.h> -#include <asm/head.h> - - /* What we used to do was lock a TLB entry into a specific - * TLB slot, clear the page with interrupts disabled, then - * restore the original TLB entry. This was great for - * disturbing the TLB as little as possible, but it meant - * we had to keep interrupts disabled for a long time. - * - * Now, we simply use the normal TLB loading mechanism, - * and this makes the cpu choose a slot all by itself. - * Then we do a normal TLB flush on exit. We need only - * disable preemption during the clear. - */ - -#define TTE_BITS_TOP (_PAGE_VALID | _PAGE_SZBITS) -#define TTE_BITS_BOTTOM (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W) -#define DCACHE_SIZE (PAGE_SIZE * 2) - -#if (PAGE_SHIFT == 13) || (PAGE_SHIFT == 19) -#define PAGE_SIZE_REM 0x80 -#elif (PAGE_SHIFT == 16) || (PAGE_SHIFT == 22) -#define PAGE_SIZE_REM 0x100 -#else -#error Wrong PAGE_SHIFT specified -#endif - -#define TOUCH(reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7) \ - fmovd %reg0, %f48; fmovd %reg1, %f50; \ - fmovd %reg2, %f52; fmovd %reg3, %f54; \ - fmovd %reg4, %f56; fmovd %reg5, %f58; \ - fmovd %reg6, %f60; fmovd %reg7, %f62; - - .text - - .align 32 - .globl copy_user_page - .type copy_user_page,#function -copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */ - lduw [%g6 + TI_PRE_COUNT], %o4 - sethi %uhi(PAGE_OFFSET), %g2 - sethi %hi(PAGE_SIZE), %o3 - - sllx %g2, 32, %g2 - sethi %uhi(TTE_BITS_TOP), %g3 - - sllx %g3, 32, %g3 - sub %o0, %g2, %g1 ! dest paddr - - sub %o1, %g2, %g2 ! src paddr - or %g3, TTE_BITS_BOTTOM, %g3 - - and %o2, %o3, %o0 ! vaddr D-cache alias bit - or %g1, %g3, %g1 ! dest TTE data - - or %g2, %g3, %g2 ! src TTE data - sethi %hi(TLBTEMP_BASE), %o3 - - sethi %hi(DCACHE_SIZE), %o1 - add %o0, %o3, %o0 ! dest TTE vaddr - - add %o4, 1, %o2 - add %o0, %o1, %o1 ! src TTE vaddr - - /* Disable preemption. */ - mov TLB_TAG_ACCESS, %g3 - stw %o2, [%g6 + TI_PRE_COUNT] - - /* Load TLB entries. */ - rdpr %pstate, %o2 - wrpr %o2, PSTATE_IE, %pstate - stxa %o0, [%g3] ASI_DMMU - stxa %g1, [%g0] ASI_DTLB_DATA_IN - membar #Sync - stxa %o1, [%g3] ASI_DMMU - stxa %g2, [%g0] ASI_DTLB_DATA_IN - membar #Sync - wrpr %o2, 0x0, %pstate - -cheetah_copy_page_insn: - ba,pt %xcc, 9f - nop - -1: - VISEntryHalf - membar #StoreLoad | #StoreStore | #LoadStore - sethi %hi((PAGE_SIZE/64)-2), %o2 - mov %o0, %g1 - prefetch [%o1 + 0x000], #one_read - or %o2, %lo((PAGE_SIZE/64)-2), %o2 - prefetch [%o1 + 0x040], #one_read - prefetch [%o1 + 0x080], #one_read - prefetch [%o1 + 0x0c0], #one_read - ldd [%o1 + 0x000], %f0 - prefetch [%o1 + 0x100], #one_read - ldd [%o1 + 0x008], %f2 - prefetch [%o1 + 0x140], #one_read - ldd [%o1 + 0x010], %f4 - prefetch [%o1 + 0x180], #one_read - fmovd %f0, %f16 - ldd [%o1 + 0x018], %f6 - fmovd %f2, %f18 - ldd [%o1 + 0x020], %f8 - fmovd %f4, %f20 - ldd [%o1 + 0x028], %f10 - fmovd %f6, %f22 - ldd [%o1 + 0x030], %f12 - fmovd %f8, %f24 - ldd [%o1 + 0x038], %f14 - fmovd %f10, %f26 - ldd [%o1 + 0x040], %f0 -1: ldd [%o1 + 0x048], %f2 - fmovd %f12, %f28 - ldd [%o1 + 0x050], %f4 - fmovd %f14, %f30 - stda %f16, [%o0] ASI_BLK_P - ldd [%o1 + 0x058], %f6 - fmovd %f0, %f16 - ldd [%o1 + 0x060], %f8 - fmovd %f2, %f18 - ldd [%o1 + 0x068], %f10 - fmovd %f4, %f20 - ldd [%o1 + 0x070], %f12 - fmovd %f6, %f22 - ldd [%o1 + 0x078], %f14 - fmovd %f8, %f24 - ldd [%o1 + 0x080], %f0 - prefetch [%o1 + 0x180], #one_read - fmovd %f10, %f26 - subcc %o2, 1, %o2 - add %o0, 0x40, %o0 - bne,pt %xcc, 1b - add %o1, 0x40, %o1 - - ldd [%o1 + 0x048], %f2 - fmovd %f12, %f28 - ldd [%o1 + 0x050], %f4 - fmovd %f14, %f30 - stda %f16, [%o0] ASI_BLK_P - ldd [%o1 + 0x058], %f6 - fmovd %f0, %f16 - ldd [%o1 + 0x060], %f8 - fmovd %f2, %f18 - ldd [%o1 + 0x068], %f10 - fmovd %f4, %f20 - ldd [%o1 + 0x070], %f12 - fmovd %f6, %f22 - add %o0, 0x40, %o0 - ldd [%o1 + 0x078], %f14 - fmovd %f8, %f24 - fmovd %f10, %f26 - fmovd %f12, %f28 - fmovd %f14, %f30 - stda %f16, [%o0] ASI_BLK_P - membar #Sync - VISExitHalf - ba,pt %xcc, 5f - nop - -9: - VISEntry - ldub [%g6 + TI_FAULT_CODE], %g3 - mov %o0, %g1 - cmp %g3, 0 - rd %asi, %g3 - be,a,pt %icc, 1f - wr %g0, ASI_BLK_P, %asi - wr %g0, ASI_BLK_COMMIT_P, %asi -1: ldda [%o1] ASI_BLK_P, %f0 - add %o1, 0x40, %o1 - ldda [%o1] ASI_BLK_P, %f16 - add %o1, 0x40, %o1 - sethi %hi(PAGE_SIZE), %o2 -1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) - ldda [%o1] ASI_BLK_P, %f32 - stda %f48, [%o0] %asi - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) - ldda [%o1] ASI_BLK_P, %f0 - stda %f48, [%o0] %asi - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - TOUCH(f32, f34, f36, f38, f40, f42, f44, f46) - ldda [%o1] ASI_BLK_P, %f16 - stda %f48, [%o0] %asi - sub %o2, 0x40, %o2 - add %o1, 0x40, %o1 - cmp %o2, PAGE_SIZE_REM - bne,pt %xcc, 1b - add %o0, 0x40, %o0 -#if (PAGE_SHIFT == 16) || (PAGE_SHIFT == 22) - TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) - ldda [%o1] ASI_BLK_P, %f32 - stda %f48, [%o0] %asi - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) - ldda [%o1] ASI_BLK_P, %f0 - stda %f48, [%o0] %asi - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - membar #Sync - stda %f32, [%o0] %asi - add %o0, 0x40, %o0 - stda %f0, [%o0] %asi -#else - membar #Sync - stda %f0, [%o0] %asi - add %o0, 0x40, %o0 - stda %f16, [%o0] %asi -#endif - membar #Sync - wr %g3, 0x0, %asi - VISExit - -5: - stxa %g0, [%g1] ASI_DMMU_DEMAP - membar #Sync - - sethi %hi(DCACHE_SIZE), %g2 - stxa %g0, [%g1 + %g2] ASI_DMMU_DEMAP - membar #Sync - - retl - stw %o4, [%g6 + TI_PRE_COUNT] - - .size copy_user_page, .-copy_user_page - - .globl cheetah_patch_copy_page -cheetah_patch_copy_page: - sethi %hi(0x01000000), %o1 ! NOP - sethi %hi(cheetah_copy_page_insn), %o0 - or %o0, %lo(cheetah_copy_page_insn), %o0 - stw %o1, [%o0] - membar #StoreStore - flush %o0 - retl - nop diff --git a/arch/sparc64/lib/csum_copy.S b/arch/sparc64/lib/csum_copy.S deleted file mode 100644 index 71af4883906..00000000000 --- a/arch/sparc64/lib/csum_copy.S +++ /dev/null @@ -1,308 +0,0 @@ -/* csum_copy.S: Checksum+copy code for sparc64 - * - * Copyright (C) 2005 David S. Miller <davem@davemloft.net> - */ - -#ifdef __KERNEL__ -#define GLOBAL_SPARE %g7 -#else -#define GLOBAL_SPARE %g5 -#endif - -#ifndef EX_LD -#define EX_LD(x) x -#endif - -#ifndef EX_ST -#define EX_ST(x) x -#endif - -#ifndef EX_RETVAL -#define EX_RETVAL(x) x -#endif - -#ifndef LOAD -#define LOAD(type,addr,dest) type [addr], dest -#endif - -#ifndef STORE -#define STORE(type,src,addr) type src, [addr] -#endif - -#ifndef FUNC_NAME -#define FUNC_NAME csum_partial_copy_nocheck -#endif - - .register %g2, #scratch - .register %g3, #scratch - - .text - -90: - /* We checked for zero length already, so there must be - * at least one byte. - */ - be,pt %icc, 1f - nop - EX_LD(LOAD(ldub, %o0 + 0x00, %o4)) - add %o0, 1, %o0 - sub %o2, 1, %o2 - EX_ST(STORE(stb, %o4, %o1 + 0x00)) - add %o1, 1, %o1 -1: andcc %o0, 0x2, %g0 - be,pn %icc, 80f - cmp %o2, 2 - blu,pn %icc, 60f - nop - EX_LD(LOAD(lduh, %o0 + 0x00, %o5)) - add %o0, 2, %o0 - sub %o2, 2, %o2 - EX_ST(STORE(sth, %o5, %o1 + 0x00)) - add %o1, 2, %o1 - ba,pt %xcc, 80f - add %o5, %o4, %o4 - - .globl FUNC_NAME -FUNC_NAME: /* %o0=src, %o1=dst, %o2=len, %o3=sum */ - LOAD(prefetch, %o0 + 0x000, #n_reads) - xor %o0, %o1, %g1 - clr %o4 - andcc %g1, 0x3, %g0 - bne,pn %icc, 95f - LOAD(prefetch, %o0 + 0x040, #n_reads) - - brz,pn %o2, 70f - andcc %o0, 0x3, %g0 - - /* We "remember" whether the lowest bit in the address - * was set in GLOBAL_SPARE. Because if it is, we have to swap - * upper and lower 8 bit fields of the sum we calculate. - */ - bne,pn %icc, 90b - andcc %o0, 0x1, GLOBAL_SPARE - -80: - LOAD(prefetch, %o0 + 0x080, #n_reads) - andncc %o2, 0x3f, %g3 - - LOAD(prefetch, %o0 + 0x0c0, #n_reads) - sub %o2, %g3, %o2 - brz,pn %g3, 2f - LOAD(prefetch, %o0 + 0x100, #n_reads) - - /* So that we don't need to use the non-pairing - * add-with-carry instructions we accumulate 32-bit - * values into a 64-bit register. At the end of the - * loop we fold it down to 32-bits and so on. - */ - ba,pt %xcc, 1f - LOAD(prefetch, %o0 + 0x140, #n_reads) - - .align 32 -1: EX_LD(LOAD(lduw, %o0 + 0x00, %o5)) - EX_LD(LOAD(lduw, %o0 + 0x04, %g1)) - EX_LD(LOAD(lduw, %o0 + 0x08, %g2)) - add %o4, %o5, %o4 - EX_ST(STORE(stw, %o5, %o1 + 0x00)) - EX_LD(LOAD(lduw, %o0 + 0x0c, %o5)) - add %o4, %g1, %o4 - EX_ST(STORE(stw, %g1, %o1 + 0x04)) - EX_LD(LOAD(lduw, %o0 + 0x10, %g1)) - add %o4, %g2, %o4 - EX_ST(STORE(stw, %g2, %o1 + 0x08)) - EX_LD(LOAD(lduw, %o0 + 0x14, %g2)) - add %o4, %o5, %o4 - EX_ST(STORE(stw, %o5, %o1 + 0x0c)) - EX_LD(LOAD(lduw, %o0 + 0x18, %o5)) - add %o4, %g1, %o4 - EX_ST(STORE(stw, %g1, %o1 + 0x10)) - EX_LD(LOAD(lduw, %o0 + 0x1c, %g1)) - add %o4, %g2, %o4 - EX_ST(STORE(stw, %g2, %o1 + 0x14)) - EX_LD(LOAD(lduw, %o0 + 0x20, %g2)) - add %o4, %o5, %o4 - EX_ST(STORE(stw, %o5, %o1 + 0x18)) - EX_LD(LOAD(lduw, %o0 + 0x24, %o5)) - add %o4, %g1, %o4 - EX_ST(STORE(stw, %g1, %o1 + 0x1c)) - EX_LD(LOAD(lduw, %o0 + 0x28, %g1)) - add %o4, %g2, %o4 - EX_ST(STORE(stw, %g2, %o1 + 0x20)) - EX_LD(LOAD(lduw, %o0 + 0x2c, %g2)) - add %o4, %o5, %o4 - EX_ST(STORE(stw, %o5, %o1 + 0x24)) - EX_LD(LOAD(lduw, %o0 + 0x30, %o5)) - add %o4, %g1, %o4 - EX_ST(STORE(stw, %g1, %o1 + 0x28)) - EX_LD(LOAD(lduw, %o0 + 0x34, %g1)) - add %o4, %g2, %o4 - EX_ST(STORE(stw, %g2, %o1 + 0x2c)) - EX_LD(LOAD(lduw, %o0 + 0x38, %g2)) - add %o4, %o5, %o4 - EX_ST(STORE(stw, %o5, %o1 + 0x30)) - EX_LD(LOAD(lduw, %o0 + 0x3c, %o5)) - add %o4, %g1, %o4 - EX_ST(STORE(stw, %g1, %o1 + 0x34)) - LOAD(prefetch, %o0 + 0x180, #n_reads) - add %o4, %g2, %o4 - EX_ST(STORE(stw, %g2, %o1 + 0x38)) - subcc %g3, 0x40, %g3 - add %o0, 0x40, %o0 - add %o4, %o5, %o4 - EX_ST(STORE(stw, %o5, %o1 + 0x3c)) - bne,pt %icc, 1b - add %o1, 0x40, %o1 - -2: and %o2, 0x3c, %g3 - brz,pn %g3, 2f - sub %o2, %g3, %o2 -1: EX_LD(LOAD(lduw, %o0 + 0x00, %o5)) - subcc %g3, 0x4, %g3 - add %o0, 0x4, %o0 - add %o4, %o5, %o4 - EX_ST(STORE(stw, %o5, %o1 + 0x00)) - bne,pt %icc, 1b - add %o1, 0x4, %o1 - -2: - /* fold 64-->32 */ - srlx %o4, 32, %o5 - srl %o4, 0, %o4 - add %o4, %o5, %o4 - srlx %o4, 32, %o5 - srl %o4, 0, %o4 - add %o4, %o5, %o4 - - /* fold 32-->16 */ - sethi %hi(0xffff0000), %g1 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - -60: - /* %o4 has the 16-bit sum we have calculated so-far. */ - cmp %o2, 2 - blu,pt %icc, 1f - nop - EX_LD(LOAD(lduh, %o0 + 0x00, %o5)) - sub %o2, 2, %o2 - add %o0, 2, %o0 - add %o4, %o5, %o4 - EX_ST(STORE(sth, %o5, %o1 + 0x00)) - add %o1, 0x2, %o1 -1: brz,pt %o2, 1f - nop - EX_LD(LOAD(ldub, %o0 + 0x00, %o5)) - sub %o2, 1, %o2 - add %o0, 1, %o0 - EX_ST(STORE(stb, %o5, %o1 + 0x00)) - sllx %o5, 8, %o5 - add %o1, 1, %o1 - add %o4, %o5, %o4 -1: - /* fold 32-->16 */ - sethi %hi(0xffff0000), %g1 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - srl %o4, 16, %o5 - andn %o4, %g1, %g2 - add %o5, %g2, %o4 - -1: brz,pt GLOBAL_SPARE, 1f - nop - - /* We started with an odd byte, byte-swap the result. */ - srl %o4, 8, %o5 - and %o4, 0xff, %g1 - sll %g1, 8, %g1 - or %o5, %g1, %o4 - -1: add %o3, %o4, %o3 - -70: - retl - mov %o3, %o0 - -95: mov 0, GLOBAL_SPARE - brlez,pn %o2, 4f - andcc %o0, 1, %o5 - be,a,pt %icc, 1f - srl %o2, 1, %g1 - sub %o2, 1, %o2 - EX_LD(LOAD(ldub, %o0, GLOBAL_SPARE)) - add %o0, 1, %o0 - EX_ST(STORE(stb, GLOBAL_SPARE, %o1)) - srl %o2, 1, %g1 - add %o1, 1, %o1 -1: brz,a,pn %g1, 3f - andcc %o2, 1, %g0 - andcc %o0, 2, %g0 - be,a,pt %icc, 1f - srl %g1, 1, %g1 - EX_LD(LOAD(lduh, %o0, %o4)) - sub %o2, 2, %o2 - srl %o4, 8, %g2 - sub %g1, 1, %g1 - EX_ST(STORE(stb, %g2, %o1)) - add %o4, GLOBAL_SPARE, GLOBAL_SPARE - EX_ST(STORE(stb, %o4, %o1 + 1)) - add %o0, 2, %o0 - srl %g1, 1, %g1 - add %o1, 2, %o1 -1: brz,a,pn %g1, 2f - andcc %o2, 2, %g0 - EX_LD(LOAD(lduw, %o0, %o4)) -5: srl %o4, 24, %g2 - srl %o4, 16, %g3 - EX_ST(STORE(stb, %g2, %o1)) - srl %o4, 8, %g2 - EX_ST(STORE(stb, %g3, %o1 + 1)) - add %o0, 4, %o0 - EX_ST(STORE(stb, %g2, %o1 + 2)) - addcc %o4, GLOBAL_SPARE, GLOBAL_SPARE - EX_ST(STORE(stb, %o4, %o1 + 3)) - addc GLOBAL_SPARE, %g0, GLOBAL_SPARE - add %o1, 4, %o1 - subcc %g1, 1, %g1 - bne,a,pt %icc, 5b - EX_LD(LOAD(lduw, %o0, %o4)) - sll GLOBAL_SPARE, 16, %g2 - srl GLOBAL_SPARE, 16, GLOBAL_SPARE - srl %g2, 16, %g2 - andcc %o2, 2, %g0 - add %g2, GLOBAL_SPARE, GLOBAL_SPARE -2: be,a,pt %icc, 3f - andcc %o2, 1, %g0 - EX_LD(LOAD(lduh, %o0, %o4)) - andcc %o2, 1, %g0 - srl %o4, 8, %g2 - add %o0, 2, %o0 - EX_ST(STORE(stb, %g2, %o1)) - add GLOBAL_SPARE, %o4, GLOBAL_SPARE - EX_ST(STORE(stb, %o4, %o1 + 1)) - add %o1, 2, %o1 -3: be,a,pt %icc, 1f - sll GLOBAL_SPARE, 16, %o4 - EX_LD(LOAD(ldub, %o0, %g2)) - sll %g2, 8, %o4 - EX_ST(STORE(stb, %g2, %o1)) - add GLOBAL_SPARE, %o4, GLOBAL_SPARE - sll GLOBAL_SPARE, 16, %o4 -1: addcc %o4, GLOBAL_SPARE, GLOBAL_SPARE - srl GLOBAL_SPARE, 16, %o4 - addc %g0, %o4, GLOBAL_SPARE - brz,pt %o5, 4f - srl GLOBAL_SPARE, 8, %o4 - and GLOBAL_SPARE, 0xff, %g2 - and %o4, 0xff, %o4 - sll %g2, 8, %g2 - or %g2, %o4, GLOBAL_SPARE -4: addcc %o3, GLOBAL_SPARE, %o3 - addc %g0, %o3, %o0 - retl - srl %o0, 0, %o0 - .size FUNC_NAME, .-FUNC_NAME diff --git a/arch/sparc64/lib/csum_copy_from_user.S b/arch/sparc64/lib/csum_copy_from_user.S deleted file mode 100644 index 817ebdae39f..00000000000 --- a/arch/sparc64/lib/csum_copy_from_user.S +++ /dev/null @@ -1,21 +0,0 @@ -/* csum_copy_from_user.S: Checksum+copy from userspace. - * - * Copyright (C) 2005 David S. Miller (davem@davemloft.net) - */ - -#define EX_LD(x) \ -98: x; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov -1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - -#define FUNC_NAME __csum_partial_copy_from_user -#define LOAD(type,addr,dest) type##a [addr] %asi, dest - -#include "csum_copy.S" diff --git a/arch/sparc64/lib/csum_copy_to_user.S b/arch/sparc64/lib/csum_copy_to_user.S deleted file mode 100644 index c2f9463ea1e..00000000000 --- a/arch/sparc64/lib/csum_copy_to_user.S +++ /dev/null @@ -1,21 +0,0 @@ -/* csum_copy_to_user.S: Checksum+copy to userspace. - * - * Copyright (C) 2005 David S. Miller (davem@davemloft.net) - */ - -#define EX_ST(x) \ -98: x; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - mov -1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - -#define FUNC_NAME __csum_partial_copy_to_user -#define STORE(type,src,addr) type##a src, [addr] %asi - -#include "csum_copy.S" diff --git a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c deleted file mode 100644 index e8808727617..00000000000 --- a/arch/sparc64/lib/delay.c +++ /dev/null @@ -1,49 +0,0 @@ -/* delay.c: Delay loops for sparc64 - * - * Copyright (C) 2004 David S. Miller <davem@redhat.com> - * - * Based heavily upon x86 variant which is: - * Copyright (C) 1993 Linus Torvalds - * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> - */ - -#include <linux/delay.h> - -void __delay(unsigned long loops) -{ - __asm__ __volatile__( -" b,pt %%xcc, 1f\n" -" cmp %0, 0\n" -" .align 32\n" -"1:\n" -" bne,pt %%xcc, 1b\n" -" subcc %0, 1, %0\n" - : "=&r" (loops) - : "0" (loops) - : "cc"); -} - -/* We used to multiply by HZ after shifting down by 32 bits - * but that runs into problems for higher values of HZ and - * slow cpus. - */ -void __const_udelay(unsigned long n) -{ - n *= 4; - - n *= (cpu_data(raw_smp_processor_id()).udelay_val * (HZ/4)); - n >>= 32; - - __delay(n + 1); -} - -void __udelay(unsigned long n) -{ - __const_udelay(n * 0x10c7UL); -} - - -void __ndelay(unsigned long n) -{ - __const_udelay(n * 0x5UL); -} diff --git a/arch/sparc64/lib/find_bit.c b/arch/sparc64/lib/find_bit.c deleted file mode 100644 index 6059557067b..00000000000 --- a/arch/sparc64/lib/find_bit.c +++ /dev/null @@ -1,127 +0,0 @@ -#include <linux/bitops.h> - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < 64) - goto found_first; - if (tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if ((tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (64 - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} - -/* find_next_zero_bit() finds the first zero bit in a bit string of length - * 'size' bits, starting the search at bit 'offset'. This is largely based - * on Linus's ALPHA routines, which are pretty portable BTW. - */ - -unsigned long find_next_zero_bit(const unsigned long *addr, - unsigned long size, unsigned long offset) -{ - const unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (64-offset); - if (size < 64) - goto found_first; - if (~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -unsigned long find_next_zero_le_bit(unsigned long *addr, unsigned long size, unsigned long offset) -{ - unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if(offset) { - tmp = __swab64p(p++); - tmp |= (~0UL >> (64-offset)); - if(size < 64) - goto found_first; - if(~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while(size & ~63) { - if(~(tmp = __swab64p(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if(!size) - return result; - tmp = __swab64p(p); -found_first: - tmp |= (~0UL << size); - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} diff --git a/arch/sparc64/lib/iomap.c b/arch/sparc64/lib/iomap.c deleted file mode 100644 index ac556db0697..00000000000 --- a/arch/sparc64/lib/iomap.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Implement the sparc64 iomap interfaces - */ -#include <linux/pci.h> -#include <linux/module.h> -#include <asm/io.h> - -/* Create a virtual mapping cookie for an IO port range */ -void __iomem *ioport_map(unsigned long port, unsigned int nr) -{ - return (void __iomem *) (unsigned long) port; -} - -void ioport_unmap(void __iomem *addr) -{ - /* Nothing to do */ -} -EXPORT_SYMBOL(ioport_map); -EXPORT_SYMBOL(ioport_unmap); - -/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) -{ - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len || !start) - return NULL; - if (maxlen && len > maxlen) - len = maxlen; - if (flags & IORESOURCE_IO) - return ioport_map(start, len); - if (flags & IORESOURCE_MEM) { - if (flags & IORESOURCE_CACHEABLE) - return ioremap(start, len); - return ioremap_nocache(start, len); - } - /* What? */ - return NULL; -} - -void pci_iounmap(struct pci_dev *dev, void __iomem * addr) -{ - /* nothing to do */ -} -EXPORT_SYMBOL(pci_iomap); -EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/sparc64/lib/ipcsum.S b/arch/sparc64/lib/ipcsum.S deleted file mode 100644 index 58ca5b9a877..00000000000 --- a/arch/sparc64/lib/ipcsum.S +++ /dev/null @@ -1,34 +0,0 @@ - .text - .align 32 - .globl ip_fast_csum - .type ip_fast_csum,#function -ip_fast_csum: /* %o0 = iph, %o1 = ihl */ - sub %o1, 4, %g7 - lduw [%o0 + 0x00], %o2 - lduw [%o0 + 0x04], %g2 - lduw [%o0 + 0x08], %g3 - addcc %g2, %o2, %o2 - lduw [%o0 + 0x0c], %g2 - addccc %g3, %o2, %o2 - lduw [%o0 + 0x10], %g3 - - addccc %g2, %o2, %o2 - addc %o2, %g0, %o2 -1: addcc %g3, %o2, %o2 - add %o0, 4, %o0 - addccc %o2, %g0, %o2 - subcc %g7, 1, %g7 - be,a,pt %icc, 2f - sll %o2, 16, %g2 - - lduw [%o0 + 0x10], %g3 - ba,pt %xcc, 1b - nop -2: addcc %o2, %g2, %g2 - srl %g2, 16, %o2 - addc %o2, %g0, %o2 - xnor %g0, %o2, %o2 - set 0xffff, %o1 - retl - and %o2, %o1, %o0 - .size ip_fast_csum, .-ip_fast_csum diff --git a/arch/sparc64/lib/mcount.S b/arch/sparc64/lib/mcount.S deleted file mode 100644 index 2ef2e268bdc..00000000000 --- a/arch/sparc64/lib/mcount.S +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) - * - * This file implements mcount(), which is used to collect profiling data. - * This can also be tweaked for kernel stack overflow detection. - */ - -#include <linux/config.h> -#include <linux/linkage.h> - -#include <asm/ptrace.h> -#include <asm/thread_info.h> - -/* - * This is the main variant and is called by C code. GCC's -pg option - * automatically instruments every C function with a call to this. - */ - -#ifdef CONFIG_STACK_DEBUG - -#define OVSTACKSIZE 4096 /* lets hope this is enough */ - - .data - .align 8 -panicstring: - .asciz "Stack overflow\n" - .align 8 -ovstack: - .skip OVSTACKSIZE -#endif - .text - .align 32 - .globl mcount, _mcount -mcount: -_mcount: -#ifdef CONFIG_STACK_DEBUG - /* - * Check whether %sp is dangerously low. - */ - ldub [%g6 + TI_FPDEPTH], %g1 - srl %g1, 1, %g3 - add %g3, 1, %g3 - sllx %g3, 8, %g3 ! each fpregs frame is 256b - add %g3, 192, %g3 - add %g6, %g3, %g3 ! where does task_struct+frame end? - sub %g3, STACK_BIAS, %g3 - cmp %sp, %g3 - bg,pt %xcc, 1f - sethi %hi(panicstring), %g3 - sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough - or %g7, %lo(ovstack), %g7 - add %g7, OVSTACKSIZE, %g7 - sub %g7, STACK_BIAS, %g7 - mov %g7, %sp - call prom_printf - or %g3, %lo(panicstring), %o0 - call prom_halt - nop -#endif -1: retl - nop diff --git a/arch/sparc64/lib/memcmp.S b/arch/sparc64/lib/memcmp.S deleted file mode 100644 index c90ad96c51b..00000000000 --- a/arch/sparc64/lib/memcmp.S +++ /dev/null @@ -1,28 +0,0 @@ -/* $Id: memcmp.S,v 1.3 2000/03/23 07:51:08 davem Exp $ - * Sparc64 optimized memcmp code. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 2000 David S. Miller (davem@redhat.com) - */ - - .text - .align 32 - .globl __memcmp, memcmp -__memcmp: -memcmp: - cmp %o2, 0 ! IEU1 Group -loop: be,pn %icc, ret_0 ! CTI - nop ! IEU0 - ldub [%o0], %g7 ! LSU Group - ldub [%o1], %g3 ! LSU Group - sub %o2, 1, %o2 ! IEU0 - add %o0, 1, %o0 ! IEU1 - add %o1, 1, %o1 ! IEU0 Group - subcc %g7, %g3, %g3 ! IEU1 Group - be,pt %icc, loop ! CTI - cmp %o2, 0 ! IEU1 Group - -ret_n0: retl - mov %g3, %o0 -ret_0: retl - mov 0, %o0 diff --git a/arch/sparc64/lib/memmove.S b/arch/sparc64/lib/memmove.S deleted file mode 100644 index 97395802c23..00000000000 --- a/arch/sparc64/lib/memmove.S +++ /dev/null @@ -1,31 +0,0 @@ -/* memmove.S: Simple memmove implementation. - * - * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com) - * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - - .text - .align 32 - .globl memmove - .type memmove,#function -memmove: /* o0=dst o1=src o2=len */ - mov %o0, %g1 - cmp %o0, %o1 - bleu,pt %xcc, memcpy - add %o1, %o2, %g7 - cmp %g7, %o0 - bleu,pt %xcc, memcpy - add %o0, %o2, %o5 - sub %g7, 1, %o1 - - sub %o5, 1, %o0 -1: ldub [%o1], %g7 - subcc %o2, 1, %o2 - sub %o1, 1, %o1 - stb %g7, [%o0] - bne,pt %icc, 1b - sub %o0, 1, %o0 - - retl - mov %g1, %o0 - .size memmove, .-memmove diff --git a/arch/sparc64/lib/memscan.S b/arch/sparc64/lib/memscan.S deleted file mode 100644 index 5e72d491141..00000000000 --- a/arch/sparc64/lib/memscan.S +++ /dev/null @@ -1,129 +0,0 @@ -/* $Id: memscan.S,v 1.3 2000/01/31 04:59:10 davem Exp $ - * memscan.S: Optimized memscan for Sparc64. - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - */ - -#define HI_MAGIC 0x8080808080808080 -#define LO_MAGIC 0x0101010101010101 -#define ASI_PL 0x88 - - .text - .align 32 - .globl __memscan_zero, __memscan_generic - .globl memscan - -__memscan_zero: - /* %o0 = bufp, %o1 = size */ - brlez,pn %o1, szzero - andcc %o0, 7, %g0 - be,pt %icc, we_are_aligned - sethi %hi(HI_MAGIC), %o4 - ldub [%o0], %o5 -1: subcc %o1, 1, %o1 - brz,pn %o5, 10f - add %o0, 1, %o0 - - be,pn %xcc, szzero - andcc %o0, 7, %g0 - bne,a,pn %icc, 1b - ldub [%o0], %o5 -we_are_aligned: - ldxa [%o0] ASI_PL, %o5 - or %o4, %lo(HI_MAGIC), %o3 - sllx %o3, 32, %o4 - or %o4, %o3, %o3 - - srlx %o3, 7, %o2 -msloop: - sub %o1, 8, %o1 - add %o0, 8, %o0 - sub %o5, %o2, %o4 - xor %o4, %o5, %o4 - andcc %o4, %o3, %g3 - bne,pn %xcc, check_bytes - srlx %o4, 32, %g3 - - brgz,a,pt %o1, msloop - ldxa [%o0] ASI_PL, %o5 -check_bytes: - bne,a,pn %icc, 2f - andcc %o5, 0xff, %g0 - add %o0, -5, %g2 - ba,pt %xcc, 3f - srlx %o5, 32, %g7 - -2: srlx %o5, 8, %g7 - be,pn %icc, 1f - add %o0, -8, %g2 - andcc %g7, 0xff, %g0 - srlx %g7, 8, %g7 - be,pn %icc, 1f - inc %g2 - andcc %g7, 0xff, %g0 - - srlx %g7, 8, %g7 - be,pn %icc, 1f - inc %g2 - andcc %g7, 0xff, %g0 - srlx %g7, 8, %g7 - be,pn %icc, 1f - inc %g2 - andcc %g3, %o3, %g0 - - be,a,pn %icc, 2f - mov %o0, %g2 -3: andcc %g7, 0xff, %g0 - srlx %g7, 8, %g7 - be,pn %icc, 1f - inc %g2 - andcc %g7, 0xff, %g0 - srlx %g7, 8, %g7 - - be,pn %icc, 1f - inc %g2 - andcc %g7, 0xff, %g0 - srlx %g7, 8, %g7 - be,pn %icc, 1f - inc %g2 - andcc %g7, 0xff, %g0 - srlx %g7, 8, %g7 - - be,pn %icc, 1f - inc %g2 -2: brgz,a,pt %o1, msloop - ldxa [%o0] ASI_PL, %o5 - inc %g2 -1: add %o0, %o1, %o0 - cmp %g2, %o0 - retl - - movle %xcc, %g2, %o0 -10: retl - sub %o0, 1, %o0 -szzero: retl - nop - -memscan: -__memscan_generic: - /* %o0 = addr, %o1 = c, %o2 = size */ - brz,pn %o2, 3f - add %o0, %o2, %o3 - ldub [%o0], %o5 - sub %g0, %o2, %o4 -1: - cmp %o5, %o1 - be,pn %icc, 2f - addcc %o4, 1, %o4 - bne,a,pt %xcc, 1b - ldub [%o3 + %o4], %o5 - retl - /* The delay slot is the same as the next insn, this is just to make it look more awful */ -2: - add %o3, %o4, %o0 - retl - sub %o0, 1, %o0 -3: - retl - nop diff --git a/arch/sparc64/lib/rwsem.S b/arch/sparc64/lib/rwsem.S deleted file mode 100644 index 75f0e6b951d..00000000000 --- a/arch/sparc64/lib/rwsem.S +++ /dev/null @@ -1,170 +0,0 @@ -/* rwsem.S: RW semaphore assembler. - * - * Written by David S. Miller (davem@redhat.com), 2001. - * Derived from asm-i386/rwsem.h - */ - -#include <asm/rwsem-const.h> - - .section .sched.text - - .globl __down_read -__down_read: -1: lduw [%o0], %g1 - add %g1, 1, %g7 - cas [%o0], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - add %g7, 1, %g7 - cmp %g7, 0 - membar #StoreLoad | #StoreStore - bl,pn %icc, 3f - nop -2: - retl - nop -3: - save %sp, -192, %sp - call rwsem_down_read_failed - mov %i0, %o0 - ret - restore - .size __down_read, .-__down_read - - .globl __down_read_trylock -__down_read_trylock: -1: lduw [%o0], %g1 - add %g1, 1, %g7 - cmp %g7, 0 - bl,pn %icc, 2f - mov 0, %o1 - cas [%o0], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - mov 1, %o1 - membar #StoreLoad | #StoreStore -2: retl - mov %o1, %o0 - .size __down_read_trylock, .-__down_read_trylock - - .globl __down_write -__down_write: - sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1 - or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1 -1: - lduw [%o0], %g3 - add %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - cmp %g7, 0 - membar #StoreLoad | #StoreStore - bne,pn %icc, 3f - nop -2: retl - nop -3: - save %sp, -192, %sp - call rwsem_down_write_failed - mov %i0, %o0 - ret - restore - .size __down_write, .-__down_write - - .globl __down_write_trylock -__down_write_trylock: - sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1 - or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1 -1: - lduw [%o0], %g3 - cmp %g3, 0 - bne,pn %icc, 2f - mov 0, %o1 - add %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - mov 1, %o1 - membar #StoreLoad | #StoreStore -2: retl - mov %o1, %o0 - .size __down_write_trylock, .-__down_write_trylock - - .globl __up_read -__up_read: -1: - lduw [%o0], %g1 - sub %g1, 1, %g7 - cas [%o0], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - cmp %g7, 0 - membar #StoreLoad | #StoreStore - bl,pn %icc, 3f - nop -2: retl - nop -3: sethi %hi(RWSEM_ACTIVE_MASK), %g1 - sub %g7, 1, %g7 - or %g1, %lo(RWSEM_ACTIVE_MASK), %g1 - andcc %g7, %g1, %g0 - bne,pn %icc, 2b - nop - save %sp, -192, %sp - call rwsem_wake - mov %i0, %o0 - ret - restore - .size __up_read, .-__up_read - - .globl __up_write -__up_write: - sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1 - or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1 -1: - lduw [%o0], %g3 - sub %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - sub %g7, %g1, %g7 - cmp %g7, 0 - membar #StoreLoad | #StoreStore - bl,pn %icc, 3f - nop -2: - retl - nop -3: - save %sp, -192, %sp - call rwsem_wake - mov %i0, %o0 - ret - restore - .size __up_write, .-__up_write - - .globl __downgrade_write -__downgrade_write: - sethi %hi(RWSEM_WAITING_BIAS), %g1 - or %g1, %lo(RWSEM_WAITING_BIAS), %g1 -1: - lduw [%o0], %g3 - sub %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - sub %g7, %g1, %g7 - cmp %g7, 0 - membar #StoreLoad | #StoreStore - bl,pn %icc, 3f - nop -2: - retl - nop -3: - save %sp, -192, %sp - call rwsem_downgrade_wake - mov %i0, %o0 - ret - restore - .size __downgrade_write, .-__downgrade_write diff --git a/arch/sparc64/lib/strlen.S b/arch/sparc64/lib/strlen.S deleted file mode 100644 index e9ba1920d81..00000000000 --- a/arch/sparc64/lib/strlen.S +++ /dev/null @@ -1,80 +0,0 @@ -/* strlen.S: Sparc64 optimized strlen code - * Hand optimized from GNU libc's strlen - * Copyright (C) 1991,1996 Free Software Foundation - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#define LO_MAGIC 0x01010101 -#define HI_MAGIC 0x80808080 - - .align 32 - .globl strlen - .type strlen,#function -strlen: - mov %o0, %o1 - andcc %o0, 3, %g0 - be,pt %icc, 9f - sethi %hi(HI_MAGIC), %o4 - ldub [%o0], %o5 - brz,pn %o5, 11f - add %o0, 1, %o0 - andcc %o0, 3, %g0 - be,pn %icc, 4f - or %o4, %lo(HI_MAGIC), %o3 - ldub [%o0], %o5 - brz,pn %o5, 12f - add %o0, 1, %o0 - andcc %o0, 3, %g0 - be,pt %icc, 5f - sethi %hi(LO_MAGIC), %o4 - ldub [%o0], %o5 - brz,pn %o5, 13f - add %o0, 1, %o0 - ba,pt %icc, 8f - or %o4, %lo(LO_MAGIC), %o2 -9: - or %o4, %lo(HI_MAGIC), %o3 -4: - sethi %hi(LO_MAGIC), %o4 -5: - or %o4, %lo(LO_MAGIC), %o2 -8: - ld [%o0], %o5 -2: - sub %o5, %o2, %o4 - andcc %o4, %o3, %g0 - be,pt %icc, 8b - add %o0, 4, %o0 - - /* Check every byte. */ - srl %o5, 24, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o0, -4, %o4 - srl %o5, 16, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o4, 1, %o4 - srl %o5, 8, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o4, 1, %o4 - andcc %o5, 0xff, %g0 - bne,a,pt %icc, 2b - ld [%o0], %o5 - add %o4, 1, %o4 -1: - retl - sub %o4, %o1, %o0 -11: - retl - mov 0, %o0 -12: - retl - mov 1, %o0 -13: - retl - mov 2, %o0 - - .size strlen, .-strlen diff --git a/arch/sparc64/lib/strlen_user.S b/arch/sparc64/lib/strlen_user.S deleted file mode 100644 index 9ed54ba14fc..00000000000 --- a/arch/sparc64/lib/strlen_user.S +++ /dev/null @@ -1,95 +0,0 @@ -/* strlen_user.S: Sparc64 optimized strlen_user code - * - * Return length of string in userspace including terminating 0 - * or 0 for error - * - * Copyright (C) 1991,1996 Free Software Foundation - * Copyright (C) 1996,1999 David S. Miller (davem@redhat.com) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <asm/asi.h> - -#define LO_MAGIC 0x01010101 -#define HI_MAGIC 0x80808080 - - .align 4 - .global __strlen_user, __strnlen_user -__strlen_user: - sethi %hi(32768), %o1 -__strnlen_user: - mov %o1, %g1 - mov %o0, %o1 - andcc %o0, 3, %g0 - be,pt %icc, 9f - sethi %hi(HI_MAGIC), %o4 -10: lduba [%o0] %asi, %o5 - brz,pn %o5, 21f - add %o0, 1, %o0 - andcc %o0, 3, %g0 - be,pn %icc, 4f - or %o4, %lo(HI_MAGIC), %o3 -11: lduba [%o0] %asi, %o5 - brz,pn %o5, 22f - add %o0, 1, %o0 - andcc %o0, 3, %g0 - be,pt %icc, 13f - srl %o3, 7, %o2 -12: lduba [%o0] %asi, %o5 - brz,pn %o5, 23f - add %o0, 1, %o0 - ba,pt %icc, 2f -15: lda [%o0] %asi, %o5 -9: or %o4, %lo(HI_MAGIC), %o3 -4: srl %o3, 7, %o2 -13: lda [%o0] %asi, %o5 -2: sub %o5, %o2, %o4 - andcc %o4, %o3, %g0 - bne,pn %icc, 82f - add %o0, 4, %o0 - sub %o0, %o1, %g2 -81: cmp %g2, %g1 - blu,pt %icc, 13b - mov %o0, %o4 - ba,a,pt %xcc, 1f - - /* Check every byte. */ -82: srl %o5, 24, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o0, -3, %o4 - srl %o5, 16, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o4, 1, %o4 - srl %o5, 8, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o4, 1, %o4 - andcc %o5, 0xff, %g0 - bne,pt %icc, 81b - sub %o0, %o1, %g2 - add %o4, 1, %o4 -1: retl - sub %o4, %o1, %o0 -21: retl - mov 1, %o0 -22: retl - mov 2, %o0 -23: retl - mov 3, %o0 - - .section .fixup,#alloc,#execinstr - .align 4 -30: - retl - clr %o0 - - .section __ex_table,#alloc - .align 4 - - .word 10b, 30b - .word 11b, 30b - .word 12b, 30b - .word 15b, 30b - .word 13b, 30b diff --git a/arch/sparc64/lib/strncmp.S b/arch/sparc64/lib/strncmp.S deleted file mode 100644 index 6f14f53dbab..00000000000 --- a/arch/sparc64/lib/strncmp.S +++ /dev/null @@ -1,32 +0,0 @@ -/* $Id: strncmp.S,v 1.2 1997/03/11 17:51:44 jj Exp $ - * Sparc64 optimized strncmp code. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <asm/asi.h> - - .text - .align 32 - .globl strncmp - .type strncmp,#function -strncmp: - brlez,pn %o2, 3f - lduba [%o0] (ASI_PNF), %o3 -1: - add %o0, 1, %o0 - ldub [%o1], %o4 - brz,pn %o3, 2f - add %o1, 1, %o1 - cmp %o3, %o4 - bne,pn %icc, 2f - subcc %o2, 1, %o2 - bne,a,pt %xcc, 1b - ldub [%o0], %o3 -2: - retl - sub %o3, %o4, %o0 -3: - retl - clr %o0 - .size strncmp, .-strncmp diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S deleted file mode 100644 index e1264650ca7..00000000000 --- a/arch/sparc64/lib/strncpy_from_user.S +++ /dev/null @@ -1,135 +0,0 @@ -/* $Id: strncpy_from_user.S,v 1.6 1999/05/25 16:53:05 jj Exp $ - * strncpy_from_user.S: Sparc64 strncpy from userspace. - * - * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <asm/asi.h> -#include <asm/errno.h> - - .data - .align 8 -0: .xword 0x0101010101010101 - - .text - .align 32 - - /* Must return: - * - * -EFAULT for an exception - * count if we hit the buffer limit - * bytes copied if we hit a null byte - * (without the null byte) - * - * This implementation assumes: - * %o1 is 8 aligned => !(%o2 & 7) - * %o0 is 8 aligned (if not, it will be slooooow, but will work) - * - * This is optimized for the common case: - * in my stats, 90% of src are 8 aligned (even on sparc32) - * and average length is 18 or so. - */ - - .globl __strncpy_from_user - .type __strncpy_from_user,#function -__strncpy_from_user: - /* %o0=dest, %o1=src, %o2=count */ - andcc %o1, 7, %g0 ! IEU1 Group - bne,pn %icc, 30f ! CTI - add %o0, %o2, %g3 ! IEU0 -60: ldxa [%o1] %asi, %g1 ! Load Group - brlez,pn %o2, 10f ! CTI - mov %o0, %o3 ! IEU0 -50: sethi %hi(0b), %o4 ! IEU0 Group - ldx [%o4 + %lo(0b)], %o4 ! Load - sllx %o4, 7, %o5 ! IEU1 Group -1: sub %g1, %o4, %g2 ! IEU0 Group - stx %g1, [%o0] ! Store - add %o0, 8, %o0 ! IEU1 - andcc %g2, %o5, %g0 ! IEU1 Group - bne,pn %xcc, 5f ! CTI - add %o1, 8, %o1 ! IEU0 - cmp %o0, %g3 ! IEU1 Group - bl,a,pt %xcc, 1b ! CTI -61: ldxa [%o1] %asi, %g1 ! Load -10: retl ! CTI Group - mov %o2, %o0 ! IEU0 -5: srlx %g2, 32, %g7 ! IEU0 Group - sethi %hi(0xff00), %o4 ! IEU1 - andcc %g7, %o5, %g0 ! IEU1 Group - be,pn %icc, 2f ! CTI - or %o4, %lo(0xff00), %o4 ! IEU0 - srlx %g1, 48, %g7 ! IEU0 Group - andcc %g7, %o4, %g0 ! IEU1 Group - be,pn %icc, 50f ! CTI - andcc %g7, 0xff, %g0 ! IEU1 Group - be,pn %icc, 51f ! CTI - srlx %g1, 32, %g7 ! IEU0 - andcc %g7, %o4, %g0 ! IEU1 Group - be,pn %icc, 52f ! CTI - andcc %g7, 0xff, %g0 ! IEU1 Group - be,pn %icc, 53f ! CTI -2: andcc %g2, %o5, %g0 ! IEU1 Group - be,pn %icc, 2f ! CTI - srl %g1, 16, %g7 ! IEU0 - andcc %g7, %o4, %g0 ! IEU1 Group - be,pn %icc, 54f ! CTI - andcc %g7, 0xff, %g0 ! IEU1 Group - be,pn %icc, 55f ! CTI - andcc %g1, %o4, %g0 ! IEU1 Group - be,pn %icc, 56f ! CTI - andcc %g1, 0xff, %g0 ! IEU1 Group - be,a,pn %icc, 57f ! CTI - sub %o0, %o3, %o0 ! IEU0 -2: cmp %o0, %g3 ! IEU1 Group - bl,a,pt %xcc, 50b ! CTI -62: ldxa [%o1] %asi, %g1 ! Load - retl ! CTI Group - mov %o2, %o0 ! IEU0 -50: sub %o0, %o3, %o0 - retl - sub %o0, 8, %o0 -51: sub %o0, %o3, %o0 - retl - sub %o0, 7, %o0 -52: sub %o0, %o3, %o0 - retl - sub %o0, 6, %o0 -53: sub %o0, %o3, %o0 - retl - sub %o0, 5, %o0 -54: sub %o0, %o3, %o0 - retl - sub %o0, 4, %o0 -55: sub %o0, %o3, %o0 - retl - sub %o0, 3, %o0 -56: sub %o0, %o3, %o0 - retl - sub %o0, 2, %o0 -57: retl - sub %o0, 1, %o0 -30: brlez,pn %o2, 3f - sub %g0, %o2, %o3 - add %o0, %o2, %o0 -63: lduba [%o1] %asi, %o4 -1: add %o1, 1, %o1 - brz,pn %o4, 2f - stb %o4, [%o0 + %o3] - addcc %o3, 1, %o3 - bne,pt %xcc, 1b -64: lduba [%o1] %asi, %o4 -3: retl - mov %o2, %o0 -2: retl - add %o2, %o3, %o0 - .size __strncpy_from_user, .-__strncpy_from_user - - .section __ex_table,#alloc - .align 4 - .word 60b, __retl_efault - .word 61b, __retl_efault - .word 62b, __retl_efault - .word 63b, __retl_efault - .word 64b, __retl_efault - .previous diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c deleted file mode 100644 index 19d1fdb17d0..00000000000 --- a/arch/sparc64/lib/user_fixup.c +++ /dev/null @@ -1,66 +0,0 @@ -/* user_fixup.c: Fix up user copy faults. - * - * Copyright (C) 2004 David S. Miller <davem@redhat.com> - */ - -#include <linux/compiler.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <asm/uaccess.h> - -/* Calculating the exact fault address when using - * block loads and stores can be very complicated. - * - * Instead of trying to be clever and handling all - * of the cases, just fix things up simply here. - */ - -static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset) -{ - unsigned long fault_addr = current_thread_info()->fault_address; - unsigned long end = start + size; - - if (fault_addr < start || fault_addr >= end) { - *offset = 0; - } else { - *offset = start - fault_addr; - size = end - fault_addr; - } - return size; -} - -unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) -{ - unsigned long offset; - - size = compute_size((unsigned long) from, size, &offset); - if (likely(size)) - memset(to + offset, 0, size); - - return size; -} - -unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size) -{ - unsigned long offset; - - return compute_size((unsigned long) to, size, &offset); -} - -unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size) -{ - unsigned long fault_addr = current_thread_info()->fault_address; - unsigned long start = (unsigned long) to; - unsigned long end = start + size; - - if (fault_addr >= start && fault_addr < end) - return end - fault_addr; - - start = (unsigned long) from; - end = start + size; - if (fault_addr >= start && fault_addr < end) - return end - fault_addr; - - return size; -} diff --git a/arch/sparc64/lib/xor.S b/arch/sparc64/lib/xor.S deleted file mode 100644 index 4cd5d2be1ae..00000000000 --- a/arch/sparc64/lib/xor.S +++ /dev/null @@ -1,354 +0,0 @@ -/* - * arch/sparc64/lib/xor.S - * - * High speed xor_block operation for RAID4/5 utilizing the - * UltraSparc Visual Instruction Set. - * - * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <asm/visasm.h> -#include <asm/asi.h> -#include <asm/dcu.h> -#include <asm/spitfire.h> - -/* - * Requirements: - * !(((long)dest | (long)sourceN) & (64 - 1)) && - * !(len & 127) && len >= 256 - */ - .text - .align 32 - .globl xor_vis_2 - .type xor_vis_2,#function -xor_vis_2: - rd %fprs, %o5 - andcc %o5, FPRS_FEF|FPRS_DU, %g0 - be,pt %icc, 0f - sethi %hi(VISenter), %g1 - jmpl %g1 + %lo(VISenter), %g7 - add %g7, 8, %g7 -0: wr %g0, FPRS_FEF, %fprs - rd %asi, %g1 - wr %g0, ASI_BLK_P, %asi - membar #LoadStore|#StoreLoad|#StoreStore - sub %o0, 128, %o0 - ldda [%o1] %asi, %f0 - ldda [%o2] %asi, %f16 - -2: ldda [%o1 + 64] %asi, %f32 - fxor %f0, %f16, %f16 - fxor %f2, %f18, %f18 - fxor %f4, %f20, %f20 - fxor %f6, %f22, %f22 - fxor %f8, %f24, %f24 - fxor %f10, %f26, %f26 - fxor %f12, %f28, %f28 - fxor %f14, %f30, %f30 - stda %f16, [%o1] %asi - ldda [%o2 + 64] %asi, %f48 - ldda [%o1 + 128] %asi, %f0 - fxor %f32, %f48, %f48 - fxor %f34, %f50, %f50 - add %o1, 128, %o1 - fxor %f36, %f52, %f52 - add %o2, 128, %o2 - fxor %f38, %f54, %f54 - subcc %o0, 128, %o0 - fxor %f40, %f56, %f56 - fxor %f42, %f58, %f58 - fxor %f44, %f60, %f60 - fxor %f46, %f62, %f62 - stda %f48, [%o1 - 64] %asi - bne,pt %xcc, 2b - ldda [%o2] %asi, %f16 - - ldda [%o1 + 64] %asi, %f32 - fxor %f0, %f16, %f16 - fxor %f2, %f18, %f18 - fxor %f4, %f20, %f20 - fxor %f6, %f22, %f22 - fxor %f8, %f24, %f24 - fxor %f10, %f26, %f26 - fxor %f12, %f28, %f28 - fxor %f14, %f30, %f30 - stda %f16, [%o1] %asi - ldda [%o2 + 64] %asi, %f48 - membar #Sync - fxor %f32, %f48, %f48 - fxor %f34, %f50, %f50 - fxor %f36, %f52, %f52 - fxor %f38, %f54, %f54 - fxor %f40, %f56, %f56 - fxor %f42, %f58, %f58 - fxor %f44, %f60, %f60 - fxor %f46, %f62, %f62 - stda %f48, [%o1 + 64] %asi - membar #Sync|#StoreStore|#StoreLoad - wr %g1, %g0, %asi - retl - wr %g0, 0, %fprs - .size xor_vis_2, .-xor_vis_2 - - .globl xor_vis_3 - .type xor_vis_3,#function -xor_vis_3: - rd %fprs, %o5 - andcc %o5, FPRS_FEF|FPRS_DU, %g0 - be,pt %icc, 0f - sethi %hi(VISenter), %g1 - jmpl %g1 + %lo(VISenter), %g7 - add %g7, 8, %g7 -0: wr %g0, FPRS_FEF, %fprs - rd %asi, %g1 - wr %g0, ASI_BLK_P, %asi - membar #LoadStore|#StoreLoad|#StoreStore - sub %o0, 64, %o0 - ldda [%o1] %asi, %f0 - ldda [%o2] %asi, %f16 - -3: ldda [%o3] %asi, %f32 - fxor %f0, %f16, %f48 - fxor %f2, %f18, %f50 - add %o1, 64, %o1 - fxor %f4, %f20, %f52 - fxor %f6, %f22, %f54 - add %o2, 64, %o2 - fxor %f8, %f24, %f56 - fxor %f10, %f26, %f58 - fxor %f12, %f28, %f60 - fxor %f14, %f30, %f62 - ldda [%o1] %asi, %f0 - fxor %f48, %f32, %f48 - fxor %f50, %f34, %f50 - fxor %f52, %f36, %f52 - fxor %f54, %f38, %f54 - add %o3, 64, %o3 - fxor %f56, %f40, %f56 - fxor %f58, %f42, %f58 - subcc %o0, 64, %o0 - fxor %f60, %f44, %f60 - fxor %f62, %f46, %f62 - stda %f48, [%o1 - 64] %asi - bne,pt %xcc, 3b - ldda [%o2] %asi, %f16 - - ldda [%o3] %asi, %f32 - fxor %f0, %f16, %f48 - fxor %f2, %f18, %f50 - fxor %f4, %f20, %f52 - fxor %f6, %f22, %f54 - fxor %f8, %f24, %f56 - fxor %f10, %f26, %f58 - fxor %f12, %f28, %f60 - fxor %f14, %f30, %f62 - membar #Sync - fxor %f48, %f32, %f48 - fxor %f50, %f34, %f50 - fxor %f52, %f36, %f52 - fxor %f54, %f38, %f54 - fxor %f56, %f40, %f56 - fxor %f58, %f42, %f58 - fxor %f60, %f44, %f60 - fxor %f62, %f46, %f62 - stda %f48, [%o1] %asi - membar #Sync|#StoreStore|#StoreLoad - wr %g1, %g0, %asi - retl - wr %g0, 0, %fprs - .size xor_vis_3, .-xor_vis_3 - - .globl xor_vis_4 - .type xor_vis_4,#function -xor_vis_4: - rd %fprs, %o5 - andcc %o5, FPRS_FEF|FPRS_DU, %g0 - be,pt %icc, 0f - sethi %hi(VISenter), %g1 - jmpl %g1 + %lo(VISenter), %g7 - add %g7, 8, %g7 -0: wr %g0, FPRS_FEF, %fprs - rd %asi, %g1 - wr %g0, ASI_BLK_P, %asi - membar #LoadStore|#StoreLoad|#StoreStore - sub %o0, 64, %o0 - ldda [%o1] %asi, %f0 - ldda [%o2] %asi, %f16 - -4: ldda [%o3] %asi, %f32 - fxor %f0, %f16, %f16 - fxor %f2, %f18, %f18 - add %o1, 64, %o1 - fxor %f4, %f20, %f20 - fxor %f6, %f22, %f22 - add %o2, 64, %o2 - fxor %f8, %f24, %f24 - fxor %f10, %f26, %f26 - fxor %f12, %f28, %f28 - fxor %f14, %f30, %f30 - ldda [%o4] %asi, %f48 - fxor %f16, %f32, %f32 - fxor %f18, %f34, %f34 - fxor %f20, %f36, %f36 - fxor %f22, %f38, %f38 - add %o3, 64, %o3 - fxor %f24, %f40, %f40 - fxor %f26, %f42, %f42 - fxor %f28, %f44, %f44 - fxor %f30, %f46, %f46 - ldda [%o1] %asi, %f0 - fxor %f32, %f48, %f48 - fxor %f34, %f50, %f50 - fxor %f36, %f52, %f52 - add %o4, 64, %o4 - fxor %f38, %f54, %f54 - fxor %f40, %f56, %f56 - fxor %f42, %f58, %f58 - subcc %o0, 64, %o0 - fxor %f44, %f60, %f60 - fxor %f46, %f62, %f62 - stda %f48, [%o1 - 64] %asi - bne,pt %xcc, 4b - ldda [%o2] %asi, %f16 - - ldda [%o3] %asi, %f32 - fxor %f0, %f16, %f16 - fxor %f2, %f18, %f18 - fxor %f4, %f20, %f20 - fxor %f6, %f22, %f22 - fxor %f8, %f24, %f24 - fxor %f10, %f26, %f26 - fxor %f12, %f28, %f28 - fxor %f14, %f30, %f30 - ldda [%o4] %asi, %f48 - fxor %f16, %f32, %f32 - fxor %f18, %f34, %f34 - fxor %f20, %f36, %f36 - fxor %f22, %f38, %f38 - fxor %f24, %f40, %f40 - fxor %f26, %f42, %f42 - fxor %f28, %f44, %f44 - fxor %f30, %f46, %f46 - membar #Sync - fxor %f32, %f48, %f48 - fxor %f34, %f50, %f50 - fxor %f36, %f52, %f52 - fxor %f38, %f54, %f54 - fxor %f40, %f56, %f56 - fxor %f42, %f58, %f58 - fxor %f44, %f60, %f60 - fxor %f46, %f62, %f62 - stda %f48, [%o1] %asi - membar #Sync|#StoreStore|#StoreLoad - wr %g1, %g0, %asi - retl - wr %g0, 0, %fprs - .size xor_vis_4, .-xor_vis_4 - - .globl xor_vis_5 - .type xor_vis_5,#function -xor_vis_5: - save %sp, -192, %sp - rd %fprs, %o5 - andcc %o5, FPRS_FEF|FPRS_DU, %g0 - be,pt %icc, 0f - sethi %hi(VISenter), %g1 - jmpl %g1 + %lo(VISenter), %g7 - add %g7, 8, %g7 -0: wr %g0, FPRS_FEF, %fprs - rd %asi, %g1 - wr %g0, ASI_BLK_P, %asi - membar #LoadStore|#StoreLoad|#StoreStore - sub %i0, 64, %i0 - ldda [%i1] %asi, %f0 - ldda [%i2] %asi, %f16 - -5: ldda [%i3] %asi, %f32 - fxor %f0, %f16, %f48 - fxor %f2, %f18, %f50 - add %i1, 64, %i1 - fxor %f4, %f20, %f52 - fxor %f6, %f22, %f54 - add %i2, 64, %i2 - fxor %f8, %f24, %f56 - fxor %f10, %f26, %f58 - fxor %f12, %f28, %f60 - fxor %f14, %f30, %f62 - ldda [%i4] %asi, %f16 - fxor %f48, %f32, %f48 - fxor %f50, %f34, %f50 - fxor %f52, %f36, %f52 - fxor %f54, %f38, %f54 - add %i3, 64, %i3 - fxor %f56, %f40, %f56 - fxor %f58, %f42, %f58 - fxor %f60, %f44, %f60 - fxor %f62, %f46, %f62 - ldda [%i5] %asi, %f32 - fxor %f48, %f16, %f48 - fxor %f50, %f18, %f50 - add %i4, 64, %i4 - fxor %f52, %f20, %f52 - fxor %f54, %f22, %f54 - add %i5, 64, %i5 - fxor %f56, %f24, %f56 - fxor %f58, %f26, %f58 - fxor %f60, %f28, %f60 - fxor %f62, %f30, %f62 - ldda [%i1] %asi, %f0 - fxor %f48, %f32, %f48 - fxor %f50, %f34, %f50 - fxor %f52, %f36, %f52 - fxor %f54, %f38, %f54 - fxor %f56, %f40, %f56 - fxor %f58, %f42, %f58 - subcc %i0, 64, %i0 - fxor %f60, %f44, %f60 - fxor %f62, %f46, %f62 - stda %f48, [%i1 - 64] %asi - bne,pt %xcc, 5b - ldda [%i2] %asi, %f16 - - ldda [%i3] %asi, %f32 - fxor %f0, %f16, %f48 - fxor %f2, %f18, %f50 - fxor %f4, %f20, %f52 - fxor %f6, %f22, %f54 - fxor %f8, %f24, %f56 - fxor %f10, %f26, %f58 - fxor %f12, %f28, %f60 - fxor %f14, %f30, %f62 - ldda [%i4] %asi, %f16 - fxor %f48, %f32, %f48 - fxor %f50, %f34, %f50 - fxor %f52, %f36, %f52 - fxor %f54, %f38, %f54 - fxor %f56, %f40, %f56 - fxor %f58, %f42, %f58 - fxor %f60, %f44, %f60 - fxor %f62, %f46, %f62 - ldda [%i5] %asi, %f32 - fxor %f48, %f16, %f48 - fxor %f50, %f18, %f50 - fxor %f52, %f20, %f52 - fxor %f54, %f22, %f54 - fxor %f56, %f24, %f56 - fxor %f58, %f26, %f58 - fxor %f60, %f28, %f60 - fxor %f62, %f30, %f62 - membar #Sync - fxor %f48, %f32, %f48 - fxor %f50, %f34, %f50 - fxor %f52, %f36, %f52 - fxor %f54, %f38, %f54 - fxor %f56, %f40, %f56 - fxor %f58, %f42, %f58 - fxor %f60, %f44, %f60 - fxor %f62, %f46, %f62 - stda %f48, [%i1] %asi - membar #Sync|#StoreStore|#StoreLoad - wr %g1, %g0, %asi - wr %g0, 0, %fprs - ret - restore - .size xor_vis_5, .-xor_vis_5 diff --git a/arch/sparc64/math-emu/Makefile b/arch/sparc64/math-emu/Makefile deleted file mode 100644 index a0b06fd2946..00000000000 --- a/arch/sparc64/math-emu/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the FPU instruction emulation. -# - -obj-y := math.o - -EXTRA_CFLAGS = -I. -Iinclude/math-emu -w diff --git a/arch/sparc64/math-emu/math.c b/arch/sparc64/math-emu/math.c deleted file mode 100644 index 2ae05cd7b77..00000000000 --- a/arch/sparc64/math-emu/math.c +++ /dev/null @@ -1,493 +0,0 @@ -/* $Id: math.c,v 1.11 1999/12/20 05:02:25 davem Exp $ - * arch/sparc64/math-emu/math.c - * - * Copyright (C) 1997,1999 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - * - * Emulation routines originate from soft-fp package, which is part - * of glibc and has appropriate copyrights in it. - */ - -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/errno.h> - -#include <asm/fpumacro.h> -#include <asm/ptrace.h> -#include <asm/uaccess.h> - -#include "sfp-util.h" -#include <math-emu/soft-fp.h> -#include <math-emu/single.h> -#include <math-emu/double.h> -#include <math-emu/quad.h> - -/* QUAD - ftt == 3 */ -#define FMOVQ 0x003 -#define FNEGQ 0x007 -#define FABSQ 0x00b -#define FSQRTQ 0x02b -#define FADDQ 0x043 -#define FSUBQ 0x047 -#define FMULQ 0x04b -#define FDIVQ 0x04f -#define FDMULQ 0x06e -#define FQTOX 0x083 -#define FXTOQ 0x08c -#define FQTOS 0x0c7 -#define FQTOD 0x0cb -#define FITOQ 0x0cc -#define FSTOQ 0x0cd -#define FDTOQ 0x0ce -#define FQTOI 0x0d3 -/* SUBNORMAL - ftt == 2 */ -#define FSQRTS 0x029 -#define FSQRTD 0x02a -#define FADDS 0x041 -#define FADDD 0x042 -#define FSUBS 0x045 -#define FSUBD 0x046 -#define FMULS 0x049 -#define FMULD 0x04a -#define FDIVS 0x04d -#define FDIVD 0x04e -#define FSMULD 0x069 -#define FSTOX 0x081 -#define FDTOX 0x082 -#define FDTOS 0x0c6 -#define FSTOD 0x0c9 -#define FSTOI 0x0d1 -#define FDTOI 0x0d2 -#define FXTOS 0x084 /* Only Ultra-III generates this. */ -#define FXTOD 0x088 /* Only Ultra-III generates this. */ -#if 0 /* Optimized inline in sparc64/kernel/entry.S */ -#define FITOS 0x0c4 /* Only Ultra-III generates this. */ -#endif -#define FITOD 0x0c8 /* Only Ultra-III generates this. */ -/* FPOP2 */ -#define FCMPQ 0x053 -#define FCMPEQ 0x057 -#define FMOVQ0 0x003 -#define FMOVQ1 0x043 -#define FMOVQ2 0x083 -#define FMOVQ3 0x0c3 -#define FMOVQI 0x103 -#define FMOVQX 0x183 -#define FMOVQZ 0x027 -#define FMOVQLE 0x047 -#define FMOVQLZ 0x067 -#define FMOVQNZ 0x0a7 -#define FMOVQGZ 0x0c7 -#define FMOVQGE 0x0e7 - -#define FSR_TEM_SHIFT 23UL -#define FSR_TEM_MASK (0x1fUL << FSR_TEM_SHIFT) -#define FSR_AEXC_SHIFT 5UL -#define FSR_AEXC_MASK (0x1fUL << FSR_AEXC_SHIFT) -#define FSR_CEXC_SHIFT 0UL -#define FSR_CEXC_MASK (0x1fUL << FSR_CEXC_SHIFT) - -/* All routines returning an exception to raise should detect - * such exceptions _before_ rounding to be consistent with - * the behavior of the hardware in the implemented cases - * (and thus with the recommendations in the V9 architecture - * manual). - * - * We return 0 if a SIGFPE should be sent, 1 otherwise. - */ -static inline int record_exception(struct pt_regs *regs, int eflag) -{ - u64 fsr = current_thread_info()->xfsr[0]; - int would_trap; - - /* Determine if this exception would have generated a trap. */ - would_trap = (fsr & ((long)eflag << FSR_TEM_SHIFT)) != 0UL; - - /* If trapping, we only want to signal one bit. */ - if(would_trap != 0) { - eflag &= ((fsr & FSR_TEM_MASK) >> FSR_TEM_SHIFT); - if((eflag & (eflag - 1)) != 0) { - if(eflag & FP_EX_INVALID) - eflag = FP_EX_INVALID; - else if(eflag & FP_EX_OVERFLOW) - eflag = FP_EX_OVERFLOW; - else if(eflag & FP_EX_UNDERFLOW) - eflag = FP_EX_UNDERFLOW; - else if(eflag & FP_EX_DIVZERO) - eflag = FP_EX_DIVZERO; - else if(eflag & FP_EX_INEXACT) - eflag = FP_EX_INEXACT; - } - } - - /* Set CEXC, here is the rule: - * - * In general all FPU ops will set one and only one - * bit in the CEXC field, this is always the case - * when the IEEE exception trap is enabled in TEM. - */ - fsr &= ~(FSR_CEXC_MASK); - fsr |= ((long)eflag << FSR_CEXC_SHIFT); - - /* Set the AEXC field, rule is: - * - * If a trap would not be generated, the - * CEXC just generated is OR'd into the - * existing value of AEXC. - */ - if(would_trap == 0) - fsr |= ((long)eflag << FSR_AEXC_SHIFT); - - /* If trapping, indicate fault trap type IEEE. */ - if(would_trap != 0) - fsr |= (1UL << 14); - - current_thread_info()->xfsr[0] = fsr; - - /* If we will not trap, advance the program counter over - * the instruction being handled. - */ - if(would_trap == 0) { - regs->tpc = regs->tnpc; - regs->tnpc += 4; - } - - return (would_trap ? 0 : 1); -} - -typedef union { - u32 s; - u64 d; - u64 q[2]; -} *argp; - -int do_mathemu(struct pt_regs *regs, struct fpustate *f) -{ - unsigned long pc = regs->tpc; - unsigned long tstate = regs->tstate; - u32 insn = 0; - int type = 0; - /* ftt tells which ftt it may happen in, r is rd, b is rs2 and a is rs1. The *u arg tells - whether the argument should be packed/unpacked (0 - do not unpack/pack, 1 - unpack/pack) - non-u args tells the size of the argument (0 - no argument, 1 - single, 2 - double, 3 - quad */ -#define TYPE(ftt, r, ru, b, bu, a, au) type = (au << 2) | (a << 0) | (bu << 5) | (b << 3) | (ru << 8) | (r << 6) | (ftt << 9) - int freg; - static u64 zero[2] = { 0L, 0L }; - int flags; - FP_DECL_EX; - FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); - FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); - FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR); - int IR; - long XR, xfsr; - - if (tstate & TSTATE_PRIV) - die_if_kernel("unfinished/unimplemented FPop from kernel", regs); - if (test_thread_flag(TIF_32BIT)) - pc = (u32)pc; - if (get_user(insn, (u32 __user *) pc) != -EFAULT) { - if ((insn & 0xc1f80000) == 0x81a00000) /* FPOP1 */ { - switch ((insn >> 5) & 0x1ff) { - /* QUAD - ftt == 3 */ - case FMOVQ: - case FNEGQ: - case FABSQ: TYPE(3,3,0,3,0,0,0); break; - case FSQRTQ: TYPE(3,3,1,3,1,0,0); break; - case FADDQ: - case FSUBQ: - case FMULQ: - case FDIVQ: TYPE(3,3,1,3,1,3,1); break; - case FDMULQ: TYPE(3,3,1,2,1,2,1); break; - case FQTOX: TYPE(3,2,0,3,1,0,0); break; - case FXTOQ: TYPE(3,3,1,2,0,0,0); break; - case FQTOS: TYPE(3,1,1,3,1,0,0); break; - case FQTOD: TYPE(3,2,1,3,1,0,0); break; - case FITOQ: TYPE(3,3,1,1,0,0,0); break; - case FSTOQ: TYPE(3,3,1,1,1,0,0); break; - case FDTOQ: TYPE(3,3,1,2,1,0,0); break; - case FQTOI: TYPE(3,1,0,3,1,0,0); break; - /* SUBNORMAL - ftt == 2 */ - case FSQRTS: TYPE(2,1,1,1,1,0,0); break; - case FSQRTD: TYPE(2,2,1,2,1,0,0); break; - case FADDD: - case FSUBD: - case FMULD: - case FDIVD: TYPE(2,2,1,2,1,2,1); break; - case FADDS: - case FSUBS: - case FMULS: - case FDIVS: TYPE(2,1,1,1,1,1,1); break; - case FSMULD: TYPE(2,2,1,1,1,1,1); break; - case FSTOX: TYPE(2,2,0,1,1,0,0); break; - case FDTOX: TYPE(2,2,0,2,1,0,0); break; - case FDTOS: TYPE(2,1,1,2,1,0,0); break; - case FSTOD: TYPE(2,2,1,1,1,0,0); break; - case FSTOI: TYPE(2,1,0,1,1,0,0); break; - case FDTOI: TYPE(2,1,0,2,1,0,0); break; - - /* Only Ultra-III generates these */ - case FXTOS: TYPE(2,1,1,2,0,0,0); break; - case FXTOD: TYPE(2,2,1,2,0,0,0); break; -#if 0 /* Optimized inline in sparc64/kernel/entry.S */ - case FITOS: TYPE(2,1,1,1,0,0,0); break; -#endif - case FITOD: TYPE(2,2,1,1,0,0,0); break; - } - } - else if ((insn & 0xc1f80000) == 0x81a80000) /* FPOP2 */ { - IR = 2; - switch ((insn >> 5) & 0x1ff) { - case FCMPQ: TYPE(3,0,0,3,1,3,1); break; - case FCMPEQ: TYPE(3,0,0,3,1,3,1); break; - /* Now the conditional fmovq support */ - case FMOVQ0: - case FMOVQ1: - case FMOVQ2: - case FMOVQ3: - /* fmovq %fccX, %fY, %fZ */ - if (!((insn >> 11) & 3)) - XR = current_thread_info()->xfsr[0] >> 10; - else - XR = current_thread_info()->xfsr[0] >> (30 + ((insn >> 10) & 0x6)); - XR &= 3; - IR = 0; - switch ((insn >> 14) & 0x7) { - /* case 0: IR = 0; break; */ /* Never */ - case 1: if (XR) IR = 1; break; /* Not Equal */ - case 2: if (XR == 1 || XR == 2) IR = 1; break; /* Less or Greater */ - case 3: if (XR & 1) IR = 1; break; /* Unordered or Less */ - case 4: if (XR == 1) IR = 1; break; /* Less */ - case 5: if (XR & 2) IR = 1; break; /* Unordered or Greater */ - case 6: if (XR == 2) IR = 1; break; /* Greater */ - case 7: if (XR == 3) IR = 1; break; /* Unordered */ - } - if ((insn >> 14) & 8) - IR ^= 1; - break; - case FMOVQI: - case FMOVQX: - /* fmovq %[ix]cc, %fY, %fZ */ - XR = regs->tstate >> 32; - if ((insn >> 5) & 0x80) - XR >>= 4; - XR &= 0xf; - IR = 0; - freg = ((XR >> 2) ^ XR) & 2; - switch ((insn >> 14) & 0x7) { - /* case 0: IR = 0; break; */ /* Never */ - case 1: if (XR & 4) IR = 1; break; /* Equal */ - case 2: if ((XR & 4) || freg) IR = 1; break; /* Less or Equal */ - case 3: if (freg) IR = 1; break; /* Less */ - case 4: if (XR & 5) IR = 1; break; /* Less or Equal Unsigned */ - case 5: if (XR & 1) IR = 1; break; /* Carry Set */ - case 6: if (XR & 8) IR = 1; break; /* Negative */ - case 7: if (XR & 2) IR = 1; break; /* Overflow Set */ - } - if ((insn >> 14) & 8) - IR ^= 1; - break; - case FMOVQZ: - case FMOVQLE: - case FMOVQLZ: - case FMOVQNZ: - case FMOVQGZ: - case FMOVQGE: - freg = (insn >> 14) & 0x1f; - if (!freg) - XR = 0; - else if (freg < 16) - XR = regs->u_regs[freg]; - else if (test_thread_flag(TIF_32BIT)) { - struct reg_window32 __user *win32; - flushw_user (); - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); - get_user(XR, &win32->locals[freg - 16]); - } else { - struct reg_window __user *win; - flushw_user (); - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); - get_user(XR, &win->locals[freg - 16]); - } - IR = 0; - switch ((insn >> 10) & 3) { - case 1: if (!XR) IR = 1; break; /* Register Zero */ - case 2: if (XR <= 0) IR = 1; break; /* Register Less Than or Equal to Zero */ - case 3: if (XR < 0) IR = 1; break; /* Register Less Than Zero */ - } - if ((insn >> 10) & 4) - IR ^= 1; - break; - } - if (IR == 0) { - /* The fmov test was false. Do a nop instead */ - current_thread_info()->xfsr[0] &= ~(FSR_CEXC_MASK); - regs->tpc = regs->tnpc; - regs->tnpc += 4; - return 1; - } else if (IR == 1) { - /* Change the instruction into plain fmovq */ - insn = (insn & 0x3e00001f) | 0x81a00060; - TYPE(3,3,0,3,0,0,0); - } - } - } - if (type) { - argp rs1 = NULL, rs2 = NULL, rd = NULL; - - freg = (current_thread_info()->xfsr[0] >> 14) & 0xf; - if (freg != (type >> 9)) - goto err; - current_thread_info()->xfsr[0] &= ~0x1c000; - freg = ((insn >> 14) & 0x1f); - switch (type & 0x3) { - case 3: if (freg & 2) { - current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */; - goto err; - } - case 2: freg = ((freg & 1) << 5) | (freg & 0x1e); - case 1: rs1 = (argp)&f->regs[freg]; - flags = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current_thread_info()->fpsaved[0] & flags)) - rs1 = (argp)&zero; - break; - } - switch (type & 0x7) { - case 7: FP_UNPACK_QP (QA, rs1); break; - case 6: FP_UNPACK_DP (DA, rs1); break; - case 5: FP_UNPACK_SP (SA, rs1); break; - } - freg = (insn & 0x1f); - switch ((type >> 3) & 0x3) { - case 3: if (freg & 2) { - current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */; - goto err; - } - case 2: freg = ((freg & 1) << 5) | (freg & 0x1e); - case 1: rs2 = (argp)&f->regs[freg]; - flags = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current_thread_info()->fpsaved[0] & flags)) - rs2 = (argp)&zero; - break; - } - switch ((type >> 3) & 0x7) { - case 7: FP_UNPACK_QP (QB, rs2); break; - case 6: FP_UNPACK_DP (DB, rs2); break; - case 5: FP_UNPACK_SP (SB, rs2); break; - } - freg = ((insn >> 25) & 0x1f); - switch ((type >> 6) & 0x3) { - case 3: if (freg & 2) { - current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */; - goto err; - } - case 2: freg = ((freg & 1) << 5) | (freg & 0x1e); - case 1: rd = (argp)&f->regs[freg]; - flags = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) { - current_thread_info()->fpsaved[0] = FPRS_FEF; - current_thread_info()->gsr[0] = 0; - } - if (!(current_thread_info()->fpsaved[0] & flags)) { - if (freg < 32) - memset(f->regs, 0, 32*sizeof(u32)); - else - memset(f->regs+32, 0, 32*sizeof(u32)); - } - current_thread_info()->fpsaved[0] |= flags; - break; - } - switch ((insn >> 5) & 0x1ff) { - /* + */ - case FADDS: FP_ADD_S (SR, SA, SB); break; - case FADDD: FP_ADD_D (DR, DA, DB); break; - case FADDQ: FP_ADD_Q (QR, QA, QB); break; - /* - */ - case FSUBS: FP_SUB_S (SR, SA, SB); break; - case FSUBD: FP_SUB_D (DR, DA, DB); break; - case FSUBQ: FP_SUB_Q (QR, QA, QB); break; - /* * */ - case FMULS: FP_MUL_S (SR, SA, SB); break; - case FSMULD: FP_CONV (D, S, 1, 1, DA, SA); - FP_CONV (D, S, 1, 1, DB, SB); - case FMULD: FP_MUL_D (DR, DA, DB); break; - case FDMULQ: FP_CONV (Q, D, 2, 1, QA, DA); - FP_CONV (Q, D, 2, 1, QB, DB); - case FMULQ: FP_MUL_Q (QR, QA, QB); break; - /* / */ - case FDIVS: FP_DIV_S (SR, SA, SB); break; - case FDIVD: FP_DIV_D (DR, DA, DB); break; - case FDIVQ: FP_DIV_Q (QR, QA, QB); break; - /* sqrt */ - case FSQRTS: FP_SQRT_S (SR, SB); break; - case FSQRTD: FP_SQRT_D (DR, DB); break; - case FSQRTQ: FP_SQRT_Q (QR, QB); break; - /* mov */ - case FMOVQ: rd->q[0] = rs2->q[0]; rd->q[1] = rs2->q[1]; break; - case FABSQ: rd->q[0] = rs2->q[0] & 0x7fffffffffffffffUL; rd->q[1] = rs2->q[1]; break; - case FNEGQ: rd->q[0] = rs2->q[0] ^ 0x8000000000000000UL; rd->q[1] = rs2->q[1]; break; - /* float to int */ - case FSTOI: FP_TO_INT_S (IR, SB, 32, 1); break; - case FDTOI: FP_TO_INT_D (IR, DB, 32, 1); break; - case FQTOI: FP_TO_INT_Q (IR, QB, 32, 1); break; - case FSTOX: FP_TO_INT_S (XR, SB, 64, 1); break; - case FDTOX: FP_TO_INT_D (XR, DB, 64, 1); break; - case FQTOX: FP_TO_INT_Q (XR, QB, 64, 1); break; - /* int to float */ - case FITOQ: IR = rs2->s; FP_FROM_INT_Q (QR, IR, 32, int); break; - case FXTOQ: XR = rs2->d; FP_FROM_INT_Q (QR, XR, 64, long); break; - /* Only Ultra-III generates these */ - case FXTOS: XR = rs2->d; FP_FROM_INT_S (SR, XR, 64, long); break; - case FXTOD: XR = rs2->d; FP_FROM_INT_D (DR, XR, 64, long); break; -#if 0 /* Optimized inline in sparc64/kernel/entry.S */ - case FITOS: IR = rs2->s; FP_FROM_INT_S (SR, IR, 32, int); break; -#endif - case FITOD: IR = rs2->s; FP_FROM_INT_D (DR, IR, 32, int); break; - /* float to float */ - case FSTOD: FP_CONV (D, S, 1, 1, DR, SB); break; - case FSTOQ: FP_CONV (Q, S, 2, 1, QR, SB); break; - case FDTOQ: FP_CONV (Q, D, 2, 1, QR, DB); break; - case FDTOS: FP_CONV (S, D, 1, 1, SR, DB); break; - case FQTOS: FP_CONV (S, Q, 1, 2, SR, QB); break; - case FQTOD: FP_CONV (D, Q, 1, 2, DR, QB); break; - /* comparison */ - case FCMPQ: - case FCMPEQ: - FP_CMP_Q(XR, QB, QA, 3); - if (XR == 3 && - (((insn >> 5) & 0x1ff) == FCMPEQ || - FP_ISSIGNAN_Q(QA) || - FP_ISSIGNAN_Q(QB))) - FP_SET_EXCEPTION (FP_EX_INVALID); - } - if (!FP_INHIBIT_RESULTS) { - switch ((type >> 6) & 0x7) { - case 0: xfsr = current_thread_info()->xfsr[0]; - if (XR == -1) XR = 2; - switch (freg & 3) { - /* fcc0, 1, 2, 3 */ - case 0: xfsr &= ~0xc00; xfsr |= (XR << 10); break; - case 1: xfsr &= ~0x300000000UL; xfsr |= (XR << 32); break; - case 2: xfsr &= ~0xc00000000UL; xfsr |= (XR << 34); break; - case 3: xfsr &= ~0x3000000000UL; xfsr |= (XR << 36); break; - } - current_thread_info()->xfsr[0] = xfsr; - break; - case 1: rd->s = IR; break; - case 2: rd->d = XR; break; - case 5: FP_PACK_SP (rd, SR); break; - case 6: FP_PACK_DP (rd, DR); break; - case 7: FP_PACK_QP (rd, QR); break; - } - } - - if(_fex != 0) - return record_exception(regs, _fex); - - /* Success and no exceptions detected. */ - current_thread_info()->xfsr[0] &= ~(FSR_CEXC_MASK); - regs->tpc = regs->tnpc; - regs->tnpc += 4; - return 1; - } -err: return 0; -} diff --git a/arch/sparc64/math-emu/sfp-util.h b/arch/sparc64/math-emu/sfp-util.h deleted file mode 100644 index 31e474738cf..00000000000 --- a/arch/sparc64/math-emu/sfp-util.h +++ /dev/null @@ -1,120 +0,0 @@ -/* $Id: sfp-util.h,v 1.5 2001/06/10 06:48:46 davem Exp $ - * arch/sparc64/math-emu/sfp-util.h - * - * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - * - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <asm/byteorder.h> - -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addcc %4,%5,%1\n\t" \ - "add %2,%3,%0\n\t" \ - "bcs,a,pn %%xcc, 1f\n\t" \ - "add %0, 1, %0\n" \ - "1:" \ - : "=r" ((UDItype)(sh)), \ - "=&r" ((UDItype)(sl)) \ - : "r" ((UDItype)(ah)), \ - "r" ((UDItype)(bh)), \ - "r" ((UDItype)(al)), \ - "r" ((UDItype)(bl)) \ - : "cc") - -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subcc %4,%5,%1\n\t" \ - "sub %2,%3,%0\n\t" \ - "bcs,a,pn %%xcc, 1f\n\t" \ - "sub %0, 1, %0\n" \ - "1:" \ - : "=r" ((UDItype)(sh)), \ - "=&r" ((UDItype)(sl)) \ - : "r" ((UDItype)(ah)), \ - "r" ((UDItype)(bh)), \ - "r" ((UDItype)(al)), \ - "r" ((UDItype)(bl)) \ - : "cc") - -#define umul_ppmm(wh, wl, u, v) \ - do { \ - UDItype tmp1, tmp2, tmp3, tmp4; \ - __asm__ __volatile__ ( \ - "srl %7,0,%3\n\t" \ - "mulx %3,%6,%1\n\t" \ - "srlx %6,32,%2\n\t" \ - "mulx %2,%3,%4\n\t" \ - "sllx %4,32,%5\n\t" \ - "srl %6,0,%3\n\t" \ - "sub %1,%5,%5\n\t" \ - "srlx %5,32,%5\n\t" \ - "addcc %4,%5,%4\n\t" \ - "srlx %7,32,%5\n\t" \ - "mulx %3,%5,%3\n\t" \ - "mulx %2,%5,%5\n\t" \ - "sethi %%hi(0x80000000),%2\n\t" \ - "addcc %4,%3,%4\n\t" \ - "srlx %4,32,%4\n\t" \ - "add %2,%2,%2\n\t" \ - "movcc %%xcc,%%g0,%2\n\t" \ - "addcc %5,%4,%5\n\t" \ - "sllx %3,32,%3\n\t" \ - "add %1,%3,%1\n\t" \ - "add %5,%2,%0" \ - : "=r" ((UDItype)(wh)), \ - "=&r" ((UDItype)(wl)), \ - "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \ - : "r" ((UDItype)(u)), \ - "r" ((UDItype)(v)) \ - : "cc"); \ - } while (0) - -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ - __d1 = (d >> 32); \ - __d0 = (USItype)d; \ - \ - __r1 = (n1) % __d1; \ - __q1 = (n1) / __d1; \ - __m = (UWtype) __q1 * __d0; \ - __r1 = (__r1 << 32) | (n0 >> 32); \ - if (__r1 < __m) \ - { \ - __q1--, __r1 += (d); \ - if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */ \ - if (__r1 < __m) \ - __q1--, __r1 += (d); \ - } \ - __r1 -= __m; \ - \ - __r0 = __r1 % __d1; \ - __q0 = __r1 / __d1; \ - __m = (UWtype) __q0 * __d0; \ - __r0 = (__r0 << 32) | ((USItype)n0); \ - if (__r0 < __m) \ - { \ - __q0--, __r0 += (d); \ - if (__r0 >= (d)) \ - if (__r0 < __m) \ - __q0--, __r0 += (d); \ - } \ - __r0 -= __m; \ - \ - (q) = (UWtype) (__q1 << 32) | __q0; \ - (r) = __r0; \ - } while (0) - -#define UDIV_NEEDS_NORMALIZATION 1 - -#define abort() \ - return 0 - -#ifdef __BIG_ENDIAN -#define __BYTE_ORDER __BIG_ENDIAN -#else -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile deleted file mode 100644 index 9d0960e69f4..00000000000 --- a/arch/sparc64/mm/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $Id: Makefile,v 1.8 2000/12/14 22:57:25 davem Exp $ -# Makefile for the linux Sparc64-specific parts of the memory manager. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -obj-y := ultra.o tlb.o fault.o init.o generic.o - -obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c deleted file mode 100644 index 6f0539aa44d..00000000000 --- a/arch/sparc64/mm/fault.c +++ /dev/null @@ -1,452 +0,0 @@ -/* $Id: fault.c,v 1.59 2002/02/09 19:49:31 davem Exp $ - * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <asm/head.h> - -#include <linux/string.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/mman.h> -#include <linux/signal.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/smp_lock.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/kprobes.h> - -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/openprom.h> -#include <asm/oplib.h> -#include <asm/uaccess.h> -#include <asm/asi.h> -#include <asm/lsu.h> -#include <asm/sections.h> -#include <asm/kdebug.h> - -/* - * To debug kernel to catch accesses to certain virtual/physical addresses. - * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. - * flags = VM_READ watches memread accesses, flags = VM_WRITE watches memwrite accesses. - * Caller passes in a 64bit aligned addr, with mask set to the bytes that need to be - * watched. This is only useful on a single cpu machine for now. After the watchpoint - * is detected, the process causing it will be killed, thus preventing an infinite loop. - */ -void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode) -{ - unsigned long lsubits; - - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (lsubits) - : "i" (ASI_LSU_CONTROL)); - lsubits &= ~(LSU_CONTROL_PM | LSU_CONTROL_VM | - LSU_CONTROL_PR | LSU_CONTROL_VR | - LSU_CONTROL_PW | LSU_CONTROL_VW); - - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (addr), "r" (mode ? VIRT_WATCHPOINT : PHYS_WATCHPOINT), - "i" (ASI_DMMU)); - - lsubits |= ((unsigned long)mask << (mode ? 25 : 33)); - if (flags & VM_READ) - lsubits |= (mode ? LSU_CONTROL_VR : LSU_CONTROL_PR); - if (flags & VM_WRITE) - lsubits |= (mode ? LSU_CONTROL_VW : LSU_CONTROL_PW); - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (lsubits), "i" (ASI_LSU_CONTROL) - : "memory"); -} - -static void __kprobes unhandled_fault(unsigned long address, - struct task_struct *tsk, - struct pt_regs *regs) -{ - if ((unsigned long) address < PAGE_SIZE) { - printk(KERN_ALERT "Unable to handle kernel NULL " - "pointer dereference\n"); - } else { - printk(KERN_ALERT "Unable to handle kernel paging request " - "at virtual address %016lx\n", (unsigned long)address); - } - printk(KERN_ALERT "tsk->{mm,active_mm}->context = %016lx\n", - (tsk->mm ? - CTX_HWBITS(tsk->mm->context) : - CTX_HWBITS(tsk->active_mm->context))); - printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n", - (tsk->mm ? (unsigned long) tsk->mm->pgd : - (unsigned long) tsk->active_mm->pgd)); - if (notify_die(DIE_GPF, "general protection fault", regs, - 0, 0, SIGSEGV) == NOTIFY_STOP) - return; - die_if_kernel("Oops", regs); -} - -static void bad_kernel_pc(struct pt_regs *regs) -{ - unsigned long *ksp; - - printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", - regs->tpc); - __asm__("mov %%sp, %0" : "=r" (ksp)); - show_stack(current, ksp); - unhandled_fault(regs->tpc, current, regs); -} - -/* - * We now make sure that mmap_sem is held in all paths that call - * this. Additionally, to prevent kswapd from ripping ptes from - * under us, raise interrupts around the time that we look at the - * pte, kswapd will have to wait to get his smp ipi response from - * us. vmtruncate likewise. This saves us having to get pte lock. - */ -static unsigned int get_user_insn(unsigned long tpc) -{ - pgd_t *pgdp = pgd_offset(current->mm, tpc); - pud_t *pudp; - pmd_t *pmdp; - pte_t *ptep, pte; - unsigned long pa; - u32 insn = 0; - unsigned long pstate; - - if (pgd_none(*pgdp)) - goto outret; - pudp = pud_offset(pgdp, tpc); - if (pud_none(*pudp)) - goto outret; - pmdp = pmd_offset(pudp, tpc); - if (pmd_none(*pmdp)) - goto outret; - - /* This disables preemption for us as well. */ - __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); - __asm__ __volatile__("wrpr %0, %1, %%pstate" - : : "r" (pstate), "i" (PSTATE_IE)); - ptep = pte_offset_map(pmdp, tpc); - pte = *ptep; - if (!pte_present(pte)) - goto out; - - pa = (pte_val(pte) & _PAGE_PADDR); - pa += (tpc & ~PAGE_MASK); - - /* Use phys bypass so we don't pollute dtlb/dcache. */ - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=r" (insn) - : "r" (pa), "i" (ASI_PHYS_USE_EC)); - -out: - pte_unmap(ptep); - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); -outret: - return insn; -} - -extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int); - -static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, - unsigned int insn, int fault_code) -{ - siginfo_t info; - - info.si_code = code; - info.si_signo = sig; - info.si_errno = 0; - if (fault_code & FAULT_CODE_ITLB) - info.si_addr = (void __user *) regs->tpc; - else - info.si_addr = (void __user *) - compute_effective_address(regs, insn, 0); - info.si_trapno = 0; - force_sig_info(sig, &info, current); -} - -extern int handle_ldf_stq(u32, struct pt_regs *); -extern int handle_ld_nf(u32, struct pt_regs *); - -static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn) -{ - if (!insn) { - if (!regs->tpc || (regs->tpc & 0x3)) - return 0; - if (regs->tstate & TSTATE_PRIV) { - insn = *(unsigned int *) regs->tpc; - } else { - insn = get_user_insn(regs->tpc); - } - } - return insn; -} - -static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, - unsigned int insn, unsigned long address) -{ - unsigned char asi = ASI_P; - - if ((!insn) && (regs->tstate & TSTATE_PRIV)) - goto cannot_handle; - - /* If user insn could be read (thus insn is zero), that - * is fine. We will just gun down the process with a signal - * in that case. - */ - - if (!(fault_code & (FAULT_CODE_WRITE|FAULT_CODE_ITLB)) && - (insn & 0xc0800000) == 0xc0800000) { - if (insn & 0x2000) - asi = (regs->tstate >> 24); - else - asi = (insn >> 5); - if ((asi & 0xf2) == 0x82) { - if (insn & 0x1000000) { - handle_ldf_stq(insn, regs); - } else { - /* This was a non-faulting load. Just clear the - * destination register(s) and continue with the next - * instruction. -jj - */ - handle_ld_nf(insn, regs); - } - return; - } - } - - /* Is this in ex_table? */ - if (regs->tstate & TSTATE_PRIV) { - const struct exception_table_entry *entry; - - if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { - if (insn & 0x2000) - asi = (regs->tstate >> 24); - else - asi = (insn >> 5); - } - - /* Look in asi.h: All _S asis have LS bit set */ - if ((asi & 0x1) && - (entry = search_exception_tables(regs->tpc))) { - regs->tpc = entry->fixup; - regs->tnpc = regs->tpc + 4; - return; - } - } else { - /* The si_code was set to make clear whether - * this was a SEGV_MAPERR or SEGV_ACCERR fault. - */ - do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code); - return; - } - -cannot_handle: - unhandled_fault (address, current, regs); -} - -asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - unsigned int insn = 0; - int si_code, fault_code; - unsigned long address; - - fault_code = get_thread_fault_code(); - - if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, - fault_code, 0, SIGSEGV) == NOTIFY_STOP) - return; - - si_code = SEGV_MAPERR; - address = current_thread_info()->fault_address; - - if ((fault_code & FAULT_CODE_ITLB) && - (fault_code & FAULT_CODE_DTLB)) - BUG(); - - if (regs->tstate & TSTATE_PRIV) { - unsigned long tpc = regs->tpc; - - /* Sanity check the PC. */ - if ((tpc >= KERNBASE && tpc < (unsigned long) _etext) || - (tpc >= MODULES_VADDR && tpc < MODULES_END)) { - /* Valid, no problems... */ - } else { - bad_kernel_pc(regs); - return; - } - } - - /* - * If we're in an interrupt or have no user - * context, we must not take the fault.. - */ - if (in_atomic() || !mm) - goto intr_or_no_mm; - - if (test_thread_flag(TIF_32BIT)) { - if (!(regs->tstate & TSTATE_PRIV)) - regs->tpc &= 0xffffffff; - address &= 0xffffffff; - } - - if (!down_read_trylock(&mm->mmap_sem)) { - if ((regs->tstate & TSTATE_PRIV) && - !search_exception_tables(regs->tpc)) { - insn = get_fault_insn(regs, insn); - goto handle_kernel_fault; - } - down_read(&mm->mmap_sem); - } - - vma = find_vma(mm, address); - if (!vma) - goto bad_area; - - /* Pure DTLB misses do not tell us whether the fault causing - * load/store/atomic was a write or not, it only says that there - * was no match. So in such a case we (carefully) read the - * instruction to try and figure this out. It's an optimization - * so it's ok if we can't do this. - * - * Special hack, window spill/fill knows the exact fault type. - */ - if (((fault_code & - (FAULT_CODE_DTLB | FAULT_CODE_WRITE | FAULT_CODE_WINFIXUP)) == FAULT_CODE_DTLB) && - (vma->vm_flags & VM_WRITE) != 0) { - insn = get_fault_insn(regs, 0); - if (!insn) - goto continue_fault; - if ((insn & 0xc0200000) == 0xc0200000 && - (insn & 0x1780000) != 0x1680000) { - /* Don't bother updating thread struct value, - * because update_mmu_cache only cares which tlb - * the access came from. - */ - fault_code |= FAULT_CODE_WRITE; - } - } -continue_fault: - - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (!(fault_code & FAULT_CODE_WRITE)) { - /* Non-faulting loads shouldn't expand stack. */ - insn = get_fault_insn(regs, insn); - if ((insn & 0xc0800000) == 0xc0800000) { - unsigned char asi; - - if (insn & 0x2000) - asi = (regs->tstate >> 24); - else - asi = (insn >> 5); - if ((asi & 0xf2) == 0x82) - goto bad_area; - } - } - if (expand_stack(vma, address)) - goto bad_area; - /* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ -good_area: - si_code = SEGV_ACCERR; - - /* If we took a ITLB miss on a non-executable page, catch - * that here. - */ - if ((fault_code & FAULT_CODE_ITLB) && !(vma->vm_flags & VM_EXEC)) { - BUG_ON(address != regs->tpc); - BUG_ON(regs->tstate & TSTATE_PRIV); - goto bad_area; - } - - if (fault_code & FAULT_CODE_WRITE) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - - /* Spitfire has an icache which does not snoop - * processor stores. Later processors do... - */ - if (tlb_type == spitfire && - (vma->vm_flags & VM_EXEC) != 0 && - vma->vm_file != NULL) - set_thread_fault_code(fault_code | - FAULT_CODE_BLKCOMMIT); - } else { - /* Allow reads even for write-only mappings */ - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; - } - - switch (handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE))) { - case VM_FAULT_MINOR: - current->min_flt++; - break; - case VM_FAULT_MAJOR: - current->maj_flt++; - break; - case VM_FAULT_SIGBUS: - goto do_sigbus; - case VM_FAULT_OOM: - goto out_of_memory; - default: - BUG(); - } - - up_read(&mm->mmap_sem); - return; - - /* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: - insn = get_fault_insn(regs, insn); - up_read(&mm->mmap_sem); - -handle_kernel_fault: - do_kernel_fault(regs, si_code, fault_code, insn, address); - return; - -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. - */ -out_of_memory: - insn = get_fault_insn(regs, insn); - up_read(&mm->mmap_sem); - printk("VM: killing process %s\n", current->comm); - if (!(regs->tstate & TSTATE_PRIV)) - do_exit(SIGKILL); - goto handle_kernel_fault; - -intr_or_no_mm: - insn = get_fault_insn(regs, 0); - goto handle_kernel_fault; - -do_sigbus: - insn = get_fault_insn(regs, insn); - up_read(&mm->mmap_sem); - - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code); - - /* Kernel mode? Handle exceptions or die */ - if (regs->tstate & TSTATE_PRIV) - goto handle_kernel_fault; -} diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c deleted file mode 100644 index 580b63da836..00000000000 --- a/arch/sparc64/mm/generic.c +++ /dev/null @@ -1,166 +0,0 @@ -/* $Id: generic.c,v 1.18 2001/12/21 04:56:15 davem Exp $ - * generic.c: Generic Sparc mm routines that are not dependent upon - * MMU type but are Sparc specific. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/swap.h> -#include <linux/pagemap.h> - -#include <asm/pgalloc.h> -#include <asm/pgtable.h> -#include <asm/page.h> -#include <asm/tlbflush.h> - -static inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space) -{ - pte_t pte; - pte_val(pte) = (((page) | pgprot_val(prot) | _PAGE_E) & - ~(unsigned long)_PAGE_CACHE); - pte_val(pte) |= (((unsigned long)space) << 32); - return pte; -} - -/* Remap IO memory, the same way as remap_pfn_range(), but use - * the obio memory space. - * - * They use a pgprot that sets PAGE_IO and does not check the - * mem_map table as this is independent of normal memory. - */ -static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, - unsigned long address, - unsigned long size, - unsigned long offset, pgprot_t prot, - int space) -{ - unsigned long end; - - /* clear hack bit that was used as a write_combine side-effect flag */ - offset &= ~0x1UL; - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - pte_t entry; - unsigned long curend = address + PAGE_SIZE; - - entry = mk_pte_io(offset, prot, space); - if (!(address & 0xffff)) { - if (!(address & 0x3fffff) && !(offset & 0x3ffffe) && end >= address + 0x400000) { - entry = mk_pte_io(offset, - __pgprot(pgprot_val (prot) | _PAGE_SZ4MB), - space); - curend = address + 0x400000; - offset += 0x400000; - } else if (!(address & 0x7ffff) && !(offset & 0x7fffe) && end >= address + 0x80000) { - entry = mk_pte_io(offset, - __pgprot(pgprot_val (prot) | _PAGE_SZ512K), - space); - curend = address + 0x80000; - offset += 0x80000; - } else if (!(offset & 0xfffe) && end >= address + 0x10000) { - entry = mk_pte_io(offset, - __pgprot(pgprot_val (prot) | _PAGE_SZ64K), - space); - curend = address + 0x10000; - offset += 0x10000; - } else - offset += PAGE_SIZE; - } else - offset += PAGE_SIZE; - - do { - BUG_ON(!pte_none(*pte)); - set_pte_at(mm, address, pte, entry); - address += PAGE_SIZE; - pte_val(entry) += PAGE_SIZE; - pte++; - } while (address < curend); - } while (address < end); -} - -static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long offset, pgprot_t prot, int space) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - offset -= address; - do { - pte_t * pte = pte_alloc_map(mm, pmd, address); - if (!pte) - return -ENOMEM; - io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); - pte_unmap(pte); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - return 0; -} - -static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size, - unsigned long offset, pgprot_t prot, int space) -{ - unsigned long end; - - address &= ~PUD_MASK; - end = address + size; - if (end > PUD_SIZE) - end = PUD_SIZE; - offset -= address; - do { - pmd_t *pmd = pmd_alloc(mm, pud, address); - if (!pud) - return -ENOMEM; - io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space); - address = (address + PUD_SIZE) & PUD_MASK; - pud++; - } while (address < end); - return 0; -} - -int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, - unsigned long pfn, unsigned long size, pgprot_t prot) -{ - int error = 0; - pgd_t * dir; - unsigned long beg = from; - unsigned long end = from + size; - struct mm_struct *mm = vma->vm_mm; - int space = GET_IOSPACE(pfn); - unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; - unsigned long phys_base; - - phys_base = offset | (((unsigned long) space) << 32UL); - - /* See comment in mm/memory.c remap_pfn_range */ - vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; - vma->vm_pgoff = phys_base >> PAGE_SHIFT; - - prot = __pgprot(pg_iobits); - offset -= from; - dir = pgd_offset(mm, from); - flush_cache_range(vma, beg, end); - - while (from < end) { - pud_t *pud = pud_alloc(mm, dir, from); - error = -ENOMEM; - if (!pud) - break; - error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space); - if (error) - break; - from = (from + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } - - flush_tlb_range(vma, beg, end); - return error; -} diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c deleted file mode 100644 index 625cbb336a2..00000000000 --- a/arch/sparc64/mm/hugetlbpage.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * SPARC64 Huge TLB page support. - * - * Copyright (C) 2002, 2003 David S. Miller (davem@redhat.com) - */ - -#include <linux/config.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/hugetlb.h> -#include <linux/pagemap.h> -#include <linux/smp_lock.h> -#include <linux/slab.h> -#include <linux/sysctl.h> - -#include <asm/mman.h> -#include <asm/pgalloc.h> -#include <asm/tlb.h> -#include <asm/tlbflush.h> -#include <asm/cacheflush.h> -#include <asm/mmu_context.h> - -pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte = NULL; - - pgd = pgd_offset(mm, addr); - if (pgd) { - pud = pud_offset(pgd, addr); - if (pud) { - pmd = pmd_alloc(mm, pud, addr); - if (pmd) - pte = pte_alloc_map(mm, pmd, addr); - } - } - return pte; -} - -pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte = NULL; - - pgd = pgd_offset(mm, addr); - if (pgd) { - pud = pud_offset(pgd, addr); - if (pud) { - pmd = pmd_offset(pud, addr); - if (pmd) - pte = pte_offset_map(pmd, addr); - } - } - return pte; -} - -#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0) - -void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t entry) -{ - int i; - - for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { - set_pte_at(mm, addr, ptep, entry); - ptep++; - addr += PAGE_SIZE; - pte_val(entry) += PAGE_SIZE; - } -} - -pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, - pte_t *ptep) -{ - pte_t entry; - int i; - - entry = *ptep; - - for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { - pte_clear(mm, addr, ptep); - addr += PAGE_SIZE; - ptep++; - } - - return entry; -} - -/* - * This function checks for proper alignment of input addr and len parameters. - */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) -{ - if (len & ~HPAGE_MASK) - return -EINVAL; - if (addr & ~HPAGE_MASK) - return -EINVAL; - return 0; -} - -struct page *follow_huge_addr(struct mm_struct *mm, - unsigned long address, int write) -{ - return ERR_PTR(-EINVAL); -} - -int pmd_huge(pmd_t pmd) -{ - return 0; -} - -struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, - pmd_t *pmd, int write) -{ - return NULL; -} - -static void context_reload(void *__data) -{ - struct mm_struct *mm = __data; - - if (mm == current->mm) - load_secondary_context(mm); -} - -void hugetlb_prefault_arch_hook(struct mm_struct *mm) -{ - /* On UltraSPARC-III+ and later, configure the second half of - * the Data-TLB for huge pages. - */ - if (tlb_type == cheetah_plus) { - unsigned long ctx; - - spin_lock(&ctx_alloc_lock); - ctx = mm->context.sparc64_ctx_val; - ctx &= ~CTX_PGSZ_MASK; - ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT; - ctx |= CTX_PGSZ_HUGE << CTX_PGSZ1_SHIFT; - - if (ctx != mm->context.sparc64_ctx_val) { - /* When changing the page size fields, we - * must perform a context flush so that no - * stale entries match. This flush must - * occur with the original context register - * settings. - */ - do_flush_tlb_mm(mm); - - /* Reload the context register of all processors - * also executing in this address space. - */ - mm->context.sparc64_ctx_val = ctx; - on_each_cpu(context_reload, mm, 0, 0); - } - spin_unlock(&ctx_alloc_lock); - } -} diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c deleted file mode 100644 index 1e44ee26cee..00000000000 --- a/arch/sparc64/mm/init.c +++ /dev/null @@ -1,1678 +0,0 @@ -/* $Id: init.c,v 1.209 2002/02/09 19:49:31 davem Exp $ - * arch/sparc64/mm/init.c - * - * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/bootmem.h> -#include <linux/mm.h> -#include <linux/hugetlb.h> -#include <linux/slab.h> -#include <linux/initrd.h> -#include <linux/swap.h> -#include <linux/pagemap.h> -#include <linux/fs.h> -#include <linux/seq_file.h> -#include <linux/kprobes.h> -#include <linux/cache.h> -#include <linux/sort.h> - -#include <asm/head.h> -#include <asm/system.h> -#include <asm/page.h> -#include <asm/pgalloc.h> -#include <asm/pgtable.h> -#include <asm/oplib.h> -#include <asm/iommu.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/mmu_context.h> -#include <asm/tlbflush.h> -#include <asm/dma.h> -#include <asm/starfire.h> -#include <asm/tlb.h> -#include <asm/spitfire.h> -#include <asm/sections.h> - -extern void device_scan(void); - -#define MAX_BANKS 32 - -static struct linux_prom64_registers pavail[MAX_BANKS] __initdata; -static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata; -static int pavail_ents __initdata; -static int pavail_rescan_ents __initdata; - -static int cmp_p64(const void *a, const void *b) -{ - const struct linux_prom64_registers *x = a, *y = b; - - if (x->phys_addr > y->phys_addr) - return 1; - if (x->phys_addr < y->phys_addr) - return -1; - return 0; -} - -static void __init read_obp_memory(const char *property, - struct linux_prom64_registers *regs, - int *num_ents) -{ - int node = prom_finddevice("/memory"); - int prop_size = prom_getproplen(node, property); - int ents, ret, i; - - ents = prop_size / sizeof(struct linux_prom64_registers); - if (ents > MAX_BANKS) { - prom_printf("The machine has more %s property entries than " - "this kernel can support (%d).\n", - property, MAX_BANKS); - prom_halt(); - } - - ret = prom_getproperty(node, property, (char *) regs, prop_size); - if (ret == -1) { - prom_printf("Couldn't get %s property from /memory.\n"); - prom_halt(); - } - - *num_ents = ents; - - /* Sanitize what we got from the firmware, by page aligning - * everything. - */ - for (i = 0; i < ents; i++) { - unsigned long base, size; - - base = regs[i].phys_addr; - size = regs[i].reg_size; - - size &= PAGE_MASK; - if (base & ~PAGE_MASK) { - unsigned long new_base = PAGE_ALIGN(base); - - size -= new_base - base; - if ((long) size < 0L) - size = 0UL; - base = new_base; - } - regs[i].phys_addr = base; - regs[i].reg_size = size; - } - sort(regs, ents, sizeof(struct linux_prom64_registers), - cmp_p64, NULL); -} - -unsigned long *sparc64_valid_addr_bitmap __read_mostly; - -/* Ugly, but necessary... -DaveM */ -unsigned long phys_base __read_mostly; -unsigned long kern_base __read_mostly; -unsigned long kern_size __read_mostly; -unsigned long pfn_base __read_mostly; - -/* get_new_mmu_context() uses "cache + 1". */ -DEFINE_SPINLOCK(ctx_alloc_lock); -unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; -#define CTX_BMAP_SLOTS (1UL << (CTX_NR_BITS - 6)) -unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; - -/* References to special section boundaries */ -extern char _start[], _end[]; - -/* Initial ramdisk setup */ -extern unsigned long sparc_ramdisk_image64; -extern unsigned int sparc_ramdisk_image; -extern unsigned int sparc_ramdisk_size; - -struct page *mem_map_zero __read_mostly; - -unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly; - -unsigned long sparc64_kern_pri_context __read_mostly; -unsigned long sparc64_kern_pri_nuc_bits __read_mostly; -unsigned long sparc64_kern_sec_context __read_mostly; - -int bigkernel = 0; - -/* XXX Tune this... */ -#define PGT_CACHE_LOW 25 -#define PGT_CACHE_HIGH 50 - -void check_pgt_cache(void) -{ - preempt_disable(); - if (pgtable_cache_size > PGT_CACHE_HIGH) { - do { - if (pgd_quicklist) - free_pgd_slow(get_pgd_fast()); - if (pte_quicklist[0]) - free_pte_slow(pte_alloc_one_fast(NULL, 0)); - if (pte_quicklist[1]) - free_pte_slow(pte_alloc_one_fast(NULL, 1 << (PAGE_SHIFT + 10))); - } while (pgtable_cache_size > PGT_CACHE_LOW); - } - preempt_enable(); -} - -#ifdef CONFIG_DEBUG_DCFLUSH -atomic_t dcpage_flushes = ATOMIC_INIT(0); -#ifdef CONFIG_SMP -atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0); -#endif -#endif - -__inline__ void flush_dcache_page_impl(struct page *page) -{ -#ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes); -#endif - -#ifdef DCACHE_ALIASING_POSSIBLE - __flush_dcache_page(page_address(page), - ((tlb_type == spitfire) && - page_mapping(page) != NULL)); -#else - if (page_mapping(page) != NULL && - tlb_type == spitfire) - __flush_icache_page(__pa(page_address(page))); -#endif -} - -#define PG_dcache_dirty PG_arch_1 -#define PG_dcache_cpu_shift 24 -#define PG_dcache_cpu_mask (256 - 1) - -#if NR_CPUS > 256 -#error D-cache dirty tracking and thread_info->cpu need fixing for > 256 cpus -#endif - -#define dcache_dirty_cpu(page) \ - (((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask) - -static __inline__ void set_dcache_dirty(struct page *page, int this_cpu) -{ - unsigned long mask = this_cpu; - unsigned long non_cpu_bits; - - non_cpu_bits = ~(PG_dcache_cpu_mask << PG_dcache_cpu_shift); - mask = (mask << PG_dcache_cpu_shift) | (1UL << PG_dcache_dirty); - - __asm__ __volatile__("1:\n\t" - "ldx [%2], %%g7\n\t" - "and %%g7, %1, %%g1\n\t" - "or %%g1, %0, %%g1\n\t" - "casx [%2], %%g7, %%g1\n\t" - "cmp %%g7, %%g1\n\t" - "membar #StoreLoad | #StoreStore\n\t" - "bne,pn %%xcc, 1b\n\t" - " nop" - : /* no outputs */ - : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags) - : "g1", "g7"); -} - -static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu) -{ - unsigned long mask = (1UL << PG_dcache_dirty); - - __asm__ __volatile__("! test_and_clear_dcache_dirty\n" - "1:\n\t" - "ldx [%2], %%g7\n\t" - "srlx %%g7, %4, %%g1\n\t" - "and %%g1, %3, %%g1\n\t" - "cmp %%g1, %0\n\t" - "bne,pn %%icc, 2f\n\t" - " andn %%g7, %1, %%g1\n\t" - "casx [%2], %%g7, %%g1\n\t" - "cmp %%g7, %%g1\n\t" - "membar #StoreLoad | #StoreStore\n\t" - "bne,pn %%xcc, 1b\n\t" - " nop\n" - "2:" - : /* no outputs */ - : "r" (cpu), "r" (mask), "r" (&page->flags), - "i" (PG_dcache_cpu_mask), - "i" (PG_dcache_cpu_shift) - : "g1", "g7"); -} - -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) -{ - struct page *page; - unsigned long pfn; - unsigned long pg_flags; - - pfn = pte_pfn(pte); - if (pfn_valid(pfn) && - (page = pfn_to_page(pfn), page_mapping(page)) && - ((pg_flags = page->flags) & (1UL << PG_dcache_dirty))) { - int cpu = ((pg_flags >> PG_dcache_cpu_shift) & - PG_dcache_cpu_mask); - int this_cpu = get_cpu(); - - /* This is just to optimize away some function calls - * in the SMP case. - */ - if (cpu == this_cpu) - flush_dcache_page_impl(page); - else - smp_flush_dcache_page_impl(page, cpu); - - clear_dcache_dirty_cpu(page, cpu); - - put_cpu(); - } -} - -void flush_dcache_page(struct page *page) -{ - struct address_space *mapping; - int this_cpu; - - /* Do not bother with the expensive D-cache flush if it - * is merely the zero page. The 'bigcore' testcase in GDB - * causes this case to run millions of times. - */ - if (page == ZERO_PAGE(0)) - return; - - this_cpu = get_cpu(); - - mapping = page_mapping(page); - if (mapping && !mapping_mapped(mapping)) { - int dirty = test_bit(PG_dcache_dirty, &page->flags); - if (dirty) { - int dirty_cpu = dcache_dirty_cpu(page); - - if (dirty_cpu == this_cpu) - goto out; - smp_flush_dcache_page_impl(page, dirty_cpu); - } - set_dcache_dirty(page, this_cpu); - } else { - /* We could delay the flush for the !page_mapping - * case too. But that case is for exec env/arg - * pages and those are %99 certainly going to get - * faulted into the tlb (and thus flushed) anyways. - */ - flush_dcache_page_impl(page); - } - -out: - put_cpu(); -} - -void __kprobes flush_icache_range(unsigned long start, unsigned long end) -{ - /* Cheetah has coherent I-cache. */ - if (tlb_type == spitfire) { - unsigned long kaddr; - - for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE) - __flush_icache_page(__get_phys(kaddr)); - } -} - -unsigned long page_to_pfn(struct page *page) -{ - return (unsigned long) ((page - mem_map) + pfn_base); -} - -struct page *pfn_to_page(unsigned long pfn) -{ - return (mem_map + (pfn - pfn_base)); -} - -void show_mem(void) -{ - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6ldkB\n", - nr_swap_pages << (PAGE_SHIFT-10)); - printk("%ld pages of RAM\n", num_physpages); - printk("%d free pages\n", nr_free_pages()); - printk("%d pages in page table cache\n",pgtable_cache_size); -} - -void mmu_info(struct seq_file *m) -{ - if (tlb_type == cheetah) - seq_printf(m, "MMU Type\t: Cheetah\n"); - else if (tlb_type == cheetah_plus) - seq_printf(m, "MMU Type\t: Cheetah+\n"); - else if (tlb_type == spitfire) - seq_printf(m, "MMU Type\t: Spitfire\n"); - else - seq_printf(m, "MMU Type\t: ???\n"); - -#ifdef CONFIG_DEBUG_DCFLUSH - seq_printf(m, "DCPageFlushes\t: %d\n", - atomic_read(&dcpage_flushes)); -#ifdef CONFIG_SMP - seq_printf(m, "DCPageFlushesXC\t: %d\n", - atomic_read(&dcpage_flushes_xcall)); -#endif /* CONFIG_SMP */ -#endif /* CONFIG_DEBUG_DCFLUSH */ -} - -struct linux_prom_translation { - unsigned long virt; - unsigned long size; - unsigned long data; -}; - -/* Exported for kernel TLB miss handling in ktlb.S */ -struct linux_prom_translation prom_trans[512] __read_mostly; -unsigned int prom_trans_ents __read_mostly; -unsigned int swapper_pgd_zero __read_mostly; - -extern unsigned long prom_boot_page; -extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); -extern int prom_get_mmu_ihandle(void); -extern void register_prom_callbacks(void); - -/* Exported for SMP bootup purposes. */ -unsigned long kern_locked_tte_data; - -/* - * Translate PROM's mapping we capture at boot time into physical address. - * The second parameter is only set from prom_callback() invocations. - */ -unsigned long prom_virt_to_phys(unsigned long promva, int *error) -{ - int i; - - for (i = 0; i < prom_trans_ents; i++) { - struct linux_prom_translation *p = &prom_trans[i]; - - if (promva >= p->virt && - promva < (p->virt + p->size)) { - unsigned long base = p->data & _PAGE_PADDR; - - if (error) - *error = 0; - return base + (promva & (8192 - 1)); - } - } - if (error) - *error = 1; - return 0UL; -} - -/* The obp translations are saved based on 8k pagesize, since obp can - * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS -> - * HI_OBP_ADDRESS range are handled in ktlb.S and do not use the vpte - * scheme (also, see rant in inherit_locked_prom_mappings()). - */ -static inline int in_obp_range(unsigned long vaddr) -{ - return (vaddr >= LOW_OBP_ADDRESS && - vaddr < HI_OBP_ADDRESS); -} - -static int cmp_ptrans(const void *a, const void *b) -{ - const struct linux_prom_translation *x = a, *y = b; - - if (x->virt > y->virt) - return 1; - if (x->virt < y->virt) - return -1; - return 0; -} - -/* Read OBP translations property into 'prom_trans[]'. */ -static void __init read_obp_translations(void) -{ - int n, node, ents, first, last, i; - - node = prom_finddevice("/virtual-memory"); - n = prom_getproplen(node, "translations"); - if (unlikely(n == 0 || n == -1)) { - prom_printf("prom_mappings: Couldn't get size.\n"); - prom_halt(); - } - if (unlikely(n > sizeof(prom_trans))) { - prom_printf("prom_mappings: Size %Zd is too big.\n", n); - prom_halt(); - } - - if ((n = prom_getproperty(node, "translations", - (char *)&prom_trans[0], - sizeof(prom_trans))) == -1) { - prom_printf("prom_mappings: Couldn't get property.\n"); - prom_halt(); - } - - n = n / sizeof(struct linux_prom_translation); - - ents = n; - - sort(prom_trans, ents, sizeof(struct linux_prom_translation), - cmp_ptrans, NULL); - - /* Now kick out all the non-OBP entries. */ - for (i = 0; i < ents; i++) { - if (in_obp_range(prom_trans[i].virt)) - break; - } - first = i; - for (; i < ents; i++) { - if (!in_obp_range(prom_trans[i].virt)) - break; - } - last = i; - - for (i = 0; i < (last - first); i++) { - struct linux_prom_translation *src = &prom_trans[i + first]; - struct linux_prom_translation *dest = &prom_trans[i]; - - *dest = *src; - } - for (; i < ents; i++) { - struct linux_prom_translation *dest = &prom_trans[i]; - dest->virt = dest->size = dest->data = 0x0UL; - } - - prom_trans_ents = last - first; - - if (tlb_type == spitfire) { - /* Clear diag TTE bits. */ - for (i = 0; i < prom_trans_ents; i++) - prom_trans[i].data &= ~0x0003fe0000000000UL; - } -} - -static void __init remap_kernel(void) -{ - unsigned long phys_page, tte_vaddr, tte_data; - int tlb_ent = sparc64_highest_locked_tlbent(); - - tte_vaddr = (unsigned long) KERNBASE; - phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL; - tte_data = (phys_page | (_PAGE_VALID | _PAGE_SZ4MB | - _PAGE_CP | _PAGE_CV | _PAGE_P | - _PAGE_L | _PAGE_W)); - - kern_locked_tte_data = tte_data; - - /* Now lock us into the TLBs via OBP. */ - prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); - prom_itlb_load(tlb_ent, tte_data, tte_vaddr); - if (bigkernel) { - tlb_ent -= 1; - prom_dtlb_load(tlb_ent, - tte_data + 0x400000, - tte_vaddr + 0x400000); - prom_itlb_load(tlb_ent, - tte_data + 0x400000, - tte_vaddr + 0x400000); - } - sparc64_highest_unlocked_tlb_ent = tlb_ent - 1; - if (tlb_type == cheetah_plus) { - sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 | - CTX_CHEETAH_PLUS_NUC); - sparc64_kern_pri_nuc_bits = CTX_CHEETAH_PLUS_NUC; - sparc64_kern_sec_context = CTX_CHEETAH_PLUS_CTX0; - } -} - - -static void __init inherit_prom_mappings(void) -{ - read_obp_translations(); - - /* Now fixup OBP's idea about where we really are mapped. */ - prom_printf("Remapping the kernel... "); - remap_kernel(); - prom_printf("done.\n"); - - prom_printf("Registering callbacks... "); - register_prom_callbacks(); - prom_printf("done.\n"); -} - -/* The OBP specifications for sun4u mark 0xfffffffc00000000 and - * upwards as reserved for use by the firmware (I wonder if this - * will be the same on Cheetah...). We use this virtual address - * range for the VPTE table mappings of the nucleus so we need - * to zap them when we enter the PROM. -DaveM - */ -static void __flush_nucleus_vptes(void) -{ - unsigned long prom_reserved_base = 0xfffffffc00000000UL; - int i; - - /* Only DTLB must be checked for VPTE entries. */ - if (tlb_type == spitfire) { - for (i = 0; i < 63; i++) { - unsigned long tag; - - /* Spitfire Errata #32 workaround */ - /* NOTE: Always runs on spitfire, so no cheetah+ - * page size encodings. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - tag = spitfire_get_dtlb_tag(i); - if (((tag & ~(PAGE_MASK)) == 0) && - ((tag & (PAGE_MASK)) >= prom_reserved_base)) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); - spitfire_put_dtlb_data(i, 0x0UL); - } - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - for (i = 0; i < 512; i++) { - unsigned long tag = cheetah_get_dtlb_tag(i, 2); - - if ((tag & ~PAGE_MASK) == 0 && - (tag & PAGE_MASK) >= prom_reserved_base) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); - cheetah_put_dtlb_data(i, 0x0UL, 2); - } - - if (tlb_type != cheetah_plus) - continue; - - tag = cheetah_get_dtlb_tag(i, 3); - - if ((tag & ~PAGE_MASK) == 0 && - (tag & PAGE_MASK) >= prom_reserved_base) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); - cheetah_put_dtlb_data(i, 0x0UL, 3); - } - } - } else { - /* Implement me :-) */ - BUG(); - } -} - -static int prom_ditlb_set; -struct prom_tlb_entry { - int tlb_ent; - unsigned long tlb_tag; - unsigned long tlb_data; -}; -struct prom_tlb_entry prom_itlb[16], prom_dtlb[16]; - -void prom_world(int enter) -{ - unsigned long pstate; - int i; - - if (!enter) - set_fs((mm_segment_t) { get_thread_current_ds() }); - - if (!prom_ditlb_set) - return; - - /* Make sure the following runs atomically. */ - __asm__ __volatile__("flushw\n\t" - "rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - if (enter) { - /* Kick out nucleus VPTEs. */ - __flush_nucleus_vptes(); - - /* Install PROM world. */ - for (i = 0; i < 16; i++) { - if (prom_dtlb[i].tlb_ent != -1) { - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), - "i" (ASI_DMMU)); - if (tlb_type == spitfire) - spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, - prom_dtlb[i].tlb_data); - else if (tlb_type == cheetah || tlb_type == cheetah_plus) - cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, - prom_dtlb[i].tlb_data); - } - if (prom_itlb[i].tlb_ent != -1) { - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : : "r" (prom_itlb[i].tlb_tag), - "r" (TLB_TAG_ACCESS), - "i" (ASI_IMMU)); - if (tlb_type == spitfire) - spitfire_put_itlb_data(prom_itlb[i].tlb_ent, - prom_itlb[i].tlb_data); - else if (tlb_type == cheetah || tlb_type == cheetah_plus) - cheetah_put_litlb_data(prom_itlb[i].tlb_ent, - prom_itlb[i].tlb_data); - } - } - } else { - for (i = 0; i < 16; i++) { - if (prom_dtlb[i].tlb_ent != -1) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); - if (tlb_type == spitfire) - spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, 0x0UL); - else - cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, 0x0UL); - } - if (prom_itlb[i].tlb_ent != -1) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : : "r" (TLB_TAG_ACCESS), - "i" (ASI_IMMU)); - if (tlb_type == spitfire) - spitfire_put_itlb_data(prom_itlb[i].tlb_ent, 0x0UL); - else - cheetah_put_litlb_data(prom_itlb[i].tlb_ent, 0x0UL); - } - } - } - __asm__ __volatile__("wrpr %0, 0, %%pstate" - : : "r" (pstate)); -} - -void inherit_locked_prom_mappings(int save_p) -{ - int i; - int dtlb_seen = 0; - int itlb_seen = 0; - - /* Fucking losing PROM has more mappings in the TLB, but - * it (conveniently) fails to mention any of these in the - * translations property. The only ones that matter are - * the locked PROM tlb entries, so we impose the following - * irrecovable rule on the PROM, it is allowed 8 locked - * entries in the ITLB and 8 in the DTLB. - * - * Supposedly the upper 16GB of the address space is - * reserved for OBP, BUT I WISH THIS WAS DOCUMENTED - * SOMEWHERE!!!!!!!!!!!!!!!!! Furthermore the entire interface - * used between the client program and the firmware on sun5 - * systems to coordinate mmu mappings is also COMPLETELY - * UNDOCUMENTED!!!!!! Thanks S(t)un! - */ - if (save_p) { - for (i = 0; i < 16; i++) { - prom_itlb[i].tlb_ent = -1; - prom_dtlb[i].tlb_ent = -1; - } - } - if (tlb_type == spitfire) { - int high = sparc64_highest_unlocked_tlb_ent; - for (i = 0; i <= high; i++) { - unsigned long data; - - /* Spitfire Errata #32 workaround */ - /* NOTE: Always runs on spitfire, so no cheetah+ - * page size encodings. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - data = spitfire_get_dtlb_data(i); - if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { - unsigned long tag; - - /* Spitfire Errata #32 workaround */ - /* NOTE: Always runs on spitfire, so no - * cheetah+ page size encodings. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - tag = spitfire_get_dtlb_tag(i); - if (save_p) { - prom_dtlb[dtlb_seen].tlb_ent = i; - prom_dtlb[dtlb_seen].tlb_tag = tag; - prom_dtlb[dtlb_seen].tlb_data = data; - } - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); - spitfire_put_dtlb_data(i, 0x0UL); - - dtlb_seen++; - if (dtlb_seen > 15) - break; - } - } - - for (i = 0; i < high; i++) { - unsigned long data; - - /* Spitfire Errata #32 workaround */ - /* NOTE: Always runs on spitfire, so no - * cheetah+ page size encodings. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - data = spitfire_get_itlb_data(i); - if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { - unsigned long tag; - - /* Spitfire Errata #32 workaround */ - /* NOTE: Always runs on spitfire, so no - * cheetah+ page size encodings. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - tag = spitfire_get_itlb_tag(i); - if (save_p) { - prom_itlb[itlb_seen].tlb_ent = i; - prom_itlb[itlb_seen].tlb_tag = tag; - prom_itlb[itlb_seen].tlb_data = data; - } - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); - spitfire_put_itlb_data(i, 0x0UL); - - itlb_seen++; - if (itlb_seen > 15) - break; - } - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - int high = sparc64_highest_unlocked_tlb_ent; - - for (i = 0; i <= high; i++) { - unsigned long data; - - data = cheetah_get_ldtlb_data(i); - if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { - unsigned long tag; - - tag = cheetah_get_ldtlb_tag(i); - if (save_p) { - prom_dtlb[dtlb_seen].tlb_ent = i; - prom_dtlb[dtlb_seen].tlb_tag = tag; - prom_dtlb[dtlb_seen].tlb_data = data; - } - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); - cheetah_put_ldtlb_data(i, 0x0UL); - - dtlb_seen++; - if (dtlb_seen > 15) - break; - } - } - - for (i = 0; i < high; i++) { - unsigned long data; - - data = cheetah_get_litlb_data(i); - if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { - unsigned long tag; - - tag = cheetah_get_litlb_tag(i); - if (save_p) { - prom_itlb[itlb_seen].tlb_ent = i; - prom_itlb[itlb_seen].tlb_tag = tag; - prom_itlb[itlb_seen].tlb_data = data; - } - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); - cheetah_put_litlb_data(i, 0x0UL); - - itlb_seen++; - if (itlb_seen > 15) - break; - } - } - } else { - /* Implement me :-) */ - BUG(); - } - if (save_p) - prom_ditlb_set = 1; -} - -/* Give PROM back his world, done during reboots... */ -void prom_reload_locked(void) -{ - int i; - - for (i = 0; i < 16; i++) { - if (prom_dtlb[i].tlb_ent != -1) { - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), - "i" (ASI_DMMU)); - if (tlb_type == spitfire) - spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, - prom_dtlb[i].tlb_data); - else if (tlb_type == cheetah || tlb_type == cheetah_plus) - cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, - prom_dtlb[i].tlb_data); - } - - if (prom_itlb[i].tlb_ent != -1) { - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : : "r" (prom_itlb[i].tlb_tag), - "r" (TLB_TAG_ACCESS), - "i" (ASI_IMMU)); - if (tlb_type == spitfire) - spitfire_put_itlb_data(prom_itlb[i].tlb_ent, - prom_itlb[i].tlb_data); - else - cheetah_put_litlb_data(prom_itlb[i].tlb_ent, - prom_itlb[i].tlb_data); - } - } -} - -#ifdef DCACHE_ALIASING_POSSIBLE -void __flush_dcache_range(unsigned long start, unsigned long end) -{ - unsigned long va; - - if (tlb_type == spitfire) { - int n = 0; - - for (va = start; va < end; va += 32) { - spitfire_put_dcache_tag(va & 0x3fe0, 0x0); - if (++n >= 512) - break; - } - } else { - start = __pa(start); - end = __pa(end); - for (va = start; va < end; va += 32) - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (va), - "i" (ASI_DCACHE_INVALIDATE)); - } -} -#endif /* DCACHE_ALIASING_POSSIBLE */ - -/* If not locked, zap it. */ -void __flush_tlb_all(void) -{ - unsigned long pstate; - int i; - - __asm__ __volatile__("flushw\n\t" - "rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - if (tlb_type == spitfire) { - for (i = 0; i < 64; i++) { - /* Spitfire Errata #32 workaround */ - /* NOTE: Always runs on spitfire, so no - * cheetah+ page size encodings. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - if (!(spitfire_get_dtlb_data(i) & _PAGE_L)) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); - spitfire_put_dtlb_data(i, 0x0UL); - } - - /* Spitfire Errata #32 workaround */ - /* NOTE: Always runs on spitfire, so no - * cheetah+ page size encodings. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - if (!(spitfire_get_itlb_data(i) & _PAGE_L)) { - __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); - spitfire_put_itlb_data(i, 0x0UL); - } - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - cheetah_flush_dtlb_all(); - cheetah_flush_itlb_all(); - } - __asm__ __volatile__("wrpr %0, 0, %%pstate" - : : "r" (pstate)); -} - -/* Caller does TLB context flushing on local CPU if necessary. - * The caller also ensures that CTX_VALID(mm->context) is false. - * - * We must be careful about boundary cases so that we never - * let the user have CTX 0 (nucleus) or we ever use a CTX - * version of zero (and thus NO_CONTEXT would not be caught - * by version mis-match tests in mmu_context.h). - */ -void get_new_mmu_context(struct mm_struct *mm) -{ - unsigned long ctx, new_ctx; - unsigned long orig_pgsz_bits; - - - spin_lock(&ctx_alloc_lock); - orig_pgsz_bits = (mm->context.sparc64_ctx_val & CTX_PGSZ_MASK); - ctx = (tlb_context_cache + 1) & CTX_NR_MASK; - new_ctx = find_next_zero_bit(mmu_context_bmap, 1 << CTX_NR_BITS, ctx); - if (new_ctx >= (1 << CTX_NR_BITS)) { - new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1); - if (new_ctx >= ctx) { - int i; - new_ctx = (tlb_context_cache & CTX_VERSION_MASK) + - CTX_FIRST_VERSION; - if (new_ctx == 1) - new_ctx = CTX_FIRST_VERSION; - - /* Don't call memset, for 16 entries that's just - * plain silly... - */ - mmu_context_bmap[0] = 3; - mmu_context_bmap[1] = 0; - mmu_context_bmap[2] = 0; - mmu_context_bmap[3] = 0; - for (i = 4; i < CTX_BMAP_SLOTS; i += 4) { - mmu_context_bmap[i + 0] = 0; - mmu_context_bmap[i + 1] = 0; - mmu_context_bmap[i + 2] = 0; - mmu_context_bmap[i + 3] = 0; - } - goto out; - } - } - mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63)); - new_ctx |= (tlb_context_cache & CTX_VERSION_MASK); -out: - tlb_context_cache = new_ctx; - mm->context.sparc64_ctx_val = new_ctx | orig_pgsz_bits; - spin_unlock(&ctx_alloc_lock); -} - -#ifndef CONFIG_SMP -struct pgtable_cache_struct pgt_quicklists; -#endif - -/* OK, we have to color these pages. The page tables are accessed - * by non-Dcache enabled mapping in the VPTE area by the dtlb_backend.S - * code, as well as by PAGE_OFFSET range direct-mapped addresses by - * other parts of the kernel. By coloring, we make sure that the tlbmiss - * fast handlers do not get data from old/garbage dcache lines that - * correspond to an old/stale virtual address (user/kernel) that - * previously mapped the pagetable page while accessing vpte range - * addresses. The idea is that if the vpte color and PAGE_OFFSET range - * color is the same, then when the kernel initializes the pagetable - * using the later address range, accesses with the first address - * range will see the newly initialized data rather than the garbage. - */ -#ifdef DCACHE_ALIASING_POSSIBLE -#define DC_ALIAS_SHIFT 1 -#else -#define DC_ALIAS_SHIFT 0 -#endif -pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) -{ - struct page *page; - unsigned long color; - - { - pte_t *ptep = pte_alloc_one_fast(mm, address); - - if (ptep) - return ptep; - } - - color = VPTE_COLOR(address); - page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, DC_ALIAS_SHIFT); - if (page) { - unsigned long *to_free; - unsigned long paddr; - pte_t *pte; - -#ifdef DCACHE_ALIASING_POSSIBLE - set_page_count(page, 1); - ClearPageCompound(page); - - set_page_count((page + 1), 1); - ClearPageCompound(page + 1); -#endif - paddr = (unsigned long) page_address(page); - memset((char *)paddr, 0, (PAGE_SIZE << DC_ALIAS_SHIFT)); - - if (!color) { - pte = (pte_t *) paddr; - to_free = (unsigned long *) (paddr + PAGE_SIZE); - } else { - pte = (pte_t *) (paddr + PAGE_SIZE); - to_free = (unsigned long *) paddr; - } - -#ifdef DCACHE_ALIASING_POSSIBLE - /* Now free the other one up, adjust cache size. */ - preempt_disable(); - *to_free = (unsigned long) pte_quicklist[color ^ 0x1]; - pte_quicklist[color ^ 0x1] = to_free; - pgtable_cache_size++; - preempt_enable(); -#endif - - return pte; - } - return NULL; -} - -void sparc_ultra_dump_itlb(void) -{ - int slot; - - if (tlb_type == spitfire) { - printk ("Contents of itlb: "); - for (slot = 0; slot < 14; slot++) printk (" "); - printk ("%2x:%016lx,%016lx\n", - 0, - spitfire_get_itlb_tag(0), spitfire_get_itlb_data(0)); - for (slot = 1; slot < 64; slot+=3) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - spitfire_get_itlb_tag(slot), spitfire_get_itlb_data(slot), - slot+1, - spitfire_get_itlb_tag(slot+1), spitfire_get_itlb_data(slot+1), - slot+2, - spitfire_get_itlb_tag(slot+2), spitfire_get_itlb_data(slot+2)); - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - printk ("Contents of itlb0:\n"); - for (slot = 0; slot < 16; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_litlb_tag(slot), cheetah_get_litlb_data(slot), - slot+1, - cheetah_get_litlb_tag(slot+1), cheetah_get_litlb_data(slot+1)); - } - printk ("Contents of itlb2:\n"); - for (slot = 0; slot < 128; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_itlb_tag(slot), cheetah_get_itlb_data(slot), - slot+1, - cheetah_get_itlb_tag(slot+1), cheetah_get_itlb_data(slot+1)); - } - } -} - -void sparc_ultra_dump_dtlb(void) -{ - int slot; - - if (tlb_type == spitfire) { - printk ("Contents of dtlb: "); - for (slot = 0; slot < 14; slot++) printk (" "); - printk ("%2x:%016lx,%016lx\n", 0, - spitfire_get_dtlb_tag(0), spitfire_get_dtlb_data(0)); - for (slot = 1; slot < 64; slot+=3) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - spitfire_get_dtlb_tag(slot), spitfire_get_dtlb_data(slot), - slot+1, - spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1), - slot+2, - spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2)); - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - printk ("Contents of dtlb0:\n"); - for (slot = 0; slot < 16; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_ldtlb_tag(slot), cheetah_get_ldtlb_data(slot), - slot+1, - cheetah_get_ldtlb_tag(slot+1), cheetah_get_ldtlb_data(slot+1)); - } - printk ("Contents of dtlb2:\n"); - for (slot = 0; slot < 512; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_dtlb_tag(slot, 2), cheetah_get_dtlb_data(slot, 2), - slot+1, - cheetah_get_dtlb_tag(slot+1, 2), cheetah_get_dtlb_data(slot+1, 2)); - } - if (tlb_type == cheetah_plus) { - printk ("Contents of dtlb3:\n"); - for (slot = 0; slot < 512; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_dtlb_tag(slot, 3), cheetah_get_dtlb_data(slot, 3), - slot+1, - cheetah_get_dtlb_tag(slot+1, 3), cheetah_get_dtlb_data(slot+1, 3)); - } - } - } -} - -extern unsigned long cmdline_memory_size; - -unsigned long __init bootmem_init(unsigned long *pages_avail) -{ - unsigned long bootmap_size, start_pfn, end_pfn; - unsigned long end_of_phys_memory = 0UL; - unsigned long bootmap_pfn, bytes_avail, size; - int i; - -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("bootmem_init: Scan pavail, "); -#endif - - bytes_avail = 0UL; - for (i = 0; i < pavail_ents; i++) { - end_of_phys_memory = pavail[i].phys_addr + - pavail[i].reg_size; - bytes_avail += pavail[i].reg_size; - if (cmdline_memory_size) { - if (bytes_avail > cmdline_memory_size) { - unsigned long slack = bytes_avail - cmdline_memory_size; - - bytes_avail -= slack; - end_of_phys_memory -= slack; - - pavail[i].reg_size -= slack; - if ((long)pavail[i].reg_size <= 0L) { - pavail[i].phys_addr = 0xdeadbeefUL; - pavail[i].reg_size = 0UL; - pavail_ents = i; - } else { - pavail[i+1].reg_size = 0Ul; - pavail[i+1].phys_addr = 0xdeadbeefUL; - pavail_ents = i + 1; - } - break; - } - } - } - - *pages_avail = bytes_avail >> PAGE_SHIFT; - - /* Start with page aligned address of last symbol in kernel - * image. The kernel is hard mapped below PAGE_OFFSET in a - * 4MB locked TLB translation. - */ - start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT; - - bootmap_pfn = start_pfn; - - end_pfn = end_of_phys_memory >> PAGE_SHIFT; - -#ifdef CONFIG_BLK_DEV_INITRD - /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ - if (sparc_ramdisk_image || sparc_ramdisk_image64) { - unsigned long ramdisk_image = sparc_ramdisk_image ? - sparc_ramdisk_image : sparc_ramdisk_image64; - if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE) - ramdisk_image -= KERNBASE; - initrd_start = ramdisk_image + phys_base; - initrd_end = initrd_start + sparc_ramdisk_size; - if (initrd_end > end_of_phys_memory) { - printk(KERN_CRIT "initrd extends beyond end of memory " - "(0x%016lx > 0x%016lx)\ndisabling initrd\n", - initrd_end, end_of_phys_memory); - initrd_start = 0; - } - if (initrd_start) { - if (initrd_start >= (start_pfn << PAGE_SHIFT) && - initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE) - bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT; - } - } -#endif - /* Initialize the boot-time allocator. */ - max_pfn = max_low_pfn = end_pfn; - min_low_pfn = pfn_base; - -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n", - min_low_pfn, bootmap_pfn, max_low_pfn); -#endif - bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn); - - /* Now register the available physical memory with the - * allocator. - */ - for (i = 0; i < pavail_ents; i++) { -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("free_bootmem(pavail:%d): base[%lx] size[%lx]\n", - i, pavail[i].phys_addr, pavail[i].reg_size); -#endif - free_bootmem(pavail[i].phys_addr, pavail[i].reg_size); - } - -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) { - size = initrd_end - initrd_start; - - /* Resert the initrd image area. */ -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n", - initrd_start, initrd_end); -#endif - reserve_bootmem(initrd_start, size); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; - - initrd_start += PAGE_OFFSET; - initrd_end += PAGE_OFFSET; - } -#endif - /* Reserve the kernel text/data/bss. */ -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size); -#endif - reserve_bootmem(kern_base, kern_size); - *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT; - - /* Reserve the bootmem map. We do not account for it - * in pages_avail because we will release that memory - * in free_all_bootmem. - */ - size = bootmap_size; -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(bootmap): base[%lx] size[%lx]\n", - (bootmap_pfn << PAGE_SHIFT), size); -#endif - reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; - - return end_pfn; -} - -#ifdef CONFIG_DEBUG_PAGEALLOC -static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, pgprot_t prot) -{ - unsigned long vstart = PAGE_OFFSET + pstart; - unsigned long vend = PAGE_OFFSET + pend; - unsigned long alloc_bytes = 0UL; - - if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) { - prom_printf("kernel_map: Unaligned physmem[%lx:%lx]\n", - vstart, vend); - prom_halt(); - } - - while (vstart < vend) { - unsigned long this_end, paddr = __pa(vstart); - pgd_t *pgd = pgd_offset_k(vstart); - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - - pud = pud_offset(pgd, vstart); - if (pud_none(*pud)) { - pmd_t *new; - - new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); - alloc_bytes += PAGE_SIZE; - pud_populate(&init_mm, pud, new); - } - - pmd = pmd_offset(pud, vstart); - if (!pmd_present(*pmd)) { - pte_t *new; - - new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); - alloc_bytes += PAGE_SIZE; - pmd_populate_kernel(&init_mm, pmd, new); - } - - pte = pte_offset_kernel(pmd, vstart); - this_end = (vstart + PMD_SIZE) & PMD_MASK; - if (this_end > vend) - this_end = vend; - - while (vstart < this_end) { - pte_val(*pte) = (paddr | pgprot_val(prot)); - - vstart += PAGE_SIZE; - paddr += PAGE_SIZE; - pte++; - } - } - - return alloc_bytes; -} - -static struct linux_prom64_registers pall[MAX_BANKS] __initdata; -static int pall_ents __initdata; - -extern unsigned int kvmap_linear_patch[1]; - -static void __init kernel_physical_mapping_init(void) -{ - unsigned long i, mem_alloced = 0UL; - - read_obp_memory("reg", &pall[0], &pall_ents); - - for (i = 0; i < pall_ents; i++) { - unsigned long phys_start, phys_end; - - phys_start = pall[i].phys_addr; - phys_end = phys_start + pall[i].reg_size; - mem_alloced += kernel_map_range(phys_start, phys_end, - PAGE_KERNEL); - } - - printk("Allocated %ld bytes for kernel page tables.\n", - mem_alloced); - - kvmap_linear_patch[0] = 0x01000000; /* nop */ - flushi(&kvmap_linear_patch[0]); - - __flush_tlb_all(); -} - -void kernel_map_pages(struct page *page, int numpages, int enable) -{ - unsigned long phys_start = page_to_pfn(page) << PAGE_SHIFT; - unsigned long phys_end = phys_start + (numpages * PAGE_SIZE); - - kernel_map_range(phys_start, phys_end, - (enable ? PAGE_KERNEL : __pgprot(0))); - - /* we should perform an IPI and flush all tlbs, - * but that can deadlock->flush only current cpu. - */ - __flush_tlb_kernel_range(PAGE_OFFSET + phys_start, - PAGE_OFFSET + phys_end); -} -#endif - -unsigned long __init find_ecache_flush_span(unsigned long size) -{ - int i; - - for (i = 0; i < pavail_ents; i++) { - if (pavail[i].reg_size >= size) - return pavail[i].phys_addr; - } - - return ~0UL; -} - -/* paging_init() sets up the page tables */ - -extern void cheetah_ecache_flush_init(void); - -static unsigned long last_valid_pfn; -pgd_t swapper_pg_dir[2048]; - -void __init paging_init(void) -{ - unsigned long end_pfn, pages_avail, shift; - unsigned long real_end, i; - - /* Find available physical memory... */ - read_obp_memory("available", &pavail[0], &pavail_ents); - - phys_base = 0xffffffffffffffffUL; - for (i = 0; i < pavail_ents; i++) - phys_base = min(phys_base, pavail[i].phys_addr); - - pfn_base = phys_base >> PAGE_SHIFT; - - kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; - kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; - - set_bit(0, mmu_context_bmap); - - shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE); - - real_end = (unsigned long)_end; - if ((real_end > ((unsigned long)KERNBASE + 0x400000))) - bigkernel = 1; - if ((real_end > ((unsigned long)KERNBASE + 0x800000))) { - prom_printf("paging_init: Kernel > 8MB, too large.\n"); - prom_halt(); - } - - /* Set kernel pgd to upper alias so physical page computations - * work. - */ - init_mm.pgd += ((shift) / (sizeof(pgd_t))); - - memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir)); - - /* Now can init the kernel/bad page tables. */ - pud_set(pud_offset(&swapper_pg_dir[0], 0), - swapper_low_pmd_dir + (shift / sizeof(pgd_t))); - - swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); - - inherit_prom_mappings(); - - /* Ok, we can use our TLB miss and window trap handlers safely. - * We need to do a quick peek here to see if we are on StarFire - * or not, so setup_tba can setup the IRQ globals correctly (it - * needs to get the hard smp processor id correctly). - */ - { - extern void setup_tba(int); - setup_tba(this_is_starfire); - } - - inherit_locked_prom_mappings(1); - - __flush_tlb_all(); - - /* Setup bootmem... */ - pages_avail = 0; - last_valid_pfn = end_pfn = bootmem_init(&pages_avail); - -#ifdef CONFIG_DEBUG_PAGEALLOC - kernel_physical_mapping_init(); -#endif - - { - unsigned long zones_size[MAX_NR_ZONES]; - unsigned long zholes_size[MAX_NR_ZONES]; - unsigned long npages; - int znum; - - for (znum = 0; znum < MAX_NR_ZONES; znum++) - zones_size[znum] = zholes_size[znum] = 0; - - npages = end_pfn - pfn_base; - zones_size[ZONE_DMA] = npages; - zholes_size[ZONE_DMA] = npages - pages_avail; - - free_area_init_node(0, &contig_page_data, zones_size, - phys_base >> PAGE_SHIFT, zholes_size); - } - - device_scan(); -} - -static void __init taint_real_pages(void) -{ - int i; - - read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents); - - /* Find changes discovered in the physmem available rescan and - * reserve the lost portions in the bootmem maps. - */ - for (i = 0; i < pavail_ents; i++) { - unsigned long old_start, old_end; - - old_start = pavail[i].phys_addr; - old_end = old_start + - pavail[i].reg_size; - while (old_start < old_end) { - int n; - - for (n = 0; pavail_rescan_ents; n++) { - unsigned long new_start, new_end; - - new_start = pavail_rescan[n].phys_addr; - new_end = new_start + - pavail_rescan[n].reg_size; - - if (new_start <= old_start && - new_end >= (old_start + PAGE_SIZE)) { - set_bit(old_start >> 22, - sparc64_valid_addr_bitmap); - goto do_next_page; - } - } - reserve_bootmem(old_start, PAGE_SIZE); - - do_next_page: - old_start += PAGE_SIZE; - } - } -} - -void __init mem_init(void) -{ - unsigned long codepages, datapages, initpages; - unsigned long addr, last; - int i; - - i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); - i += 1; - sparc64_valid_addr_bitmap = (unsigned long *) alloc_bootmem(i << 3); - if (sparc64_valid_addr_bitmap == NULL) { - prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); - prom_halt(); - } - memset(sparc64_valid_addr_bitmap, 0, i << 3); - - addr = PAGE_OFFSET + kern_base; - last = PAGE_ALIGN(kern_size) + addr; - while (addr < last) { - set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap); - addr += PAGE_SIZE; - } - - taint_real_pages(); - - max_mapnr = last_valid_pfn - pfn_base; - high_memory = __va(last_valid_pfn << PAGE_SHIFT); - -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("mem_init: Calling free_all_bootmem().\n"); -#endif - totalram_pages = num_physpages = free_all_bootmem() - 1; - - /* - * Set up the zero page, mark it reserved, so that page count - * is not manipulated when freeing the page from user ptes. - */ - mem_map_zero = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0); - if (mem_map_zero == NULL) { - prom_printf("paging_init: Cannot alloc zero page.\n"); - prom_halt(); - } - SetPageReserved(mem_map_zero); - - codepages = (((unsigned long) _etext) - ((unsigned long) _start)); - codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; - datapages = (((unsigned long) _edata) - ((unsigned long) _etext)); - datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT; - initpages = (((unsigned long) __init_end) - ((unsigned long) __init_begin)); - initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT; - - printk("Memory: %uk available (%ldk kernel code, %ldk data, %ldk init) [%016lx,%016lx]\n", - nr_free_pages() << (PAGE_SHIFT-10), - codepages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10), - initpages << (PAGE_SHIFT-10), - PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); - - if (tlb_type == cheetah || tlb_type == cheetah_plus) - cheetah_ecache_flush_init(); -} - -void free_initmem(void) -{ - unsigned long addr, initend; - - /* - * The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes. - */ - addr = PAGE_ALIGN((unsigned long)(__init_begin)); - initend = (unsigned long)(__init_end) & PAGE_MASK; - for (; addr < initend; addr += PAGE_SIZE) { - unsigned long page; - struct page *p; - - page = (addr + - ((unsigned long) __va(kern_base)) - - ((unsigned long) KERNBASE)); - memset((void *)addr, 0xcc, PAGE_SIZE); - p = virt_to_page(page); - - ClearPageReserved(p); - set_page_count(p, 1); - __free_page(p); - num_physpages++; - totalram_pages++; - } -} - -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - if (start < end) - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - struct page *p = virt_to_page(start); - - ClearPageReserved(p); - set_page_count(p, 1); - __free_page(p); - num_physpages++; - totalram_pages++; - } -} -#endif diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c deleted file mode 100644 index 8b104be4662..00000000000 --- a/arch/sparc64/mm/tlb.c +++ /dev/null @@ -1,150 +0,0 @@ -/* arch/sparc64/mm/tlb.c - * - * Copyright (C) 2004 David S. Miller <davem@redhat.com> - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/percpu.h> -#include <linux/mm.h> -#include <linux/swap.h> - -#include <asm/pgtable.h> -#include <asm/pgalloc.h> -#include <asm/tlbflush.h> -#include <asm/cacheflush.h> -#include <asm/mmu_context.h> -#include <asm/tlb.h> - -/* Heavily inspired by the ppc64 code. */ - -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; - -void flush_tlb_pending(void) -{ - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); - - if (mp->tlb_nr) { - if (CTX_VALID(mp->mm->context)) { -#ifdef CONFIG_SMP - smp_flush_tlb_pending(mp->mm, mp->tlb_nr, - &mp->vaddrs[0]); -#else - __flush_tlb_pending(CTX_HWBITS(mp->mm->context), - mp->tlb_nr, &mp->vaddrs[0]); -#endif - } - mp->tlb_nr = 0; - } -} - -void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig) -{ - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); - unsigned long nr; - - vaddr &= PAGE_MASK; - if (pte_exec(orig)) - vaddr |= 0x1UL; - - if (pte_dirty(orig)) { - unsigned long paddr, pfn = pte_pfn(orig); - struct address_space *mapping; - struct page *page; - - if (!pfn_valid(pfn)) - goto no_cache_flush; - - page = pfn_to_page(pfn); - if (PageReserved(page)) - goto no_cache_flush; - - /* A real file page? */ - mapping = page_mapping(page); - if (!mapping) - goto no_cache_flush; - - paddr = (unsigned long) page_address(page); - if ((paddr ^ vaddr) & (1 << 13)) - flush_dcache_page_all(mm, page); - } - -no_cache_flush: - - if (mp->fullmm) - return; - - nr = mp->tlb_nr; - - if (unlikely(nr != 0 && mm != mp->mm)) { - flush_tlb_pending(); - nr = 0; - } - - if (nr == 0) - mp->mm = mm; - - mp->vaddrs[nr] = vaddr; - mp->tlb_nr = ++nr; - if (nr >= TLB_BATCH_NR) - flush_tlb_pending(); -} - -void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) -{ - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); - unsigned long nr = mp->tlb_nr; - long s = start, e = end, vpte_base; - - if (mp->fullmm) - return; - - /* If start is greater than end, that is a real problem. */ - BUG_ON(start > end); - - /* However, straddling the VA space hole is quite normal. */ - s &= PMD_MASK; - e = (e + PMD_SIZE - 1) & PMD_MASK; - - vpte_base = (tlb_type == spitfire ? - VPTE_BASE_SPITFIRE : - VPTE_BASE_CHEETAH); - - if (unlikely(nr != 0 && mm != mp->mm)) { - flush_tlb_pending(); - nr = 0; - } - - if (nr == 0) - mp->mm = mm; - - start = vpte_base + (s >> (PAGE_SHIFT - 3)); - end = vpte_base + (e >> (PAGE_SHIFT - 3)); - - /* If the request straddles the VA space hole, we - * need to swap start and end. The reason this - * occurs is that "vpte_base" is the center of - * the linear page table mapping area. Thus, - * high addresses with the sign bit set map to - * addresses below vpte_base and non-sign bit - * addresses map to addresses above vpte_base. - */ - if (end < start) { - unsigned long tmp = start; - - start = end; - end = tmp; - } - - while (start < end) { - mp->vaddrs[nr] = start; - mp->tlb_nr = ++nr; - if (nr >= TLB_BATCH_NR) { - flush_tlb_pending(); - nr = 0; - } - start += PAGE_SIZE; - } - if (nr) - flush_tlb_pending(); -} diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S deleted file mode 100644 index e4c9151fa11..00000000000 --- a/arch/sparc64/mm/ultra.S +++ /dev/null @@ -1,530 +0,0 @@ -/* $Id: ultra.S,v 1.72 2002/02/09 19:49:31 davem Exp $ - * ultra.S: Don't expand these all over the place... - * - * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com) - */ - -#include <linux/config.h> -#include <asm/asi.h> -#include <asm/pgtable.h> -#include <asm/page.h> -#include <asm/spitfire.h> -#include <asm/mmu_context.h> -#include <asm/mmu.h> -#include <asm/pil.h> -#include <asm/head.h> -#include <asm/thread_info.h> -#include <asm/cacheflush.h> - - /* Basically, most of the Spitfire vs. Cheetah madness - * has to do with the fact that Cheetah does not support - * IMMU flushes out of the secondary context. Someone needs - * to throw a south lake birthday party for the folks - * in Microelectronics who refused to fix this shit. - */ - - /* This file is meant to be read efficiently by the CPU, not humans. - * Staraj sie tego nikomu nie pierdolnac... - */ - .text - .align 32 - .globl __flush_tlb_mm -__flush_tlb_mm: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */ - ldxa [%o1] ASI_DMMU, %g2 - cmp %g2, %o0 - bne,pn %icc, __spitfire_flush_tlb_mm_slow - mov 0x50, %g3 - stxa %g0, [%g3] ASI_DMMU_DEMAP - stxa %g0, [%g3] ASI_IMMU_DEMAP - retl - flush %g6 - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - - .align 32 - .globl __flush_tlb_pending -__flush_tlb_pending: - /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */ - rdpr %pstate, %g7 - sllx %o1, 3, %o1 - andn %g7, PSTATE_IE, %g2 - wrpr %g2, %pstate - mov SECONDARY_CONTEXT, %o4 - ldxa [%o4] ASI_DMMU, %g2 - stxa %o0, [%o4] ASI_DMMU -1: sub %o1, (1 << 3), %o1 - ldx [%o2 + %o1], %o3 - andcc %o3, 1, %g0 - andn %o3, 1, %o3 - be,pn %icc, 2f - or %o3, 0x10, %o3 - stxa %g0, [%o3] ASI_IMMU_DEMAP -2: stxa %g0, [%o3] ASI_DMMU_DEMAP - membar #Sync - brnz,pt %o1, 1b - nop - stxa %g2, [%o4] ASI_DMMU - flush %g6 - retl - wrpr %g7, 0x0, %pstate - nop - nop - nop - nop - - .align 32 - .globl __flush_tlb_kernel_range -__flush_tlb_kernel_range: /* %o0=start, %o1=end */ - cmp %o0, %o1 - be,pn %xcc, 2f - sethi %hi(PAGE_SIZE), %o4 - sub %o1, %o0, %o3 - sub %o3, %o4, %o3 - or %o0, 0x20, %o0 ! Nucleus -1: stxa %g0, [%o0 + %o3] ASI_DMMU_DEMAP - stxa %g0, [%o0 + %o3] ASI_IMMU_DEMAP - membar #Sync - brnz,pt %o3, 1b - sub %o3, %o4, %o3 -2: retl - flush %g6 - -__spitfire_flush_tlb_mm_slow: - rdpr %pstate, %g1 - wrpr %g1, PSTATE_IE, %pstate - stxa %o0, [%o1] ASI_DMMU - stxa %g0, [%g3] ASI_DMMU_DEMAP - stxa %g0, [%g3] ASI_IMMU_DEMAP - flush %g6 - stxa %g2, [%o1] ASI_DMMU - flush %g6 - retl - wrpr %g1, 0, %pstate - -/* - * The following code flushes one page_size worth. - */ -#if (PAGE_SHIFT == 13) -#define ITAG_MASK 0xfe -#elif (PAGE_SHIFT == 16) -#define ITAG_MASK 0x7fe -#else -#error unsupported PAGE_SIZE -#endif - .section .kprobes.text, "ax" - .align 32 - .globl __flush_icache_page -__flush_icache_page: /* %o0 = phys_page */ - membar #StoreStore - srlx %o0, PAGE_SHIFT, %o0 - sethi %uhi(PAGE_OFFSET), %g1 - sllx %o0, PAGE_SHIFT, %o0 - sethi %hi(PAGE_SIZE), %g2 - sllx %g1, 32, %g1 - add %o0, %g1, %o0 -1: subcc %g2, 32, %g2 - bne,pt %icc, 1b - flush %o0 + %g2 - retl - nop - -#ifdef DCACHE_ALIASING_POSSIBLE - -#if (PAGE_SHIFT != 13) -#error only page shift of 13 is supported by dcache flush -#endif - -#define DTAG_MASK 0x3 - - /* This routine is Spitfire specific so the hardcoded - * D-cache size and line-size are OK. - */ - .align 64 - .globl __flush_dcache_page -__flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */ - sethi %uhi(PAGE_OFFSET), %g1 - sllx %g1, 32, %g1 - sub %o0, %g1, %o0 ! physical address - srlx %o0, 11, %o0 ! make D-cache TAG - sethi %hi(1 << 14), %o2 ! D-cache size - sub %o2, (1 << 5), %o2 ! D-cache line size -1: ldxa [%o2] ASI_DCACHE_TAG, %o3 ! load D-cache TAG - andcc %o3, DTAG_MASK, %g0 ! Valid? - be,pn %xcc, 2f ! Nope, branch - andn %o3, DTAG_MASK, %o3 ! Clear valid bits - cmp %o3, %o0 ! TAG match? - bne,pt %xcc, 2f ! Nope, branch - nop - stxa %g0, [%o2] ASI_DCACHE_TAG ! Invalidate TAG - membar #Sync -2: brnz,pt %o2, 1b - sub %o2, (1 << 5), %o2 ! D-cache line size - - /* The I-cache does not snoop local stores so we - * better flush that too when necessary. - */ - brnz,pt %o1, __flush_icache_page - sllx %o0, 11, %o0 - retl - nop - -#endif /* DCACHE_ALIASING_POSSIBLE */ - - .previous - - /* Cheetah specific versions, patched at boot time. */ -__cheetah_flush_tlb_mm: /* 18 insns */ - rdpr %pstate, %g7 - andn %g7, PSTATE_IE, %g2 - wrpr %g2, 0x0, %pstate - wrpr %g0, 1, %tl - mov PRIMARY_CONTEXT, %o2 - mov 0x40, %g3 - ldxa [%o2] ASI_DMMU, %g2 - srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o1 - sllx %o1, CTX_PGSZ1_NUC_SHIFT, %o1 - or %o0, %o1, %o0 /* Preserve nucleus page size fields */ - stxa %o0, [%o2] ASI_DMMU - stxa %g0, [%g3] ASI_DMMU_DEMAP - stxa %g0, [%g3] ASI_IMMU_DEMAP - stxa %g2, [%o2] ASI_DMMU - flush %g6 - wrpr %g0, 0, %tl - retl - wrpr %g7, 0x0, %pstate - -__cheetah_flush_tlb_pending: /* 26 insns */ - /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */ - rdpr %pstate, %g7 - sllx %o1, 3, %o1 - andn %g7, PSTATE_IE, %g2 - wrpr %g2, 0x0, %pstate - wrpr %g0, 1, %tl - mov PRIMARY_CONTEXT, %o4 - ldxa [%o4] ASI_DMMU, %g2 - srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o3 - sllx %o3, CTX_PGSZ1_NUC_SHIFT, %o3 - or %o0, %o3, %o0 /* Preserve nucleus page size fields */ - stxa %o0, [%o4] ASI_DMMU -1: sub %o1, (1 << 3), %o1 - ldx [%o2 + %o1], %o3 - andcc %o3, 1, %g0 - be,pn %icc, 2f - andn %o3, 1, %o3 - stxa %g0, [%o3] ASI_IMMU_DEMAP -2: stxa %g0, [%o3] ASI_DMMU_DEMAP - membar #Sync - brnz,pt %o1, 1b - nop - stxa %g2, [%o4] ASI_DMMU - flush %g6 - wrpr %g0, 0, %tl - retl - wrpr %g7, 0x0, %pstate - -#ifdef DCACHE_ALIASING_POSSIBLE -__cheetah_flush_dcache_page: /* 11 insns */ - sethi %uhi(PAGE_OFFSET), %g1 - sllx %g1, 32, %g1 - sub %o0, %g1, %o0 - sethi %hi(PAGE_SIZE), %o4 -1: subcc %o4, (1 << 5), %o4 - stxa %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE - membar #Sync - bne,pt %icc, 1b - nop - retl /* I-cache flush never needed on Cheetah, see callers. */ - nop -#endif /* DCACHE_ALIASING_POSSIBLE */ - -cheetah_patch_one: -1: lduw [%o1], %g1 - stw %g1, [%o0] - flush %o0 - subcc %o2, 1, %o2 - add %o1, 4, %o1 - bne,pt %icc, 1b - add %o0, 4, %o0 - retl - nop - - .globl cheetah_patch_cachetlbops -cheetah_patch_cachetlbops: - save %sp, -128, %sp - - sethi %hi(__flush_tlb_mm), %o0 - or %o0, %lo(__flush_tlb_mm), %o0 - sethi %hi(__cheetah_flush_tlb_mm), %o1 - or %o1, %lo(__cheetah_flush_tlb_mm), %o1 - call cheetah_patch_one - mov 18, %o2 - - sethi %hi(__flush_tlb_pending), %o0 - or %o0, %lo(__flush_tlb_pending), %o0 - sethi %hi(__cheetah_flush_tlb_pending), %o1 - or %o1, %lo(__cheetah_flush_tlb_pending), %o1 - call cheetah_patch_one - mov 26, %o2 - -#ifdef DCACHE_ALIASING_POSSIBLE - sethi %hi(__flush_dcache_page), %o0 - or %o0, %lo(__flush_dcache_page), %o0 - sethi %hi(__cheetah_flush_dcache_page), %o1 - or %o1, %lo(__cheetah_flush_dcache_page), %o1 - call cheetah_patch_one - mov 11, %o2 -#endif /* DCACHE_ALIASING_POSSIBLE */ - - ret - restore - -#ifdef CONFIG_SMP - /* These are all called by the slaves of a cross call, at - * trap level 1, with interrupts fully disabled. - * - * Register usage: - * %g5 mm->context (all tlb flushes) - * %g1 address arg 1 (tlb page and range flushes) - * %g7 address arg 2 (tlb range flush only) - * - * %g6 ivector table, don't touch - * %g2 scratch 1 - * %g3 scratch 2 - * %g4 scratch 3 - * - * TODO: Make xcall TLB range flushes use the tricks above... -DaveM - */ - .align 32 - .globl xcall_flush_tlb_mm -xcall_flush_tlb_mm: - mov PRIMARY_CONTEXT, %g2 - ldxa [%g2] ASI_DMMU, %g3 - srlx %g3, CTX_PGSZ1_NUC_SHIFT, %g4 - sllx %g4, CTX_PGSZ1_NUC_SHIFT, %g4 - or %g5, %g4, %g5 /* Preserve nucleus page size fields */ - stxa %g5, [%g2] ASI_DMMU - mov 0x40, %g4 - stxa %g0, [%g4] ASI_DMMU_DEMAP - stxa %g0, [%g4] ASI_IMMU_DEMAP - stxa %g3, [%g2] ASI_DMMU - retry - - .globl xcall_flush_tlb_pending -xcall_flush_tlb_pending: - /* %g5=context, %g1=nr, %g7=vaddrs[] */ - sllx %g1, 3, %g1 - mov PRIMARY_CONTEXT, %g4 - ldxa [%g4] ASI_DMMU, %g2 - srlx %g2, CTX_PGSZ1_NUC_SHIFT, %g4 - sllx %g4, CTX_PGSZ1_NUC_SHIFT, %g4 - or %g5, %g4, %g5 - mov PRIMARY_CONTEXT, %g4 - stxa %g5, [%g4] ASI_DMMU -1: sub %g1, (1 << 3), %g1 - ldx [%g7 + %g1], %g5 - andcc %g5, 0x1, %g0 - be,pn %icc, 2f - - andn %g5, 0x1, %g5 - stxa %g0, [%g5] ASI_IMMU_DEMAP -2: stxa %g0, [%g5] ASI_DMMU_DEMAP - membar #Sync - brnz,pt %g1, 1b - nop - stxa %g2, [%g4] ASI_DMMU - retry - - .globl xcall_flush_tlb_kernel_range -xcall_flush_tlb_kernel_range: - sethi %hi(PAGE_SIZE - 1), %g2 - or %g2, %lo(PAGE_SIZE - 1), %g2 - andn %g1, %g2, %g1 - andn %g7, %g2, %g7 - sub %g7, %g1, %g3 - add %g2, 1, %g2 - sub %g3, %g2, %g3 - or %g1, 0x20, %g1 ! Nucleus -1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP - stxa %g0, [%g1 + %g3] ASI_IMMU_DEMAP - membar #Sync - brnz,pt %g3, 1b - sub %g3, %g2, %g3 - retry - nop - nop - - /* This runs in a very controlled environment, so we do - * not need to worry about BH races etc. - */ - .globl xcall_sync_tick -xcall_sync_tick: - rdpr %pstate, %g2 - wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate - rdpr %pil, %g2 - wrpr %g0, 15, %pil - sethi %hi(109f), %g7 - b,pt %xcc, etrap_irq -109: or %g7, %lo(109b), %g7 - call smp_synchronize_tick_client - nop - clr %l6 - b rtrap_xcall - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 - - /* NOTE: This is SPECIAL!! We do etrap/rtrap however - * we choose to deal with the "BH's run with - * %pil==15" problem (described in asm/pil.h) - * by just invoking rtrap directly past where - * BH's are checked for. - * - * We do it like this because we do not want %pil==15 - * lockups to prevent regs being reported. - */ - .globl xcall_report_regs -xcall_report_regs: - rdpr %pstate, %g2 - wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate - rdpr %pil, %g2 - wrpr %g0, 15, %pil - sethi %hi(109f), %g7 - b,pt %xcc, etrap_irq -109: or %g7, %lo(109b), %g7 - call __show_regs - add %sp, PTREGS_OFF, %o0 - clr %l6 - /* Has to be a non-v9 branch due to the large distance. */ - b rtrap_xcall - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 - -#ifdef DCACHE_ALIASING_POSSIBLE - .align 32 - .globl xcall_flush_dcache_page_cheetah -xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */ - sethi %hi(PAGE_SIZE), %g3 -1: subcc %g3, (1 << 5), %g3 - stxa %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE - membar #Sync - bne,pt %icc, 1b - nop - retry - nop -#endif /* DCACHE_ALIASING_POSSIBLE */ - - .globl xcall_flush_dcache_page_spitfire -xcall_flush_dcache_page_spitfire: /* %g1 == physical page address - %g7 == kernel page virtual address - %g5 == (page->mapping != NULL) */ -#ifdef DCACHE_ALIASING_POSSIBLE - srlx %g1, (13 - 2), %g1 ! Form tag comparitor - sethi %hi(L1DCACHE_SIZE), %g3 ! D$ size == 16K - sub %g3, (1 << 5), %g3 ! D$ linesize == 32 -1: ldxa [%g3] ASI_DCACHE_TAG, %g2 - andcc %g2, 0x3, %g0 - be,pn %xcc, 2f - andn %g2, 0x3, %g2 - cmp %g2, %g1 - - bne,pt %xcc, 2f - nop - stxa %g0, [%g3] ASI_DCACHE_TAG - membar #Sync -2: cmp %g3, 0 - bne,pt %xcc, 1b - sub %g3, (1 << 5), %g3 - - brz,pn %g5, 2f -#endif /* DCACHE_ALIASING_POSSIBLE */ - sethi %hi(PAGE_SIZE), %g3 - -1: flush %g7 - subcc %g3, (1 << 5), %g3 - bne,pt %icc, 1b - add %g7, (1 << 5), %g7 - -2: retry - nop - nop - - .data - -errata32_hwbug: - .xword 0 - - .text - - /* These two are not performance critical... */ - .globl xcall_flush_tlb_all_spitfire -xcall_flush_tlb_all_spitfire: - /* Spitfire Errata #32 workaround. */ - sethi %hi(errata32_hwbug), %g4 - stx %g0, [%g4 + %lo(errata32_hwbug)] - - clr %g2 - clr %g3 -1: ldxa [%g3] ASI_DTLB_DATA_ACCESS, %g4 - and %g4, _PAGE_L, %g5 - brnz,pn %g5, 2f - mov TLB_TAG_ACCESS, %g7 - - stxa %g0, [%g7] ASI_DMMU - membar #Sync - stxa %g0, [%g3] ASI_DTLB_DATA_ACCESS - membar #Sync - - /* Spitfire Errata #32 workaround. */ - sethi %hi(errata32_hwbug), %g4 - stx %g0, [%g4 + %lo(errata32_hwbug)] - -2: ldxa [%g3] ASI_ITLB_DATA_ACCESS, %g4 - and %g4, _PAGE_L, %g5 - brnz,pn %g5, 2f - mov TLB_TAG_ACCESS, %g7 - - stxa %g0, [%g7] ASI_IMMU - membar #Sync - stxa %g0, [%g3] ASI_ITLB_DATA_ACCESS - membar #Sync - - /* Spitfire Errata #32 workaround. */ - sethi %hi(errata32_hwbug), %g4 - stx %g0, [%g4 + %lo(errata32_hwbug)] - -2: add %g2, 1, %g2 - cmp %g2, SPITFIRE_HIGHEST_LOCKED_TLBENT - ble,pt %icc, 1b - sll %g2, 3, %g3 - flush %g6 - retry - - .globl xcall_flush_tlb_all_cheetah -xcall_flush_tlb_all_cheetah: - mov 0x80, %g2 - stxa %g0, [%g2] ASI_DMMU_DEMAP - stxa %g0, [%g2] ASI_IMMU_DEMAP - retry - - /* These just get rescheduled to PIL vectors. */ - .globl xcall_call_function -xcall_call_function: - wr %g0, (1 << PIL_SMP_CALL_FUNC), %set_softint - retry - - .globl xcall_receive_signal -xcall_receive_signal: - wr %g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint - retry - - .globl xcall_capture -xcall_capture: - wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint - retry - -#endif /* CONFIG_SMP */ diff --git a/arch/sparc64/oprofile/Kconfig b/arch/sparc64/oprofile/Kconfig deleted file mode 100644 index d8a84088471..00000000000 --- a/arch/sparc64/oprofile/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -config PROFILING - bool "Profiling support (EXPERIMENTAL)" - help - Say Y here to enable the extended profiling support mechanisms used - by profilers such as OProfile. - - -config OPROFILE - tristate "OProfile system profiling (EXPERIMENTAL)" - depends on PROFILING - help - OProfile is a profiling system capable of profiling the - whole system, include the kernel, kernel modules, libraries, - and applications. - - If unsure, say N. - diff --git a/arch/sparc64/oprofile/Makefile b/arch/sparc64/oprofile/Makefile deleted file mode 100644 index e9feca1ca28..00000000000 --- a/arch/sparc64/oprofile/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -obj-$(CONFIG_OPROFILE) += oprofile.o - -DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ - oprof.o cpu_buffer.o buffer_sync.o \ - event_buffer.o oprofile_files.o \ - oprofilefs.o oprofile_stats.o \ - timer_int.o ) - -oprofile-y := $(DRIVER_OBJS) init.o diff --git a/arch/sparc64/oprofile/init.c b/arch/sparc64/oprofile/init.c deleted file mode 100644 index 9ab815b95b5..00000000000 --- a/arch/sparc64/oprofile/init.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file init.c - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon <levon@movementarian.org> - */ - -#include <linux/kernel.h> -#include <linux/oprofile.h> -#include <linux/errno.h> -#include <linux/init.h> - -int __init oprofile_arch_init(struct oprofile_operations * ops) -{ - return -ENODEV; -} - - -void oprofile_arch_exit(void) -{ -} diff --git a/arch/sparc64/prom/Makefile b/arch/sparc64/prom/Makefile deleted file mode 100644 index 3d33ed27bc2..00000000000 --- a/arch/sparc64/prom/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $Id: Makefile,v 1.7 2000/12/14 22:57:25 davem Exp $ -# Makefile for the Sun Boot PROM interface library under -# Linux. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -lib-y := bootstr.o devops.o init.o misc.o \ - tree.o console.o printf.o p1275.o cif.o diff --git a/arch/sparc64/prom/bootstr.c b/arch/sparc64/prom/bootstr.c deleted file mode 100644 index a7278614e99..00000000000 --- a/arch/sparc64/prom/bootstr.c +++ /dev/null @@ -1,40 +0,0 @@ -/* $Id: bootstr.c,v 1.6 1999/08/31 06:55:01 davem Exp $ - * bootstr.c: Boot string/argument acquisition from the PROM. - * - * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright(C) 1996,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/string.h> -#include <linux/init.h> -#include <asm/oplib.h> - -/* WARNING: The boot loader knows that these next three variables come one right - * after another in the .data section. Do not move this stuff into - * the .bss section or it will break things. - */ - -#define BARG_LEN 256 -struct { - int bootstr_len; - int bootstr_valid; - char bootstr_buf[BARG_LEN]; -} bootstr_info = { - .bootstr_len = BARG_LEN, -#ifdef CONFIG_CMDLINE - .bootstr_valid = 1, - .bootstr_buf = CONFIG_CMDLINE, -#endif -}; - -char * __init -prom_getbootargs(void) -{ - /* This check saves us from a panic when bootfd patches args. */ - if (bootstr_info.bootstr_valid) - return bootstr_info.bootstr_buf; - prom_getstring(prom_chosen_node, "bootargs", - bootstr_info.bootstr_buf, BARG_LEN); - bootstr_info.bootstr_valid = 1; - return bootstr_info.bootstr_buf; -} diff --git a/arch/sparc64/prom/cif.S b/arch/sparc64/prom/cif.S deleted file mode 100644 index 29d0ae74aed..00000000000 --- a/arch/sparc64/prom/cif.S +++ /dev/null @@ -1,225 +0,0 @@ -/* cif.S: PROM entry/exit assembler trampolines. - * - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 2005 David S. Miller <davem@davemloft.net> - */ - -#include <asm/pstate.h> - - .text - .globl prom_cif_interface -prom_cif_interface: - sethi %hi(p1275buf), %o0 - or %o0, %lo(p1275buf), %o0 - ldx [%o0 + 0x010], %o1 ! prom_cif_stack - save %o1, -0x190, %sp - ldx [%i0 + 0x008], %l2 ! prom_cif_handler - rdpr %pstate, %l4 - wrpr %g0, 0x15, %pstate ! save alternate globals - stx %g1, [%sp + 2047 + 0x0b0] - stx %g2, [%sp + 2047 + 0x0b8] - stx %g3, [%sp + 2047 + 0x0c0] - stx %g4, [%sp + 2047 + 0x0c8] - stx %g5, [%sp + 2047 + 0x0d0] - stx %g6, [%sp + 2047 + 0x0d8] - stx %g7, [%sp + 2047 + 0x0e0] - wrpr %g0, 0x814, %pstate ! save interrupt globals - stx %g1, [%sp + 2047 + 0x0e8] - stx %g2, [%sp + 2047 + 0x0f0] - stx %g3, [%sp + 2047 + 0x0f8] - stx %g4, [%sp + 2047 + 0x100] - stx %g5, [%sp + 2047 + 0x108] - stx %g6, [%sp + 2047 + 0x110] - stx %g7, [%sp + 2047 + 0x118] - wrpr %g0, 0x14, %pstate ! save normal globals - stx %g1, [%sp + 2047 + 0x120] - stx %g2, [%sp + 2047 + 0x128] - stx %g3, [%sp + 2047 + 0x130] - stx %g4, [%sp + 2047 + 0x138] - stx %g5, [%sp + 2047 + 0x140] - stx %g6, [%sp + 2047 + 0x148] - stx %g7, [%sp + 2047 + 0x150] - wrpr %g0, 0x414, %pstate ! save mmu globals - stx %g1, [%sp + 2047 + 0x158] - stx %g2, [%sp + 2047 + 0x160] - stx %g3, [%sp + 2047 + 0x168] - stx %g4, [%sp + 2047 + 0x170] - stx %g5, [%sp + 2047 + 0x178] - stx %g6, [%sp + 2047 + 0x180] - stx %g7, [%sp + 2047 + 0x188] - mov %g1, %l0 ! also save to locals, so we can handle - mov %g2, %l1 ! tlb faults later on, when accessing - mov %g3, %l3 ! the stack. - mov %g7, %l5 - wrpr %l4, PSTATE_IE, %pstate ! turn off interrupts - call %l2 - add %i0, 0x018, %o0 ! prom_args - wrpr %g0, 0x414, %pstate ! restore mmu globals - mov %l0, %g1 - mov %l1, %g2 - mov %l3, %g3 - mov %l5, %g7 - wrpr %g0, 0x14, %pstate ! restore normal globals - ldx [%sp + 2047 + 0x120], %g1 - ldx [%sp + 2047 + 0x128], %g2 - ldx [%sp + 2047 + 0x130], %g3 - ldx [%sp + 2047 + 0x138], %g4 - ldx [%sp + 2047 + 0x140], %g5 - ldx [%sp + 2047 + 0x148], %g6 - ldx [%sp + 2047 + 0x150], %g7 - wrpr %g0, 0x814, %pstate ! restore interrupt globals - ldx [%sp + 2047 + 0x0e8], %g1 - ldx [%sp + 2047 + 0x0f0], %g2 - ldx [%sp + 2047 + 0x0f8], %g3 - ldx [%sp + 2047 + 0x100], %g4 - ldx [%sp + 2047 + 0x108], %g5 - ldx [%sp + 2047 + 0x110], %g6 - ldx [%sp + 2047 + 0x118], %g7 - wrpr %g0, 0x15, %pstate ! restore alternate globals - ldx [%sp + 2047 + 0x0b0], %g1 - ldx [%sp + 2047 + 0x0b8], %g2 - ldx [%sp + 2047 + 0x0c0], %g3 - ldx [%sp + 2047 + 0x0c8], %g4 - ldx [%sp + 2047 + 0x0d0], %g5 - ldx [%sp + 2047 + 0x0d8], %g6 - ldx [%sp + 2047 + 0x0e0], %g7 - wrpr %l4, 0, %pstate ! restore original pstate - ret - restore - - .globl prom_cif_callback -prom_cif_callback: - sethi %hi(p1275buf), %o1 - or %o1, %lo(p1275buf), %o1 - save %sp, -0x270, %sp - rdpr %pstate, %l4 - wrpr %g0, 0x15, %pstate ! save PROM alternate globals - stx %g1, [%sp + 2047 + 0x0b0] - stx %g2, [%sp + 2047 + 0x0b8] - stx %g3, [%sp + 2047 + 0x0c0] - stx %g4, [%sp + 2047 + 0x0c8] - stx %g5, [%sp + 2047 + 0x0d0] - stx %g6, [%sp + 2047 + 0x0d8] - stx %g7, [%sp + 2047 + 0x0e0] - ! restore Linux alternate globals - ldx [%sp + 2047 + 0x190], %g1 - ldx [%sp + 2047 + 0x198], %g2 - ldx [%sp + 2047 + 0x1a0], %g3 - ldx [%sp + 2047 + 0x1a8], %g4 - ldx [%sp + 2047 + 0x1b0], %g5 - ldx [%sp + 2047 + 0x1b8], %g6 - ldx [%sp + 2047 + 0x1c0], %g7 - wrpr %g0, 0x814, %pstate ! save PROM interrupt globals - stx %g1, [%sp + 2047 + 0x0e8] - stx %g2, [%sp + 2047 + 0x0f0] - stx %g3, [%sp + 2047 + 0x0f8] - stx %g4, [%sp + 2047 + 0x100] - stx %g5, [%sp + 2047 + 0x108] - stx %g6, [%sp + 2047 + 0x110] - stx %g7, [%sp + 2047 + 0x118] - ! restore Linux interrupt globals - ldx [%sp + 2047 + 0x1c8], %g1 - ldx [%sp + 2047 + 0x1d0], %g2 - ldx [%sp + 2047 + 0x1d8], %g3 - ldx [%sp + 2047 + 0x1e0], %g4 - ldx [%sp + 2047 + 0x1e8], %g5 - ldx [%sp + 2047 + 0x1f0], %g6 - ldx [%sp + 2047 + 0x1f8], %g7 - wrpr %g0, 0x14, %pstate ! save PROM normal globals - stx %g1, [%sp + 2047 + 0x120] - stx %g2, [%sp + 2047 + 0x128] - stx %g3, [%sp + 2047 + 0x130] - stx %g4, [%sp + 2047 + 0x138] - stx %g5, [%sp + 2047 + 0x140] - stx %g6, [%sp + 2047 + 0x148] - stx %g7, [%sp + 2047 + 0x150] - ! restore Linux normal globals - ldx [%sp + 2047 + 0x200], %g1 - ldx [%sp + 2047 + 0x208], %g2 - ldx [%sp + 2047 + 0x210], %g3 - ldx [%sp + 2047 + 0x218], %g4 - ldx [%sp + 2047 + 0x220], %g5 - ldx [%sp + 2047 + 0x228], %g6 - ldx [%sp + 2047 + 0x230], %g7 - wrpr %g0, 0x414, %pstate ! save PROM mmu globals - stx %g1, [%sp + 2047 + 0x158] - stx %g2, [%sp + 2047 + 0x160] - stx %g3, [%sp + 2047 + 0x168] - stx %g4, [%sp + 2047 + 0x170] - stx %g5, [%sp + 2047 + 0x178] - stx %g6, [%sp + 2047 + 0x180] - stx %g7, [%sp + 2047 + 0x188] - ! restore Linux mmu globals - ldx [%sp + 2047 + 0x238], %o0 - ldx [%sp + 2047 + 0x240], %o1 - ldx [%sp + 2047 + 0x248], %l2 - ldx [%sp + 2047 + 0x250], %l3 - ldx [%sp + 2047 + 0x258], %l5 - ldx [%sp + 2047 + 0x260], %l6 - ldx [%sp + 2047 + 0x268], %l7 - ! switch to Linux tba - sethi %hi(sparc64_ttable_tl0), %l1 - rdpr %tba, %l0 ! save PROM tba - mov %o0, %g1 - mov %o1, %g2 - mov %l2, %g3 - mov %l3, %g4 - mov %l5, %g5 - mov %l6, %g6 - mov %l7, %g7 - wrpr %l1, %tba ! install Linux tba - wrpr %l4, 0, %pstate ! restore PSTATE - call prom_world - mov %g0, %o0 - ldx [%i1 + 0x000], %l2 - call %l2 - mov %i0, %o0 - mov %o0, %l1 - call prom_world - or %g0, 1, %o0 - wrpr %g0, 0x14, %pstate ! interrupts off - ! restore PROM mmu globals - ldx [%sp + 2047 + 0x158], %o0 - ldx [%sp + 2047 + 0x160], %o1 - ldx [%sp + 2047 + 0x168], %l2 - ldx [%sp + 2047 + 0x170], %l3 - ldx [%sp + 2047 + 0x178], %l5 - ldx [%sp + 2047 + 0x180], %l6 - ldx [%sp + 2047 + 0x188], %l7 - wrpr %g0, 0x414, %pstate ! restore PROM mmu globals - mov %o0, %g1 - mov %o1, %g2 - mov %l2, %g3 - mov %l3, %g4 - mov %l5, %g5 - mov %l6, %g6 - mov %l7, %g7 - wrpr %l0, %tba ! restore PROM tba - wrpr %g0, 0x14, %pstate ! restore PROM normal globals - ldx [%sp + 2047 + 0x120], %g1 - ldx [%sp + 2047 + 0x128], %g2 - ldx [%sp + 2047 + 0x130], %g3 - ldx [%sp + 2047 + 0x138], %g4 - ldx [%sp + 2047 + 0x140], %g5 - ldx [%sp + 2047 + 0x148], %g6 - ldx [%sp + 2047 + 0x150], %g7 - wrpr %g0, 0x814, %pstate ! restore PROM interrupt globals - ldx [%sp + 2047 + 0x0e8], %g1 - ldx [%sp + 2047 + 0x0f0], %g2 - ldx [%sp + 2047 + 0x0f8], %g3 - ldx [%sp + 2047 + 0x100], %g4 - ldx [%sp + 2047 + 0x108], %g5 - ldx [%sp + 2047 + 0x110], %g6 - ldx [%sp + 2047 + 0x118], %g7 - wrpr %g0, 0x15, %pstate ! restore PROM alternate globals - ldx [%sp + 2047 + 0x0b0], %g1 - ldx [%sp + 2047 + 0x0b8], %g2 - ldx [%sp + 2047 + 0x0c0], %g3 - ldx [%sp + 2047 + 0x0c8], %g4 - ldx [%sp + 2047 + 0x0d0], %g5 - ldx [%sp + 2047 + 0x0d8], %g6 - ldx [%sp + 2047 + 0x0e0], %g7 - wrpr %l4, 0, %pstate - ret - restore %l1, 0, %o0 - diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c deleted file mode 100644 index ac6d035dd15..00000000000 --- a/arch/sparc64/prom/console.c +++ /dev/null @@ -1,154 +0,0 @@ -/* $Id: console.c,v 1.9 1997/10/29 07:41:43 ecd Exp $ - * console.c: Routines that deal with sending and receiving IO - * to/from the current console device using the PROM. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <asm/openprom.h> -#include <asm/oplib.h> -#include <asm/system.h> -#include <linux/string.h> - -extern int prom_stdin, prom_stdout; - -/* Non blocking get character from console input device, returns -1 - * if no input was taken. This can be used for polling. - */ -__inline__ int -prom_nbgetchar(void) -{ - char inc; - - if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)| - P1275_INOUT(3,1), - prom_stdin, &inc, P1275_SIZE(1)) == 1) - return inc; - else - return -1; -} - -/* Non blocking put character to console device, returns -1 if - * unsuccessful. - */ -__inline__ int -prom_nbputchar(char c) -{ - char outc; - - outc = c; - if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)| - P1275_INOUT(3,1), - prom_stdout, &outc, P1275_SIZE(1)) == 1) - return 0; - else - return -1; -} - -/* Blocking version of get character routine above. */ -char -prom_getchar(void) -{ - int character; - while((character = prom_nbgetchar()) == -1) ; - return (char) character; -} - -/* Blocking version of put character routine above. */ -void -prom_putchar(char c) -{ - prom_nbputchar(c); - return; -} - -void -prom_puts(const char *s, int len) -{ - p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)| - P1275_INOUT(3,1), - prom_stdout, s, P1275_SIZE(len)); -} - -/* Query for input device type */ -enum prom_input_device -prom_query_input_device(void) -{ - int st_p; - char propb[64]; - - st_p = prom_inst2pkg(prom_stdin); - if(prom_node_has_property(st_p, "keyboard")) - return PROMDEV_IKBD; - prom_getproperty(st_p, "device_type", propb, sizeof(propb)); - if(strncmp(propb, "serial", 6)) - return PROMDEV_I_UNK; - /* FIXME: Is there any better way how to find out? */ - memset(propb, 0, sizeof(propb)); - st_p = prom_finddevice ("/options"); - prom_getproperty(st_p, "input-device", propb, sizeof(propb)); - - /* - * If we get here with propb == 'keyboard', we are on ttya, as - * the PROM defaulted to this due to 'no input device'. - */ - if (!strncmp(propb, "keyboard", 8)) - return PROMDEV_ITTYA; - - if (!strncmp (propb, "rsc", 3)) - return PROMDEV_IRSC; - - if (strncmp (propb, "tty", 3) || !propb[3]) - return PROMDEV_I_UNK; - - switch (propb[3]) { - case 'a': return PROMDEV_ITTYA; - case 'b': return PROMDEV_ITTYB; - default: return PROMDEV_I_UNK; - } -} - -/* Query for output device type */ - -enum prom_output_device -prom_query_output_device(void) -{ - int st_p; - char propb[64]; - int propl; - - st_p = prom_inst2pkg(prom_stdout); - propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); - if (propl >= 0 && propl == sizeof("display") && - strncmp("display", propb, sizeof("display")) == 0) - return PROMDEV_OSCREEN; - if(strncmp("serial", propb, 6)) - return PROMDEV_O_UNK; - /* FIXME: Is there any better way how to find out? */ - memset(propb, 0, sizeof(propb)); - st_p = prom_finddevice ("/options"); - prom_getproperty(st_p, "output-device", propb, sizeof(propb)); - - /* - * If we get here with propb == 'screen', we are on ttya, as - * the PROM defaulted to this due to 'no input device'. - */ - if (!strncmp(propb, "screen", 6)) - return PROMDEV_OTTYA; - - if (!strncmp (propb, "rsc", 3)) - return PROMDEV_ORSC; - - if (strncmp (propb, "tty", 3) || !propb[3]) - return PROMDEV_O_UNK; - - switch (propb[3]) { - case 'a': return PROMDEV_OTTYA; - case 'b': return PROMDEV_OTTYB; - default: return PROMDEV_O_UNK; - } -} diff --git a/arch/sparc64/prom/devops.c b/arch/sparc64/prom/devops.c deleted file mode 100644 index 4641839eb39..00000000000 --- a/arch/sparc64/prom/devops.c +++ /dev/null @@ -1,41 +0,0 @@ -/* $Id: devops.c,v 1.3 1997/10/29 07:43:28 ecd Exp $ - * devops.c: Device operations using the PROM. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> - -#include <asm/openprom.h> -#include <asm/oplib.h> - -/* Open the device described by the string 'dstr'. Returns the handle - * to that device used for subsequent operations on that device. - * Returns 0 on failure. - */ -int -prom_devopen(const char *dstr) -{ - return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)| - P1275_INOUT(1,1), - dstr); -} - -/* Close the device described by device handle 'dhandle'. */ -int -prom_devclose(int dhandle) -{ - p1275_cmd ("close", P1275_INOUT(1,0), dhandle); - return 0; -} - -/* Seek to specified location described by 'seekhi' and 'seeklo' - * for device 'dhandle'. - */ -void -prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) -{ - p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo); -} diff --git a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c deleted file mode 100644 index f3cc2d8578b..00000000000 --- a/arch/sparc64/prom/init.c +++ /dev/null @@ -1,98 +0,0 @@ -/* $Id: init.c,v 1.10 1999/09/21 14:35:59 davem Exp $ - * init.c: Initialize internal variables used by the PROM - * library functions. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/ctype.h> - -#include <asm/openprom.h> -#include <asm/oplib.h> - -enum prom_major_version prom_vers; -unsigned int prom_rev, prom_prev; - -/* The root node of the prom device tree. */ -int prom_root_node; -int prom_stdin, prom_stdout; -int prom_chosen_node; - -/* You must call prom_init() before you attempt to use any of the - * routines in the prom library. It returns 0 on success, 1 on - * failure. It gets passed the pointer to the PROM vector. - */ - -extern void prom_cif_init(void *, void *); - -void __init prom_init(void *cif_handler, void *cif_stack) -{ - char buffer[80], *p; - int ints[3]; - int node; - int i = 0; - int bufadjust; - - prom_vers = PROM_P1275; - - prom_cif_init(cif_handler, cif_stack); - - prom_root_node = prom_getsibling(0); - if((prom_root_node == 0) || (prom_root_node == -1)) - prom_halt(); - - prom_chosen_node = prom_finddevice(prom_chosen_path); - if (!prom_chosen_node || prom_chosen_node == -1) - prom_halt(); - - prom_stdin = prom_getint (prom_chosen_node, "stdin"); - prom_stdout = prom_getint (prom_chosen_node, "stdout"); - - node = prom_finddevice("/openprom"); - if (!node || node == -1) - prom_halt(); - - prom_getstring (node, "version", buffer, sizeof (buffer)); - - prom_printf ("\n"); - - if (strncmp (buffer, "OBP ", 4)) - goto strange_version; - - /* - * Version field is expected to be 'OBP xx.yy.zz date...' - * However, Sun can't stick to this format very well, so - * we need to check for 'OBP xx.yy.zz date...' and adjust - * accordingly. -spot - */ - - if (strncmp (buffer, "OBP ", 5)) - bufadjust = 4; - else - bufadjust = 5; - - p = buffer + bufadjust; - while (p && isdigit(*p) && i < 3) { - ints[i++] = simple_strtoul(p, NULL, 0); - if ((p = strchr(p, '.')) != NULL) - p++; - } - if (i != 3) - goto strange_version; - - prom_rev = ints[1]; - prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2]; - - printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust); - - /* Initialization successful. */ - return; - -strange_version: - prom_printf ("Strange OBP version `%s'.\n", buffer); - prom_halt (); -} diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c deleted file mode 100644 index 87f5cfce23b..00000000000 --- a/arch/sparc64/prom/misc.c +++ /dev/null @@ -1,325 +0,0 @@ -/* $Id: misc.c,v 1.20 2001/09/21 03:17:07 kanoj Exp $ - * misc.c: Miscellaneous prom functions that don't belong - * anywhere else. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <asm/openprom.h> -#include <asm/oplib.h> -#include <asm/system.h> - -/* Reset and reboot the machine with the command 'bcommand'. */ -void prom_reboot(const char *bcommand) -{ - p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_INOUT(1, 0), bcommand); -} - -/* Forth evaluate the expression contained in 'fstring'. */ -void prom_feval(const char *fstring) -{ - if (!fstring || fstring[0] == 0) - return; - p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_INOUT(1, 1), fstring); -} - -/* We want to do this more nicely some day. */ -extern void (*prom_palette)(int); - -#ifdef CONFIG_SMP -extern void smp_capture(void); -extern void smp_release(void); -#endif - -/* Drop into the prom, with the chance to continue with the 'go' - * prom command. - */ -void prom_cmdline(void) -{ - unsigned long flags; - - local_irq_save(flags); - - if (!serial_console && prom_palette) - prom_palette(1); - -#ifdef CONFIG_SMP - smp_capture(); -#endif - - p1275_cmd("enter", P1275_INOUT(0, 0)); - -#ifdef CONFIG_SMP - smp_release(); -#endif - - if (!serial_console && prom_palette) - prom_palette(0); - - local_irq_restore(flags); -} - -/* Drop into the prom, but completely terminate the program. - * No chance of continuing. - */ -void prom_halt(void) -{ -again: - p1275_cmd("exit", P1275_INOUT(0, 0)); - goto again; /* PROM is out to get me -DaveM */ -} - -void prom_halt_power_off(void) -{ - p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0)); - - /* if nothing else helps, we just halt */ - prom_halt(); -} - -/* Set prom sync handler to call function 'funcp'. */ -void prom_setcallback(callback_func_t funcp) -{ - if (!funcp) - return; - p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) | - P1275_INOUT(1, 1), funcp); -} - -/* Get the idprom and stuff it into buffer 'idbuf'. Returns the - * format type. 'num_bytes' is the number of bytes that your idbuf - * has space for. Returns 0xff on error. - */ -unsigned char prom_get_idprom(char *idbuf, int num_bytes) -{ - int len; - - len = prom_getproplen(prom_root_node, "idprom"); - if ((len >num_bytes) || (len == -1)) - return 0xff; - if (!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes)) - return idbuf[0]; - - return 0xff; -} - -/* Get the major prom version number. */ -int prom_version(void) -{ - return PROM_P1275; -} - -/* Get the prom plugin-revision. */ -int prom_getrev(void) -{ - return prom_rev; -} - -/* Get the prom firmware print revision. */ -int prom_getprev(void) -{ - return prom_prev; -} - -/* Install Linux trap table so PROM uses that instead of its own. */ -void prom_set_trap_table(unsigned long tba) -{ - p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba); -} - -int prom_get_mmu_ihandle(void) -{ - int node, ret; - - if (prom_mmu_ihandle_cache != 0) - return prom_mmu_ihandle_cache; - - node = prom_finddevice(prom_chosen_path); - ret = prom_getint(node, prom_mmu_name); - if (ret == -1 || ret == 0) - prom_mmu_ihandle_cache = -1; - else - prom_mmu_ihandle_cache = ret; - - return ret; -} - -static int prom_get_memory_ihandle(void) -{ - static int memory_ihandle_cache; - int node, ret; - - if (memory_ihandle_cache != 0) - return memory_ihandle_cache; - - node = prom_finddevice("/chosen"); - ret = prom_getint(node, "memory"); - if (ret == -1 || ret == 0) - memory_ihandle_cache = -1; - else - memory_ihandle_cache = ret; - - return ret; -} - -/* Load explicit I/D TLB entries. */ -long prom_itlb_load(unsigned long index, - unsigned long tte_data, - unsigned long vaddr) -{ - return p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(2, P1275_ARG_IN_64B) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_INOUT(5, 1)), - "SUNW,itlb-load", - prom_get_mmu_ihandle(), - /* And then our actual args are pushed backwards. */ - vaddr, - tte_data, - index); -} - -long prom_dtlb_load(unsigned long index, - unsigned long tte_data, - unsigned long vaddr) -{ - return p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(2, P1275_ARG_IN_64B) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_INOUT(5, 1)), - "SUNW,dtlb-load", - prom_get_mmu_ihandle(), - /* And then our actual args are pushed backwards. */ - vaddr, - tte_data, - index); -} - -int prom_map(int mode, unsigned long size, - unsigned long vaddr, unsigned long paddr) -{ - int ret = p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_ARG(4, P1275_ARG_IN_64B) | - P1275_ARG(6, P1275_ARG_IN_64B) | - P1275_INOUT(7, 1)), - prom_map_name, - prom_get_mmu_ihandle(), - mode, - size, - vaddr, - 0, - paddr); - - if (ret == 0) - ret = -1; - return ret; -} - -void prom_unmap(unsigned long size, unsigned long vaddr) -{ - p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(2, P1275_ARG_IN_64B) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_INOUT(4, 0)), - prom_unmap_name, - prom_get_mmu_ihandle(), - size, - vaddr); -} - -/* Set aside physical memory which is not touched or modified - * across soft resets. - */ -unsigned long prom_retain(const char *name, - unsigned long pa_low, unsigned long pa_high, - long size, long align) -{ - /* XXX I don't think we return multiple values correctly. - * XXX OBP supposedly returns pa_low/pa_high here, how does - * XXX it work? - */ - - /* If align is zero, the pa_low/pa_high args are passed, - * else they are not. - */ - if (align == 0) - return p1275_cmd("SUNW,retain", - (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)), - name, pa_low, pa_high, size, align); - else - return p1275_cmd("SUNW,retain", - (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)), - name, size, align); -} - -/* Get "Unumber" string for the SIMM at the given - * memory address. Usually this will be of the form - * "Uxxxx" where xxxx is a decimal number which is - * etched into the motherboard next to the SIMM slot - * in question. - */ -int prom_getunumber(int syndrome_code, - unsigned long phys_addr, - char *buf, int buflen) -{ - return p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(3, P1275_ARG_OUT_BUF) | - P1275_ARG(6, P1275_ARG_IN_64B) | - P1275_INOUT(8, 2)), - "SUNW,get-unumber", prom_get_memory_ihandle(), - buflen, buf, P1275_SIZE(buflen), - 0, phys_addr, syndrome_code); -} - -/* Power management extensions. */ -void prom_sleepself(void) -{ - p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0)); -} - -int prom_sleepsystem(void) -{ - return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1)); -} - -int prom_wakeupsystem(void) -{ - return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1)); -} - -#ifdef CONFIG_SMP -void prom_startcpu(int cpunode, unsigned long pc, unsigned long o0) -{ - p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, o0); -} - -void prom_stopself(void) -{ - p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0)); -} - -void prom_idleself(void) -{ - p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0)); -} - -void prom_resumecpu(int cpunode) -{ - p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode); -} -#endif diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc64/prom/p1275.c deleted file mode 100644 index a5a7c571202..00000000000 --- a/arch/sparc64/prom/p1275.c +++ /dev/null @@ -1,161 +0,0 @@ -/* $Id: p1275.c,v 1.22 2001/10/18 09:40:00 davem Exp $ - * p1275.c: Sun IEEE 1275 PROM low level interface routines - * - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/string.h> -#include <linux/spinlock.h> - -#include <asm/openprom.h> -#include <asm/oplib.h> -#include <asm/system.h> -#include <asm/spitfire.h> -#include <asm/pstate.h> - -struct { - long prom_callback; /* 0x00 */ - void (*prom_cif_handler)(long *); /* 0x08 */ - unsigned long prom_cif_stack; /* 0x10 */ - unsigned long prom_args [23]; /* 0x18 */ - char prom_buffer [3000]; -} p1275buf; - -extern void prom_world(int); - -extern void prom_cif_interface(void); -extern void prom_cif_callback(void); - -static inline unsigned long spitfire_get_primary_context(void) -{ - unsigned long ctx; - - __asm__ __volatile__("ldxa [%1] %2, %0" - : "=r" (ctx) - : "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - return ctx; -} - -/* - * This provides SMP safety on the p1275buf. prom_callback() drops this lock - * to allow recursuve acquisition. - */ -DEFINE_SPINLOCK(prom_entry_lock); - -long p1275_cmd(const char *service, long fmt, ...) -{ - char *p, *q; - unsigned long flags; - int nargs, nrets, i; - va_list list; - long attrs, x; - - p = p1275buf.prom_buffer; - BUG_ON((spitfire_get_primary_context() & CTX_NR_MASK) != 0); - - spin_lock_irqsave(&prom_entry_lock, flags); - - p1275buf.prom_args[0] = (unsigned long)p; /* service */ - strcpy (p, service); - p = (char *)(((long)(strchr (p, 0) + 8)) & ~7); - p1275buf.prom_args[1] = nargs = (fmt & 0x0f); /* nargs */ - p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); /* nrets */ - attrs = fmt >> 8; - va_start(list, fmt); - for (i = 0; i < nargs; i++, attrs >>= 3) { - switch (attrs & 0x7) { - case P1275_ARG_NUMBER: - p1275buf.prom_args[i + 3] = - (unsigned)va_arg(list, long); - break; - case P1275_ARG_IN_64B: - p1275buf.prom_args[i + 3] = - va_arg(list, unsigned long); - break; - case P1275_ARG_IN_STRING: - strcpy (p, va_arg(list, char *)); - p1275buf.prom_args[i + 3] = (unsigned long)p; - p = (char *)(((long)(strchr (p, 0) + 8)) & ~7); - break; - case P1275_ARG_OUT_BUF: - (void) va_arg(list, char *); - p1275buf.prom_args[i + 3] = (unsigned long)p; - x = va_arg(list, long); - i++; attrs >>= 3; - p = (char *)(((long)(p + (int)x + 7)) & ~7); - p1275buf.prom_args[i + 3] = x; - break; - case P1275_ARG_IN_BUF: - q = va_arg(list, char *); - p1275buf.prom_args[i + 3] = (unsigned long)p; - x = va_arg(list, long); - i++; attrs >>= 3; - memcpy (p, q, (int)x); - p = (char *)(((long)(p + (int)x + 7)) & ~7); - p1275buf.prom_args[i + 3] = x; - break; - case P1275_ARG_OUT_32B: - (void) va_arg(list, char *); - p1275buf.prom_args[i + 3] = (unsigned long)p; - p += 32; - break; - case P1275_ARG_IN_FUNCTION: - p1275buf.prom_args[i + 3] = - (unsigned long)prom_cif_callback; - p1275buf.prom_callback = va_arg(list, long); - break; - } - } - va_end(list); - - prom_world(1); - prom_cif_interface(); - prom_world(0); - - attrs = fmt >> 8; - va_start(list, fmt); - for (i = 0; i < nargs; i++, attrs >>= 3) { - switch (attrs & 0x7) { - case P1275_ARG_NUMBER: - (void) va_arg(list, long); - break; - case P1275_ARG_IN_STRING: - (void) va_arg(list, char *); - break; - case P1275_ARG_IN_FUNCTION: - (void) va_arg(list, long); - break; - case P1275_ARG_IN_BUF: - (void) va_arg(list, char *); - (void) va_arg(list, long); - i++; attrs >>= 3; - break; - case P1275_ARG_OUT_BUF: - p = va_arg(list, char *); - x = va_arg(list, long); - memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x); - i++; attrs >>= 3; - break; - case P1275_ARG_OUT_32B: - p = va_arg(list, char *); - memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32); - break; - } - } - va_end(list); - x = p1275buf.prom_args [nargs + 3]; - - spin_unlock_irqrestore(&prom_entry_lock, flags); - - return x; -} - -void prom_cif_init(void *cif_handler, void *cif_stack) -{ - p1275buf.prom_cif_handler = (void (*)(long *))cif_handler; - p1275buf.prom_cif_stack = (unsigned long)cif_stack; -} diff --git a/arch/sparc64/prom/printf.c b/arch/sparc64/prom/printf.c deleted file mode 100644 index 660943ee4c2..00000000000 --- a/arch/sparc64/prom/printf.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * printf.c: Internal prom library printf facility. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (c) 2002 Pete Zaitcev (zaitcev@yahoo.com) - * - * We used to warn all over the code: DO NOT USE prom_printf(), - * and yet people do. Anton's banking code was outputting banks - * with prom_printf for most of the 2.4 lifetime. Since an effective - * stick is not available, we deployed a carrot: an early printk - * through PROM by means of -p boot option. This ought to fix it. - * USE printk; if you need, deploy -p. - */ - -#include <linux/kernel.h> - -#include <asm/openprom.h> -#include <asm/oplib.h> - -static char ppbuf[1024]; - -void -prom_write(const char *buf, unsigned int n) -{ - char ch; - - while (n != 0) { - --n; - if ((ch = *buf++) == '\n') - prom_putchar('\r'); - prom_putchar(ch); - } -} - -void -prom_printf(const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args); - va_end(args); - - prom_write(ppbuf, i); -} diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c deleted file mode 100644 index b1ff9e87dcc..00000000000 --- a/arch/sparc64/prom/tree.c +++ /dev/null @@ -1,379 +0,0 @@ -/* $Id: tree.c,v 1.10 1998/01/10 22:39:00 ecd Exp $ - * tree.c: Basic device tree traversal/scanning for the Linux - * prom library. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/string.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> - -#include <asm/openprom.h> -#include <asm/oplib.h> - -/* Return the child of node 'node' or zero if no this node has no - * direct descendent. - */ -__inline__ int -__prom_getchild(int node) -{ - return p1275_cmd ("child", P1275_INOUT(1, 1), node); -} - -__inline__ int -prom_getchild(int node) -{ - int cnode; - - if(node == -1) return 0; - cnode = __prom_getchild(node); - if(cnode == -1) return 0; - return (int)cnode; -} - -__inline__ int -prom_getparent(int node) -{ - int cnode; - - if(node == -1) return 0; - cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node); - if(cnode == -1) return 0; - return (int)cnode; -} - -/* Return the next sibling of node 'node' or zero if no more siblings - * at this level of depth in the tree. - */ -__inline__ int -__prom_getsibling(int node) -{ - return p1275_cmd ("peer", P1275_INOUT(1, 1), node); -} - -__inline__ int -prom_getsibling(int node) -{ - int sibnode; - - if(node == -1) return 0; - sibnode = __prom_getsibling(node); - if(sibnode == -1) return 0; - return sibnode; -} - -/* Return the length in bytes of property 'prop' at node 'node'. - * Return -1 on error. - */ -__inline__ int -prom_getproplen(int node, const char *prop) -{ - if((!node) || (!prop)) return -1; - return p1275_cmd ("getproplen", - P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_INOUT(2, 1), - node, prop); -} - -/* Acquire a property 'prop' at node 'node' and place it in - * 'buffer' which has a size of 'bufsize'. If the acquisition - * was successful the length will be returned, else -1 is returned. - */ -__inline__ int -prom_getproperty(int node, const char *prop, char *buffer, int bufsize) -{ - int plen; - - plen = prom_getproplen(node, prop); - if ((plen > bufsize) || (plen == 0) || (plen == -1)) { - return -1; - } else { - /* Ok, things seem all right. */ - return p1275_cmd(prom_getprop_name, - P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_ARG(2,P1275_ARG_OUT_BUF)| - P1275_INOUT(4, 1), - node, prop, buffer, P1275_SIZE(plen)); - } -} - -/* Acquire an integer property and return its value. Returns -1 - * on failure. - */ -__inline__ int -prom_getint(int node, const char *prop) -{ - int intprop; - - if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1) - return intprop; - - return -1; -} - -/* Acquire an integer property, upon error return the passed default - * integer. - */ - -int -prom_getintdefault(int node, const char *property, int deflt) -{ - int retval; - - retval = prom_getint(node, property); - if(retval == -1) return deflt; - - return retval; -} - -/* Acquire a boolean property, 1=TRUE 0=FALSE. */ -int -prom_getbool(int node, const char *prop) -{ - int retval; - - retval = prom_getproplen(node, prop); - if(retval == -1) return 0; - return 1; -} - -/* Acquire a property whose value is a string, returns a null - * string on error. The char pointer is the user supplied string - * buffer. - */ -void -prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size) -{ - int len; - - len = prom_getproperty(node, prop, user_buf, ubuf_size); - if(len != -1) return; - user_buf[0] = 0; - return; -} - - -/* Does the device at node 'node' have name 'name'? - * YES = 1 NO = 0 - */ -int -prom_nodematch(int node, const char *name) -{ - char namebuf[128]; - prom_getproperty(node, "name", namebuf, sizeof(namebuf)); - if(strcmp(namebuf, name) == 0) return 1; - return 0; -} - -/* Search siblings at 'node_start' for a node with name - * 'nodename'. Return node if successful, zero if not. - */ -int -prom_searchsiblings(int node_start, const char *nodename) -{ - - int thisnode, error; - char promlib_buf[128]; - - for(thisnode = node_start; thisnode; - thisnode=prom_getsibling(thisnode)) { - error = prom_getproperty(thisnode, "name", promlib_buf, - sizeof(promlib_buf)); - /* Should this ever happen? */ - if(error == -1) continue; - if(strcmp(nodename, promlib_buf)==0) return thisnode; - } - - return 0; -} - -/* Gets name in the {name@x,yyyyy|name (if no reg)} form */ -int -prom_getname (int node, char *buffer, int len) -{ - int i, sbus = 0; - int pci = 0, ebus = 0, ide = 0; - struct linux_prom_registers *reg; - struct linux_prom64_registers reg64[PROMREG_MAX]; - - for (sbus = prom_getparent (node); sbus; sbus = prom_getparent (sbus)) { - i = prom_getproperty (sbus, "name", buffer, len); - if (i > 0) { - buffer [i] = 0; - if (!strcmp (buffer, "sbus")) - goto getit; - } - } - if ((pci = prom_getparent (node))) { - i = prom_getproperty (pci, "name", buffer, len); - if (i > 0) { - buffer [i] = 0; - if (!strcmp (buffer, "pci")) - goto getit; - } - pci = 0; - } - if ((ebus = prom_getparent (node))) { - i = prom_getproperty (ebus, "name", buffer, len); - if (i > 0) { - buffer[i] = 0; - if (!strcmp (buffer, "ebus")) - goto getit; - } - ebus = 0; - } - if ((ide = prom_getparent (node))) { - i = prom_getproperty (ide, "name", buffer, len); - if (i > 0) { - buffer [i] = 0; - if (!strcmp (buffer, "ide")) - goto getit; - } - ide = 0; - } -getit: - i = prom_getproperty (node, "name", buffer, len); - if (i <= 0) { - buffer [0] = 0; - return -1; - } - buffer [i] = 0; - len -= i; - i = prom_getproperty (node, "reg", (char *)reg64, sizeof (reg64)); - if (i <= 0) return 0; - if (len < 16) return -1; - buffer = strchr (buffer, 0); - if (sbus) { - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr); - } else if (pci) { - int dev, fn; - reg = (struct linux_prom_registers *)reg64; - fn = (reg[0].which_io >> 8) & 0x07; - dev = (reg[0].which_io >> 11) & 0x1f; - if (fn) - sprintf (buffer, "@%x,%x", dev, fn); - else - sprintf (buffer, "@%x", dev); - } else if (ebus) { - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr); - } else if (ide) { - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr); - } else if (i == 4) { /* Happens on 8042's children on Ultra/PCI. */ - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x", reg[0].which_io); - } else { - sprintf (buffer, "@%x,%x", - (unsigned int)(reg64[0].phys_addr >> 36), - (unsigned int)(reg64[0].phys_addr)); - } - return 0; -} - -/* Return the first property type for node 'node'. - * buffer should be at least 32B in length - */ -__inline__ char * -prom_firstprop(int node, char *buffer) -{ - *buffer = 0; - if(node == -1) return buffer; - p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)| - P1275_INOUT(3, 0), - node, (char *) 0x0, buffer); - return buffer; -} - -/* Return the property type string after property type 'oprop' - * at node 'node' . Returns NULL string if no more - * property types for this node. - */ -__inline__ char * -prom_nextprop(int node, const char *oprop, char *buffer) -{ - char buf[32]; - - if(node == -1) { - *buffer = 0; - return buffer; - } - if (oprop == buffer) { - strcpy (buf, oprop); - oprop = buf; - } - p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_ARG(2,P1275_ARG_OUT_32B)| - P1275_INOUT(3, 0), - node, oprop, buffer); - return buffer; -} - -int -prom_finddevice(const char *name) -{ - if (!name) - return 0; - return p1275_cmd(prom_finddev_name, - P1275_ARG(0,P1275_ARG_IN_STRING)| - P1275_INOUT(1, 1), - name); -} - -int prom_node_has_property(int node, const char *prop) -{ - char buf [32]; - - *buf = 0; - do { - prom_nextprop(node, buf, buf); - if(!strcmp(buf, prop)) - return 1; - } while (*buf); - return 0; -} - -/* Set property 'pname' at node 'node' to value 'value' which has a length - * of 'size' bytes. Return the number of bytes the prom accepted. - */ -int -prom_setprop(int node, const char *pname, char *value, int size) -{ - if(size == 0) return 0; - if((pname == 0) || (value == 0)) return 0; - - return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_ARG(2,P1275_ARG_IN_BUF)| - P1275_INOUT(4, 1), - node, pname, value, P1275_SIZE(size)); -} - -__inline__ int -prom_inst2pkg(int inst) -{ - int node; - - node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst); - if (node == -1) return 0; - return node; -} - -/* Return 'node' assigned to a particular prom 'path' - * FIXME: Should work for v0 as well - */ -int -prom_pathtoinode(const char *path) -{ - int node, inst; - - inst = prom_devopen (path); - if (inst == 0) return 0; - node = prom_inst2pkg (inst); - prom_devclose (inst); - if (node == -1) return 0; - return node; -} diff --git a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile deleted file mode 100644 index 8c8663033bf..00000000000 --- a/arch/sparc64/solaris/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for the Solaris binary emulation. -# - -EXTRA_AFLAGS := -ansi - -solaris-objs := entry64.o fs.o misc.o signal.o systbl.o socket.o \ - ioctl.o ipc.o socksys.o timod.o - -obj-$(CONFIG_SOLARIS_EMUL) += solaris.o diff --git a/arch/sparc64/solaris/conv.h b/arch/sparc64/solaris/conv.h deleted file mode 100644 index 5faf59a9de3..00000000000 --- a/arch/sparc64/solaris/conv.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $Id: conv.h,v 1.4 1998/08/15 20:42:51 davem Exp $ - * conv.h: Utility macros for Solaris emulation - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -/* #define DEBUG_SOLARIS */ -#define DEBUG_SOLARIS_KMALLOC - -#ifndef __ASSEMBLY__ - -#include <asm/unistd.h> - -/* Use this to get at 32-bit user passed pointers. */ -#define A(__x) \ -({ unsigned long __ret; \ - __asm__ ("srl %0, 0, %0" \ - : "=r" (__ret) \ - : "0" (__x)); \ - (void __user *)__ret; \ -}) - -extern unsigned sys_call_table[]; -extern unsigned sys_call_table32[]; -extern unsigned sunos_sys_table[]; - -#define SYS(name) ((long)sys_call_table[__NR_##name]) -#define SUNOS(x) ((long)sunos_sys_table[x]) - -#ifdef DEBUG_SOLARIS -#define SOLD(s) printk("%s,%d,%s(): %s\n",__FILE__,__LINE__,__FUNCTION__,(s)) -#define SOLDD(s) printk("solaris: "); printk s -#else -#define SOLD(s) -#define SOLDD(s) -#endif - -#endif /* __ASSEMBLY__ */ diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S deleted file mode 100644 index eb314ed23cd..00000000000 --- a/arch/sparc64/solaris/entry64.S +++ /dev/null @@ -1,223 +0,0 @@ -/* $Id: entry64.S,v 1.7 2002/02/09 19:49:31 davem Exp $ - * entry64.S: Solaris syscall emulation entry point. - * - * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - */ - -#include <linux/errno.h> - -#include <asm/head.h> -#include <asm/asi.h> -#include <asm/smp.h> -#include <asm/ptrace.h> -#include <asm/page.h> -#include <asm/signal.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/thread_info.h> - -#include "conv.h" - -#define NR_SYSCALLS 256 - - .text -solaris_syscall_trace: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 0, %o1 - srl %i0, 0, %o0 - mov %i4, %o4 - srl %i1, 0, %o1 - mov %i5, %o5 - andcc %l3, 1, %g0 - be,pt %icc, 2f - srl %i2, 0, %o2 - b,pt %xcc, 2f - add %sp, PTREGS_OFF, %o0 - -solaris_sucks: -/* Solaris is a big system which needs to be able to do all the things - * in Inf+1 different ways */ - add %i6, 0x5c, %o0 - mov %i0, %g1 - mov %i1, %i0 - mov %i2, %i1 - srl %o0, 0, %o0 - mov %i3, %i2 - movrz %g1, 256, %g1 /* Ensure we don't loop forever */ - mov %i4, %i3 - mov %i5, %i4 - ba,pt %xcc, solaris_sparc_syscall -exen: lduwa [%o0] ASI_S, %i5 - -exenf: ba,pt %xcc, solaris_sparc_syscall - clr %i5 - -/* For shared binaries, binfmt_elf32 already sets up personality - and exec_domain. This is to handle static binaries as well */ -solaris_reg: - call solaris_register - nop - ba,pt %xcc, 1f - mov %i4, %o4 - -linux_syscall_for_solaris: - sethi %hi(sys_call_table32), %l6 - or %l6, %lo(sys_call_table32), %l6 - sll %l3, 2, %l4 - ba,pt %xcc, 10f - lduw [%l6 + %l4], %l3 - - /* Solaris system calls enter here... */ - .align 32 - .globl solaris_sparc_syscall, entry64_personality_patch -solaris_sparc_syscall: -entry64_personality_patch: - ldub [%g4 + 0x0], %l0 - cmp %g1, 255 - bg,pn %icc, solaris_unimplemented - srl %g1, 0, %g1 - sethi %hi(solaris_sys_table), %l7 - or %l7, %lo(solaris_sys_table), %l7 - brz,pn %g1, solaris_sucks - mov %i4, %o4 - sll %g1, 2, %l4 - cmp %l0, 1 - bne,pn %icc, solaris_reg -1: srl %i0, 0, %o0 - lduw [%l7 + %l4], %l3 - srl %i1, 0, %o1 - ldx [%g6 + TI_FLAGS], %l5 - cmp %l3, NR_SYSCALLS - bleu,a,pn %xcc, linux_syscall_for_solaris - nop - andcc %l3, 1, %g0 - bne,a,pn %icc, 10f - add %sp, PTREGS_OFF, %o0 -10: srl %i2, 0, %o2 - mov %i5, %o5 - andn %l3, 3, %l7 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - bne,pn %icc, solaris_syscall_trace - mov %i0, %l5 -2: call %l7 - srl %i3, 0, %o3 -ret_from_solaris: - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - ldx [%g6 + TI_FLAGS], %l6 - sra %o0, 0, %o0 - mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - cmp %o0, -ERESTART_RESTARTBLOCK - sllx %g2, 32, %g2 - bgeu,pn %xcc, 1f - andcc %l6, _TIF_SYSCALL_TRACE, %l6 - - /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, solaris_syscall_trace2 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 - andcc %l1, 1, %g0 - bne,pn %icc, 2f - clr %l6 - add %l1, 0x4, %l2 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ! pc = npc - call rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4 - - /* When tnpc & 1, this comes from setcontext and we don't want to advance pc */ -2: andn %l1, 3, %l1 - call rtrap - stx %l1, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc&~3 - -1: - /* System call failure, set Carry condition code. - * Also, get abs(errno) to return to the process. - */ - sub %g0, %o0, %o0 - or %g3, %g2, %g3 - cmp %o0, ERANGE /* 0-ERANGE are identity mapped */ - bleu,pt %icc, 1f - cmp %o0, EMEDIUMTYPE - bgu,pn %icc, 1f - sethi %hi(solaris_err_table), %l6 - sll %o0, 2, %o0 - or %l6, %lo(solaris_err_table), %l6 - ldsw [%l6 + %o0], %o0 -1: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - mov 1, %l6 - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, solaris_syscall_trace2 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 - andcc %l1, 1, %g0 - bne,pn %icc, 2b - add %l1, 0x4, %l2 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ! pc = npc - call rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4 - -solaris_syscall_trace2: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 - add %l1, 0x4, %l2 /* npc = npc+4 */ - andcc %l1, 1, %g0 - bne,pn %icc, 2b - nop - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] - call rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] - - /* This one is tricky, so that's why we do it in assembly */ - .globl solaris_sigsuspend -solaris_sigsuspend: - call do_sol_sigsuspend - nop - brlz,pn %o0, ret_from_solaris - nop - call sys_sigsuspend - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_getpid -solaris_getpid: - call sys_getppid - nop - call sys_getpid - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_getuid -solaris_getuid: - call sys_geteuid - nop - call sys_getuid - stx %o1, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_getgid -solaris_getgid: - call sys_getegid - nop - call sys_getgid - stx %o1, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_unimplemented -solaris_unimplemented: - call do_sol_unimplemented - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, ret_from_solaris - nop - - .section __ex_table,#alloc - .align 4 - .word exen, exenf - diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c deleted file mode 100644 index 4885ca6cbc7..00000000000 --- a/arch/sparc64/solaris/fs.c +++ /dev/null @@ -1,740 +0,0 @@ -/* $Id: fs.c,v 1.27 2002/02/08 03:57:14 davem Exp $ - * fs.c: fs related syscall emulation for Solaris - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * 1999-08-19 Implemented solaris F_FREESP (truncate) - * fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu) - */ - -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/capability.h> -#include <linux/fs.h> -#include <linux/namei.h> -#include <linux/mm.h> -#include <linux/file.h> -#include <linux/stat.h> -#include <linux/smp_lock.h> -#include <linux/limits.h> -#include <linux/resource.h> -#include <linux/quotaops.h> -#include <linux/mount.h> -#include <linux/vfs.h> - -#include <asm/uaccess.h> -#include <asm/string.h> -#include <asm/ptrace.h> - -#include "conv.h" - -#define R3_VERSION 1 -#define R4_VERSION 2 - -typedef struct { - s32 tv_sec; - s32 tv_nsec; -} timestruct_t; - -struct sol_stat { - u32 st_dev; - s32 st_pad1[3]; /* network id */ - u32 st_ino; - u32 st_mode; - u32 st_nlink; - u32 st_uid; - u32 st_gid; - u32 st_rdev; - s32 st_pad2[2]; - s32 st_size; - s32 st_pad3; /* st_size, off_t expansion */ - timestruct_t st_atime; - timestruct_t st_mtime; - timestruct_t st_ctime; - s32 st_blksize; - s32 st_blocks; - char st_fstype[16]; - s32 st_pad4[8]; /* expansion area */ -}; - -struct sol_stat64 { - u32 st_dev; - s32 st_pad1[3]; /* network id */ - u64 st_ino; - u32 st_mode; - u32 st_nlink; - u32 st_uid; - u32 st_gid; - u32 st_rdev; - s32 st_pad2[2]; - s64 st_size; - timestruct_t st_atime; - timestruct_t st_mtime; - timestruct_t st_ctime; - s64 st_blksize; - s32 st_blocks; - char st_fstype[16]; - s32 st_pad4[4]; /* expansion area */ -}; - -#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8)) - -static inline int putstat(struct sol_stat __user *ubuf, struct kstat *kbuf) -{ - if (kbuf->size > MAX_NON_LFS || - !sysv_valid_dev(kbuf->dev) || - !sysv_valid_dev(kbuf->rdev)) - return -EOVERFLOW; - if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev) || - __put_user (kbuf->ino, &ubuf->st_ino) || - __put_user (kbuf->mode, &ubuf->st_mode) || - __put_user (kbuf->nlink, &ubuf->st_nlink) || - __put_user (kbuf->uid, &ubuf->st_uid) || - __put_user (kbuf->gid, &ubuf->st_gid) || - __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev) || - __put_user (kbuf->size, &ubuf->st_size) || - __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) || - __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) || - __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) || - __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) || - __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) || - __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) || - __put_user (kbuf->blksize, &ubuf->st_blksize) || - __put_user (kbuf->blocks, &ubuf->st_blocks) || - __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype)) - return -EFAULT; - return 0; -} - -static inline int putstat64(struct sol_stat64 __user *ubuf, struct kstat *kbuf) -{ - if (!sysv_valid_dev(kbuf->dev) || !sysv_valid_dev(kbuf->rdev)) - return -EOVERFLOW; - if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev) || - __put_user (kbuf->ino, &ubuf->st_ino) || - __put_user (kbuf->mode, &ubuf->st_mode) || - __put_user (kbuf->nlink, &ubuf->st_nlink) || - __put_user (kbuf->uid, &ubuf->st_uid) || - __put_user (kbuf->gid, &ubuf->st_gid) || - __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev) || - __put_user (kbuf->size, &ubuf->st_size) || - __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) || - __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) || - __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) || - __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) || - __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) || - __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) || - __put_user (kbuf->blksize, &ubuf->st_blksize) || - __put_user (kbuf->blocks, &ubuf->st_blocks) || - __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype)) - return -EFAULT; - return 0; -} - -asmlinkage int solaris_stat(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_stat(A(filename), &s); - if (!ret) - return putstat(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf) -{ - /* Solaris doesn't bother with looking at vers, so we do neither */ - return solaris_stat(filename, statbuf); -} - -asmlinkage int solaris_stat64(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_stat(A(filename), &s); - if (!ret) - return putstat64(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_lstat(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_lstat(A(filename), &s); - if (!ret) - return putstat(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf) -{ - return solaris_lstat(filename, statbuf); -} - -asmlinkage int solaris_lstat64(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_lstat(A(filename), &s); - if (!ret) - return putstat64(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf) -{ - struct kstat s; - int ret = vfs_fstat(fd, &s); - if (!ret) - return putstat(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf) -{ - return solaris_fstat(fd, statbuf); -} - -asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf) -{ - struct kstat s; - int ret = vfs_fstat(fd, &s); - if (!ret) - return putstat64(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev) -{ - int (*sys_mknod)(const char __user *,int,unsigned) = - (int (*)(const char __user *,int,unsigned))SYS(mknod); - int major = sysv_major(dev); - int minor = sysv_minor(dev); - - /* minor is guaranteed to be OK for MKDEV, major might be not */ - if (major > 0xfff) - return -EINVAL; - return sys_mknod(A(path), mode, new_encode_dev(MKDEV(major,minor))); -} - -asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev) -{ - return solaris_mknod(path, mode, dev); -} - -asmlinkage int solaris_getdents64(unsigned int fd, void __user *dirent, unsigned int count) -{ - int (*sys_getdents)(unsigned int, void __user *, unsigned int) = - (int (*)(unsigned int, void __user *, unsigned int))SYS(getdents); - - return sys_getdents(fd, dirent, count); -} - -/* This statfs thingie probably will go in the near future, but... */ - -struct sol_statfs { - short f_type; - s32 f_bsize; - s32 f_frsize; - s32 f_blocks; - s32 f_bfree; - u32 f_files; - u32 f_ffree; - char f_fname[6]; - char f_fpack[6]; -}; - -asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - int (*sys_statfs)(const char __user *,struct statfs __user *) = - (int (*)(const char __user *,struct statfs __user *))SYS(statfs); - struct sol_statfs __user *ss = A(buf); - - if (len != sizeof(struct sol_statfs)) return -EINVAL; - if (!fstype) { - /* FIXME: mixing userland and kernel pointers */ - set_fs (KERNEL_DS); - ret = sys_statfs(A(path), &s); - set_fs (old_fs); - if (!ret) { - if (put_user (s.f_type, &ss->f_type) || - __put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; - } - return ret; - } -/* Linux can't stat unmounted filesystems so we - * simply lie and claim 100MB of 1GB is free. Sorry. - */ - if (put_user (fstype, &ss->f_type) || - __put_user (1024, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (1024*1024, &ss->f_blocks) || - __put_user (100*1024, &ss->f_bfree) || - __put_user (60000, &ss->f_files) || - __put_user (50000, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; - return 0; -} - -asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - int (*sys_fstatfs)(unsigned,struct statfs __user *) = - (int (*)(unsigned,struct statfs __user *))SYS(fstatfs); - struct sol_statfs __user *ss = A(buf); - - if (len != sizeof(struct sol_statfs)) return -EINVAL; - if (!fstype) { - set_fs (KERNEL_DS); - ret = sys_fstatfs(fd, &s); - set_fs (old_fs); - if (!ret) { - if (put_user (s.f_type, &ss->f_type) || - __put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; - } - return ret; - } - /* Otherwise fstatfs is the same as statfs */ - return solaris_statfs(0, buf, len, fstype); -} - -struct sol_statvfs { - u32 f_bsize; - u32 f_frsize; - u32 f_blocks; - u32 f_bfree; - u32 f_bavail; - u32 f_files; - u32 f_ffree; - u32 f_favail; - u32 f_fsid; - char f_basetype[16]; - u32 f_flag; - u32 f_namemax; - char f_fstr[32]; - u32 f_filler[16]; -}; - -struct sol_statvfs64 { - u32 f_bsize; - u32 f_frsize; - u64 f_blocks; - u64 f_bfree; - u64 f_bavail; - u64 f_files; - u64 f_ffree; - u64 f_favail; - u32 f_fsid; - char f_basetype[16]; - u32 f_flag; - u32 f_namemax; - char f_fstr[32]; - u32 f_filler[16]; -}; - -static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf) -{ - struct kstatfs s; - int error; - struct sol_statvfs __user *ss = A(buf); - - error = vfs_statfs(mnt->mnt_sb, &s); - if (!error) { - const char *p = mnt->mnt_sb->s_type->name; - int i = 0; - int j = strlen (p); - - if (j > 15) j = 15; - if (IS_RDONLY(inode)) i = 1; - if (mnt->mnt_flags & MNT_NOSUID) i |= 2; - if (!sysv_valid_dev(inode->i_sb->s_dev)) - return -EOVERFLOW; - if (put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_bavail, &ss->f_bavail) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __put_user (s.f_ffree, &ss->f_favail) || - __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) || - __copy_to_user (ss->f_basetype,p,j) || - __put_user (0, (char __user *)&ss->f_basetype[j]) || - __put_user (s.f_namelen, &ss->f_namemax) || - __put_user (i, &ss->f_flag) || - __clear_user (&ss->f_fstr, 32)) - return -EFAULT; - } - return error; -} - -static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf) -{ - struct kstatfs s; - int error; - struct sol_statvfs64 __user *ss = A(buf); - - error = vfs_statfs(mnt->mnt_sb, &s); - if (!error) { - const char *p = mnt->mnt_sb->s_type->name; - int i = 0; - int j = strlen (p); - - if (j > 15) j = 15; - if (IS_RDONLY(inode)) i = 1; - if (mnt->mnt_flags & MNT_NOSUID) i |= 2; - if (!sysv_valid_dev(inode->i_sb->s_dev)) - return -EOVERFLOW; - if (put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_bavail, &ss->f_bavail) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __put_user (s.f_ffree, &ss->f_favail) || - __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) || - __copy_to_user (ss->f_basetype,p,j) || - __put_user (0, (char __user *)&ss->f_basetype[j]) || - __put_user (s.f_namelen, &ss->f_namemax) || - __put_user (i, &ss->f_flag) || - __clear_user (&ss->f_fstr, 32)) - return -EFAULT; - } - return error; -} - -asmlinkage int solaris_statvfs(u32 path, u32 buf) -{ - struct nameidata nd; - int error; - - error = user_path_walk(A(path),&nd); - if (!error) { - struct inode * inode = nd.dentry->d_inode; - error = report_statvfs(nd.mnt, inode, buf); - path_release(&nd); - } - return error; -} - -asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf) -{ - struct file * file; - int error; - - error = -EBADF; - file = fget(fd); - if (file) { - error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf); - fput(file); - } - - return error; -} - -asmlinkage int solaris_statvfs64(u32 path, u32 buf) -{ - struct nameidata nd; - int error; - - lock_kernel(); - error = user_path_walk(A(path), &nd); - if (!error) { - struct inode * inode = nd.dentry->d_inode; - error = report_statvfs64(nd.mnt, inode, buf); - path_release(&nd); - } - unlock_kernel(); - return error; -} - -asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf) -{ - struct file * file; - int error; - - error = -EBADF; - file = fget(fd); - if (file) { - lock_kernel(); - error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf); - unlock_kernel(); - fput(file); - } - return error; -} - -extern asmlinkage long sparc32_open(const char * filename, int flags, int mode); - -asmlinkage int solaris_open(u32 fname, int flags, u32 mode) -{ - const char *filename = (const char *)(long)fname; - int fl = flags & 0xf; - - /* Translate flags first. */ - if (flags & 0x2000) fl |= O_LARGEFILE; - if (flags & 0x8050) fl |= O_SYNC; - if (flags & 0x80) fl |= O_NONBLOCK; - if (flags & 0x100) fl |= O_CREAT; - if (flags & 0x200) fl |= O_TRUNC; - if (flags & 0x400) fl |= O_EXCL; - if (flags & 0x800) fl |= O_NOCTTY; - flags = fl; - - return sparc32_open(filename, flags, mode); -} - -#define SOL_F_SETLK 6 -#define SOL_F_SETLKW 7 -#define SOL_F_FREESP 11 -#define SOL_F_ISSTREAM 13 -#define SOL_F_GETLK 14 -#define SOL_F_PRIV 15 -#define SOL_F_NPRIV 16 -#define SOL_F_QUOTACTL 17 -#define SOL_F_BLOCKS 18 -#define SOL_F_BLKSIZE 19 -#define SOL_F_GETOWN 23 -#define SOL_F_SETOWN 24 - -struct sol_flock { - short l_type; - short l_whence; - u32 l_start; - u32 l_len; - s32 l_sysid; - s32 l_pid; - s32 l_pad[4]; -}; - -asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg) -{ - int (*sys_fcntl)(unsigned,unsigned,unsigned long) = - (int (*)(unsigned,unsigned,unsigned long))SYS(fcntl); - int ret, flags; - - switch (cmd) { - case F_DUPFD: - case F_GETFD: - case F_SETFD: return sys_fcntl(fd, cmd, (unsigned long)arg); - case F_GETFL: - flags = sys_fcntl(fd, cmd, 0); - ret = flags & 0xf; - if (flags & O_SYNC) ret |= 0x8050; - if (flags & O_NONBLOCK) ret |= 0x80; - return ret; - case F_SETFL: - flags = arg & 0xf; - if (arg & 0x8050) flags |= O_SYNC; - if (arg & 0x80) flags |= O_NONBLOCK; - return sys_fcntl(fd, cmd, (long)flags); - case SOL_F_GETLK: - case SOL_F_SETLK: - case SOL_F_SETLKW: - { - struct flock f; - struct sol_flock __user *p = A(arg); - mm_segment_t old_fs = get_fs(); - - switch (cmd) { - case SOL_F_GETLK: cmd = F_GETLK; break; - case SOL_F_SETLK: cmd = F_SETLK; break; - case SOL_F_SETLKW: cmd = F_SETLKW; break; - } - - if (get_user (f.l_type, &p->l_type) || - __get_user (f.l_whence, &p->l_whence) || - __get_user (f.l_start, &p->l_start) || - __get_user (f.l_len, &p->l_len) || - __get_user (f.l_pid, &p->l_sysid)) - return -EFAULT; - - set_fs(KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs(old_fs); - - if (__put_user (f.l_type, &p->l_type) || - __put_user (f.l_whence, &p->l_whence) || - __put_user (f.l_start, &p->l_start) || - __put_user (f.l_len, &p->l_len) || - __put_user (f.l_pid, &p->l_pid) || - __put_user (0, &p->l_sysid)) - return -EFAULT; - - return ret; - } - case SOL_F_FREESP: - { - int length; - int (*sys_newftruncate)(unsigned int, unsigned long)= - (int (*)(unsigned int, unsigned long))SYS(ftruncate); - - if (get_user(length, &((struct sol_flock __user *)A(arg))->l_start)) - return -EFAULT; - - return sys_newftruncate(fd, length); - } - }; - return -EINVAL; -} - -asmlinkage int solaris_ulimit(int cmd, int val) -{ - switch (cmd) { - case 1: /* UL_GETFSIZE - in 512B chunks */ - return current->signal->rlim[RLIMIT_FSIZE].rlim_cur >> 9; - case 2: /* UL_SETFSIZE */ - if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE; - val <<= 9; - task_lock(current->group_leader); - if (val > current->signal->rlim[RLIMIT_FSIZE].rlim_max) { - if (!capable(CAP_SYS_RESOURCE)) { - task_unlock(current->group_leader); - return -EPERM; - } - current->signal->rlim[RLIMIT_FSIZE].rlim_max = val; - } - current->signal->rlim[RLIMIT_FSIZE].rlim_cur = val; - task_unlock(current->group_leader); - return 0; - case 3: /* UL_GMEMLIM */ - return current->signal->rlim[RLIMIT_DATA].rlim_cur; - case 4: /* UL_GDESLIM */ - return NR_OPEN; - } - return -EINVAL; -} - -/* At least at the time I'm writing this, Linux doesn't have ACLs, so we - just fake this */ -asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp) -{ - return -ENOSYS; -} - -asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp) -{ - return -ENOSYS; -} - -asmlinkage int solaris_pread(unsigned int fd, char __user *buf, u32 count, u32 pos) -{ - ssize_t (*sys_pread64)(unsigned int, char __user *, size_t, loff_t) = - (ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pread64); - - return sys_pread64(fd, buf, count, (loff_t)pos); -} - -asmlinkage int solaris_pwrite(unsigned int fd, char __user *buf, u32 count, u32 pos) -{ - ssize_t (*sys_pwrite64)(unsigned int, char __user *, size_t, loff_t) = - (ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pwrite64); - - return sys_pwrite64(fd, buf, count, (loff_t)pos); -} - -/* POSIX.1 names */ -#define _PC_LINK_MAX 1 -#define _PC_MAX_CANON 2 -#define _PC_MAX_INPUT 3 -#define _PC_NAME_MAX 4 -#define _PC_PATH_MAX 5 -#define _PC_PIPE_BUF 6 -#define _PC_NO_TRUNC 7 -#define _PC_VDISABLE 8 -#define _PC_CHOWN_RESTRICTED 9 -/* POSIX.4 names */ -#define _PC_ASYNC_IO 10 -#define _PC_PRIO_IO 11 -#define _PC_SYNC_IO 12 -#define _PC_LAST 12 - -/* This is not a real and complete implementation yet, just to keep - * the easy Solaris binaries happy. - */ -asmlinkage int solaris_fpathconf(int fd, int name) -{ - int ret; - - switch(name) { - case _PC_LINK_MAX: - ret = LINK_MAX; - break; - case _PC_MAX_CANON: - ret = MAX_CANON; - break; - case _PC_MAX_INPUT: - ret = MAX_INPUT; - break; - case _PC_NAME_MAX: - ret = NAME_MAX; - break; - case _PC_PATH_MAX: - ret = PATH_MAX; - break; - case _PC_PIPE_BUF: - ret = PIPE_BUF; - break; - case _PC_CHOWN_RESTRICTED: - ret = 1; - break; - case _PC_NO_TRUNC: - case _PC_VDISABLE: - ret = 0; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -asmlinkage int solaris_pathconf(u32 path, int name) -{ - return solaris_fpathconf(0, name); -} - -/* solaris_llseek returns long long - quite difficult */ -asmlinkage long solaris_llseek(struct pt_regs *regs, u32 off_hi, u32 off_lo, int whence) -{ - int (*sys_llseek)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int) = - (int (*)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int))SYS(_llseek); - int ret; - mm_segment_t old_fs = get_fs(); - loff_t retval; - - set_fs(KERNEL_DS); - ret = sys_llseek((unsigned int)regs->u_regs[UREG_I0], off_hi, off_lo, &retval, whence); - set_fs(old_fs); - if (ret < 0) return ret; - regs->u_regs[UREG_I1] = (u32)retval; - return (retval >> 32); -} - -/* Have to mask out all but lower 3 bits */ -asmlinkage int solaris_access(u32 filename, long mode) -{ - int (*sys_access)(const char __user *, int) = - (int (*)(const char __user *, int))SYS(access); - - return sys_access(A(filename), mode & 7); -} diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c deleted file mode 100644 index be0a054e3ed..00000000000 --- a/arch/sparc64/solaris/ioctl.c +++ /dev/null @@ -1,823 +0,0 @@ -/* $Id: ioctl.c,v 1.17 2002/02/08 03:57:14 davem Exp $ - * ioctl.c: Solaris ioctl emulation. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997,1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - * - * Streams & timod emulation based on code - * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) - * - * 1999-08-19 Implemented solaris 'm' (mag tape) and - * 'O' (openprom) ioctls, by Jason Rappleye - * (rappleye@ccr.buffalo.edu) - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/syscalls.h> -#include <linux/ioctl.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/netdevice.h> -#include <linux/mtio.h> -#include <linux/time.h> -#include <linux/rcupdate.h> -#include <linux/compat.h> - -#include <net/sock.h> - -#include <asm/uaccess.h> -#include <asm/termios.h> -#include <asm/openpromio.h> - -#include "conv.h" -#include "socksys.h" - -extern asmlinkage int compat_sys_ioctl(unsigned int fd, unsigned int cmd, - u32 arg); -asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg); - -extern int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len, - char __user *data_buf, int data_len, int flags); -extern int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, int __user *ctl_len, - char __user *data_buf, int data_maxlen, int __user *data_len, int *flags); - -/* termio* stuff {{{ */ - -struct solaris_termios { - u32 c_iflag; - u32 c_oflag; - u32 c_cflag; - u32 c_lflag; - u8 c_cc[19]; -}; - -struct solaris_termio { - u16 c_iflag; - u16 c_oflag; - u16 c_cflag; - u16 c_lflag; - s8 c_line; - u8 c_cc[8]; -}; - -struct solaris_termiox { - u16 x_hflag; - u16 x_cflag; - u16 x_rflag[5]; - u16 x_sflag; -}; - -static u32 solaris_to_linux_cflag(u32 cflag) -{ - cflag &= 0x7fdff000; - if (cflag & 0x200000) { - int baud = cflag & 0xf; - cflag &= ~0x20000f; - switch (baud) { - case 0: baud = B57600; break; - case 1: baud = B76800; break; - case 2: baud = B115200; break; - case 3: baud = B153600; break; - case 4: baud = B230400; break; - case 5: baud = B307200; break; - case 6: baud = B460800; break; - } - cflag |= CBAUDEX | baud; - } - return cflag; -} - -static u32 linux_to_solaris_cflag(u32 cflag) -{ - cflag &= ~(CMSPAR | CIBAUD); - if (cflag & CBAUDEX) { - int baud = cflag & CBAUD; - cflag &= ~CBAUD; - switch (baud) { - case B57600: baud = 0; break; - case B76800: baud = 1; break; - case B115200: baud = 2; break; - case B153600: baud = 3; break; - case B230400: baud = 4; break; - case B307200: baud = 5; break; - case B460800: baud = 6; break; - case B614400: baud = 7; break; - case B921600: baud = 8; break; -#if 0 - case B1843200: baud = 9; break; -#endif - } - cflag |= 0x200000 | baud; - } - return cflag; -} - -static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg) -{ - struct solaris_termio __user *p = A(arg); - int ret; - - ret = sys_ioctl(fd, cmd, (unsigned long)p); - if (!ret) { - u32 cflag; - - if (__get_user (cflag, &p->c_cflag)) - return -EFAULT; - cflag = linux_to_solaris_cflag(cflag); - if (__put_user (cflag, &p->c_cflag)) - return -EFAULT; - } - return ret; -} - -static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - struct solaris_termio s; - mm_segment_t old_fs = get_fs(); - - if (copy_from_user (&s, (struct solaris_termio __user *)A(arg), sizeof(struct solaris_termio))) - return -EFAULT; - s.c_cflag = solaris_to_linux_cflag(s.c_cflag); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long)&s); - set_fs(old_fs); - return ret; -} - -static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - struct solaris_termios s; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long)&s); - set_fs(old_fs); - if (!ret) { - struct solaris_termios __user *p = A(arg); - if (put_user (s.c_iflag, &p->c_iflag) || - __put_user (s.c_oflag, &p->c_oflag) || - __put_user (linux_to_solaris_cflag(s.c_cflag), &p->c_cflag) || - __put_user (s.c_lflag, &p->c_lflag) || - __copy_to_user (p->c_cc, s.c_cc, 16) || - __clear_user (p->c_cc + 16, 2)) - return -EFAULT; - } - return ret; -} - -static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - struct solaris_termios s; - struct solaris_termios __user *p = A(arg); - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, TCGETS, (unsigned long)&s); - set_fs(old_fs); - if (ret) return ret; - if (put_user (s.c_iflag, &p->c_iflag) || - __put_user (s.c_oflag, &p->c_oflag) || - __put_user (s.c_cflag, &p->c_cflag) || - __put_user (s.c_lflag, &p->c_lflag) || - __copy_from_user (s.c_cc, p->c_cc, 16)) - return -EFAULT; - s.c_cflag = solaris_to_linux_cflag(s.c_cflag); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long)&s); - set_fs(old_fs); - return ret; -} - -static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 1: /* TCGETA */ - return linux_to_solaris_termio(fd, TCGETA, arg); - case 2: /* TCSETA */ - return solaris_to_linux_termio(fd, TCSETA, arg); - case 3: /* TCSETAW */ - return solaris_to_linux_termio(fd, TCSETAW, arg); - case 4: /* TCSETAF */ - return solaris_to_linux_termio(fd, TCSETAF, arg); - case 5: /* TCSBRK */ - return sys_ioctl(fd, TCSBRK, arg); - case 6: /* TCXONC */ - return sys_ioctl(fd, TCXONC, arg); - case 7: /* TCFLSH */ - return sys_ioctl(fd, TCFLSH, arg); - case 13: /* TCGETS */ - return linux_to_solaris_termios(fd, TCGETS, arg); - case 14: /* TCSETS */ - return solaris_to_linux_termios(fd, TCSETS, arg); - case 15: /* TCSETSW */ - return solaris_to_linux_termios(fd, TCSETSW, arg); - case 16: /* TCSETSF */ - return solaris_to_linux_termios(fd, TCSETSF, arg); - case 103: /* TIOCSWINSZ */ - return sys_ioctl(fd, TIOCSWINSZ, arg); - case 104: /* TIOCGWINSZ */ - return sys_ioctl(fd, TIOCGWINSZ, arg); - } - return -ENOSYS; -} - -static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 20: /* TIOCGPGRP */ - return sys_ioctl(fd, TIOCGPGRP, arg); - case 21: /* TIOCSPGRP */ - return sys_ioctl(fd, TIOCSPGRP, arg); - } - return -ENOSYS; -} - -/* }}} */ - -/* A pseudo STREAMS support {{{ */ - -struct strioctl { - int cmd, timeout, len; - u32 data; -}; - -struct solaris_si_sockparams { - int sp_family; - int sp_type; - int sp_protocol; -}; - -struct solaris_o_si_udata { - int tidusize; - int addrsize; - int optsize; - int etsdusize; - int servtype; - int so_state; - int so_options; - int tsdusize; -}; - -struct solaris_si_udata { - int tidusize; - int addrsize; - int optsize; - int etsdusize; - int servtype; - int so_state; - int so_options; - int tsdusize; - struct solaris_si_sockparams sockparams; -}; - -#define SOLARIS_MODULE_TIMOD 0 -#define SOLARIS_MODULE_SOCKMOD 1 -#define SOLARIS_MODULE_MAX 2 - -static struct module_info { - const char *name; - /* can be expanded further if needed */ -} module_table[ SOLARIS_MODULE_MAX + 1 ] = { - /* the ordering here must match the module numbers above! */ - { "timod" }, - { "sockmod" }, - { NULL } -}; - -static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) -{ - struct inode *ino; - struct fdtable *fdt; - /* I wonder which of these tests are superfluous... --patrik */ - rcu_read_lock(); - fdt = files_fdtable(current->files); - if (! fdt->fd[fd] || - ! fdt->fd[fd]->f_dentry || - ! (ino = fdt->fd[fd]->f_dentry->d_inode) || - ! S_ISSOCK(ino->i_mode)) { - rcu_read_unlock(); - return TBADF; - } - rcu_read_unlock(); - - switch (cmd & 0xff) { - case 109: /* SI_SOCKPARAMS */ - { - struct solaris_si_sockparams si; - if (copy_from_user (&si, A(arg), sizeof(si))) - return (EFAULT << 8) | TSYSERR; - - /* Should we modify socket ino->socket_i.ops and type? */ - return 0; - } - case 110: /* SI_GETUDATA */ - { - int etsdusize, servtype; - struct solaris_si_udata __user *p = A(arg); - switch (SOCKET_I(ino)->type) { - case SOCK_STREAM: - etsdusize = 1; - servtype = 2; - break; - default: - etsdusize = -2; - servtype = 3; - break; - } - if (put_user(16384, &p->tidusize) || - __put_user(sizeof(struct sockaddr), &p->addrsize) || - __put_user(-1, &p->optsize) || - __put_user(etsdusize, &p->etsdusize) || - __put_user(servtype, &p->servtype) || - __put_user(0, &p->so_state) || - __put_user(0, &p->so_options) || - __put_user(16384, &p->tsdusize) || - __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_family) || - __put_user(SOCKET_I(ino)->type, &p->sockparams.sp_type) || - __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_protocol)) - return (EFAULT << 8) | TSYSERR; - return 0; - } - case 101: /* O_SI_GETUDATA */ - { - int etsdusize, servtype; - struct solaris_o_si_udata __user *p = A(arg); - switch (SOCKET_I(ino)->type) { - case SOCK_STREAM: - etsdusize = 1; - servtype = 2; - break; - default: - etsdusize = -2; - servtype = 3; - break; - } - if (put_user(16384, &p->tidusize) || - __put_user(sizeof(struct sockaddr), &p->addrsize) || - __put_user(-1, &p->optsize) || - __put_user(etsdusize, &p->etsdusize) || - __put_user(servtype, &p->servtype) || - __put_user(0, &p->so_state) || - __put_user(0, &p->so_options) || - __put_user(16384, &p->tsdusize)) - return (EFAULT << 8) | TSYSERR; - return 0; - } - case 102: /* SI_SHUTDOWN */ - case 103: /* SI_LISTEN */ - case 104: /* SI_SETMYNAME */ - case 105: /* SI_SETPEERNAME */ - case 106: /* SI_GETINTRANSIT */ - case 107: /* SI_TCL_LINK */ - case 108: /* SI_TCL_UNLINK */ - ; - } - return TNOTSUPPORT; -} - -static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg, - int len, int __user *len_p) -{ - int ret; - - switch (cmd & 0xff) { - case 141: /* TI_OPTMGMT */ - { - int i; - u32 prim; - SOLD("TI_OPMGMT entry"); - ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0); - SOLD("timod_putmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - i = MSG_HIPRI; - SOLD("calling timod_getmsg()"); - ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i); - SOLD("timod_getmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - SOLD("ret ok"); - if (get_user(prim, (u32 __user *)A(arg))) - return (EFAULT << 8) | TSYSERR; - SOLD("got prim"); - if (prim == T_ERROR_ACK) { - u32 tmp, tmp2; - SOLD("prim is T_ERROR_ACK"); - if (get_user(tmp, (u32 __user *)A(arg)+3) || - get_user(tmp2, (u32 __user *)A(arg)+2)) - return (EFAULT << 8) | TSYSERR; - return (tmp2 << 8) | tmp; - } - SOLD("TI_OPMGMT return 0"); - return 0; - } - case 142: /* TI_BIND */ - { - int i; - u32 prim; - SOLD("TI_BIND entry"); - ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0); - SOLD("timod_putmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - len = 1024; /* Solaris allows arbitrary return size */ - i = MSG_HIPRI; - SOLD("calling timod_getmsg()"); - ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i); - SOLD("timod_getmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - SOLD("ret ok"); - if (get_user(prim, (u32 __user *)A(arg))) - return (EFAULT << 8) | TSYSERR; - SOLD("got prim"); - if (prim == T_ERROR_ACK) { - u32 tmp, tmp2; - SOLD("prim is T_ERROR_ACK"); - if (get_user(tmp, (u32 __user *)A(arg)+3) || - get_user(tmp2, (u32 __user *)A(arg)+2)) - return (EFAULT << 8) | TSYSERR; - return (tmp2 << 8) | tmp; - } - SOLD("no ERROR_ACK requested"); - if (prim != T_OK_ACK) - return TBADSEQ; - SOLD("OK_ACK requested"); - i = MSG_HIPRI; - SOLD("calling timod_getmsg()"); - ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i); - SOLD("timod_getmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - SOLD("TI_BIND return ok"); - return 0; - } - case 140: /* TI_GETINFO */ - case 143: /* TI_UNBIND */ - case 144: /* TI_GETMYNAME */ - case 145: /* TI_GETPEERNAME */ - case 146: /* TI_SETMYNAME */ - case 147: /* TI_SETPEERNAME */ - ; - } - return TNOTSUPPORT; -} - -static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg) -{ - char *p; - int ret; - mm_segment_t old_fs; - struct strioctl si; - struct inode *ino; - struct sol_socket_struct *sock; - struct module_info *mi; - - ino = filp->f_dentry->d_inode; - if (!S_ISSOCK(ino->i_mode)) - return -EBADF; - sock = filp->private_data; - if (! sock) { - printk("solaris_S: NULL private_data\n"); - return -EBADF; - } - if (sock->magic != SOLARIS_SOCKET_MAGIC) { - printk("solaris_S: invalid magic\n"); - return -EBADF; - } - - - switch (cmd & 0xff) { - case 1: /* I_NREAD */ - return -ENOSYS; - case 2: /* I_PUSH */ - { - p = getname (A(arg)); - if (IS_ERR (p)) - return PTR_ERR(p); - ret = -EINVAL; - for (mi = module_table; mi->name; mi++) { - if (strcmp(mi->name, p) == 0) { - sol_module m; - if (sock->modcount >= MAX_NR_STREAM_MODULES) { - ret = -ENXIO; - break; - } - m = (sol_module) (mi - module_table); - sock->module[sock->modcount++] = m; - ret = 0; - break; - } - } - putname (p); - return ret; - } - case 3: /* I_POP */ - if (sock->modcount <= 0) return -EINVAL; - sock->modcount--; - return 0; - case 4: /* I_LOOK */ - { - const char *p; - if (sock->modcount <= 0) return -EINVAL; - p = module_table[(unsigned)sock->module[sock->modcount]].name; - if (copy_to_user (A(arg), p, strlen(p))) - return -EFAULT; - return 0; - } - case 5: /* I_FLUSH */ - return 0; - case 8: /* I_STR */ - if (copy_from_user(&si, A(arg), sizeof(struct strioctl))) - return -EFAULT; - /* We ignore what module is actually at the top of stack. */ - switch ((si.cmd >> 8) & 0xff) { - case 'I': - return solaris_sockmod(fd, si.cmd, si.data); - case 'T': - return solaris_timod(fd, si.cmd, si.data, si.len, - &((struct strioctl __user *)A(arg))->len); - default: - return solaris_ioctl(fd, si.cmd, si.data); - } - case 9: /* I_SETSIG */ - return sys_ioctl(fd, FIOSETOWN, current->pid); - case 10: /* I_GETSIG */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret); - set_fs(old_fs); - if (ret == current->pid) return 0x3ff; - else return -EINVAL; - case 11: /* I_FIND */ - { - int i; - p = getname (A(arg)); - if (IS_ERR (p)) - return PTR_ERR(p); - ret = 0; - for (i = 0; i < sock->modcount; i++) { - unsigned m = sock->module[i]; - if (strcmp(module_table[m].name, p) == 0) { - ret = 1; - break; - } - } - putname (p); - return ret; - } - case 19: /* I_SWROPT */ - case 32: /* I_SETCLTIME */ - return 0; /* Lie */ - } - return -ENOSYS; -} - -static inline int solaris_s(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 0: /* SIOCSHIWAT */ - case 2: /* SIOCSLOWAT */ - return 0; /* We don't support them */ - case 1: /* SIOCGHIWAT */ - case 3: /* SIOCGLOWAT */ - if (put_user (0, (u32 __user *)A(arg))) - return -EFAULT; - return 0; /* Lie */ - case 7: /* SIOCATMARK */ - return sys_ioctl(fd, SIOCATMARK, arg); - case 8: /* SIOCSPGRP */ - return sys_ioctl(fd, SIOCSPGRP, arg); - case 9: /* SIOCGPGRP */ - return sys_ioctl(fd, SIOCGPGRP, arg); - } - return -ENOSYS; -} - -static inline int solaris_r(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 10: /* SIOCADDRT */ - return compat_sys_ioctl(fd, SIOCADDRT, arg); - case 11: /* SIOCDELRT */ - return compat_sys_ioctl(fd, SIOCDELRT, arg); - } - return -ENOSYS; -} - -static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 12: /* SIOCSIFADDR */ - return compat_sys_ioctl(fd, SIOCSIFADDR, arg); - case 13: /* SIOCGIFADDR */ - return compat_sys_ioctl(fd, SIOCGIFADDR, arg); - case 14: /* SIOCSIFDSTADDR */ - return compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg); - case 15: /* SIOCGIFDSTADDR */ - return compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg); - case 16: /* SIOCSIFFLAGS */ - return compat_sys_ioctl(fd, SIOCSIFFLAGS, arg); - case 17: /* SIOCGIFFLAGS */ - return compat_sys_ioctl(fd, SIOCGIFFLAGS, arg); - case 18: /* SIOCSIFMEM */ - return compat_sys_ioctl(fd, SIOCSIFMEM, arg); - case 19: /* SIOCGIFMEM */ - return compat_sys_ioctl(fd, SIOCGIFMEM, arg); - case 20: /* SIOCGIFCONF */ - return compat_sys_ioctl(fd, SIOCGIFCONF, arg); - case 21: /* SIOCSIFMTU */ - return compat_sys_ioctl(fd, SIOCSIFMTU, arg); - case 22: /* SIOCGIFMTU */ - return compat_sys_ioctl(fd, SIOCGIFMTU, arg); - case 23: /* SIOCGIFBRDADDR */ - return compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg); - case 24: /* SIOCSIFBRDADDR */ - return compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg); - case 25: /* SIOCGIFNETMASK */ - return compat_sys_ioctl(fd, SIOCGIFNETMASK, arg); - case 26: /* SIOCSIFNETMASK */ - return compat_sys_ioctl(fd, SIOCSIFNETMASK, arg); - case 27: /* SIOCGIFMETRIC */ - return compat_sys_ioctl(fd, SIOCGIFMETRIC, arg); - case 28: /* SIOCSIFMETRIC */ - return compat_sys_ioctl(fd, SIOCSIFMETRIC, arg); - case 30: /* SIOCSARP */ - return compat_sys_ioctl(fd, SIOCSARP, arg); - case 31: /* SIOCGARP */ - return compat_sys_ioctl(fd, SIOCGARP, arg); - case 32: /* SIOCDARP */ - return compat_sys_ioctl(fd, SIOCDARP, arg); - case 52: /* SIOCGETNAME */ - case 53: /* SIOCGETPEER */ - { - struct sockaddr uaddr; - int uaddr_len = sizeof(struct sockaddr), ret; - long args[3]; - mm_segment_t old_fs = get_fs(); - int (*sys_socketcall)(int, unsigned long *) = - (int (*)(int, unsigned long *))SYS(socketcall); - - args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len; - set_fs(KERNEL_DS); - ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME, - args); - set_fs(old_fs); - if (ret >= 0) { - if (copy_to_user(A(arg), &uaddr, uaddr_len)) - return -EFAULT; - } - return ret; - } -#if 0 - case 86: /* SIOCSOCKSYS */ - return socksys_syscall(fd, arg); -#endif - case 87: /* SIOCGIFNUM */ - { - struct net_device *d; - int i = 0; - - read_lock_bh(&dev_base_lock); - for (d = dev_base; d; d = d->next) i++; - read_unlock_bh(&dev_base_lock); - - if (put_user (i, (int __user *)A(arg))) - return -EFAULT; - return 0; - } - } - return -ENOSYS; -} - -static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - - switch (cmd & 0xff) { - case 1: /* MTIOCTOP */ - ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg); - break; - case 2: /* MTIOCGET */ - ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg); - break; - case 3: /* MTIOCGETDRIVETYPE */ - case 4: /* MTIOCPERSISTENT */ - case 5: /* MTIOCPERSISTENTSTATUS */ - case 6: /* MTIOCLRERR */ - case 7: /* MTIOCGUARANTEEDORDER */ - case 8: /* MTIOCRESERVE */ - case 9: /* MTIOCRELEASE */ - case 10: /* MTIOCFORCERESERVE */ - case 13: /* MTIOCSTATE */ - case 14: /* MTIOCREADIGNOREILI */ - case 15: /* MTIOCREADIGNOREEOFS */ - case 16: /* MTIOCSHORTFMK */ - default: - ret = -ENOSYS; /* linux doesn't support these */ - break; - }; - - return ret; -} - -static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret = -EINVAL; - - switch (cmd & 0xff) { - case 1: /* OPROMGETOPT */ - ret = sys_ioctl(fd, OPROMGETOPT, arg); - break; - case 2: /* OPROMSETOPT */ - ret = sys_ioctl(fd, OPROMSETOPT, arg); - break; - case 3: /* OPROMNXTOPT */ - ret = sys_ioctl(fd, OPROMNXTOPT, arg); - break; - case 4: /* OPROMSETOPT2 */ - ret = sys_ioctl(fd, OPROMSETOPT2, arg); - break; - case 5: /* OPROMNEXT */ - ret = sys_ioctl(fd, OPROMNEXT, arg); - break; - case 6: /* OPROMCHILD */ - ret = sys_ioctl(fd, OPROMCHILD, arg); - break; - case 7: /* OPROMGETPROP */ - ret = sys_ioctl(fd, OPROMGETPROP, arg); - break; - case 8: /* OPROMNXTPROP */ - ret = sys_ioctl(fd, OPROMNXTPROP, arg); - break; - case 9: /* OPROMU2P */ - ret = sys_ioctl(fd, OPROMU2P, arg); - break; - case 10: /* OPROMGETCONS */ - ret = sys_ioctl(fd, OPROMGETCONS, arg); - break; - case 11: /* OPROMGETFBNAME */ - ret = sys_ioctl(fd, OPROMGETFBNAME, arg); - break; - case 12: /* OPROMGETBOOTARGS */ - ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg); - break; - case 13: /* OPROMGETVERSION */ - case 14: /* OPROMPATH2DRV */ - case 15: /* OPROMDEV2PROMNAME */ - case 16: /* OPROMPROM2DEVNAME */ - case 17: /* OPROMGETPROPLEN */ - default: - ret = -EINVAL; - break; - }; - return ret; -} - -/* }}} */ - -asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg) -{ - struct file *filp; - int error = -EBADF; - - filp = fget(fd); - if (!filp) - goto out; - - lock_kernel(); - error = -EFAULT; - switch ((cmd >> 8) & 0xff) { - case 'S': error = solaris_S(filp, fd, cmd, arg); break; - case 'T': error = solaris_T(fd, cmd, arg); break; - case 'i': error = solaris_i(fd, cmd, arg); break; - case 'r': error = solaris_r(fd, cmd, arg); break; - case 's': error = solaris_s(fd, cmd, arg); break; - case 't': error = solaris_t(fd, cmd, arg); break; - case 'f': error = sys_ioctl(fd, cmd, arg); break; - case 'm': error = solaris_m(fd, cmd, arg); break; - case 'O': error = solaris_O(fd, cmd, arg); break; - default: - error = -ENOSYS; - break; - } - unlock_kernel(); - fput(filp); -out: - if (error == -ENOSYS) { - unsigned char c = cmd>>8; - - if (c < ' ' || c > 126) c = '.'; - printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n", - (int)fd, (unsigned int)cmd, c, (unsigned int)arg); - error = -EINVAL; - } - return error; -} diff --git a/arch/sparc64/solaris/ipc.c b/arch/sparc64/solaris/ipc.c deleted file mode 100644 index 8cef5fd57b2..00000000000 --- a/arch/sparc64/solaris/ipc.c +++ /dev/null @@ -1,127 +0,0 @@ -/* $Id: ipc.c,v 1.5 1999/12/09 00:41:00 davem Exp $ - * ipc.c: Solaris IPC emulation - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/smp_lock.h> -#include <linux/wait.h> -#include <linux/mm.h> -#include <linux/shm.h> -#include <linux/sem.h> -#include <linux/msg.h> - -#include <asm/uaccess.h> -#include <asm/string.h> -#include <asm/ipc.h> - -#include "conv.h" - -struct solaris_ipc_perm { - s32 uid; - s32 gid; - s32 cuid; - s32 cgid; - u32 mode; - u32 seq; - int key; - s32 pad[4]; -}; - -struct solaris_shmid_ds { - struct solaris_ipc_perm shm_perm; - int shm_segsz; - u32 shm_amp; - unsigned short shm_lkcnt; - char __padxx[2]; - s32 shm_lpid; - s32 shm_cpid; - u32 shm_nattch; - u32 shm_cnattch; - s32 shm_atime; - s32 shm_pad1; - s32 shm_dtime; - s32 shm_pad2; - s32 shm_ctime; - s32 shm_pad3; - unsigned short shm_cv; - char shm_pad4[2]; - u32 shm_sptas; - s32 shm_pad5[2]; -}; - -asmlinkage long solaris_shmsys(int cmd, u32 arg1, u32 arg2, u32 arg3) -{ - int (*sys_ipc)(unsigned,int,int,unsigned long,void __user *,long) = - (int (*)(unsigned,int,int,unsigned long,void __user *,long))SYS(ipc); - mm_segment_t old_fs; - unsigned long raddr; - int ret; - - switch (cmd) { - case 0: /* shmat */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ipc(SHMAT, arg1, arg3 & ~0x4000, (unsigned long)&raddr, A(arg2), 0); - set_fs(old_fs); - if (ret >= 0) return (u32)raddr; - else return ret; - case 1: /* shmctl */ - switch (arg2) { - case 3: /* SHM_LOCK */ - case 4: /* SHM_UNLOCK */ - return sys_ipc(SHMCTL, arg1, (arg2 == 3) ? SHM_LOCK : SHM_UNLOCK, 0, NULL, 0); - case 10: /* IPC_RMID */ - return sys_ipc(SHMCTL, arg1, IPC_RMID, 0, NULL, 0); - case 11: /* IPC_SET */ - { - struct shmid_ds s; - struct solaris_shmid_ds __user *p = A(arg3); - - if (get_user (s.shm_perm.uid, &p->shm_perm.uid) || - __get_user (s.shm_perm.gid, &p->shm_perm.gid) || - __get_user (s.shm_perm.mode, &p->shm_perm.mode)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); - set_fs(old_fs); - return ret; - } - case 12: /* IPC_STAT */ - { - struct shmid_ds s; - struct solaris_shmid_ds __user *p = A(arg3); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); - set_fs(old_fs); - if (put_user (s.shm_perm.uid, &(p->shm_perm.uid)) || - __put_user (s.shm_perm.gid, &(p->shm_perm.gid)) || - __put_user (s.shm_perm.cuid, &(p->shm_perm.cuid)) || - __put_user (s.shm_perm.cgid, &(p->shm_perm.cgid)) || - __put_user (s.shm_perm.mode, &(p->shm_perm.mode)) || - __put_user (s.shm_perm.seq, &(p->shm_perm.seq)) || - __put_user (s.shm_perm.key, &(p->shm_perm.key)) || - __put_user (s.shm_segsz, &(p->shm_segsz)) || - __put_user (s.shm_lpid, &(p->shm_lpid)) || - __put_user (s.shm_cpid, &(p->shm_cpid)) || - __put_user (s.shm_nattch, &(p->shm_nattch)) || - __put_user (s.shm_atime, &(p->shm_atime)) || - __put_user (s.shm_dtime, &(p->shm_dtime)) || - __put_user (s.shm_ctime, &(p->shm_ctime))) - return -EFAULT; - return ret; - } - default: return -EINVAL; - } - case 2: /* shmdt */ - return sys_ipc(SHMDT, 0, 0, 0, A(arg1), 0); - case 3: /* shmget */ - return sys_ipc(SHMGET, arg1, arg2, arg3, NULL, 0); - } - return -EINVAL; -} diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c deleted file mode 100644 index 3ab4677395f..00000000000 --- a/arch/sparc64/solaris/misc.c +++ /dev/null @@ -1,786 +0,0 @@ -/* $Id: misc.c,v 1.36 2002/02/09 19:49:31 davem Exp $ - * misc.c: Miscellaneous syscall emulation for Solaris - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/smp_lock.h> -#include <linux/utsname.h> -#include <linux/limits.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/mman.h> -#include <linux/file.h> -#include <linux/timex.h> -#include <linux/major.h> -#include <linux/compat.h> - -#include <asm/uaccess.h> -#include <asm/string.h> -#include <asm/oplib.h> -#include <asm/idprom.h> -#include <asm/smp.h> - -#include "conv.h" - -/* Conversion from Linux to Solaris errnos. 0-34 are identity mapped. - Some Linux errnos (EPROCLIM, EDOTDOT, ERREMOTE, EUCLEAN, ENOTNAM, - ENAVAIL, EISNAM, EREMOTEIO, ENOMEDIUM, EMEDIUMTYPE) have no Solaris - equivalents. I return EINVAL in that case, which is very wrong. If - someone suggest a better value for them, you're welcomed. - On the other side, Solaris ECANCELED and ENOTSUP have no Linux equivalents, - but that doesn't matter here. --jj */ -int solaris_err_table[] = { -/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -/* 10 */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -/* 20 */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -/* 30 */ 30, 31, 32, 33, 34, 22, 150, 149, 95, 96, -/* 40 */ 97, 98, 99, 120, 121, 122, 123, 124, 125, 126, -/* 50 */ 127, 128, 129, 130, 131, 132, 133, 134, 143, 144, -/* 60 */ 145, 146, 90, 78, 147, 148, 93, 22, 94, 49, -/* 70 */ 151, 66, 60, 62, 63, 35, 77, 36, 45, 46, -/* 80 */ 64, 22, 67, 68, 69, 70, 71, 74, 22, 82, -/* 90 */ 89, 92, 79, 81, 37, 38, 39, 40, 41, 42, -/* 100 */ 43, 44, 50, 51, 52, 53, 54, 55, 56, 57, -/* 110 */ 87, 61, 84, 65, 83, 80, 91, 22, 22, 22, -/* 120 */ 22, 22, 88, 86, 85, 22, 22, -}; - -#define SOLARIS_NR_OPEN 256 - -static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off) -{ - struct file *file = NULL; - unsigned long retval, ret_type; - - /* Do we need it here? */ - set_personality(PER_SVR4); - if (flags & MAP_NORESERVE) { - static int cnt; - - if (cnt < 5) { - printk("%s: unimplemented Solaris MAP_NORESERVE mmap() flag\n", - current->comm); - cnt++; - } - flags &= ~MAP_NORESERVE; - } - retval = -EBADF; - if(!(flags & MAP_ANONYMOUS)) { - if(fd >= SOLARIS_NR_OPEN) - goto out; - file = fget(fd); - if (!file) - goto out; - else { - struct inode * inode = file->f_dentry->d_inode; - if(imajor(inode) == MEM_MAJOR && - iminor(inode) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } - } - } - - retval = -EINVAL; - len = PAGE_ALIGN(len); - if(!(flags & MAP_FIXED)) - addr = 0; - else if (len > 0xf0000000UL || addr > 0xf0000000UL - len) - goto out_putf; - ret_type = flags & _MAP_NEW; - flags &= ~_MAP_NEW; - - down_write(¤t->mm->mmap_sem); - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - retval = do_mmap(file, - (unsigned long) addr, (unsigned long) len, - (unsigned long) prot, (unsigned long) flags, off); - up_write(¤t->mm->mmap_sem); - if(!ret_type) - retval = ((retval < 0xf0000000) ? 0 : retval); - -out_putf: - if (file) - fput(file); -out: - return (u32) retval; -} - -asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off) -{ - return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off); -} - -asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi) -{ - u32 offlo; - - if (regs->u_regs[UREG_G1]) { - if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c))) - return -EFAULT; - } else { - if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x60))) - return -EFAULT; - } - return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo); -} - -asmlinkage int solaris_brk(u32 brk) -{ - int (*sunos_brk)(u32) = (int (*)(u32))SUNOS(17); - - return sunos_brk(brk); -} - -static int __set_utsfield(char __user *to, int to_size, - const char *from, int from_size, - int dotchop, int countfrom) -{ - int len = countfrom ? (to_size > from_size ? - from_size : to_size) : to_size; - int off; - - if (copy_to_user(to, from, len)) - return -EFAULT; - - off = len < to_size? len: len - 1; - if (dotchop) { - const char *p = strnchr(from, len, '.'); - if (p) off = p - from; - } - - if (__put_user('\0', to + off)) - return -EFAULT; - - return 0; -} - -#define set_utsfield(to, from, dotchop, countfrom) \ - __set_utsfield((to), sizeof(to), \ - (from), sizeof(from), \ - (dotchop), (countfrom)) - -struct sol_uname { - char sysname[9]; - char nodename[9]; - char release[9]; - char version[9]; - char machine[9]; -}; - -struct sol_utsname { - char sysname[257]; - char nodename[257]; - char release[257]; - char version[257]; - char machine[257]; -}; - -static char *machine(void) -{ - switch (sparc_cpu_model) { - case sun4: return "sun4"; - case sun4c: return "sun4c"; - case sun4e: return "sun4e"; - case sun4m: return "sun4m"; - case sun4d: return "sun4d"; - case sun4u: return "sun4u"; - default: return "sparc"; - } -} - -static char *platform(char *buffer) -{ - int len; - - *buffer = 0; - len = prom_getproperty(prom_root_node, "name", buffer, 256); - if(len > 0) - buffer[len] = 0; - if (*buffer) { - char *p; - - for (p = buffer; *p; p++) - if (*p == '/' || *p == ' ') *p = '_'; - return buffer; - } - - return "sun4u"; -} - -static char *serial(char *buffer) -{ - int node = prom_getchild(prom_root_node); - int len; - - node = prom_searchsiblings(node, "options"); - *buffer = 0; - len = prom_getproperty(node, "system-board-serial#", buffer, 256); - if(len > 0) - buffer[len] = 0; - if (!*buffer) - return "4512348717234"; - else - return buffer; -} - -asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2) -{ - struct sol_uname __user *v = A(buf); - int err; - - switch (which) { - case 0: /* old uname */ - /* Let's cheat */ - err = set_utsfield(v->sysname, "SunOS", 1, 0); - down_read(&uts_sem); - err |= set_utsfield(v->nodename, system_utsname.nodename, - 1, 1); - up_read(&uts_sem); - err |= set_utsfield(v->release, "2.6", 0, 0); - err |= set_utsfield(v->version, "Generic", 0, 0); - err |= set_utsfield(v->machine, machine(), 0, 0); - return (err ? -EFAULT : 0); - case 2: /* ustat */ - return -ENOSYS; - case 3: /* fusers */ - return -ENOSYS; - default: - return -ENOSYS; - } -} - -asmlinkage int solaris_utsname(u32 buf) -{ - struct sol_utsname __user *v = A(buf); - int err; - - /* Why should we not lie a bit? */ - down_read(&uts_sem); - err = set_utsfield(v->sysname, "SunOS", 0, 0); - err |= set_utsfield(v->nodename, system_utsname.nodename, 1, 1); - err |= set_utsfield(v->release, "5.6", 0, 0); - err |= set_utsfield(v->version, "Generic", 0, 0); - err |= set_utsfield(v->machine, machine(), 0, 0); - up_read(&uts_sem); - - return (err ? -EFAULT : 0); -} - -#define SI_SYSNAME 1 /* return name of operating system */ -#define SI_HOSTNAME 2 /* return name of node */ -#define SI_RELEASE 3 /* return release of operating system */ -#define SI_VERSION 4 /* return version field of utsname */ -#define SI_MACHINE 5 /* return kind of machine */ -#define SI_ARCHITECTURE 6 /* return instruction set arch */ -#define SI_HW_SERIAL 7 /* return hardware serial number */ -#define SI_HW_PROVIDER 8 /* return hardware manufacturer */ -#define SI_SRPC_DOMAIN 9 /* return secure RPC domain */ -#define SI_PLATFORM 513 /* return platform identifier */ - -asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count) -{ - char *p, *q, *r; - char buffer[256]; - int len; - - /* Again, we cheat :)) */ - switch (cmd) { - case SI_SYSNAME: r = "SunOS"; break; - case SI_HOSTNAME: - r = buffer + 256; - down_read(&uts_sem); - for (p = system_utsname.nodename, q = buffer; - q < r && *p && *p != '.'; *q++ = *p++); - up_read(&uts_sem); - *q = 0; - r = buffer; - break; - case SI_RELEASE: r = "5.6"; break; - case SI_MACHINE: r = machine(); break; - case SI_ARCHITECTURE: r = "sparc"; break; - case SI_HW_PROVIDER: r = "Sun_Microsystems"; break; - case SI_HW_SERIAL: r = serial(buffer); break; - case SI_PLATFORM: r = platform(buffer); break; - case SI_SRPC_DOMAIN: r = ""; break; - case SI_VERSION: r = "Generic"; break; - default: return -EINVAL; - } - len = strlen(r) + 1; - if (count < len) { - if (copy_to_user(A(buf), r, count - 1) || - __put_user(0, (char __user *)A(buf) + count - 1)) - return -EFAULT; - } else { - if (copy_to_user(A(buf), r, len)) - return -EFAULT; - } - return len; -} - -#define SOLARIS_CONFIG_NGROUPS 2 -#define SOLARIS_CONFIG_CHILD_MAX 3 -#define SOLARIS_CONFIG_OPEN_FILES 4 -#define SOLARIS_CONFIG_POSIX_VER 5 -#define SOLARIS_CONFIG_PAGESIZE 6 -#define SOLARIS_CONFIG_CLK_TCK 7 -#define SOLARIS_CONFIG_XOPEN_VER 8 -#define SOLARIS_CONFIG_PROF_TCK 10 -#define SOLARIS_CONFIG_NPROC_CONF 11 -#define SOLARIS_CONFIG_NPROC_ONLN 12 -#define SOLARIS_CONFIG_AIO_LISTIO_MAX 13 -#define SOLARIS_CONFIG_AIO_MAX 14 -#define SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX 15 -#define SOLARIS_CONFIG_DELAYTIMER_MAX 16 -#define SOLARIS_CONFIG_MQ_OPEN_MAX 17 -#define SOLARIS_CONFIG_MQ_PRIO_MAX 18 -#define SOLARIS_CONFIG_RTSIG_MAX 19 -#define SOLARIS_CONFIG_SEM_NSEMS_MAX 20 -#define SOLARIS_CONFIG_SEM_VALUE_MAX 21 -#define SOLARIS_CONFIG_SIGQUEUE_MAX 22 -#define SOLARIS_CONFIG_SIGRT_MIN 23 -#define SOLARIS_CONFIG_SIGRT_MAX 24 -#define SOLARIS_CONFIG_TIMER_MAX 25 -#define SOLARIS_CONFIG_PHYS_PAGES 26 -#define SOLARIS_CONFIG_AVPHYS_PAGES 27 - -asmlinkage int solaris_sysconf(int id) -{ - switch (id) { - case SOLARIS_CONFIG_NGROUPS: return NGROUPS_MAX; - case SOLARIS_CONFIG_CHILD_MAX: return -1; /* no limit */ - case SOLARIS_CONFIG_OPEN_FILES: return OPEN_MAX; - case SOLARIS_CONFIG_POSIX_VER: return 199309; - case SOLARIS_CONFIG_PAGESIZE: return PAGE_SIZE; - case SOLARIS_CONFIG_XOPEN_VER: return 3; - case SOLARIS_CONFIG_CLK_TCK: - case SOLARIS_CONFIG_PROF_TCK: - return sparc64_get_clock_tick(smp_processor_id()); -#ifdef CONFIG_SMP - case SOLARIS_CONFIG_NPROC_CONF: return NR_CPUS; - case SOLARIS_CONFIG_NPROC_ONLN: return num_online_cpus(); -#else - case SOLARIS_CONFIG_NPROC_CONF: return 1; - case SOLARIS_CONFIG_NPROC_ONLN: return 1; -#endif - case SOLARIS_CONFIG_SIGRT_MIN: return 37; - case SOLARIS_CONFIG_SIGRT_MAX: return 44; - case SOLARIS_CONFIG_PHYS_PAGES: - case SOLARIS_CONFIG_AVPHYS_PAGES: - { - struct sysinfo s; - - si_meminfo(&s); - if (id == SOLARIS_CONFIG_PHYS_PAGES) - return s.totalram >>= PAGE_SHIFT; - else - return s.freeram >>= PAGE_SHIFT; - } - /* XXX support these as well -jj */ - case SOLARIS_CONFIG_AIO_LISTIO_MAX: return -EINVAL; - case SOLARIS_CONFIG_AIO_MAX: return -EINVAL; - case SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX: return -EINVAL; - case SOLARIS_CONFIG_DELAYTIMER_MAX: return -EINVAL; - case SOLARIS_CONFIG_MQ_OPEN_MAX: return -EINVAL; - case SOLARIS_CONFIG_MQ_PRIO_MAX: return -EINVAL; - case SOLARIS_CONFIG_RTSIG_MAX: return -EINVAL; - case SOLARIS_CONFIG_SEM_NSEMS_MAX: return -EINVAL; - case SOLARIS_CONFIG_SEM_VALUE_MAX: return -EINVAL; - case SOLARIS_CONFIG_SIGQUEUE_MAX: return -EINVAL; - case SOLARIS_CONFIG_TIMER_MAX: return -EINVAL; - default: return -EINVAL; - } -} - -asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) -{ - int ret; - - switch (cmd) { - case 0: /* getpgrp */ - return process_group(current); - case 1: /* setpgrp */ - { - int (*sys_setpgid)(pid_t,pid_t) = - (int (*)(pid_t,pid_t))SYS(setpgid); - - /* can anyone explain me the difference between - Solaris setpgrp and setsid? */ - ret = sys_setpgid(0, 0); - if (ret) return ret; - current->signal->tty = NULL; - return process_group(current); - } - case 2: /* getsid */ - { - int (*sys_getsid)(pid_t) = (int (*)(pid_t))SYS(getsid); - return sys_getsid(pid); - } - case 3: /* setsid */ - { - int (*sys_setsid)(void) = (int (*)(void))SYS(setsid); - return sys_setsid(); - } - case 4: /* getpgid */ - { - int (*sys_getpgid)(pid_t) = (int (*)(pid_t))SYS(getpgid); - return sys_getpgid(pid); - } - case 5: /* setpgid */ - { - int (*sys_setpgid)(pid_t,pid_t) = - (int (*)(pid_t,pid_t))SYS(setpgid); - return sys_setpgid(pid,pgid); - } - } - return -EINVAL; -} - -asmlinkage int solaris_gettimeofday(u32 tim) -{ - int (*sys_gettimeofday)(struct timeval *, struct timezone *) = - (int (*)(struct timeval *, struct timezone *))SYS(gettimeofday); - - return sys_gettimeofday((struct timeval *)(u64)tim, NULL); -} - -#define RLIM_SOL_INFINITY32 0x7fffffff -#define RLIM_SOL_SAVED_MAX32 0x7ffffffe -#define RLIM_SOL_SAVED_CUR32 0x7ffffffd -#define RLIM_SOL_INFINITY ((u64)-3) -#define RLIM_SOL_SAVED_MAX ((u64)-2) -#define RLIM_SOL_SAVED_CUR ((u64)-1) -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) -#define RLIMIT_SOL_NOFILE 5 -#define RLIMIT_SOL_VMEM 6 - -struct rlimit32 { - u32 rlim_cur; - u32 rlim_max; -}; - -asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 __user *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit *) = - (int (*)(unsigned int, struct rlimit *))SYS(getrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs (old_fs); - if (!ret) { - if (r.rlim_cur == RLIM_INFINITY) - r.rlim_cur = RLIM_SOL_INFINITY32; - else if ((u64)r.rlim_cur > RLIM_SOL_INFINITY32) - r.rlim_cur = RLIM_SOL_SAVED_CUR32; - if (r.rlim_max == RLIM_INFINITY) - r.rlim_max = RLIM_SOL_INFINITY32; - else if ((u64)r.rlim_max > RLIM_SOL_INFINITY32) - r.rlim_max = RLIM_SOL_SAVED_MAX32; - ret = put_user (r.rlim_cur, &rlim->rlim_cur); - ret |= __put_user (r.rlim_max, &rlim->rlim_max); - } - return ret; -} - -asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 __user *rlim) -{ - struct rlimit r, rold; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit); - int (*sys_setrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &rold); - if (!ret) { - if (r.rlim_cur == RLIM_SOL_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - else if (r.rlim_cur == RLIM_SOL_SAVED_CUR32) - r.rlim_cur = rold.rlim_cur; - else if (r.rlim_cur == RLIM_SOL_SAVED_MAX32) - r.rlim_cur = rold.rlim_max; - if (r.rlim_max == RLIM_SOL_INFINITY32) - r.rlim_max = RLIM_INFINITY; - else if (r.rlim_max == RLIM_SOL_SAVED_CUR32) - r.rlim_max = rold.rlim_cur; - else if (r.rlim_max == RLIM_SOL_SAVED_MAX32) - r.rlim_max = rold.rlim_max; - ret = sys_setrlimit(resource, &r); - } - set_fs (old_fs); - return ret; -} - -asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit __user *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs (old_fs); - if (!ret) { - if (r.rlim_cur == RLIM_INFINITY) - r.rlim_cur = RLIM_SOL_INFINITY; - if (r.rlim_max == RLIM_INFINITY) - r.rlim_max = RLIM_SOL_INFINITY; - ret = put_user (r.rlim_cur, &rlim->rlim_cur); - ret |= __put_user (r.rlim_max, &rlim->rlim_max); - } - return ret; -} - -asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit __user *rlim) -{ - struct rlimit r, rold; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit); - int (*sys_setrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &rold); - if (!ret) { - if (r.rlim_cur == RLIM_SOL_INFINITY) - r.rlim_cur = RLIM_INFINITY; - else if (r.rlim_cur == RLIM_SOL_SAVED_CUR) - r.rlim_cur = rold.rlim_cur; - else if (r.rlim_cur == RLIM_SOL_SAVED_MAX) - r.rlim_cur = rold.rlim_max; - if (r.rlim_max == RLIM_SOL_INFINITY) - r.rlim_max = RLIM_INFINITY; - else if (r.rlim_max == RLIM_SOL_SAVED_CUR) - r.rlim_max = rold.rlim_cur; - else if (r.rlim_max == RLIM_SOL_SAVED_MAX) - r.rlim_max = rold.rlim_max; - ret = sys_setrlimit(resource, &r); - } - set_fs (old_fs); - return ret; -} - -struct sol_ntptimeval { - struct compat_timeval time; - s32 maxerror; - s32 esterror; -}; - -struct sol_timex { - u32 modes; - s32 offset; - s32 freq; - s32 maxerror; - s32 esterror; - s32 status; - s32 constant; - s32 precision; - s32 tolerance; - s32 ppsfreq; - s32 jitter; - s32 shift; - s32 stabil; - s32 jitcnt; - s32 calcnt; - s32 errcnt; - s32 stbcnt; -}; - -asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval __user *ntp) -{ - int (*sys_adjtimex)(struct timex __user *) = - (int (*)(struct timex __user *))SYS(adjtimex); - struct timex t; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - t.modes = 0; - ret = sys_adjtimex(&t); - set_fs(old_fs); - if (ret < 0) - return ret; - ret = put_user (t.time.tv_sec, &ntp->time.tv_sec); - ret |= __put_user (t.time.tv_usec, &ntp->time.tv_usec); - ret |= __put_user (t.maxerror, &ntp->maxerror); - ret |= __put_user (t.esterror, &ntp->esterror); - return ret; -} - -asmlinkage int solaris_ntp_adjtime(struct sol_timex __user *txp) -{ - int (*sys_adjtimex)(struct timex __user *) = - (int (*)(struct timex __user *))SYS(adjtimex); - struct timex t; - int ret, err; - mm_segment_t old_fs = get_fs(); - - ret = get_user (t.modes, &txp->modes); - ret |= __get_user (t.offset, &txp->offset); - ret |= __get_user (t.freq, &txp->freq); - ret |= __get_user (t.maxerror, &txp->maxerror); - ret |= __get_user (t.esterror, &txp->esterror); - ret |= __get_user (t.status, &txp->status); - ret |= __get_user (t.constant, &txp->constant); - set_fs(KERNEL_DS); - ret = sys_adjtimex(&t); - set_fs(old_fs); - if (ret < 0) - return ret; - err = put_user (t.offset, &txp->offset); - err |= __put_user (t.freq, &txp->freq); - err |= __put_user (t.maxerror, &txp->maxerror); - err |= __put_user (t.esterror, &txp->esterror); - err |= __put_user (t.status, &txp->status); - err |= __put_user (t.constant, &txp->constant); - err |= __put_user (t.precision, &txp->precision); - err |= __put_user (t.tolerance, &txp->tolerance); - err |= __put_user (t.ppsfreq, &txp->ppsfreq); - err |= __put_user (t.jitter, &txp->jitter); - err |= __put_user (t.shift, &txp->shift); - err |= __put_user (t.stabil, &txp->stabil); - err |= __put_user (t.jitcnt, &txp->jitcnt); - err |= __put_user (t.calcnt, &txp->calcnt); - err |= __put_user (t.errcnt, &txp->errcnt); - err |= __put_user (t.stbcnt, &txp->stbcnt); - if (err) - return -EFAULT; - return ret; -} - -asmlinkage int do_sol_unimplemented(struct pt_regs *regs) -{ - printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n", - (int)regs->u_regs[UREG_G1], - (int)regs->u_regs[UREG_I0], - (int)regs->u_regs[UREG_I1], - (int)regs->u_regs[UREG_I2], - (int)regs->u_regs[UREG_I3]); - return -ENOSYS; -} - -asmlinkage void solaris_register(void) -{ - set_personality(PER_SVR4); -} - -extern long solaris_to_linux_signals[], linux_to_solaris_signals[]; - -struct exec_domain solaris_exec_domain = { - .name = "Solaris", - .handler = NULL, - .pers_low = 1, /* PER_SVR4 personality */ - .pers_high = 1, - .signal_map = solaris_to_linux_signals, - .signal_invmap =linux_to_solaris_signals, - .module = THIS_MODULE, - .next = NULL -}; - -extern int init_socksys(void); - -#ifdef MODULE - -MODULE_AUTHOR("Jakub Jelinek (jj@ultra.linux.cz), Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)"); -MODULE_DESCRIPTION("Solaris binary emulation module"); -MODULE_LICENSE("GPL"); - -#ifdef __sparc_v9__ -extern u32 tl0_solaris[8]; -#define update_ttable(x) \ - tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \ - wmb(); \ - __asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3])) -#else -#endif - -extern u32 solaris_sparc_syscall[]; -extern u32 solaris_syscall[]; -extern void cleanup_socksys(void); - -extern u32 entry64_personality_patch; - -int init_module(void) -{ - int ret; - - SOLDD(("Solaris module at %p\n", solaris_sparc_syscall)); - register_exec_domain(&solaris_exec_domain); - if ((ret = init_socksys())) { - unregister_exec_domain(&solaris_exec_domain); - return ret; - } - update_ttable(solaris_sparc_syscall); - entry64_personality_patch |= - (offsetof(struct task_struct, personality) + - (sizeof(unsigned long) - 1)); - wmb(); - __asm__ __volatile__("flush %0" - : : "r" (&entry64_personality_patch)); - return 0; -} - -void cleanup_module(void) -{ - update_ttable(solaris_syscall); - cleanup_socksys(); - unregister_exec_domain(&solaris_exec_domain); -} - -#else -int init_solaris_emul(void) -{ - register_exec_domain(&solaris_exec_domain); - init_socksys(); - return 0; -} -#endif - diff --git a/arch/sparc64/solaris/signal.c b/arch/sparc64/solaris/signal.c deleted file mode 100644 index 7fa2634e208..00000000000 --- a/arch/sparc64/solaris/signal.c +++ /dev/null @@ -1,430 +0,0 @@ -/* $Id: signal.c,v 1.7 2000/09/05 21:44:54 davem Exp $ - * signal.c: Signal emulation for Solaris - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include <linux/types.h> -#include <linux/smp_lock.h> -#include <linux/errno.h> - -#include <asm/uaccess.h> -#include <asm/svr4.h> -#include <asm/string.h> - -#include "conv.h" -#include "signal.h" - -#define _S(nr) (1L<<((nr)-1)) - -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) - -long linux_to_solaris_signals[] = { - 0, - SOLARIS_SIGHUP, SOLARIS_SIGINT, - SOLARIS_SIGQUIT, SOLARIS_SIGILL, - SOLARIS_SIGTRAP, SOLARIS_SIGIOT, - SOLARIS_SIGEMT, SOLARIS_SIGFPE, - SOLARIS_SIGKILL, SOLARIS_SIGBUS, - SOLARIS_SIGSEGV, SOLARIS_SIGSYS, - SOLARIS_SIGPIPE, SOLARIS_SIGALRM, - SOLARIS_SIGTERM, SOLARIS_SIGURG, - SOLARIS_SIGSTOP, SOLARIS_SIGTSTP, - SOLARIS_SIGCONT, SOLARIS_SIGCLD, - SOLARIS_SIGTTIN, SOLARIS_SIGTTOU, - SOLARIS_SIGPOLL, SOLARIS_SIGXCPU, - SOLARIS_SIGXFSZ, SOLARIS_SIGVTALRM, - SOLARIS_SIGPROF, SOLARIS_SIGWINCH, - SOLARIS_SIGUSR1, SOLARIS_SIGUSR1, - SOLARIS_SIGUSR2, -1, -}; - -long solaris_to_linux_signals[] = { - 0, - SIGHUP, SIGINT, SIGQUIT, SIGILL, - SIGTRAP, SIGIOT, SIGEMT, SIGFPE, - SIGKILL, SIGBUS, SIGSEGV, SIGSYS, - SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, - SIGUSR2, SIGCHLD, -1, SIGWINCH, - SIGURG, SIGPOLL, SIGSTOP, SIGTSTP, - SIGCONT, SIGTTIN, SIGTTOU, SIGVTALRM, - SIGPROF, SIGXCPU, SIGXFSZ, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, -}; - -static inline long mapsig(long sig) -{ - if ((unsigned long)sig > SOLARIS_NSIGNALS) - return -EINVAL; - return solaris_to_linux_signals[sig]; -} - -asmlinkage int solaris_kill(int pid, int sig) -{ - int (*sys_kill)(int,int) = - (int (*)(int,int))SYS(kill); - int s = mapsig(sig); - - if (s < 0) return s; - return sys_kill(pid, s); -} - -static long sig_handler(int sig, u32 arg, int one_shot) -{ - struct sigaction sa, old; - int ret; - mm_segment_t old_fs = get_fs(); - int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) = - (int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction); - - sigemptyset(&sa.sa_mask); - sa.sa_restorer = NULL; - sa.sa_handler = (__sighandler_t)A(arg); - sa.sa_flags = 0; - if (one_shot) sa.sa_flags = SA_ONESHOT | SA_NOMASK; - set_fs (KERNEL_DS); - ret = sys_sigaction(sig, (void __user *)&sa, (void __user *)&old); - set_fs (old_fs); - if (ret < 0) return ret; - return (u32)(unsigned long)old.sa_handler; -} - -static inline long solaris_signal(int sig, u32 arg) -{ - return sig_handler (sig, arg, 1); -} - -static long solaris_sigset(int sig, u32 arg) -{ - if (arg != 2) /* HOLD */ { - spin_lock_irq(¤t->sighand->siglock); - sigdelsetmask(¤t->blocked, _S(sig)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return sig_handler (sig, arg, 0); - } else { - spin_lock_irq(¤t->sighand->siglock); - sigaddsetmask(¤t->blocked, (_S(sig) & ~_BLOCKABLE)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return 0; - } -} - -static inline long solaris_sighold(int sig) -{ - return solaris_sigset(sig, 2); -} - -static inline long solaris_sigrelse(int sig) -{ - spin_lock_irq(¤t->sighand->siglock); - sigdelsetmask(¤t->blocked, _S(sig)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return 0; -} - -static inline long solaris_sigignore(int sig) -{ - return sig_handler(sig, (u32)(unsigned long)SIG_IGN, 0); -} - -static inline long solaris_sigpause(int sig) -{ - printk ("Need to support solaris sigpause\n"); - return -ENOSYS; -} - -asmlinkage long solaris_sigfunc(int sig, u32 arg) -{ - int func = sig & ~0xff; - - sig = mapsig(sig & 0xff); - if (sig < 0) return sig; - switch (func) { - case 0: return solaris_signal(sig, arg); - case 0x100: return solaris_sigset(sig, arg); - case 0x200: return solaris_sighold(sig); - case 0x400: return solaris_sigrelse(sig); - case 0x800: return solaris_sigignore(sig); - case 0x1000: return solaris_sigpause(sig); - } - return -EINVAL; -} - -typedef struct { - u32 __sigbits[4]; -} sol_sigset_t; - -static inline int mapin(u32 *p, sigset_t *q) -{ - int i; - u32 x; - int sig; - - sigemptyset(q); - x = p[0]; - for (i = 1; i <= SOLARIS_NSIGNALS; i++) { - if (x & 1) { - sig = solaris_to_linux_signals[i]; - if (sig == -1) - return -EINVAL; - sigaddsetmask(q, (1L << (sig - 1))); - } - x >>= 1; - if (i == 32) - x = p[1]; - } - return 0; -} - -static inline int mapout(sigset_t *q, u32 *p) -{ - int i; - int sig; - - p[0] = 0; - p[1] = 0; - for (i = 1; i <= 32; i++) { - if (sigismember(q, sigmask(i))) { - sig = linux_to_solaris_signals[i]; - if (sig == -1) - return -EINVAL; - if (sig > 32) - p[1] |= 1L << (sig - 33); - else - p[0] |= 1L << (sig - 1); - } - } - return 0; -} - -asmlinkage int solaris_sigprocmask(int how, u32 in, u32 out) -{ - sigset_t in_s, *ins, out_s, *outs; - mm_segment_t old_fs = get_fs(); - int ret; - int (*sys_sigprocmask)(int,sigset_t __user *,sigset_t __user *) = - (int (*)(int,sigset_t __user *,sigset_t __user *))SYS(sigprocmask); - - ins = NULL; outs = NULL; - if (in) { - u32 tmp[2]; - - if (copy_from_user (tmp, (void __user *)A(in), 2*sizeof(u32))) - return -EFAULT; - ins = &in_s; - if (mapin (tmp, ins)) return -EINVAL; - } - if (out) outs = &out_s; - set_fs (KERNEL_DS); - ret = sys_sigprocmask((how == 3) ? SIG_SETMASK : how, - (void __user *)ins, (void __user *)outs); - set_fs (old_fs); - if (ret) return ret; - if (out) { - u32 tmp[4]; - - tmp[2] = 0; tmp[3] = 0; - if (mapout (outs, tmp)) return -EINVAL; - if (copy_to_user((void __user *)A(out), tmp, 4*sizeof(u32))) - return -EFAULT; - } - return 0; -} - -asmlinkage long do_sol_sigsuspend(u32 mask) -{ - sigset_t s; - u32 tmp[2]; - - if (copy_from_user (tmp, (sol_sigset_t __user *)A(mask), 2*sizeof(u32))) - return -EFAULT; - if (mapin (tmp, &s)) return -EINVAL; - return (long)s.sig[0]; -} - -struct sol_sigaction { - int sa_flags; - u32 sa_handler; - u32 sa_mask[4]; - int sa_resv[2]; -}; - -asmlinkage int solaris_sigaction(int sig, u32 act, u32 old) -{ - u32 tmp, tmp2[4]; - struct sigaction s, s2; - int ret; - mm_segment_t old_fs = get_fs(); - struct sol_sigaction __user *p = (void __user *)A(old); - int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) = - (int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction); - - sig = mapsig(sig); - if (sig < 0) { - /* We cheat a little bit for Solaris only signals */ - if (old && clear_user(p, sizeof(struct sol_sigaction))) - return -EFAULT; - return 0; - } - if (act) { - if (get_user (tmp, &p->sa_flags)) - return -EFAULT; - s.sa_flags = 0; - if (tmp & SOLARIS_SA_ONSTACK) s.sa_flags |= SA_STACK; - if (tmp & SOLARIS_SA_RESTART) s.sa_flags |= SA_RESTART; - if (tmp & SOLARIS_SA_NODEFER) s.sa_flags |= SA_NOMASK; - if (tmp & SOLARIS_SA_RESETHAND) s.sa_flags |= SA_ONESHOT; - if (tmp & SOLARIS_SA_NOCLDSTOP) s.sa_flags |= SA_NOCLDSTOP; - if (get_user (tmp, &p->sa_handler) || - copy_from_user (tmp2, &p->sa_mask, 2*sizeof(u32))) - return -EFAULT; - s.sa_handler = (__sighandler_t)A(tmp); - if (mapin (tmp2, &s.sa_mask)) return -EINVAL; - s.sa_restorer = NULL; - } - set_fs(KERNEL_DS); - ret = sys_sigaction(sig, act ? (void __user *)&s : NULL, - old ? (void __user *)&s2 : NULL); - set_fs(old_fs); - if (ret) return ret; - if (old) { - if (mapout (&s2.sa_mask, tmp2)) return -EINVAL; - tmp = 0; tmp2[2] = 0; tmp2[3] = 0; - if (s2.sa_flags & SA_STACK) tmp |= SOLARIS_SA_ONSTACK; - if (s2.sa_flags & SA_RESTART) tmp |= SOLARIS_SA_RESTART; - if (s2.sa_flags & SA_NOMASK) tmp |= SOLARIS_SA_NODEFER; - if (s2.sa_flags & SA_ONESHOT) tmp |= SOLARIS_SA_RESETHAND; - if (s2.sa_flags & SA_NOCLDSTOP) tmp |= SOLARIS_SA_NOCLDSTOP; - if (put_user (tmp, &p->sa_flags) || - __put_user ((u32)(unsigned long)s2.sa_handler, &p->sa_handler) || - copy_to_user (&p->sa_mask, tmp2, 4*sizeof(u32))) - return -EFAULT; - } - return 0; -} - -asmlinkage int solaris_sigpending(int which, u32 set) -{ - sigset_t s; - u32 tmp[4]; - switch (which) { - case 1: /* sigpending */ - spin_lock_irq(¤t->sighand->siglock); - sigandsets(&s, ¤t->blocked, ¤t->pending.signal); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - break; - case 2: /* sigfillset - I just set signals which have linux equivalents */ - sigfillset(&s); - break; - default: return -EINVAL; - } - if (mapout (&s, tmp)) return -EINVAL; - tmp[2] = 0; tmp[3] = 0; - if (copy_to_user ((u32 __user *)A(set), tmp, sizeof(tmp))) - return -EFAULT; - return 0; -} - -asmlinkage int solaris_wait(u32 stat_loc) -{ - unsigned __user *p = (unsigned __user *)A(stat_loc); - int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) = - (int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4); - int ret, status; - - ret = sys_wait4(-1, p, WUNTRACED, NULL); - if (ret >= 0 && stat_loc) { - if (get_user (status, p)) - return -EFAULT; - if (((status - 1) & 0xffff) < 0xff) - status = linux_to_solaris_signals[status & 0x7f] & 0x7f; - else if ((status & 0xff) == 0x7f) - status = (linux_to_solaris_signals[(status >> 8) & 0xff] << 8) | 0x7f; - if (__put_user (status, p)) - return -EFAULT; - } - return ret; -} - -asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options) -{ - int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) = - (int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4); - int opts, status, ret; - - switch (idtype) { - case 0: /* P_PID */ break; - case 1: /* P_PGID */ pid = -pid; break; - case 7: /* P_ALL */ pid = -1; break; - default: return -EINVAL; - } - opts = 0; - if (options & SOLARIS_WUNTRACED) opts |= WUNTRACED; - if (options & SOLARIS_WNOHANG) opts |= WNOHANG; - current->state = TASK_RUNNING; - ret = sys_wait4(pid, (unsigned int __user *)A(info), opts, NULL); - if (ret < 0) return ret; - if (info) { - struct sol_siginfo __user *s = (void __user *)A(info); - - if (get_user (status, (unsigned int __user *)A(info))) - return -EFAULT; - - if (__put_user (SOLARIS_SIGCLD, &s->si_signo) || - __put_user (ret, &s->_data._proc._pid)) - return -EFAULT; - - switch (status & 0xff) { - case 0: ret = SOLARIS_CLD_EXITED; - status = (status >> 8) & 0xff; - break; - case 0x7f: - status = (status >> 8) & 0xff; - switch (status) { - case SIGSTOP: - case SIGTSTP: ret = SOLARIS_CLD_STOPPED; - default: ret = SOLARIS_CLD_EXITED; - } - status = linux_to_solaris_signals[status]; - break; - default: - if (status & 0x80) ret = SOLARIS_CLD_DUMPED; - else ret = SOLARIS_CLD_KILLED; - status = linux_to_solaris_signals[status & 0x7f]; - break; - } - - if (__put_user (ret, &s->si_code) || - __put_user (status, &s->_data._proc._pdata._cld._status)) - return -EFAULT; - } - return 0; -} - -extern int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs); -extern int svr4_getcontext(svr4_ucontext_t *c, struct pt_regs *regs); - -asmlinkage int solaris_context(struct pt_regs *regs) -{ - switch ((unsigned)regs->u_regs[UREG_I0]) { - case 0: /* getcontext */ - return svr4_getcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs); - case 1: /* setcontext */ - return svr4_setcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs); - default: - return -EINVAL; - - } -} - -asmlinkage int solaris_sigaltstack(u32 ss, u32 oss) -{ -/* XXX Implement this soon */ - return 0; -} diff --git a/arch/sparc64/solaris/signal.h b/arch/sparc64/solaris/signal.h deleted file mode 100644 index e9157080305..00000000000 --- a/arch/sparc64/solaris/signal.h +++ /dev/null @@ -1,108 +0,0 @@ -/* $Id: signal.h,v 1.3 1998/04/12 06:20:33 davem Exp $ - * signal.h: Signal emulation for Solaris - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#define SOLARIS_SIGHUP 1 -#define SOLARIS_SIGINT 2 -#define SOLARIS_SIGQUIT 3 -#define SOLARIS_SIGILL 4 -#define SOLARIS_SIGTRAP 5 -#define SOLARIS_SIGIOT 6 -#define SOLARIS_SIGEMT 7 -#define SOLARIS_SIGFPE 8 -#define SOLARIS_SIGKILL 9 -#define SOLARIS_SIGBUS 10 -#define SOLARIS_SIGSEGV 11 -#define SOLARIS_SIGSYS 12 -#define SOLARIS_SIGPIPE 13 -#define SOLARIS_SIGALRM 14 -#define SOLARIS_SIGTERM 15 -#define SOLARIS_SIGUSR1 16 -#define SOLARIS_SIGUSR2 17 -#define SOLARIS_SIGCLD 18 -#define SOLARIS_SIGPWR 19 -#define SOLARIS_SIGWINCH 20 -#define SOLARIS_SIGURG 21 -#define SOLARIS_SIGPOLL 22 -#define SOLARIS_SIGSTOP 23 -#define SOLARIS_SIGTSTP 24 -#define SOLARIS_SIGCONT 25 -#define SOLARIS_SIGTTIN 26 -#define SOLARIS_SIGTTOU 27 -#define SOLARIS_SIGVTALRM 28 -#define SOLARIS_SIGPROF 29 -#define SOLARIS_SIGXCPU 30 -#define SOLARIS_SIGXFSZ 31 -#define SOLARIS_SIGWAITING 32 -#define SOLARIS_SIGLWP 33 -#define SOLARIS_SIGFREEZE 34 -#define SOLARIS_SIGTHAW 35 -#define SOLARIS_SIGCANCEL 36 -#define SOLARIS_SIGRTMIN 37 -#define SOLARIS_SIGRTMAX 44 -#define SOLARIS_NSIGNALS 44 - - -#define SOLARIS_SA_ONSTACK 1 -#define SOLARIS_SA_RESETHAND 2 -#define SOLARIS_SA_RESTART 4 -#define SOLARIS_SA_SIGINFO 8 -#define SOLARIS_SA_NODEFER 16 -#define SOLARIS_SA_NOCLDWAIT 0x10000 -#define SOLARIS_SA_NOCLDSTOP 0x20000 - -struct sol_siginfo { - int si_signo; - int si_code; - int si_errno; - union { - char pad[128-3*sizeof(int)]; - struct { - s32 _pid; - union { - struct { - s32 _uid; - s32 _value; - } _kill; - struct { - s32 _utime; - int _status; - s32 _stime; - } _cld; - } _pdata; - } _proc; - struct { /* SIGSEGV, SIGBUS, SIGILL and SIGFPE */ - u32 _addr; - int _trapno; - } _fault; - struct { /* SIGPOLL, SIGXFSZ */ - int _fd; - s32 _band; - } _file; - } _data; -}; - -#define SOLARIS_WUNTRACED 0x04 -#define SOLARIS_WNOHANG 0x40 -#define SOLARIS_WEXITED 0x01 -#define SOLARIS_WTRAPPED 0x02 -#define SOLARIS_WSTOPPED WUNTRACED -#define SOLARIS_WCONTINUED 0x08 -#define SOLARIS_WNOWAIT 0x80 - -#define SOLARIS_TRAP_BRKPT 1 -#define SOLARIS_TRAP_TRACE 2 -#define SOLARIS_CLD_EXITED 1 -#define SOLARIS_CLD_KILLED 2 -#define SOLARIS_CLD_DUMPED 3 -#define SOLARIS_CLD_TRAPPED 4 -#define SOLARIS_CLD_STOPPED 5 -#define SOLARIS_CLD_CONTINUED 6 -#define SOLARIS_POLL_IN 1 -#define SOLARIS_POLL_OUT 2 -#define SOLARIS_POLL_MSG 3 -#define SOLARIS_POLL_ERR 4 -#define SOLARIS_POLL_PRI 5 -#define SOLARIS_POLL_HUP 6 diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c deleted file mode 100644 index d3a66ea74a7..00000000000 --- a/arch/sparc64/solaris/socket.c +++ /dev/null @@ -1,462 +0,0 @@ -/* $Id: socket.c,v 1.6 2002/02/08 03:57:14 davem Exp $ - * socket.c: Socket syscall emulation for Solaris 2.6+ - * - * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) - * - * 1999-08-19 Fixed socketpair code - * Jason Rappleye (rappleye@ccr.buffalo.edu) - */ - -#include <linux/types.h> -#include <linux/smp_lock.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/socket.h> -#include <linux/file.h> -#include <linux/net.h> -#include <linux/compat.h> -#include <net/compat.h> -#include <net/sock.h> - -#include <asm/uaccess.h> -#include <asm/string.h> -#include <asm/oplib.h> -#include <asm/idprom.h> - -#include "conv.h" - -#define SOCK_SOL_STREAM 2 -#define SOCK_SOL_DGRAM 1 -#define SOCK_SOL_RAW 4 -#define SOCK_SOL_RDM 5 -#define SOCK_SOL_SEQPACKET 6 - -#define SOL_SO_SNDLOWAT 0x1003 -#define SOL_SO_RCVLOWAT 0x1004 -#define SOL_SO_SNDTIMEO 0x1005 -#define SOL_SO_RCVTIMEO 0x1006 -#define SOL_SO_STATE 0x2000 - -#define SOL_SS_NDELAY 0x040 -#define SOL_SS_NONBLOCK 0x080 -#define SOL_SS_ASYNC 0x100 - -#define SO_STATE 0x000e - -static int socket_check(int family, int type) -{ - if (family != PF_UNIX && family != PF_INET) - return -ESOCKTNOSUPPORT; - switch (type) { - case SOCK_SOL_STREAM: type = SOCK_STREAM; break; - case SOCK_SOL_DGRAM: type = SOCK_DGRAM; break; - case SOCK_SOL_RAW: type = SOCK_RAW; break; - case SOCK_SOL_RDM: type = SOCK_RDM; break; - case SOCK_SOL_SEQPACKET: type = SOCK_SEQPACKET; break; - default: return -EINVAL; - } - return type; -} - -static int solaris_to_linux_sockopt(int optname) -{ - switch (optname) { - case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break; - case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break; - case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break; - case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break; - case SOL_SO_STATE: optname = SO_STATE; break; - }; - - return optname; -} - -asmlinkage int solaris_socket(int family, int type, int protocol) -{ - int (*sys_socket)(int, int, int) = - (int (*)(int, int, int))SYS(socket); - - type = socket_check (family, type); - if (type < 0) return type; - return sys_socket(family, type, protocol); -} - -asmlinkage int solaris_socketpair(int *usockvec) -{ - int (*sys_socketpair)(int, int, int, int *) = - (int (*)(int, int, int, int *))SYS(socketpair); - - /* solaris socketpair really only takes one arg at the syscall - * level, int * usockvec. The libs apparently take care of - * making sure that family==AF_UNIX and type==SOCK_STREAM. The - * pointer we really want ends up residing in the first (and - * supposedly only) argument. - */ - - return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)usockvec); -} - -asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen) -{ - int (*sys_bind)(int, struct sockaddr *, int) = - (int (*)(int, struct sockaddr *, int))SUNOS(104); - - return sys_bind(fd, addr, addrlen); -} - -asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int optlen) -{ - int (*sunos_setsockopt)(int, int, int, u32, int) = - (int (*)(int, int, int, u32, int))SUNOS(105); - - optname = solaris_to_linux_sockopt(optname); - if (optname < 0) - return optname; - if (optname == SO_STATE) - return 0; - - return sunos_setsockopt(fd, level, optname, optval, optlen); -} - -asmlinkage int solaris_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen) -{ - int (*sunos_getsockopt)(int, int, int, u32, u32) = - (int (*)(int, int, int, u32, u32))SUNOS(118); - - optname = solaris_to_linux_sockopt(optname); - if (optname < 0) - return optname; - - if (optname == SO_STATE) - optname = SOL_SO_STATE; - - return sunos_getsockopt(fd, level, optname, optval, optlen); -} - -asmlinkage int solaris_connect(int fd, struct sockaddr __user *addr, int addrlen) -{ - int (*sys_connect)(int, struct sockaddr __user *, int) = - (int (*)(int, struct sockaddr __user *, int))SYS(connect); - - return sys_connect(fd, addr, addrlen); -} - -asmlinkage int solaris_accept(int fd, struct sockaddr __user *addr, int __user *addrlen) -{ - int (*sys_accept)(int, struct sockaddr __user *, int __user *) = - (int (*)(int, struct sockaddr __user *, int __user *))SYS(accept); - - return sys_accept(fd, addr, addrlen); -} - -asmlinkage int solaris_listen(int fd, int backlog) -{ - int (*sys_listen)(int, int) = - (int (*)(int, int))SUNOS(106); - - return sys_listen(fd, backlog); -} - -asmlinkage int solaris_shutdown(int fd, int how) -{ - int (*sys_shutdown)(int, int) = - (int (*)(int, int))SYS(shutdown); - - return sys_shutdown(fd, how); -} - -#define MSG_SOL_OOB 0x1 -#define MSG_SOL_PEEK 0x2 -#define MSG_SOL_DONTROUTE 0x4 -#define MSG_SOL_EOR 0x8 -#define MSG_SOL_CTRUNC 0x10 -#define MSG_SOL_TRUNC 0x20 -#define MSG_SOL_WAITALL 0x40 -#define MSG_SOL_DONTWAIT 0x80 - -static int solaris_to_linux_msgflags(int flags) -{ - int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE); - - if (flags & MSG_SOL_EOR) fl |= MSG_EOR; - if (flags & MSG_SOL_CTRUNC) fl |= MSG_CTRUNC; - if (flags & MSG_SOL_TRUNC) fl |= MSG_TRUNC; - if (flags & MSG_SOL_WAITALL) fl |= MSG_WAITALL; - if (flags & MSG_SOL_DONTWAIT) fl |= MSG_DONTWAIT; - return fl; -} - -static int linux_to_solaris_msgflags(int flags) -{ - int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE); - - if (flags & MSG_EOR) fl |= MSG_SOL_EOR; - if (flags & MSG_CTRUNC) fl |= MSG_SOL_CTRUNC; - if (flags & MSG_TRUNC) fl |= MSG_SOL_TRUNC; - if (flags & MSG_WAITALL) fl |= MSG_SOL_WAITALL; - if (flags & MSG_DONTWAIT) fl |= MSG_SOL_DONTWAIT; - return fl; -} - -asmlinkage int solaris_recvfrom(int s, char __user *buf, int len, int flags, u32 from, u32 fromlen) -{ - int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom); - - return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), A(from), A(fromlen)); -} - -asmlinkage int solaris_recv(int s, char __user *buf, int len, int flags) -{ - int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom); - - return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL); -} - -asmlinkage int solaris_sendto(int s, char __user *buf, int len, int flags, u32 to, u32 tolen) -{ - int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(sendto); - - return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), A(to), A(tolen)); -} - -asmlinkage int solaris_send(int s, char *buf, int len, int flags) -{ - int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) = - (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto); - - return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL); -} - -asmlinkage int solaris_getpeername(int fd, struct sockaddr *addr, int *addrlen) -{ - int (*sys_getpeername)(int, struct sockaddr *, int *) = - (int (*)(int, struct sockaddr *, int *))SYS(getpeername); - - return sys_getpeername(fd, addr, addrlen); -} - -asmlinkage int solaris_getsockname(int fd, struct sockaddr *addr, int *addrlen) -{ - int (*sys_getsockname)(int, struct sockaddr *, int *) = - (int (*)(int, struct sockaddr *, int *))SYS(getsockname); - - return sys_getsockname(fd, addr, addrlen); -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct sol_nmsghdr { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - u32 msg_iovlen; - u32 msg_control; - u32 msg_controllen; - u32 msg_flags; -}; - -struct sol_cmsghdr { - u32 cmsg_len; - int cmsg_level; - int cmsg_type; - unsigned char cmsg_data[0]; -}; - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct sol_nmsghdr __user *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = A(tmp1); - kmsg->msg_iov = A(tmp2); - kmsg->msg_control = A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - kmsg->msg_flags = solaris_to_linux_msgflags(kmsg->msg_flags); - - return err; -} - -asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EMSGSIZE; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - - ctl_len = msg_sys.msg_controllen; - if (ctl_len) { - struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control; - unsigned long *kcmsg; - compat_size_t cmlen; - - err = -EINVAL; - if (ctl_len <= sizeof(compat_size_t)) - goto out_freeiov; - - if (ctl_len > sizeof(ctl)) { - err = -ENOBUFS; - ctl_buf = kmalloc(ctl_len, GFP_KERNEL); - if (!ctl_buf) - goto out_freeiov; - } - __get_user(cmlen, &ucmsg->cmsg_len); - kcmsg = (unsigned long *) ctl_buf; - *kcmsg++ = (unsigned long)cmlen; - err = -EFAULT; - if (copy_from_user(kcmsg, &ucmsg->cmsg_level, - ctl_len - sizeof(compat_size_t))) - goto out_freectl; - msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags); - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr __user *uaddr; - int __user *uaddr_len; - - if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) - return -EFAULT; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EMSGSIZE; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = (void __user *) msg_sys.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len = err; - - cmsg_ptr = (unsigned long) msg_sys.msg_control; - msg_sys.msg_flags = MSG_CMSG_COMPAT; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - err = sock_recvmsg(sock, &msg_sys, total_len, user_flags); - if(err < 0) - goto out_freeiov; - - len = err; - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr, - &user_msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c deleted file mode 100644 index fc6669e8dde..00000000000 --- a/arch/sparc64/solaris/socksys.c +++ /dev/null @@ -1,211 +0,0 @@ -/* $Id: socksys.c,v 1.21 2002/02/08 03:57:14 davem Exp $ - * socksys.c: /dev/inet/ stuff for Solaris emulation. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997, 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) - */ - -/* - * Dave, _please_ give me specifications on this fscking mess so that I - * could at least get it into the state when it wouldn't screw the rest of - * the kernel over. socksys.c and timod.c _stink_ and we are not talking - * H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/ioctl.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/init.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/syscalls.h> -#include <linux/in.h> -#include <linux/devfs_fs_kernel.h> - -#include <net/sock.h> - -#include <asm/uaccess.h> -#include <asm/termios.h> - -#include "conv.h" -#include "socksys.h" - -static int af_inet_protocols[] = { -IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP, -IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW, -0, 0, 0, 0, 0, 0, -}; - -#ifndef DEBUG_SOLARIS_KMALLOC - -#define mykmalloc kmalloc -#define mykfree kfree - -#else - -extern void * mykmalloc(size_t s, gfp_t gfp); -extern void mykfree(void *); - -#endif - -static unsigned int (*sock_poll)(struct file *, poll_table *); - -static struct file_operations socksys_file_ops = { - /* Currently empty */ -}; - -static int socksys_open(struct inode * inode, struct file * filp) -{ - int family, type, protocol, fd; - struct dentry *dentry; - int (*sys_socket)(int,int,int) = - (int (*)(int,int,int))SUNOS(97); - struct sol_socket_struct * sock; - - family = ((iminor(inode) >> 4) & 0xf); - switch (family) { - case AF_UNIX: - type = SOCK_STREAM; - protocol = 0; - break; - case AF_INET: - protocol = af_inet_protocols[iminor(inode) & 0xf]; - switch (protocol) { - case IPPROTO_TCP: type = SOCK_STREAM; break; - case IPPROTO_UDP: type = SOCK_DGRAM; break; - default: type = SOCK_RAW; break; - } - break; - default: - type = SOCK_RAW; - protocol = 0; - break; - } - - fd = sys_socket(family, type, protocol); - if (fd < 0) - return fd; - /* - * N.B. The following operations are not legal! - * - * No shit. WTF is it supposed to do, anyway? - * - * Try instead: - * d_delete(filp->f_dentry), then d_instantiate with sock inode - */ - dentry = filp->f_dentry; - filp->f_dentry = dget(fcheck(fd)->f_dentry); - filp->f_dentry->d_inode->i_rdev = inode->i_rdev; - filp->f_dentry->d_inode->i_flock = inode->i_flock; - SOCKET_I(filp->f_dentry->d_inode)->file = filp; - filp->f_op = &socksys_file_ops; - sock = (struct sol_socket_struct*) - mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL); - if (!sock) return -ENOMEM; - SOLDD(("sock=%016lx(%016lx)\n", sock, filp)); - sock->magic = SOLARIS_SOCKET_MAGIC; - sock->modcount = 0; - sock->state = TS_UNBND; - sock->offset = 0; - sock->pfirst = sock->plast = NULL; - filp->private_data = sock; - SOLDD(("filp->private_data %016lx\n", filp->private_data)); - - sys_close(fd); - dput(dentry); - return 0; -} - -static int socksys_release(struct inode * inode, struct file * filp) -{ - struct sol_socket_struct * sock; - struct T_primsg *it; - - /* XXX: check this */ - sock = (struct sol_socket_struct *)filp->private_data; - SOLDD(("sock release %016lx(%016lx)\n", sock, filp)); - it = sock->pfirst; - while (it) { - struct T_primsg *next = it->next; - - SOLDD(("socksys_release %016lx->%016lx\n", it, next)); - mykfree((char*)it); - it = next; - } - filp->private_data = NULL; - SOLDD(("socksys_release %016lx\n", sock)); - mykfree((char*)sock); - return 0; -} - -static unsigned int socksys_poll(struct file * filp, poll_table * wait) -{ - struct inode *ino; - unsigned int mask = 0; - - ino=filp->f_dentry->d_inode; - if (ino && S_ISSOCK(ino->i_mode)) { - struct sol_socket_struct *sock; - sock = (struct sol_socket_struct*)filp->private_data; - if (sock && sock->pfirst) { - mask |= POLLIN | POLLRDNORM; - if (sock->pfirst->pri == MSG_HIPRI) - mask |= POLLPRI; - } - } - if (sock_poll) - mask |= (*sock_poll)(filp, wait); - return mask; -} - -static struct file_operations socksys_fops = { - .open = socksys_open, - .release = socksys_release, -}; - -int __init -init_socksys(void) -{ - int ret; - struct file * file; - int (*sys_socket)(int,int,int) = - (int (*)(int,int,int))SUNOS(97); - int (*sys_close)(unsigned int) = - (int (*)(unsigned int))SYS(close); - - ret = register_chrdev (30, "socksys", &socksys_fops); - if (ret < 0) { - printk ("Couldn't register socksys character device\n"); - return ret; - } - ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (ret < 0) { - printk ("Couldn't create socket\n"); - return ret; - } - - devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUSR|S_IWUSR, "socksys"); - - file = fcheck(ret); - /* N.B. Is this valid? Suppose the f_ops are in a module ... */ - socksys_file_ops = *file->f_op; - sys_close(ret); - sock_poll = socksys_file_ops.poll; - socksys_file_ops.poll = socksys_poll; - socksys_file_ops.release = socksys_release; - return 0; -} - -void -cleanup_socksys(void) -{ - if (unregister_chrdev(30, "socksys")) - printk ("Couldn't unregister socksys character device\n"); - devfs_remove ("socksys"); -} diff --git a/arch/sparc64/solaris/socksys.h b/arch/sparc64/solaris/socksys.h deleted file mode 100644 index 5d1b78ec160..00000000000 --- a/arch/sparc64/solaris/socksys.h +++ /dev/null @@ -1,208 +0,0 @@ -/* $Id: socksys.h,v 1.2 1998/03/26 08:46:07 jj Exp $ - * socksys.h: Definitions for STREAMS modules emulation code. - * - * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - */ - -#define MSG_HIPRI 0x01 -#define MSG_ANY 0x02 -#define MSG_BAND 0x04 - -#define MORECTL 1 -#define MOREDATA 2 - -#define TBADADDR 1 -#define TBADOPT 2 -#define TACCES 3 -#define TBADF 4 -#define TNOADDR 5 -#define TOUTSTATE 6 -#define TBADSEQ 7 -#define TSYSERR 8 -#define TLOOK 9 -#define TBADDATA 10 -#define TBUFOVFLW 11 -#define TFLOW 12 -#define TNODATA 13 -#define TNODIS 14 -#define TNOUDERR 15 -#define TBADFLAG 16 -#define TNOREL 17 -#define TNOTSUPPORT 18 -#define TSTATECHNG 19 - -#define T_CONN_REQ 0 -#define T_CONN_RES 1 -#define T_DISCON_REQ 2 -#define T_DATA_REQ 3 -#define T_EXDATA_REQ 4 -#define T_INFO_REQ 5 -#define T_BIND_REQ 6 -#define T_UNBIND_REQ 7 -#define T_UNITDATA_REQ 8 -#define T_OPTMGMT_REQ 9 -#define T_ORDREL_REQ 10 - -#define T_CONN_IND 11 -#define T_CONN_CON 12 -#define T_DISCON_IND 13 -#define T_DATA_IND 14 -#define T_EXDATA_IND 15 -#define T_INFO_ACK 16 -#define T_BIND_ACK 17 -#define T_ERROR_ACK 18 -#define T_OK_ACK 19 -#define T_UNITDATA_IND 20 -#define T_UDERROR_IND 21 -#define T_OPTMGMT_ACK 22 -#define T_ORDREL_IND 23 - -#define T_NEGOTIATE 0x0004 -#define T_FAILURE 0x0040 - -#define TS_UNBND 0 /* unbound */ -#define TS_WACK_BREQ 1 /* waiting for T_BIND_REQ ack */ -#define TS_WACK_UREQ 2 /* waiting for T_UNBIND_REQ ack */ -#define TS_IDLE 3 /* idle */ -#define TS_WACK_OPTREQ 4 /* waiting for T_OPTMGMT_REQ ack */ -#define TS_WACK_CREQ 5 /* waiting for T_CONN_REQ ack */ -#define TS_WCON_CREQ 6 /* waiting for T_CONN_REQ confirmation */ -#define TS_WRES_CIND 7 /* waiting for T_CONN_IND */ -#define TS_WACK_CRES 8 /* waiting for T_CONN_RES ack */ -#define TS_DATA_XFER 9 /* data transfer */ -#define TS_WIND_ORDREL 10 /* releasing read but not write */ -#define TS_WREQ_ORDREL 11 /* wait to release write but not read */ -#define TS_WACK_DREQ6 12 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ7 13 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ9 14 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ10 15 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ11 16 /* waiting for T_DISCON_REQ ack */ -#define TS_NOSTATES 17 - -struct T_conn_req { - s32 PRIM_type; - s32 DEST_length; - s32 DEST_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_bind_req { - s32 PRIM_type; - s32 ADDR_length; - s32 ADDR_offset; - u32 CONIND_number; -}; - -struct T_unitdata_req { - s32 PRIM_type; - s32 DEST_length; - s32 DEST_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_optmgmt_req { - s32 PRIM_type; - s32 OPT_length; - s32 OPT_offset; - s32 MGMT_flags; -}; - -struct T_bind_ack { - s32 PRIM_type; - s32 ADDR_length; - s32 ADDR_offset; - u32 CONIND_number; -}; - -struct T_error_ack { - s32 PRIM_type; - s32 ERROR_prim; - s32 TLI_error; - s32 UNIX_error; -}; - -struct T_ok_ack { - s32 PRIM_type; - s32 CORRECT_prim; -}; - -struct T_conn_ind { - s32 PRIM_type; - s32 SRC_length; - s32 SRC_offset; - s32 OPT_length; - s32 OPT_offset; - s32 SEQ_number; -}; - -struct T_conn_con { - s32 PRIM_type; - s32 RES_length; - s32 RES_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_discon_ind { - s32 PRIM_type; - s32 DISCON_reason; - s32 SEQ_number; -}; - -struct T_unitdata_ind { - s32 PRIM_type; - s32 SRC_length; - s32 SRC_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_optmgmt_ack { - s32 PRIM_type; - s32 OPT_length; - s32 OPT_offset; - s32 MGMT_flags; -}; - -struct opthdr { - s32 level; - s32 name; - s32 len; - char value[0]; -}; - -struct T_primsg { - struct T_primsg *next; - unsigned char pri; - unsigned char band; - int length; - s32 type; -}; - -struct strbuf { - s32 maxlen; - s32 len; - u32 buf; -} ; - -/* Constants used by STREAMS modules emulation code */ - -typedef char sol_module; - -#define MAX_NR_STREAM_MODULES 16 - -/* Private data structure assigned to sockets. */ - -struct sol_socket_struct { - int magic; - int modcount; - sol_module module[MAX_NR_STREAM_MODULES]; - long state; - int offset; - struct T_primsg *pfirst, *plast; -}; - -#define SOLARIS_SOCKET_MAGIC 0xADDED - diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S deleted file mode 100644 index d25667eeae1..00000000000 --- a/arch/sparc64/solaris/systbl.S +++ /dev/null @@ -1,314 +0,0 @@ -/* $Id: systbl.S,v 1.11 2000/03/13 21:57:35 davem Exp $ - * systbl.S: System call entry point table for Solaris compatibility. - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - */ - -#include <asm/unistd.h> - -/* Fall back to sys_call_table32 entry */ -#define CHAIN(name) __NR_##name - -/* Pass pt_regs pointer as first argument */ -#define REGS(name) name+1 - -/* Hack till all be implemented */ -#define solaris_getpmsg solaris_unimplemented -#define solaris_hrtsys solaris_unimplemented -#define solaris_msgsys solaris_unimplemented -#define solaris_putpmsg solaris_unimplemented -#define solaris_semsys solaris_unimplemented - - .data - .globl solaris_sys_table -solaris_sys_table: - .word solaris_unimplemented /* nosys 0 */ - .word CHAIN(exit) /* exit d 1 */ - .word CHAIN(fork) /* fork 2 */ - .word CHAIN(read) /* read dpd 3 */ - .word CHAIN(write) /* write dpd 4 */ - .word solaris_open /* open soo 5 */ - .word CHAIN(close) /* close d 6 */ - .word solaris_wait /* wait xxx 7 */ - .word CHAIN(creat) /* creat so 8 */ - .word CHAIN(link) /* link ss 9 */ - .word CHAIN(unlink) /* unlink s 10 */ - .word solaris_unimplemented /* exec sxx 11 */ - .word CHAIN(chdir) /* chdir s 12 */ - .word CHAIN(time) /* time 13 */ - .word solaris_mknod /* mknod sox 14 */ - .word CHAIN(chmod) /* chmod so 15 */ - .word CHAIN(chown) /* chown sdd 16 */ - .word solaris_brk /* brk/break x 17 */ - .word solaris_stat /* stat sp 18 */ - .word CHAIN(lseek) /* seek/lseek ddd 19 */ - .word solaris_getpid /* getpid 20 */ - .word solaris_unimplemented /* mount 21 */ - .word CHAIN(umount) /* umount s 22 */ - .word CHAIN(setuid) /* setuid d 23 */ - .word solaris_getuid /* getuid 24 */ - .word CHAIN(stime) /* stime d 25 */ -#if 0 - .word solaris_ptrace /* ptrace xdxx 26 */ -#else - .word CHAIN(ptrace) /* ptrace xdxx 26 */ -#endif - .word CHAIN(alarm) /* alarm d 27 */ - .word solaris_fstat /* fstat dp 28 */ - .word CHAIN(pause) /* pause 29 */ - .word CHAIN(utime) /* utime xx 30 */ - .word solaris_unimplemented /* stty 31 */ - .word solaris_unimplemented /* gtty 32 */ - .word solaris_access /* access so 33 */ - .word CHAIN(nice) /* nice d 34 */ - .word solaris_statfs /* statfs spdd 35 */ - .word CHAIN(sync) /* sync 36 */ - .word solaris_kill /* kill dd 37 */ - .word solaris_fstatfs /* fstatfs dpdd 38 */ - .word solaris_procids /* pgrpsys ddd 39 */ - .word solaris_unimplemented /* xenix 40 */ - .word CHAIN(dup) /* dup d 41 */ - .word CHAIN(pipe) /* pipe 42 */ - .word CHAIN(times) /* times p 43 */ - .word 44 /*CHAIN(profil)*/ /* prof xxxx 44 */ - .word solaris_unimplemented /* lock/plock 45 */ - .word CHAIN(setgid) /* setgid d 46 */ - .word solaris_getgid /* getgid 47 */ - .word solaris_sigfunc /* sigfunc xx 48 */ - .word REGS(solaris_msgsys) /* msgsys dxddd 49 */ - .word solaris_unimplemented /* syssun/3b 50 */ - .word CHAIN(acct) /* acct/sysacct x 51 */ - .word solaris_shmsys /* shmsys ddxo 52 */ - .word REGS(solaris_semsys) /* semsys dddx 53 */ - .word solaris_ioctl /* ioctl dxx 54 */ - .word solaris_unimplemented /* uadmin xxx 55 */ - .word solaris_unimplemented /* reserved:exch 56 */ - .word solaris_utssys /* utssys x 57 */ - .word CHAIN(fsync) /* fsync d 58 */ - .word CHAIN(execve) /* execv spp 59 */ - .word CHAIN(umask) /* umask o 60 */ - .word CHAIN(chroot) /* chroot s 61 */ - .word solaris_fcntl /* fcntl dxx 62 */ - .word solaris_ulimit /* ulimit xx 63 */ - .word solaris_unimplemented /* ? 64 */ - .word solaris_unimplemented /* ? 65 */ - .word solaris_unimplemented /* ? 66 */ - .word solaris_unimplemented /* ? 67 */ - .word solaris_unimplemented /* ? 68 */ - .word solaris_unimplemented /* ? 69 */ - .word solaris_unimplemented /* advfs 70 */ - .word solaris_unimplemented /* unadvfs 71 */ - .word solaris_unimplemented /* rmount 72 */ - .word solaris_unimplemented /* rumount 73 */ - .word solaris_unimplemented /* rfstart 74 */ - .word solaris_unimplemented /* ? 75 */ - .word solaris_unimplemented /* rdebug 76 */ - .word solaris_unimplemented /* rfstop 77 */ - .word solaris_unimplemented /* rfsys 78 */ - .word CHAIN(rmdir) /* rmdir s 79 */ - .word CHAIN(mkdir) /* mkdir so 80 */ - .word CHAIN(getdents) /* getdents dxd 81 */ - .word solaris_unimplemented /* libattach 82 */ - .word solaris_unimplemented /* libdetach 83 */ - .word CHAIN(sysfs) /* sysfs dxx 84 */ - .word solaris_getmsg /* getmsg dxxx 85 */ - .word solaris_putmsg /* putmsg dxxd 86 */ - .word CHAIN(poll) /* poll xdd 87 */ - .word solaris_lstat /* lstat sp 88 */ - .word CHAIN(symlink) /* symlink ss 89 */ - .word CHAIN(readlink) /* readlink spd 90 */ - .word CHAIN(setgroups) /* setgroups dp 91 */ - .word CHAIN(getgroups) /* getgroups dp 92 */ - .word CHAIN(fchmod) /* fchmod do 93 */ - .word CHAIN(fchown) /* fchown ddd 94 */ - .word solaris_sigprocmask /* sigprocmask dxx 95 */ - .word solaris_sigsuspend /* sigsuspend x 96 */ - .word solaris_sigaltstack /* sigaltstack xx 97 */ - .word solaris_sigaction /* sigaction dxx 98 */ - .word solaris_sigpending /* sigpending dd 99 */ - .word REGS(solaris_context) /* context 100 */ - .word solaris_unimplemented /* evsys 101 */ - .word solaris_unimplemented /* evtrapret 102 */ - .word solaris_statvfs /* statvfs sp 103 */ - .word solaris_fstatvfs /* fstatvfs dp 104 */ - .word solaris_unimplemented /* unknown 105 */ - .word solaris_unimplemented /* nfssys 106 */ - .word solaris_waitid /* waitid ddxd 107 */ - .word solaris_unimplemented /* sigsendsys ddd 108 */ - .word REGS(solaris_hrtsys) /* hrtsys xxx 109 */ - .word solaris_unimplemented /* acancel dxd 110 */ - .word solaris_unimplemented /* async 111 */ - .word solaris_unimplemented /* priocntlsys 112 */ - .word solaris_pathconf /* pathconf sd 113 */ - .word CHAIN(mincore) /* mincore d 114 */ - .word solaris_mmap /* mmap xxxxdx 115 */ - .word CHAIN(mprotect) /* mprotect xdx 116 */ - .word CHAIN(munmap) /* munmap xd 117 */ - .word solaris_fpathconf /* fpathconf dd 118 */ - .word CHAIN(fork) /* fork 119 */ - .word solaris_unimplemented /* fchdir d 120 */ - .word CHAIN(readv) /* readv dxd 121 */ - .word CHAIN(writev) /* writev dxd 122 */ - .word solaris_xstat /* xstat dsx 123 */ - .word solaris_lxstat /* lxstat dsx 124 */ - .word solaris_fxstat /* fxstat ddx 125 */ - .word solaris_xmknod /* xmknod dsox 126 */ - .word solaris_unimplemented /* syslocal d 127 */ - .word solaris_setrlimit /* setrlimit dp 128 */ - .word solaris_getrlimit /* getrlimit dp 129 */ - .word CHAIN(chown) /* lchown sdd 130 */ - .word solaris_unimplemented /* memcntl 131 */ - .word solaris_getpmsg /* getpmsg dxxxx 132 */ - .word solaris_putpmsg /* putpmsg dxxdd 133 */ - .word CHAIN(rename) /* rename ss 134 */ - .word solaris_utsname /* uname x 135 */ - .word solaris_unimplemented /* setegid 136 */ - .word solaris_sysconf /* sysconfig d 137 */ - .word solaris_unimplemented /* adjtime 138 */ - .word solaris_sysinfo /* systeminfo dsd 139 */ - .word solaris_unimplemented /* ? 140 */ - .word solaris_unimplemented /* seteuid 141 */ - .word solaris_unimplemented /* ? 142 */ - .word solaris_unimplemented /* ? 143 */ - .word solaris_unimplemented /* secsys dx 144 */ - .word solaris_unimplemented /* filepriv sdxd 145 */ - .word solaris_unimplemented /* procpriv dxd 146 */ - .word solaris_unimplemented /* devstat sdx 147 */ - .word solaris_unimplemented /* aclipc ddddx 148 */ - .word solaris_unimplemented /* fdevstat ddx 149 */ - .word solaris_unimplemented /* flvlfile ddx 150 */ - .word solaris_unimplemented /* lvlfile sdx 151 */ - .word solaris_unimplemented /* ? 152 */ - .word solaris_unimplemented /* fchroot d 153 */ - .word solaris_unimplemented /* lvlproc dx 154 */ - .word solaris_unimplemented /* ? 155 */ - .word solaris_gettimeofday /* gettimeofday x 156 */ - .word CHAIN(getitimer) /* getitimer dx 157 */ - .word CHAIN(setitimer) /* setitimer dxx 158 */ - .word solaris_unimplemented /* lwp-xxx 159 */ - .word solaris_unimplemented /* lwp-xxx 160 */ - .word solaris_unimplemented /* lwp-xxx 161 */ - .word solaris_unimplemented /* lwp-xxx 162 */ - .word solaris_unimplemented /* lwp-xxx 163 */ - .word solaris_unimplemented /* lwp-xxx 164 */ - .word solaris_unimplemented /* lwp-xxx 165 */ - .word solaris_unimplemented /* lwp-xxx 166 */ - .word solaris_unimplemented /* lwp-xxx 167 */ - .word solaris_unimplemented /* lwp-xxx 168 */ - .word solaris_unimplemented /* lwp-xxx 169 */ - .word solaris_unimplemented /* lwp-xxx 170 */ - .word solaris_unimplemented /* lwp-xxx 171 */ - .word solaris_unimplemented /* lwp-xxx 172 */ - .word solaris_pread /* pread dpdd 173 */ - .word solaris_pwrite /* pwrite dpdd 174 */ - .word REGS(solaris_llseek) /* llseek dLd 175 */ - .word solaris_unimplemented /* lwpself 176 */ - .word solaris_unimplemented /* lwpinfo 177 */ - .word solaris_unimplemented /* lwpprivate 178 */ - .word solaris_unimplemented /* processorbind 179 */ - .word solaris_unimplemented /* processorexbind 180 */ - .word solaris_unimplemented /* 181 */ - .word solaris_unimplemented /* sync_mailbox 182 */ - .word solaris_unimplemented /* prepblock 183 */ - .word solaris_unimplemented /* block 184 */ - .word solaris_acl /* acl sddp 185 */ - .word solaris_unimplemented /* unblock 186 */ - .word solaris_unimplemented /* cancelblock 187 */ - .word solaris_unimplemented /* ? 188 */ - .word solaris_unimplemented /* xxxxx 189 */ - .word solaris_unimplemented /* xxxxxe 190 */ - .word solaris_unimplemented /* 191 */ - .word solaris_unimplemented /* 192 */ - .word solaris_unimplemented /* 193 */ - .word solaris_unimplemented /* 194 */ - .word solaris_unimplemented /* 195 */ - .word solaris_unimplemented /* 196 */ - .word solaris_unimplemented /* 197 */ - .word solaris_unimplemented /* 198 */ - .word CHAIN(nanosleep) /* nanosleep dd 199 */ - .word solaris_facl /* facl dddp 200 */ - .word solaris_unimplemented /* 201 */ - .word CHAIN(setreuid) /* setreuid dd 202 */ - .word CHAIN(setregid) /* setregid dd 203 */ - .word solaris_unimplemented /* 204 */ - .word solaris_unimplemented /* 205 */ - .word solaris_unimplemented /* 206 */ - .word solaris_unimplemented /* 207 */ - .word solaris_unimplemented /* 208 */ - .word solaris_unimplemented /* 209 */ - .word solaris_unimplemented /* 210 */ - .word solaris_unimplemented /* 211 */ - .word solaris_unimplemented /* 212 */ - .word solaris_getdents64 /* getdents64 dpd 213 */ - .word REGS(solaris_mmap64) /* mmap64 xxxxdX 214 */ - .word solaris_stat64 /* stat64 sP 215 */ - .word solaris_lstat64 /* lstat64 sP 216 */ - .word solaris_fstat64 /* fstat64 dP 217 */ - .word solaris_statvfs64 /* statvfs64 sP 218 */ - .word solaris_fstatvfs64 /* fstatvfs64 dP 219 */ - .word solaris_setrlimit64 /* setrlimit64 dP 220 */ - .word solaris_getrlimit64 /* getrlimit64 dP 221 */ - .word CHAIN(pread64) /* pread64 dpdD 222 */ - .word CHAIN(pwrite64) /* pwrite64 dpdD 223 */ - .word CHAIN(creat) /* creat64 so 224 */ - .word solaris_open /* open64 soo 225 */ - .word solaris_unimplemented /* 226 */ - .word solaris_unimplemented /* 227 */ - .word solaris_unimplemented /* 228 */ - .word solaris_unimplemented /* 229 */ - .word solaris_socket /* socket ddd 230 */ - .word solaris_socketpair /* socketpair dddp 231 */ - .word solaris_bind /* bind dpd 232 */ - .word solaris_listen /* listen dd 233 */ - .word solaris_accept /* accept dpp 234 */ - .word solaris_connect /* connect dpd 235 */ - .word solaris_shutdown /* shutdown dd 236 */ - .word solaris_recv /* recv dpdd 237 */ - .word solaris_recvfrom /* recvfrom dpddpp 238 */ - .word solaris_recvmsg /* recvmsg dpd 239 */ - .word solaris_send /* send dpdd 240 */ - .word solaris_sendmsg /* sendmsg dpd 241 */ - .word solaris_sendto /* sendto dpddpd 242 */ - .word solaris_getpeername /* getpeername dpp 243 */ - .word solaris_getsockname /* getsockname dpp 244 */ - .word solaris_getsockopt /* getsockopt dddpp 245 */ - .word solaris_setsockopt /* setsockopt dddpp 246 */ - .word solaris_unimplemented /* 247 */ - .word solaris_ntp_gettime /* ntp_gettime p 248 */ - .word solaris_ntp_adjtime /* ntp_adjtime p 249 */ - .word solaris_unimplemented /* 250 */ - .word solaris_unimplemented /* 251 */ - .word solaris_unimplemented /* 252 */ - .word solaris_unimplemented /* 253 */ - .word solaris_unimplemented /* 254 */ - .word solaris_unimplemented /* 255 */ - .word solaris_unimplemented /* 256 */ - .word solaris_unimplemented /* 257 */ - .word solaris_unimplemented /* 258 */ - .word solaris_unimplemented /* 259 */ - .word solaris_unimplemented /* 260 */ - .word solaris_unimplemented /* 261 */ - .word solaris_unimplemented /* 262 */ - .word solaris_unimplemented /* 263 */ - .word solaris_unimplemented /* 264 */ - .word solaris_unimplemented /* 265 */ - .word solaris_unimplemented /* 266 */ - .word solaris_unimplemented /* 267 */ - .word solaris_unimplemented /* 268 */ - .word solaris_unimplemented /* 269 */ - .word solaris_unimplemented /* 270 */ - .word solaris_unimplemented /* 271 */ - .word solaris_unimplemented /* 272 */ - .word solaris_unimplemented /* 273 */ - .word solaris_unimplemented /* 274 */ - .word solaris_unimplemented /* 275 */ - .word solaris_unimplemented /* 276 */ - .word solaris_unimplemented /* 277 */ - .word solaris_unimplemented /* 278 */ - .word solaris_unimplemented /* 279 */ - .word solaris_unimplemented /* 280 */ - .word solaris_unimplemented /* 281 */ - .word solaris_unimplemented /* 282 */ - .word solaris_unimplemented /* 283 */ - diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c deleted file mode 100644 index b84e5456b02..00000000000 --- a/arch/sparc64/solaris/timod.c +++ /dev/null @@ -1,974 +0,0 @@ -/* $Id: timod.c,v 1.19 2002/02/08 03:57:14 davem Exp $ - * timod.c: timod emulation. - * - * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - * - * Streams & timod emulation based on code - * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) - * - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/ioctl.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/netdevice.h> -#include <linux/poll.h> - -#include <net/sock.h> - -#include <asm/uaccess.h> -#include <asm/termios.h> - -#include "conv.h" -#include "socksys.h" - -asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg); - -static DEFINE_SPINLOCK(timod_pagelock); -static char * page = NULL ; - -#ifndef DEBUG_SOLARIS_KMALLOC - -#define mykmalloc kmalloc -#define mykfree kfree - -#else - -void * mykmalloc(size_t s, gfp_t gfp) -{ - static char * page; - static size_t free; - void * r; - s = ((s + 63) & ~63); - if( s > PAGE_SIZE ) { - SOLD("too big size, calling real kmalloc"); - return kmalloc(s, gfp); - } - if( s > free ) { - /* we are wasting memory, but we don't care */ - page = (char *)__get_free_page(gfp); - free = PAGE_SIZE; - } - r = page; - page += s; - free -= s; - return r; -} - -void mykfree(void *p) -{ -} - -#endif - -#ifndef DEBUG_SOLARIS - -#define BUF_SIZE PAGE_SIZE -#define PUT_MAGIC(a,m) -#define SCHECK_MAGIC(a,m) -#define BUF_OFFSET 0 -#define MKCTL_TRAILER 0 - -#else - -#define BUF_SIZE (PAGE_SIZE-2*sizeof(u64)) -#define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL -#define MKCTL_MAGIC 0xDEADBABEBADC0DEDL -#define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0) -#define SCHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\ - __FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0) -#define BUF_OFFSET sizeof(u64) -#define MKCTL_TRAILER sizeof(u64) - -#endif - -static char *getpage( void ) -{ - char *r; - SOLD("getting page"); - spin_lock(&timod_pagelock); - if (page) { - r = page; - page = NULL; - spin_unlock(&timod_pagelock); - SOLD("got cached"); - return r + BUF_OFFSET; - } - spin_unlock(&timod_pagelock); - SOLD("getting new"); - r = (char *)__get_free_page(GFP_KERNEL); - PUT_MAGIC(r,BUFPAGE_MAGIC); - PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC); - return r + BUF_OFFSET; -} - -static void putpage(char *p) -{ - SOLD("putting page"); - p = p - BUF_OFFSET; - SCHECK_MAGIC(p,BUFPAGE_MAGIC); - SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC); - spin_lock(&timod_pagelock); - if (page) { - spin_unlock(&timod_pagelock); - free_page((unsigned long)p); - SOLD("freed it"); - } else { - page = p; - spin_unlock(&timod_pagelock); - SOLD("cached it"); - } -} - -static struct T_primsg *timod_mkctl(int size) -{ - struct T_primsg *it; - - SOLD("creating primsg"); - it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL); - if (it) { - SOLD("got it"); - it->pri = MSG_HIPRI; - it->length = size; - PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC); - } - return it; -} - -static void timod_wake_socket(unsigned int fd) -{ - struct socket *sock; - struct fdtable *fdt; - - SOLD("wakeing socket"); - fdt = files_fdtable(current->files); - sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode); - wake_up_interruptible(&sock->wait); - read_lock(&sock->sk->sk_callback_lock); - if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) - __kill_fasync(sock->fasync_list, SIGIO, POLL_IN); - read_unlock(&sock->sk->sk_callback_lock); - SOLD("done"); -} - -static void timod_queue(unsigned int fd, struct T_primsg *it) -{ - struct sol_socket_struct *sock; - struct fdtable *fdt; - - SOLD("queuing primsg"); - fdt = files_fdtable(current->files); - sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data; - it->next = sock->pfirst; - sock->pfirst = it; - if (!sock->plast) - sock->plast = it; - timod_wake_socket(fd); - SOLD("done"); -} - -static void timod_queue_end(unsigned int fd, struct T_primsg *it) -{ - struct sol_socket_struct *sock; - struct fdtable *fdt; - - SOLD("queuing primsg at end"); - fdt = files_fdtable(current->files); - sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data; - it->next = NULL; - if (sock->plast) - sock->plast->next = it; - else - sock->pfirst = it; - sock->plast = it; - SOLD("done"); -} - -static void timod_error(unsigned int fd, int prim, int terr, int uerr) -{ - struct T_primsg *it; - - SOLD("making error"); - it = timod_mkctl(sizeof(struct T_error_ack)); - if (it) { - struct T_error_ack *err = (struct T_error_ack *)&it->type; - - SOLD("got it"); - err->PRIM_type = T_ERROR_ACK; - err->ERROR_prim = prim; - err->TLI_error = terr; - err->UNIX_error = uerr; /* FIXME: convert this */ - timod_queue(fd, it); - } - SOLD("done"); -} - -static void timod_ok(unsigned int fd, int prim) -{ - struct T_primsg *it; - struct T_ok_ack *ok; - - SOLD("creating ok ack"); - it = timod_mkctl(sizeof(*ok)); - if (it) { - SOLD("got it"); - ok = (struct T_ok_ack *)&it->type; - ok->PRIM_type = T_OK_ACK; - ok->CORRECT_prim = prim; - timod_queue(fd, it); - } - SOLD("done"); -} - -static int timod_optmgmt(unsigned int fd, int flag, char __user *opt_buf, int opt_len, int do_ret) -{ - int error, failed; - int ret_space, ret_len; - long args[5]; - char *ret_pos,*ret_buf; - int (*sys_socketcall)(int, unsigned long *) = - (int (*)(int, unsigned long *))SYS(socketcall); - mm_segment_t old_fs = get_fs(); - - SOLD("entry"); - SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret)); - if (!do_ret && (!opt_buf || opt_len <= 0)) - return 0; - SOLD("getting page"); - ret_pos = ret_buf = getpage(); - ret_space = BUF_SIZE; - ret_len = 0; - - error = failed = 0; - SOLD("looping"); - while(opt_len >= sizeof(struct opthdr)) { - struct opthdr *opt; - int orig_opt_len; - SOLD("loop start"); - opt = (struct opthdr *)ret_pos; - if (ret_space < sizeof(struct opthdr)) { - failed = TSYSERR; - break; - } - SOLD("getting opthdr"); - if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) || - opt->len > opt_len) { - failed = TBADOPT; - break; - } - SOLD("got opthdr"); - if (flag == T_NEGOTIATE) { - char *buf; - - SOLD("handling T_NEGOTIATE"); - buf = ret_pos + sizeof(struct opthdr); - if (ret_space < opt->len + sizeof(struct opthdr) || - copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) { - failed = TSYSERR; - break; - } - SOLD("got optdata"); - args[0] = fd; - args[1] = opt->level; - args[2] = opt->name; - args[3] = (long)buf; - args[4] = opt->len; - SOLD("calling SETSOCKOPT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_SETSOCKOPT, args); - set_fs(old_fs); - if (error) { - failed = TBADOPT; - break; - } - SOLD("SETSOCKOPT ok"); - } - orig_opt_len = opt->len; - opt->len = ret_space - sizeof(struct opthdr); - if (opt->len < 0) { - failed = TSYSERR; - break; - } - args[0] = fd; - args[1] = opt->level; - args[2] = opt->name; - args[3] = (long)(ret_pos+sizeof(struct opthdr)); - args[4] = (long)&opt->len; - SOLD("calling GETSOCKOPT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_GETSOCKOPT, args); - set_fs(old_fs); - if (error) { - failed = TBADOPT; - break; - } - SOLD("GETSOCKOPT ok"); - ret_space -= sizeof(struct opthdr) + opt->len; - ret_len += sizeof(struct opthdr) + opt->len; - ret_pos += sizeof(struct opthdr) + opt->len; - opt_len -= sizeof(struct opthdr) + orig_opt_len; - opt_buf += sizeof(struct opthdr) + orig_opt_len; - SOLD("loop end"); - } - SOLD("loop done"); - if (do_ret) { - SOLD("generating ret msg"); - if (failed) - timod_error(fd, T_OPTMGMT_REQ, failed, -error); - else { - struct T_primsg *it; - it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len); - if (it) { - struct T_optmgmt_ack *ack = - (struct T_optmgmt_ack *)&it->type; - SOLD("got primsg"); - ack->PRIM_type = T_OPTMGMT_ACK; - ack->OPT_length = ret_len; - ack->OPT_offset = sizeof(struct T_optmgmt_ack); - ack->MGMT_flags = (failed ? T_FAILURE : flag); - memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack), - ret_buf, ret_len); - timod_queue(fd, it); - } - } - } - SOLDD(("put_page %p\n", ret_buf)); - putpage(ret_buf); - SOLD("done"); - return 0; -} - -int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len, - char __user *data_buf, int data_len, int flags) -{ - int ret, error, terror; - char *buf; - struct file *filp; - struct inode *ino; - struct fdtable *fdt; - struct sol_socket_struct *sock; - mm_segment_t old_fs = get_fs(); - long args[6]; - int (*sys_socketcall)(int, unsigned long __user *) = - (int (*)(int, unsigned long __user *))SYS(socketcall); - int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int))SYS(sendto); - - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - ino = filp->f_dentry->d_inode; - sock = (struct sol_socket_struct *)filp->private_data; - SOLD("entry"); - if (get_user(ret, (int __user *)A(ctl_buf))) - return -EFAULT; - switch (ret) { - case T_BIND_REQ: - { - struct T_bind_req req; - - SOLDD(("bind %016lx(%016lx)\n", sock, filp)); - SOLD("T_BIND_REQ"); - if (sock->state != TS_UNBND) { - timod_error(fd, T_BIND_REQ, TOUTSTATE, 0); - return 0; - } - SOLD("state ok"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) { - timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("got ctl req"); - if (req.ADDR_offset && req.ADDR_length) { - if (req.ADDR_length > BUF_SIZE) { - timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("req size ok"); - buf = getpage(); - if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) { - timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); - putpage(buf); - return 0; - } - SOLD("got ctl data"); - args[0] = fd; - args[1] = (long)buf; - args[2] = req.ADDR_length; - SOLD("calling BIND"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_BIND, args); - set_fs(old_fs); - putpage(buf); - SOLD("BIND returned"); - } else - error = 0; - if (!error) { - struct T_primsg *it; - if (req.CONIND_number) { - args[0] = fd; - args[1] = req.CONIND_number; - SOLD("calling LISTEN"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_LISTEN, args); - set_fs(old_fs); - SOLD("LISTEN done"); - } - it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr)); - if (it) { - struct T_bind_ack *ack; - - ack = (struct T_bind_ack *)&it->type; - ack->PRIM_type = T_BIND_ACK; - ack->ADDR_offset = sizeof(*ack); - ack->ADDR_length = sizeof(struct sockaddr); - ack->CONIND_number = req.CONIND_number; - args[0] = fd; - args[1] = (long)(ack+sizeof(*ack)); - args[2] = (long)&ack->ADDR_length; - set_fs(KERNEL_DS); - sys_socketcall(SYS_GETSOCKNAME,args); - set_fs(old_fs); - sock->state = TS_IDLE; - timod_ok(fd, T_BIND_REQ); - timod_queue_end(fd, it); - SOLD("BIND done"); - return 0; - } - } - SOLD("some error"); - switch (error) { - case -EINVAL: - terror = TOUTSTATE; - error = 0; - break; - case -EACCES: - terror = TACCES; - error = 0; - break; - case -EADDRNOTAVAIL: - case -EADDRINUSE: - terror = TNOADDR; - error = 0; - break; - default: - terror = TSYSERR; - break; - } - timod_error(fd, T_BIND_REQ, terror, -error); - SOLD("BIND done"); - return 0; - } - case T_CONN_REQ: - { - struct T_conn_req req; - unsigned short oldflags; - struct T_primsg *it; - SOLD("T_CONN_REQ"); - if (sock->state != TS_UNBND && sock->state != TS_IDLE) { - timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); - return 0; - } - SOLD("state ok"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("got ctl req"); - if (ctl_len > BUF_SIZE) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("req size ok"); - buf = getpage(); - if (copy_from_user(buf, ctl_buf, ctl_len)) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - putpage(buf); - return 0; - } -#ifdef DEBUG_SOLARIS - { - char * ptr = buf; - int len = ctl_len; - printk("returned data (%d bytes): ",len); - while( len-- ) { - if (!(len & 7)) - printk(" "); - printk("%02x",(unsigned char)*ptr++); - } - printk("\n"); - } -#endif - SOLD("got ctl data"); - args[0] = fd; - args[1] = (long)buf+req.DEST_offset; - args[2] = req.DEST_length; - oldflags = filp->f_flags; - filp->f_flags &= ~O_NONBLOCK; - SOLD("calling CONNECT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_CONNECT, args); - set_fs(old_fs); - filp->f_flags = oldflags; - SOLD("CONNECT done"); - if (!error) { - struct T_conn_con *con; - SOLD("no error"); - it = timod_mkctl(ctl_len); - if (!it) { - putpage(buf); - return -ENOMEM; - } - con = (struct T_conn_con *)&it->type; -#ifdef DEBUG_SOLARIS - { - char * ptr = buf; - int len = ctl_len; - printk("returned data (%d bytes): ",len); - while( len-- ) { - if (!(len & 7)) - printk(" "); - printk("%02x",(unsigned char)*ptr++); - } - printk("\n"); - } -#endif - memcpy(con, buf, ctl_len); - SOLD("copied ctl_buf"); - con->PRIM_type = T_CONN_CON; - sock->state = TS_DATA_XFER; - } else { - struct T_discon_ind *dis; - SOLD("some error"); - it = timod_mkctl(sizeof(*dis)); - if (!it) { - putpage(buf); - return -ENOMEM; - } - SOLD("got primsg"); - dis = (struct T_discon_ind *)&it->type; - dis->PRIM_type = T_DISCON_IND; - dis->DISCON_reason = -error; /* FIXME: convert this as in iABI_errors() */ - dis->SEQ_number = 0; - } - putpage(buf); - timod_ok(fd, T_CONN_REQ); - it->pri = 0; - timod_queue_end(fd, it); - SOLD("CONNECT done"); - return 0; - } - case T_OPTMGMT_REQ: - { - struct T_optmgmt_req req; - SOLD("OPTMGMT_REQ"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) - return -EFAULT; - SOLD("got req"); - return timod_optmgmt(fd, req.MGMT_flags, - req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL, - req.OPT_length, 1); - } - case T_UNITDATA_REQ: - { - struct T_unitdata_req req; - - int err; - SOLD("T_UNITDATA_REQ"); - if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) { - timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); - return 0; - } - SOLD("state ok"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("got ctl req"); -#ifdef DEBUG_SOLARIS - { - char * ptr = ctl_buf+req.DEST_offset; - int len = req.DEST_length; - printk("socket address (%d bytes): ",len); - while( len-- ) { - char c; - if (get_user(c,ptr)) - printk("??"); - else - printk("%02x",(unsigned char)c); - ptr++; - } - printk("\n"); - } -#endif - err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr __user *)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length); - if (err == data_len) - return 0; - if(err >= 0) { - printk("timod: sendto failed to send all the data\n"); - return 0; - } - timod_error(fd, T_CONN_REQ, TSYSERR, -err); - return 0; - } - default: - printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret); - break; - } - return -EINVAL; -} - -int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __user *ctl_len, - char __user *data_buf, int data_maxlen, s32 __user *data_len, int *flags_p) -{ - int error; - int oldflags; - struct file *filp; - struct inode *ino; - struct fdtable *fdt; - struct sol_socket_struct *sock; - struct T_unitdata_ind udi; - mm_segment_t old_fs = get_fs(); - long args[6]; - char __user *tmpbuf; - int tmplen; - int (*sys_socketcall)(int, unsigned long __user *) = - (int (*)(int, unsigned long __user *))SYS(socketcall); - int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *); - - SOLD("entry"); - SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p)); - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - ino = filp->f_dentry->d_inode; - sock = (struct sol_socket_struct *)filp->private_data; - SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); - if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM - && sock->state == TS_IDLE) { - SOLD("calling LISTEN"); - args[0] = fd; - args[1] = -1; - set_fs(KERNEL_DS); - sys_socketcall(SYS_LISTEN, args); - set_fs(old_fs); - SOLD("LISTEN done"); - } - if (!(filp->f_flags & O_NONBLOCK)) { - struct poll_wqueues wait_table; - poll_table *wait; - - poll_initwait(&wait_table); - wait = &wait_table.pt; - for(;;) { - SOLD("loop"); - set_current_state(TASK_INTERRUPTIBLE); - /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */ - /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */ - if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI)) - break; - SOLD("cond 1 passed"); - if ( - #if 1 - *flags_p != MSG_HIPRI && - #endif - ((filp->f_op->poll(filp, wait) & POLLIN) || - (filp->f_op->poll(filp, NULL) & POLLIN) || - signal_pending(current)) - ) { - break; - } - if( *flags_p == MSG_HIPRI ) { - SOLD("avoiding lockup"); - break ; - } - if(wait_table.error) { - SOLD("wait-table error"); - poll_freewait(&wait_table); - return wait_table.error; - } - SOLD("scheduling"); - schedule(); - } - SOLD("loop done"); - current->state = TASK_RUNNING; - poll_freewait(&wait_table); - if (signal_pending(current)) { - SOLD("signal pending"); - return -EINTR; - } - } - if (ctl_maxlen >= 0 && sock->pfirst) { - struct T_primsg *it = sock->pfirst; - int l = min_t(int, ctl_maxlen, it->length); - SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC); - SOLD("purting ctl data"); - if(copy_to_user(ctl_buf, - (char*)&it->type + sock->offset, l)) - return -EFAULT; - SOLD("pur it"); - if(put_user(l, ctl_len)) - return -EFAULT; - SOLD("set ctl_len"); - *flags_p = it->pri; - it->length -= l; - if (it->length) { - SOLD("more ctl"); - sock->offset += l; - return MORECTL; - } else { - SOLD("removing message"); - sock->pfirst = it->next; - if (!sock->pfirst) - sock->plast = NULL; - SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst)); - mykfree(it); - sock->offset = 0; - SOLD("ctl done"); - return 0; - } - } - *flags_p = 0; - if (ctl_maxlen >= 0) { - SOLD("ACCEPT perhaps?"); - if (SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) { - struct T_conn_ind ind; - char *buf = getpage(); - int len = BUF_SIZE; - - SOLD("trying ACCEPT"); - if (put_user(ctl_maxlen - sizeof(ind), ctl_len)) - return -EFAULT; - args[0] = fd; - args[1] = (long)buf; - args[2] = (long)&len; - oldflags = filp->f_flags; - filp->f_flags |= O_NONBLOCK; - SOLD("calling ACCEPT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_ACCEPT, args); - set_fs(old_fs); - filp->f_flags = oldflags; - if (error < 0) { - SOLD("some error"); - putpage(buf); - return error; - } - if (error) { - SOLD("connect"); - putpage(buf); - if (sizeof(ind) > ctl_maxlen) { - SOLD("generating CONN_IND"); - ind.PRIM_type = T_CONN_IND; - ind.SRC_length = len; - ind.SRC_offset = sizeof(ind); - ind.OPT_length = ind.OPT_offset = 0; - ind.SEQ_number = error; - if(copy_to_user(ctl_buf, &ind, sizeof(ind))|| - put_user(sizeof(ind)+ind.SRC_length,ctl_len)) - return -EFAULT; - SOLD("CONN_IND created"); - } - if (data_maxlen >= 0) - put_user(0, data_len); - SOLD("CONN_IND done"); - return 0; - } - if (len>ctl_maxlen) { - SOLD("data don't fit"); - putpage(buf); - return -EFAULT; /* XXX - is this ok ? */ - } - if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){ - SOLD("can't copy data"); - putpage(buf); - return -EFAULT; - } - SOLD("ACCEPT done"); - putpage(buf); - } - } - SOLD("checking data req"); - if (data_maxlen <= 0) { - if (data_maxlen == 0) - put_user(0, data_len); - if (ctl_maxlen >= 0) - put_user(0, ctl_len); - return -EAGAIN; - } - SOLD("wants data"); - if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { - SOLD("udi fits"); - tmpbuf = ctl_buf + sizeof(udi); - tmplen = ctl_maxlen - sizeof(udi); - } else { - SOLD("udi does not fit"); - tmpbuf = NULL; - tmplen = 0; - } - if (put_user(tmplen, ctl_len)) - return -EFAULT; - SOLD("set ctl_len"); - oldflags = filp->f_flags; - filp->f_flags |= O_NONBLOCK; - SOLD("calling recvfrom"); - sys_recvfrom = (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom); - error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr __user *)tmpbuf, ctl_len); - filp->f_flags = oldflags; - if (error < 0) - return error; - SOLD("error >= 0" ) ; - if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { - SOLD("generating udi"); - udi.PRIM_type = T_UNITDATA_IND; - if (get_user(udi.SRC_length, ctl_len)) - return -EFAULT; - udi.SRC_offset = sizeof(udi); - udi.OPT_length = udi.OPT_offset = 0; - if (copy_to_user(ctl_buf, &udi, sizeof(udi)) || - put_user(sizeof(udi)+udi.SRC_length, ctl_len)) - return -EFAULT; - SOLD("udi done"); - } else { - if (put_user(0, ctl_len)) - return -EFAULT; - } - put_user(error, data_len); - SOLD("done"); - return 0; -} - -asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) -{ - struct file *filp; - struct inode *ino; - struct strbuf __user *ctlptr; - struct strbuf __user *datptr; - struct strbuf ctl, dat; - int __user *flgptr; - int flags; - int error = -EBADF; - struct fdtable *fdt; - - SOLD("entry"); - lock_kernel(); - if(fd >= NR_OPEN) goto out; - - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - if(!filp) goto out; - - ino = filp->f_dentry->d_inode; - if (!ino || !S_ISSOCK(ino->i_mode)) - goto out; - - ctlptr = (struct strbuf __user *)A(arg1); - datptr = (struct strbuf __user *)A(arg2); - flgptr = (int __user *)A(arg3); - - error = -EFAULT; - - if (ctlptr) { - if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) || - put_user(-1,&ctlptr->len)) - goto out; - } else - ctl.maxlen = -1; - - if (datptr) { - if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) || - put_user(-1,&datptr->len)) - goto out; - } else - dat.maxlen = -1; - - if (get_user(flags,flgptr)) - goto out; - - switch (flags) { - case 0: - case MSG_HIPRI: - case MSG_ANY: - case MSG_BAND: - break; - default: - error = -EINVAL; - goto out; - } - - error = timod_getmsg(fd,A(ctl.buf),ctl.maxlen,&ctlptr->len, - A(dat.buf),dat.maxlen,&datptr->len,&flags); - - if (!error && put_user(flags,flgptr)) - error = -EFAULT; -out: - unlock_kernel(); - SOLD("done"); - return error; -} - -asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) -{ - struct file *filp; - struct inode *ino; - struct strbuf __user *ctlptr; - struct strbuf __user *datptr; - struct strbuf ctl, dat; - int flags = (int) arg3; - int error = -EBADF; - struct fdtable *fdt; - - SOLD("entry"); - lock_kernel(); - if(fd >= NR_OPEN) goto out; - - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - if(!filp) goto out; - - ino = filp->f_dentry->d_inode; - if (!ino) goto out; - - if (!S_ISSOCK(ino->i_mode) && - (imajor(ino) != 30 || iminor(ino) != 1)) - goto out; - - ctlptr = A(arg1); - datptr = A(arg2); - - error = -EFAULT; - - if (ctlptr) { - if (copy_from_user(&ctl,ctlptr,sizeof(ctl))) - goto out; - if (ctl.len < 0 && flags) { - error = -EINVAL; - goto out; - } - } else { - ctl.len = 0; - ctl.buf = 0; - } - - if (datptr) { - if (copy_from_user(&dat,datptr,sizeof(dat))) - goto out; - } else { - dat.len = 0; - dat.buf = 0; - } - - error = timod_putmsg(fd,A(ctl.buf),ctl.len, - A(dat.buf),dat.len,flags); -out: - unlock_kernel(); - SOLD("done"); - return error; -} |
