diff options
Diffstat (limited to 'arch/sh64/kernel')
29 files changed, 0 insertions, 9875 deletions
diff --git a/arch/sh64/kernel/Makefile b/arch/sh64/kernel/Makefile deleted file mode 100644 index e3467bda6167..000000000000 --- a/arch/sh64/kernel/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2000, 2001 Paolo Alberelli -# Copyright (C) 2003 Paul Mundt -# -# Makefile for the Linux sh64 kernel. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -extra-y := head.o init_task.o vmlinux.lds - -obj-y := process.o signal.o entry.o traps.o irq.o irq_intc.o \ - ptrace.o setup.o time.o sys_sh64.o semaphore.o sh_ksyms.o \ - switchto.o syscalls.o - -obj-$(CONFIG_HEARTBEAT) += led.o -obj-$(CONFIG_SH_ALPHANUMERIC) += alphanum.o -obj-$(CONFIG_SH_DMA) += dma.o -obj-$(CONFIG_SH_FPU) += fpu.o -obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_KALLSYMS) += unwind.o -obj-$(CONFIG_PCI) += pcibios.o -obj-$(CONFIG_MODULES) += module.o - -ifeq ($(CONFIG_PCI),y) -obj-$(CONFIG_CPU_SH5) += pci_sh5.o -endif - -USE_STANDARD_AS_RULE := true - diff --git a/arch/sh64/kernel/alphanum.c b/arch/sh64/kernel/alphanum.c deleted file mode 100644 index d1619d95fbaa..000000000000 --- a/arch/sh64/kernel/alphanum.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * arch/sh64/kernel/alphanum.c - * - * Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com> - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine-independent functions for handling 8-digit alphanumeric display - * (e.g. Agilent HDSP-253x) - */ -#include <linux/stddef.h> -#include <linux/sched.h> - -void mach_alphanum(int pos, unsigned char val); - -void print_seg(char *file, int line) -{ - int i; - unsigned int nibble; - - for (i = 0; i < 5; i++) { - mach_alphanum(i, file[i]); - } - - for (i = 0; i < 3; i++) { - nibble = ((line >> (i * 4)) & 0xf); - mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48)); - } -} - -void print_seg_num(unsigned num) -{ - int i; - unsigned int nibble; - - for (i = 0; i < 8; i++) { - nibble = ((num >> (i * 4)) & 0xf); - - mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48)); - } -} - diff --git a/arch/sh64/kernel/asm-offsets.c b/arch/sh64/kernel/asm-offsets.c deleted file mode 100644 index ca76537c16c0..000000000000 --- a/arch/sh64/kernel/asm-offsets.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#include <linux/stddef.h> -#include <linux/types.h> -#include <linux/mm.h> -#include <asm/thread_info.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - -int main(void) -{ - /* offsets into the thread_info struct */ - DEFINE(TI_TASK, offsetof(struct thread_info, task)); - DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); - - return 0; -} diff --git a/arch/sh64/kernel/dma.c b/arch/sh64/kernel/dma.c deleted file mode 100644 index 32c6f0549bf1..000000000000 --- a/arch/sh64/kernel/dma.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * arch/sh64/kernel/dma.c - * - * DMA routines for the SH-5 DMAC. - * - * Copyright (C) 2003 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/types.h> -#include <linux/irq.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <asm/hardware.h> -#include <asm/dma.h> -#include <asm/signal.h> -#include <asm/errno.h> -#include <asm/io.h> - -typedef struct { - unsigned long dev_addr; - unsigned long mem_addr; - - unsigned int mode; - unsigned int count; -} dma_info_t; - -static dma_info_t dma_info[MAX_DMA_CHANNELS]; -static DEFINE_SPINLOCK(dma_spin_lock); - -/* arch/sh64/kernel/irq_intc.c */ -extern void make_intc_irq(unsigned int irq); - -/* DMAC Interrupts */ -#define DMA_IRQ_DMTE0 18 -#define DMA_IRQ_DERR 22 - -#define DMAC_COMMON_BASE (dmac_base + 0x08) -#define DMAC_SAR_BASE (dmac_base + 0x10) -#define DMAC_DAR_BASE (dmac_base + 0x18) -#define DMAC_COUNT_BASE (dmac_base + 0x20) -#define DMAC_CTRL_BASE (dmac_base + 0x28) -#define DMAC_STATUS_BASE (dmac_base + 0x30) - -#define DMAC_SAR(n) (DMAC_SAR_BASE + ((n) * 0x28)) -#define DMAC_DAR(n) (DMAC_DAR_BASE + ((n) * 0x28)) -#define DMAC_COUNT(n) (DMAC_COUNT_BASE + ((n) * 0x28)) -#define DMAC_CTRL(n) (DMAC_CTRL_BASE + ((n) * 0x28)) -#define DMAC_STATUS(n) (DMAC_STATUS_BASE + ((n) * 0x28)) - -/* DMAC.COMMON Bit Definitions */ -#define DMAC_COMMON_PR 0x00000001 /* Priority */ - /* Bits 1-2 Reserved */ -#define DMAC_COMMON_ME 0x00000008 /* Master Enable */ -#define DMAC_COMMON_NMI 0x00000010 /* NMI Flag */ - /* Bits 5-6 Reserved */ -#define DMAC_COMMON_ER 0x00000780 /* Error Response */ -#define DMAC_COMMON_AAE 0x00007800 /* Address Alignment Error */ - /* Bits 15-63 Reserved */ - -/* DMAC.SAR Bit Definitions */ -#define DMAC_SAR_ADDR 0xffffffff /* Source Address */ - -/* DMAC.DAR Bit Definitions */ -#define DMAC_DAR_ADDR 0xffffffff /* Destination Address */ - -/* DMAC.COUNT Bit Definitions */ -#define DMAC_COUNT_CNT 0xffffffff /* Transfer Count */ - -/* DMAC.CTRL Bit Definitions */ -#define DMAC_CTRL_TS 0x00000007 /* Transfer Size */ -#define DMAC_CTRL_SI 0x00000018 /* Source Increment */ -#define DMAC_CTRL_DI 0x00000060 /* Destination Increment */ -#define DMAC_CTRL_RS 0x00000780 /* Resource Select */ -#define DMAC_CTRL_IE 0x00000800 /* Interrupt Enable */ -#define DMAC_CTRL_TE 0x00001000 /* Transfer Enable */ - /* Bits 15-63 Reserved */ - -/* DMAC.STATUS Bit Definitions */ -#define DMAC_STATUS_TE 0x00000001 /* Transfer End */ -#define DMAC_STATUS_AAE 0x00000002 /* Address Alignment Error */ - /* Bits 2-63 Reserved */ - -static unsigned long dmac_base; - -void set_dma_count(unsigned int chan, unsigned int count); -void set_dma_addr(unsigned int chan, unsigned int addr); - -static irqreturn_t dma_mte(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int chan = irq - DMA_IRQ_DMTE0; - dma_info_t *info = dma_info + chan; - u64 status; - - if (info->mode & DMA_MODE_WRITE) { - sh64_out64(info->mem_addr & DMAC_SAR_ADDR, DMAC_SAR(chan)); - } else { - sh64_out64(info->mem_addr & DMAC_DAR_ADDR, DMAC_DAR(chan)); - } - - set_dma_count(chan, info->count); - - /* Clear the TE bit */ - status = sh64_in64(DMAC_STATUS(chan)); - status &= ~DMAC_STATUS_TE; - sh64_out64(status, DMAC_STATUS(chan)); - - return IRQ_HANDLED; -} - -static struct irqaction irq_dmte = { - .handler = dma_mte, - .flags = IRQF_DISABLED, - .name = "DMA MTE", -}; - -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) -{ - u64 tmp; - u8 chan; - - printk(KERN_NOTICE "DMAC: Got a DMA Error!\n"); - - tmp = sh64_in64(DMAC_COMMON_BASE); - - /* Check for the type of error */ - if ((chan = tmp & DMAC_COMMON_AAE)) { - /* It's an address alignment error.. */ - printk(KERN_NOTICE "DMAC: Alignment error on channel %d, ", chan); - - printk(KERN_NOTICE "SAR: 0x%08llx, DAR: 0x%08llx, COUNT: %lld\n", - (sh64_in64(DMAC_SAR(chan)) & DMAC_SAR_ADDR), - (sh64_in64(DMAC_DAR(chan)) & DMAC_DAR_ADDR), - (sh64_in64(DMAC_COUNT(chan)) & DMAC_COUNT_CNT)); - - } else if ((chan = tmp & DMAC_COMMON_ER)) { - /* Something else went wrong.. */ - printk(KERN_NOTICE "DMAC: Error on channel %d\n", chan); - } - - /* Reset the ME bit to clear the interrupt */ - tmp |= DMAC_COMMON_ME; - sh64_out64(tmp, DMAC_COMMON_BASE); - - return IRQ_HANDLED; -} - -static struct irqaction irq_derr = { - .handler = dma_err, - .flags = IRQF_DISABLED, - .name = "DMA Error", -}; - -static inline unsigned long calc_xmit_shift(unsigned int chan) -{ - return sh64_in64(DMAC_CTRL(chan)) & 0x03; -} - -void setup_dma(unsigned int chan, dma_info_t *info) -{ - unsigned int irq = DMA_IRQ_DMTE0 + chan; - dma_info_t *dma = dma_info + chan; - - make_intc_irq(irq); - setup_irq(irq, &irq_dmte); - dma = info; -} - -void enable_dma(unsigned int chan) -{ - u64 ctrl; - - ctrl = sh64_in64(DMAC_CTRL(chan)); - ctrl |= DMAC_CTRL_TE; - sh64_out64(ctrl, DMAC_CTRL(chan)); -} - -void disable_dma(unsigned int chan) -{ - u64 ctrl; - - ctrl = sh64_in64(DMAC_CTRL(chan)); - ctrl &= ~DMAC_CTRL_TE; - sh64_out64(ctrl, DMAC_CTRL(chan)); -} - -void set_dma_mode(unsigned int chan, char mode) -{ - dma_info_t *info = dma_info + chan; - - info->mode = mode; - - set_dma_addr(chan, info->mem_addr); - set_dma_count(chan, info->count); -} - -void set_dma_addr(unsigned int chan, unsigned int addr) -{ - dma_info_t *info = dma_info + chan; - unsigned long sar, dar; - - info->mem_addr = addr; - sar = (info->mode & DMA_MODE_WRITE) ? info->mem_addr : info->dev_addr; - dar = (info->mode & DMA_MODE_WRITE) ? info->dev_addr : info->mem_addr; - - sh64_out64(sar & DMAC_SAR_ADDR, DMAC_SAR(chan)); - sh64_out64(dar & DMAC_SAR_ADDR, DMAC_DAR(chan)); -} - -void set_dma_count(unsigned int chan, unsigned int count) -{ - dma_info_t *info = dma_info + chan; - u64 tmp; - - info->count = count; - - tmp = (info->count >> calc_xmit_shift(chan)) & DMAC_COUNT_CNT; - - sh64_out64(tmp, DMAC_COUNT(chan)); -} - -unsigned long claim_dma_lock(void) -{ - unsigned long flags; - - spin_lock_irqsave(&dma_spin_lock, flags); - - return flags; -} - -void release_dma_lock(unsigned long flags) -{ - spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -int get_dma_residue(unsigned int chan) -{ - return sh64_in64(DMAC_COUNT(chan) << calc_xmit_shift(chan)); -} - -int __init init_dma(void) -{ - struct vcr_info vcr; - u64 tmp; - - /* Remap the DMAC */ - dmac_base = onchip_remap(PHYS_DMAC_BLOCK, 1024, "DMAC"); - if (!dmac_base) { - printk(KERN_ERR "Unable to remap DMAC\n"); - return -ENOMEM; - } - - /* Report DMAC.VCR Info */ - vcr = sh64_get_vcr_info(dmac_base); - printk("DMAC: Module ID: 0x%04x, Module version: 0x%04x\n", - vcr.mod_id, vcr.mod_vers); - - /* Set the ME bit */ - tmp = sh64_in64(DMAC_COMMON_BASE); - tmp |= DMAC_COMMON_ME; - sh64_out64(tmp, DMAC_COMMON_BASE); - - /* Enable the DMAC Error Interrupt */ - make_intc_irq(DMA_IRQ_DERR); - setup_irq(DMA_IRQ_DERR, &irq_derr); - - return 0; -} - -static void __exit exit_dma(void) -{ - onchip_unmap(dmac_base); - free_irq(DMA_IRQ_DERR, 0); -} - -module_init(init_dma); -module_exit(exit_dma); - -MODULE_AUTHOR("Paul Mundt"); -MODULE_DESCRIPTION("DMA API for SH-5 DMAC"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(setup_dma); -EXPORT_SYMBOL(claim_dma_lock); -EXPORT_SYMBOL(release_dma_lock); -EXPORT_SYMBOL(enable_dma); -EXPORT_SYMBOL(disable_dma); -EXPORT_SYMBOL(set_dma_mode); -EXPORT_SYMBOL(set_dma_addr); -EXPORT_SYMBOL(set_dma_count); -EXPORT_SYMBOL(get_dma_residue); - diff --git a/arch/sh64/kernel/early_printk.c b/arch/sh64/kernel/early_printk.c deleted file mode 100644 index 4f9131123672..000000000000 --- a/arch/sh64/kernel/early_printk.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * arch/sh64/kernel/early_printk.c - * - * SH-5 Early SCIF console (cloned and hacked from sh implementation) - * - * Copyright (C) 2003, 2004 Paul Mundt <lethal@linux-sh.org> - * Copyright (C) 2002 M. R. Brown <mrbrown@0xd6.org> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/console.h> -#include <linux/tty.h> -#include <linux/init.h> -#include <asm/io.h> -#include <asm/hardware.h> - -#define SCIF_BASE_ADDR 0x01030000 -#define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR - -/* - * Fixed virtual address where SCIF is mapped (should already be done - * in arch/sh64/kernel/head.S!). - */ -#define SCIF_REG 0xfa030000 - -enum { - SCIF_SCSMR2 = SCIF_REG + 0x00, - SCIF_SCBRR2 = SCIF_REG + 0x04, - SCIF_SCSCR2 = SCIF_REG + 0x08, - SCIF_SCFTDR2 = SCIF_REG + 0x0c, - SCIF_SCFSR2 = SCIF_REG + 0x10, - SCIF_SCFRDR2 = SCIF_REG + 0x14, - SCIF_SCFCR2 = SCIF_REG + 0x18, - SCIF_SCFDR2 = SCIF_REG + 0x1c, - SCIF_SCSPTR2 = SCIF_REG + 0x20, - SCIF_SCLSR2 = SCIF_REG + 0x24, -}; - -static void sh_console_putc(int c) -{ - while (!(ctrl_inw(SCIF_SCFSR2) & 0x20)) - cpu_relax(); - - ctrl_outb(c, SCIF_SCFTDR2); - ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0x9f), SCIF_SCFSR2); - - if (c == '\n') - sh_console_putc('\r'); -} - -static void sh_console_flush(void) -{ - ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2); - - while (!(ctrl_inw(SCIF_SCFSR2) & 0x40)) - cpu_relax(); - - ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2); -} - -static void sh_console_write(struct console *con, const char *s, unsigned count) -{ - while (count-- > 0) - sh_console_putc(*s++); - - sh_console_flush(); -} - -static int __init sh_console_setup(struct console *con, char *options) -{ - con->cflag = CREAD | HUPCL | CLOCAL | B19200 | CS8; - - return 0; -} - -static struct console sh_console = { - .name = "scifcon", - .write = sh_console_write, - .setup = sh_console_setup, - .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1, -}; - -void __init enable_early_printk(void) -{ - ctrl_outb(0x2a, SCIF_SCBRR2); /* 19200bps */ - - ctrl_outw(0x04, SCIF_SCFCR2); /* Reset TFRST */ - ctrl_outw(0x10, SCIF_SCFCR2); /* TTRG0=1 */ - - ctrl_outw(0, SCIF_SCSPTR2); - ctrl_outw(0x60, SCIF_SCFSR2); - ctrl_outw(0, SCIF_SCLSR2); - ctrl_outw(0x30, SCIF_SCSCR2); - - register_console(&sh_console); -} diff --git a/arch/sh64/kernel/entry.S b/arch/sh64/kernel/entry.S deleted file mode 100644 index 7013fcb6665c..000000000000 --- a/arch/sh64/kernel/entry.S +++ /dev/null @@ -1,2102 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/entry.S - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2004, 2005 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - */ - -#include <linux/errno.h> -#include <linux/sys.h> - -#include <asm/processor.h> -#include <asm/registers.h> -#include <asm/unistd.h> -#include <asm/thread_info.h> -#include <asm/asm-offsets.h> - -/* - * SR fields. - */ -#define SR_ASID_MASK 0x00ff0000 -#define SR_FD_MASK 0x00008000 -#define SR_SS 0x08000000 -#define SR_BL 0x10000000 -#define SR_MD 0x40000000 - -/* - * Event code. - */ -#define EVENT_INTERRUPT 0 -#define EVENT_FAULT_TLB 1 -#define EVENT_FAULT_NOT_TLB 2 -#define EVENT_DEBUG 3 - -/* EXPEVT values */ -#define RESET_CAUSE 0x20 -#define DEBUGSS_CAUSE 0x980 - -/* - * Frame layout. Quad index. - */ -#define FRAME_T(x) FRAME_TBASE+(x*8) -#define FRAME_R(x) FRAME_RBASE+(x*8) -#define FRAME_S(x) FRAME_SBASE+(x*8) -#define FSPC 0 -#define FSSR 1 -#define FSYSCALL_ID 2 - -/* Arrange the save frame to be a multiple of 32 bytes long */ -#define FRAME_SBASE 0 -#define FRAME_RBASE (FRAME_SBASE+(3*8)) /* SYSCALL_ID - SSR - SPC */ -#define FRAME_TBASE (FRAME_RBASE+(63*8)) /* r0 - r62 */ -#define FRAME_PBASE (FRAME_TBASE+(8*8)) /* tr0 -tr7 */ -#define FRAME_SIZE (FRAME_PBASE+(2*8)) /* pad0-pad1 */ - -#define FP_FRAME_SIZE FP_FRAME_BASE+(33*8) /* dr0 - dr31 + fpscr */ -#define FP_FRAME_BASE 0 - -#define SAVED_R2 0*8 -#define SAVED_R3 1*8 -#define SAVED_R4 2*8 -#define SAVED_R5 3*8 -#define SAVED_R18 4*8 -#define SAVED_R6 5*8 -#define SAVED_TR0 6*8 - -/* These are the registers saved in the TLB path that aren't saved in the first - level of the normal one. */ -#define TLB_SAVED_R25 7*8 -#define TLB_SAVED_TR1 8*8 -#define TLB_SAVED_TR2 9*8 -#define TLB_SAVED_TR3 10*8 -#define TLB_SAVED_TR4 11*8 -/* Save R0/R1 : PT-migrating compiler currently dishounours -ffixed-r0 and -ffixed-r1 causing - breakage otherwise. */ -#define TLB_SAVED_R0 12*8 -#define TLB_SAVED_R1 13*8 - -#define CLI() \ - getcon SR, r6; \ - ori r6, 0xf0, r6; \ - putcon r6, SR; - -#define STI() \ - getcon SR, r6; \ - andi r6, ~0xf0, r6; \ - putcon r6, SR; - -#ifdef CONFIG_PREEMPT -# define preempt_stop() CLI() -#else -# define preempt_stop() -# define resume_kernel restore_all -#endif - - .section .data, "aw" - -#define FAST_TLBMISS_STACK_CACHELINES 4 -#define FAST_TLBMISS_STACK_QUADWORDS (4*FAST_TLBMISS_STACK_CACHELINES) - -/* Register back-up area for all exceptions */ - .balign 32 - /* Allow for 16 quadwords to be pushed by fast tlbmiss handling - * register saves etc. */ - .fill FAST_TLBMISS_STACK_QUADWORDS, 8, 0x0 -/* This is 32 byte aligned by construction */ -/* Register back-up area for all exceptions */ -reg_save_area: - .quad 0 - .quad 0 - .quad 0 - .quad 0 - - .quad 0 - .quad 0 - .quad 0 - .quad 0 - - .quad 0 - .quad 0 - .quad 0 - .quad 0 - - .quad 0 - .quad 0 - -/* Save area for RESVEC exceptions. We cannot use reg_save_area because of - * reentrancy. Note this area may be accessed via physical address. - * Align so this fits a whole single cache line, for ease of purging. - */ - .balign 32,0,32 -resvec_save_area: - .quad 0 - .quad 0 - .quad 0 - .quad 0 - .quad 0 - .balign 32,0,32 - -/* Jump table of 3rd level handlers */ -trap_jtable: - .long do_exception_error /* 0x000 */ - .long do_exception_error /* 0x020 */ - .long tlb_miss_load /* 0x040 */ - .long tlb_miss_store /* 0x060 */ - ! ARTIFICIAL pseudo-EXPEVT setting - .long do_debug_interrupt /* 0x080 */ - .long tlb_miss_load /* 0x0A0 */ - .long tlb_miss_store /* 0x0C0 */ - .long do_address_error_load /* 0x0E0 */ - .long do_address_error_store /* 0x100 */ -#ifdef CONFIG_SH_FPU - .long do_fpu_error /* 0x120 */ -#else - .long do_exception_error /* 0x120 */ -#endif - .long do_exception_error /* 0x140 */ - .long system_call /* 0x160 */ - .long do_reserved_inst /* 0x180 */ - .long do_illegal_slot_inst /* 0x1A0 */ - .long do_NMI /* 0x1C0 */ - .long do_exception_error /* 0x1E0 */ - .rept 15 - .long do_IRQ /* 0x200 - 0x3C0 */ - .endr - .long do_exception_error /* 0x3E0 */ - .rept 32 - .long do_IRQ /* 0x400 - 0x7E0 */ - .endr - .long fpu_error_or_IRQA /* 0x800 */ - .long fpu_error_or_IRQB /* 0x820 */ - .long do_IRQ /* 0x840 */ - .long do_IRQ /* 0x860 */ - .rept 6 - .long do_exception_error /* 0x880 - 0x920 */ - .endr - .long do_software_break_point /* 0x940 */ - .long do_exception_error /* 0x960 */ - .long do_single_step /* 0x980 */ - - .rept 3 - .long do_exception_error /* 0x9A0 - 0x9E0 */ - .endr - .long do_IRQ /* 0xA00 */ - .long do_IRQ /* 0xA20 */ - .long itlb_miss_or_IRQ /* 0xA40 */ - .long do_IRQ /* 0xA60 */ - .long do_IRQ /* 0xA80 */ - .long itlb_miss_or_IRQ /* 0xAA0 */ - .long do_exception_error /* 0xAC0 */ - .long do_address_error_exec /* 0xAE0 */ - .rept 8 - .long do_exception_error /* 0xB00 - 0xBE0 */ - .endr - .rept 18 - .long do_IRQ /* 0xC00 - 0xE20 */ - .endr - - .section .text64, "ax" - -/* - * --- Exception/Interrupt/Event Handling Section - */ - -/* - * VBR and RESVEC blocks. - * - * First level handler for VBR-based exceptions. - * - * To avoid waste of space, align to the maximum text block size. - * This is assumed to be at most 128 bytes or 32 instructions. - * DO NOT EXCEED 32 instructions on the first level handlers ! - * - * Also note that RESVEC is contained within the VBR block - * where the room left (1KB - TEXT_SIZE) allows placing - * the RESVEC block (at most 512B + TEXT_SIZE). - * - * So first (and only) level handler for RESVEC-based exceptions. - * - * Where the fault/interrupt is handled (not_a_tlb_miss, tlb_miss - * and interrupt) we are a lot tight with register space until - * saving onto the stack frame, which is done in handle_exception(). - * - */ - -#define TEXT_SIZE 128 -#define BLOCK_SIZE 1664 /* Dynamic check, 13*128 */ - - .balign TEXT_SIZE -LVBR_block: - .space 256, 0 /* Power-on class handler, */ - /* not required here */ -not_a_tlb_miss: - synco /* TAKum03020 (but probably a good idea anyway.) */ - /* Save original stack pointer into KCR1 */ - putcon SP, KCR1 - - /* Save other original registers into reg_save_area */ - movi reg_save_area, SP - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* Set args for Non-debug, Not a TLB miss class handler */ - getcon EXPEVT, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_FAULT_NOT_TLB, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - - .balign 256 - ! VBR+0x200 - nop - .balign 256 - ! VBR+0x300 - nop - .balign 256 - /* - * Instead of the natural .balign 1024 place RESVEC here - * respecting the final 1KB alignment. - */ - .balign TEXT_SIZE - /* - * Instead of '.space 1024-TEXT_SIZE' place the RESVEC - * block making sure the final alignment is correct. - */ -tlb_miss: - synco /* TAKum03020 (but probably a good idea anyway.) */ - putcon SP, KCR1 - movi reg_save_area, SP - /* SP is guaranteed 32-byte aligned. */ - st.q SP, TLB_SAVED_R0 , r0 - st.q SP, TLB_SAVED_R1 , r1 - st.q SP, SAVED_R2 , r2 - st.q SP, SAVED_R3 , r3 - st.q SP, SAVED_R4 , r4 - st.q SP, SAVED_R5 , r5 - st.q SP, SAVED_R6 , r6 - st.q SP, SAVED_R18, r18 - - /* Save R25 for safety; as/ld may want to use it to achieve the call to - * the code in mm/tlbmiss.c */ - st.q SP, TLB_SAVED_R25, r25 - gettr tr0, r2 - gettr tr1, r3 - gettr tr2, r4 - gettr tr3, r5 - gettr tr4, r18 - st.q SP, SAVED_TR0 , r2 - st.q SP, TLB_SAVED_TR1 , r3 - st.q SP, TLB_SAVED_TR2 , r4 - st.q SP, TLB_SAVED_TR3 , r5 - st.q SP, TLB_SAVED_TR4 , r18 - - pt do_fast_page_fault, tr0 - getcon SSR, r2 - getcon EXPEVT, r3 - getcon TEA, r4 - shlri r2, 30, r2 - andi r2, 1, r2 /* r2 = SSR.MD */ - blink tr0, LINK - - pt fixup_to_invoke_general_handler, tr1 - - /* If the fast path handler fixed the fault, just drop through quickly - to the restore code right away to return to the excepting context. - */ - beqi/u r2, 0, tr1 - -fast_tlb_miss_restore: - ld.q SP, SAVED_TR0, r2 - ld.q SP, TLB_SAVED_TR1, r3 - ld.q SP, TLB_SAVED_TR2, r4 - - ld.q SP, TLB_SAVED_TR3, r5 - ld.q SP, TLB_SAVED_TR4, r18 - - ptabs r2, tr0 - ptabs r3, tr1 - ptabs r4, tr2 - ptabs r5, tr3 - ptabs r18, tr4 - - ld.q SP, TLB_SAVED_R0, r0 - ld.q SP, TLB_SAVED_R1, r1 - ld.q SP, SAVED_R2, r2 - ld.q SP, SAVED_R3, r3 - ld.q SP, SAVED_R4, r4 - ld.q SP, SAVED_R5, r5 - ld.q SP, SAVED_R6, r6 - ld.q SP, SAVED_R18, r18 - ld.q SP, TLB_SAVED_R25, r25 - - getcon KCR1, SP - rte - nop /* for safety, in case the code is run on sh5-101 cut1.x */ - -fixup_to_invoke_general_handler: - - /* OK, new method. Restore stuff that's not expected to get saved into - the 'first-level' reg save area, then just fall through to setting - up the registers and calling the second-level handler. */ - - /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved. So we must restore - r25,tr1-4 and save r6 to get into the right state. */ - - ld.q SP, TLB_SAVED_TR1, r3 - ld.q SP, TLB_SAVED_TR2, r4 - ld.q SP, TLB_SAVED_TR3, r5 - ld.q SP, TLB_SAVED_TR4, r18 - ld.q SP, TLB_SAVED_R25, r25 - - ld.q SP, TLB_SAVED_R0, r0 - ld.q SP, TLB_SAVED_R1, r1 - - ptabs/u r3, tr1 - ptabs/u r4, tr2 - ptabs/u r5, tr3 - ptabs/u r18, tr4 - - /* Set args for Non-debug, TLB miss class handler */ - getcon EXPEVT, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_FAULT_TLB, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - -/* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE - DOES END UP AT VBR+0x600 */ - nop - nop - nop - nop - nop - nop - - .balign 256 - /* VBR + 0x600 */ - -interrupt: - synco /* TAKum03020 (but probably a good idea anyway.) */ - /* Save original stack pointer into KCR1 */ - putcon SP, KCR1 - - /* Save other original registers into reg_save_area */ - movi reg_save_area, SP - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* Set args for interrupt class handler */ - getcon INTEVT, r2 - movi ret_from_irq, r3 - ori r3, 1, r3 - movi EVENT_INTERRUPT, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - .balign TEXT_SIZE /* let's waste the bare minimum */ - -LVBR_block_end: /* Marker. Used for total checking */ - - .balign 256 -LRESVEC_block: - /* Panic handler. Called with MMU off. Possible causes/actions: - * - Reset: Jump to program start. - * - Single Step: Turn off Single Step & return. - * - Others: Call panic handler, passing PC as arg. - * (this may need to be extended...) - */ -reset_or_panic: - synco /* TAKum03020 (but probably a good idea anyway.) */ - putcon SP, DCR - /* First save r0-1 and tr0, as we need to use these */ - movi resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP - st.q SP, 0, r0 - st.q SP, 8, r1 - gettr tr0, r0 - st.q SP, 32, r0 - - /* Check cause */ - getcon EXPEVT, r0 - movi RESET_CAUSE, r1 - sub r1, r0, r1 /* r1=0 if reset */ - movi _stext-CONFIG_CACHED_MEMORY_OFFSET, r0 - ori r0, 1, r0 - ptabs r0, tr0 - beqi r1, 0, tr0 /* Jump to start address if reset */ - - getcon EXPEVT, r0 - movi DEBUGSS_CAUSE, r1 - sub r1, r0, r1 /* r1=0 if single step */ - pta single_step_panic, tr0 - beqi r1, 0, tr0 /* jump if single step */ - - /* Now jump to where we save the registers. */ - movi panic_stash_regs-CONFIG_CACHED_MEMORY_OFFSET, r1 - ptabs r1, tr0 - blink tr0, r63 - -single_step_panic: - /* We are in a handler with Single Step set. We need to resume the - * handler, by turning on MMU & turning off Single Step. */ - getcon SSR, r0 - movi SR_MMU, r1 - or r0, r1, r0 - movi ~SR_SS, r1 - and r0, r1, r0 - putcon r0, SSR - /* Restore EXPEVT, as the rte won't do this */ - getcon PEXPEVT, r0 - putcon r0, EXPEVT - /* Restore regs */ - ld.q SP, 32, r0 - ptabs r0, tr0 - ld.q SP, 0, r0 - ld.q SP, 8, r1 - getcon DCR, SP - synco - rte - - - .balign 256 -debug_exception: - synco /* TAKum03020 (but probably a good idea anyway.) */ - /* - * Single step/software_break_point first level handler. - * Called with MMU off, so the first thing we do is enable it - * by doing an rte with appropriate SSR. - */ - putcon SP, DCR - /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */ - movi resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP - - /* With the MMU off, we are bypassing the cache, so purge any - * data that will be made stale by the following stores. - */ - ocbp SP, 0 - synco - - st.q SP, 0, r0 - st.q SP, 8, r1 - getcon SPC, r0 - st.q SP, 16, r0 - getcon SSR, r0 - st.q SP, 24, r0 - - /* Enable MMU, block exceptions, set priv mode, disable single step */ - movi SR_MMU | SR_BL | SR_MD, r1 - or r0, r1, r0 - movi ~SR_SS, r1 - and r0, r1, r0 - putcon r0, SSR - /* Force control to debug_exception_2 when rte is executed */ - movi debug_exeception_2, r0 - ori r0, 1, r0 /* force SHmedia, just in case */ - putcon r0, SPC - getcon DCR, SP - synco - rte -debug_exeception_2: - /* Restore saved regs */ - putcon SP, KCR1 - movi resvec_save_area, SP - ld.q SP, 24, r0 - putcon r0, SSR - ld.q SP, 16, r0 - putcon r0, SPC - ld.q SP, 0, r0 - ld.q SP, 8, r1 - - /* Save other original registers into reg_save_area */ - movi reg_save_area, SP - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* Set args for debug class handler */ - getcon EXPEVT, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_DEBUG, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - - .balign 256 -debug_interrupt: - /* !!! WE COME HERE IN REAL MODE !!! */ - /* Hook-up debug interrupt to allow various debugging options to be - * hooked into its handler. */ - /* Save original stack pointer into KCR1 */ - synco - putcon SP, KCR1 - movi resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP - ocbp SP, 0 - ocbp SP, 32 - synco - - /* Save other original registers into reg_save_area thru real addresses */ - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* move (spc,ssr)->(pspc,pssr). The rte will shift - them back again, so that they look like the originals - as far as the real handler code is concerned. */ - getcon spc, r6 - putcon r6, pspc - getcon ssr, r6 - putcon r6, pssr - - ! construct useful SR for handle_exception - movi 3, r6 - shlli r6, 30, r6 - getcon sr, r18 - or r18, r6, r6 - putcon r6, ssr - - ! SSR is now the current SR with the MD and MMU bits set - ! i.e. the rte will switch back to priv mode and put - ! the mmu back on - - ! construct spc - movi handle_exception, r18 - ori r18, 1, r18 ! for safety (do we need this?) - putcon r18, spc - - /* Set args for Non-debug, Not a TLB miss class handler */ - - ! EXPEVT==0x80 is unused, so 'steal' this value to put the - ! debug interrupt handler in the vectoring table - movi 0x80, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_FAULT_NOT_TLB, r4 - - or SP, ZERO, r5 - movi CONFIG_CACHED_MEMORY_OFFSET, r6 - add r6, r5, r5 - getcon KCR1, SP - - synco ! for safety - rte ! -> handle_exception, switch back to priv mode again - -LRESVEC_block_end: /* Marker. Unused. */ - - .balign TEXT_SIZE - -/* - * Second level handler for VBR-based exceptions. Pre-handler. - * In common to all stack-frame sensitive handlers. - * - * Inputs: - * (KCR0) Current [current task union] - * (KCR1) Original SP - * (r2) INTEVT/EXPEVT - * (r3) appropriate return address - * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug) - * (r5) Pointer to reg_save_area - * (SP) Original SP - * - * Available registers: - * (r6) - * (r18) - * (tr0) - * - */ -handle_exception: - /* Common 2nd level handler. */ - - /* First thing we need an appropriate stack pointer */ - getcon SSR, r6 - shlri r6, 30, r6 - andi r6, 1, r6 - pta stack_ok, tr0 - bne r6, ZERO, tr0 /* Original stack pointer is fine */ - - /* Set stack pointer for user fault */ - getcon KCR0, SP - movi THREAD_SIZE, r6 /* Point to the end */ - add SP, r6, SP - -stack_ok: - -/* DEBUG : check for underflow/overflow of the kernel stack */ - pta no_underflow, tr0 - getcon KCR0, r6 - movi 1024, r18 - add r6, r18, r6 - bge SP, r6, tr0 ! ? below 1k from bottom of stack : danger zone - -/* Just panic to cause a crash. */ -bad_sp: - ld.b r63, 0, r6 - nop - -no_underflow: - pta bad_sp, tr0 - getcon kcr0, r6 - movi THREAD_SIZE, r18 - add r18, r6, r6 - bgt SP, r6, tr0 ! sp above the stack - - /* Make some room for the BASIC frame. */ - movi -(FRAME_SIZE), r6 - add SP, r6, SP - -/* Could do this with no stalling if we had another spare register, but the - code below will be OK. */ - ld.q r5, SAVED_R2, r6 - ld.q r5, SAVED_R3, r18 - st.q SP, FRAME_R(2), r6 - ld.q r5, SAVED_R4, r6 - st.q SP, FRAME_R(3), r18 - ld.q r5, SAVED_R5, r18 - st.q SP, FRAME_R(4), r6 - ld.q r5, SAVED_R6, r6 - st.q SP, FRAME_R(5), r18 - ld.q r5, SAVED_R18, r18 - st.q SP, FRAME_R(6), r6 - ld.q r5, SAVED_TR0, r6 - st.q SP, FRAME_R(18), r18 - st.q SP, FRAME_T(0), r6 - - /* Keep old SP around */ - getcon KCR1, r6 - - /* Save the rest of the general purpose registers */ - st.q SP, FRAME_R(0), r0 - st.q SP, FRAME_R(1), r1 - st.q SP, FRAME_R(7), r7 - st.q SP, FRAME_R(8), r8 - st.q SP, FRAME_R(9), r9 - st.q SP, FRAME_R(10), r10 - st.q SP, FRAME_R(11), r11 - st.q SP, FRAME_R(12), r12 - st.q SP, FRAME_R(13), r13 - st.q SP, FRAME_R(14), r14 - - /* SP is somewhere else */ - st.q SP, FRAME_R(15), r6 - - st.q SP, FRAME_R(16), r16 - st.q SP, FRAME_R(17), r17 - /* r18 is saved earlier. */ - st.q SP, FRAME_R(19), r19 - st.q SP, FRAME_R(20), r20 - st.q SP, FRAME_R(21), r21 - st.q SP, FRAME_R(22), r22 - st.q SP, FRAME_R(23), r23 - st.q SP, FRAME_R(24), r24 - st.q SP, FRAME_R(25), r25 - st.q SP, FRAME_R(26), r26 - st.q SP, FRAME_R(27), r27 - st.q SP, FRAME_R(28), r28 - st.q SP, FRAME_R(29), r29 - st.q SP, FRAME_R(30), r30 - st.q SP, FRAME_R(31), r31 - st.q SP, FRAME_R(32), r32 - st.q SP, FRAME_R(33), r33 - st.q SP, FRAME_R(34), r34 - st.q SP, FRAME_R(35), r35 - st.q SP, FRAME_R(36), r36 - st.q SP, FRAME_R(37), r37 - st.q SP, FRAME_R(38), r38 - st.q SP, FRAME_R(39), r39 - st.q SP, FRAME_R(40), r40 - st.q SP, FRAME_R(41), r41 - st.q SP, FRAME_R(42), r42 - st.q SP, FRAME_R(43), r43 - st.q SP, FRAME_R(44), r44 - st.q SP, FRAME_R(45), r45 - st.q SP, FRAME_R(46), r46 - st.q SP, FRAME_R(47), r47 - st.q SP, FRAME_R(48), r48 - st.q SP, FRAME_R(49), r49 - st.q SP, FRAME_R(50), r50 - st.q SP, FRAME_R(51), r51 - st.q SP, FRAME_R(52), r52 - st.q SP, FRAME_R(53), r53 - st.q SP, FRAME_R(54), r54 - st.q SP, FRAME_R(55), r55 - st.q SP, FRAME_R(56), r56 - st.q SP, FRAME_R(57), r57 - st.q SP, FRAME_R(58), r58 - st.q SP, FRAME_R(59), r59 - st.q SP, FRAME_R(60), r60 - st.q SP, FRAME_R(61), r61 - st.q SP, FRAME_R(62), r62 - - /* - * Save the S* registers. - */ - getcon SSR, r61 - st.q SP, FRAME_S(FSSR), r61 - getcon SPC, r62 - st.q SP, FRAME_S(FSPC), r62 - movi -1, r62 /* Reset syscall_nr */ - st.q SP, FRAME_S(FSYSCALL_ID), r62 - - /* Save the rest of the target registers */ - gettr tr1, r6 - st.q SP, FRAME_T(1), r6 - gettr tr2, r6 - st.q SP, FRAME_T(2), r6 - gettr tr3, r6 - st.q SP, FRAME_T(3), r6 - gettr tr4, r6 - st.q SP, FRAME_T(4), r6 - gettr tr5, r6 - st.q SP, FRAME_T(5), r6 - gettr tr6, r6 - st.q SP, FRAME_T(6), r6 - gettr tr7, r6 - st.q SP, FRAME_T(7), r6 - - ! setup FP so that unwinder can wind back through nested kernel mode - ! exceptions - add SP, ZERO, r14 - -#ifdef CONFIG_POOR_MANS_STRACE - /* We've pushed all the registers now, so only r2-r4 hold anything - * useful. Move them into callee save registers */ - or r2, ZERO, r28 - or r3, ZERO, r29 - or r4, ZERO, r30 - - /* Preserve r2 as the event code */ - movi evt_debug, r3 - ori r3, 1, r3 - ptabs r3, tr0 - - or SP, ZERO, r6 - getcon TRA, r5 - blink tr0, LINK - - or r28, ZERO, r2 - or r29, ZERO, r3 - or r30, ZERO, r4 -#endif - - /* For syscall and debug race condition, get TRA now */ - getcon TRA, r5 - - /* We are in a safe position to turn SR.BL off, but set IMASK=0xf - * Also set FD, to catch FPU usage in the kernel. - * - * benedict.gaster@superh.com 29/07/2002 - * - * On all SH5-101 revisions it is unsafe to raise the IMASK and at the - * same time change BL from 1->0, as any pending interrupt of a level - * higher than he previous value of IMASK will leak through and be - * taken unexpectedly. - * - * To avoid this we raise the IMASK and then issue another PUTCON to - * enable interrupts. - */ - getcon SR, r6 - movi SR_IMASK | SR_FD, r7 - or r6, r7, r6 - putcon r6, SR - movi SR_UNBLOCK_EXC, r7 - and r6, r7, r6 - putcon r6, SR - - - /* Now call the appropriate 3rd level handler */ - or r3, ZERO, LINK - movi trap_jtable, r3 - shlri r2, 3, r2 - ldx.l r2, r3, r3 - shlri r2, 2, r2 - ptabs r3, tr0 - or SP, ZERO, r3 - blink tr0, ZERO - -/* - * Second level handler for VBR-based exceptions. Post-handlers. - * - * Post-handlers for interrupts (ret_from_irq), exceptions - * (ret_from_exception) and common reentrance doors (restore_all - * to get back to the original context, ret_from_syscall loop to - * check kernel exiting). - * - * ret_with_reschedule and work_notifysig are an inner lables of - * the ret_from_syscall loop. - * - * In common to all stack-frame sensitive handlers. - * - * Inputs: - * (SP) struct pt_regs *, original register's frame pointer (basic) - * - */ - .global ret_from_irq -ret_from_irq: -#ifdef CONFIG_POOR_MANS_STRACE - pta evt_debug_ret_from_irq, tr0 - ori SP, 0, r2 - blink tr0, LINK -#endif - ld.q SP, FRAME_S(FSSR), r6 - shlri r6, 30, r6 - andi r6, 1, r6 - pta resume_kernel, tr0 - bne r6, ZERO, tr0 /* no further checks */ - STI() - pta ret_with_reschedule, tr0 - blink tr0, ZERO /* Do not check softirqs */ - - .global ret_from_exception -ret_from_exception: - preempt_stop() - -#ifdef CONFIG_POOR_MANS_STRACE - pta evt_debug_ret_from_exc, tr0 - ori SP, 0, r2 - blink tr0, LINK -#endif - - ld.q SP, FRAME_S(FSSR), r6 - shlri r6, 30, r6 - andi r6, 1, r6 - pta resume_kernel, tr0 - bne r6, ZERO, tr0 /* no further checks */ - - /* Check softirqs */ - -#ifdef CONFIG_PREEMPT - pta ret_from_syscall, tr0 - blink tr0, ZERO - -resume_kernel: - pta restore_all, tr0 - - getcon KCR0, r6 - ld.l r6, TI_PRE_COUNT, r7 - beq/u r7, ZERO, tr0 - -need_resched: - ld.l r6, TI_FLAGS, r7 - movi (1 << TIF_NEED_RESCHED), r8 - and r8, r7, r8 - bne r8, ZERO, tr0 - - getcon SR, r7 - andi r7, 0xf0, r7 - bne r7, ZERO, tr0 - - movi ((PREEMPT_ACTIVE >> 16) & 65535), r8 - shori (PREEMPT_ACTIVE & 65535), r8 - st.l r6, TI_PRE_COUNT, r8 - - STI() - movi schedule, r7 - ori r7, 1, r7 - ptabs r7, tr1 - blink tr1, LINK - - st.l r6, TI_PRE_COUNT, ZERO - CLI() - - pta need_resched, tr1 - blink tr1, ZERO -#endif - - .global ret_from_syscall -ret_from_syscall: - -ret_with_reschedule: - getcon KCR0, r6 ! r6 contains current_thread_info - ld.l r6, TI_FLAGS, r7 ! r7 contains current_thread_info->flags - - ! FIXME:!!! - ! no handling of TIF_SYSCALL_TRACE yet!! - - movi _TIF_NEED_RESCHED, r8 - and r8, r7, r8 - pta work_resched, tr0 - bne r8, ZERO, tr0 - - pta restore_all, tr1 - - movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8 - and r8, r7, r8 - pta work_notifysig, tr0 - bne r8, ZERO, tr0 - - blink tr1, ZERO - -work_resched: - pta ret_from_syscall, tr0 - gettr tr0, LINK - movi schedule, r6 - ptabs r6, tr0 - blink tr0, ZERO /* Call schedule(), return on top */ - -work_notifysig: - gettr tr1, LINK - - movi do_signal, r6 - ptabs r6, tr0 - or SP, ZERO, r2 - or ZERO, ZERO, r3 - blink tr0, LINK /* Call do_signal(regs, 0), return here */ - -restore_all: - /* Do prefetches */ - - ld.q SP, FRAME_T(0), r6 - ld.q SP, FRAME_T(1), r7 - ld.q SP, FRAME_T(2), r8 - ld.q SP, FRAME_T(3), r9 - ptabs r6, tr0 - ptabs r7, tr1 - ptabs r8, tr2 - ptabs r9, tr3 - ld.q SP, FRAME_T(4), r6 - ld.q SP, FRAME_T(5), r7 - ld.q SP, FRAME_T(6), r8 - ld.q SP, FRAME_T(7), r9 - ptabs r6, tr4 - ptabs r7, tr5 - ptabs r8, tr6 - ptabs r9, tr7 - - ld.q SP, FRAME_R(0), r0 - ld.q SP, FRAME_R(1), r1 - ld.q SP, FRAME_R(2), r2 - ld.q SP, FRAME_R(3), r3 - ld.q SP, FRAME_R(4), r4 - ld.q SP, FRAME_R(5), r5 - ld.q SP, FRAME_R(6), r6 - ld.q SP, FRAME_R(7), r7 - ld.q SP, FRAME_R(8), r8 - ld.q SP, FRAME_R(9), r9 - ld.q SP, FRAME_R(10), r10 - ld.q SP, FRAME_R(11), r11 - ld.q SP, FRAME_R(12), r12 - ld.q SP, FRAME_R(13), r13 - ld.q SP, FRAME_R(14), r14 - - ld.q SP, FRAME_R(16), r16 - ld.q SP, FRAME_R(17), r17 - ld.q SP, FRAME_R(18), r18 - ld.q SP, FRAME_R(19), r19 - ld.q SP, FRAME_R(20), r20 - ld.q SP, FRAME_R(21), r21 - ld.q SP, FRAME_R(22), r22 - ld.q SP, FRAME_R(23), r23 - ld.q SP, FRAME_R(24), r24 - ld.q SP, FRAME_R(25), r25 - ld.q SP, FRAME_R(26), r26 - ld.q SP, FRAME_R(27), r27 - ld.q SP, FRAME_R(28), r28 - ld.q SP, FRAME_R(29), r29 - ld.q SP, FRAME_R(30), r30 - ld.q SP, FRAME_R(31), r31 - ld.q SP, FRAME_R(32), r32 - ld.q SP, FRAME_R(33), r33 - ld.q SP, FRAME_R(34), r34 - ld.q SP, FRAME_R(35), r35 - ld.q SP, FRAME_R(36), r36 - ld.q SP, FRAME_R(37), r37 - ld.q SP, FRAME_R(38), r38 - ld.q SP, FRAME_R(39), r39 - ld.q SP, FRAME_R(40), r40 - ld.q SP, FRAME_R(41), r41 - ld.q SP, FRAME_R(42), r42 - ld.q SP, FRAME_R(43), r43 - ld.q SP, FRAME_R(44), r44 - ld.q SP, FRAME_R(45), r45 - ld.q SP, FRAME_R(46), r46 - ld.q SP, FRAME_R(47), r47 - ld.q SP, FRAME_R(48), r48 - ld.q SP, FRAME_R(49), r49 - ld.q SP, FRAME_R(50), r50 - ld.q SP, FRAME_R(51), r51 - ld.q SP, FRAME_R(52), r52 - ld.q SP, FRAME_R(53), r53 - ld.q SP, FRAME_R(54), r54 - ld.q SP, FRAME_R(55), r55 - ld.q SP, FRAME_R(56), r56 - ld.q SP, FRAME_R(57), r57 - ld.q SP, FRAME_R(58), r58 - - getcon SR, r59 - movi SR_BLOCK_EXC, r60 - or r59, r60, r59 - putcon r59, SR /* SR.BL = 1, keep nesting out */ - ld.q SP, FRAME_S(FSSR), r61 - ld.q SP, FRAME_S(FSPC), r62 - movi SR_ASID_MASK, r60 - and r59, r60, r59 - andc r61, r60, r61 /* Clear out older ASID */ - or r59, r61, r61 /* Retain current ASID */ - putcon r61, SSR - putcon r62, SPC - - /* Ignore FSYSCALL_ID */ - - ld.q SP, FRAME_R(59), r59 - ld.q SP, FRAME_R(60), r60 - ld.q SP, FRAME_R(61), r61 - ld.q SP, FRAME_R(62), r62 - - /* Last touch */ - ld.q SP, FRAME_R(15), SP - rte - nop - -/* - * Third level handlers for VBR-based exceptions. Adapting args to - * and/or deflecting to fourth level handlers. - * - * Fourth level handlers interface. - * Most are C-coded handlers directly pointed by the trap_jtable. - * (Third = Fourth level) - * Inputs: - * (r2) fault/interrupt code, entry number (e.g. NMI = 14, - * IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...) - * (r3) struct pt_regs *, original register's frame pointer - * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault) - * (r5) TRA control register (for syscall/debug benefit only) - * (LINK) return address - * (SP) = r3 - * - * Kernel TLB fault handlers will get a slightly different interface. - * (r2) struct pt_regs *, original register's frame pointer - * (r3) writeaccess, whether it's a store fault as opposed to load fault - * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault - * (r5) Effective Address of fault - * (LINK) return address - * (SP) = r2 - * - * fpu_error_or_IRQ? is a helper to deflect to the right cause. - * - */ -tlb_miss_load: - or SP, ZERO, r2 - or ZERO, ZERO, r3 /* Read */ - or ZERO, ZERO, r4 /* Data */ - getcon TEA, r5 - pta call_do_page_fault, tr0 - beq ZERO, ZERO, tr0 - -tlb_miss_store: - or SP, ZERO, r2 - movi 1, r3 /* Write */ - or ZERO, ZERO, r4 /* Data */ - getcon TEA, r5 - pta call_do_page_fault, tr0 - beq ZERO, ZERO, tr0 - -itlb_miss_or_IRQ: - pta its_IRQ, tr0 - beqi/u r4, EVENT_INTERRUPT, tr0 - or SP, ZERO, r2 - or ZERO, ZERO, r3 /* Read */ - movi 1, r4 /* Text */ - getcon TEA, r5 - /* Fall through */ - -call_do_page_fault: - movi do_page_fault, r6 - ptabs r6, tr0 - blink tr0, ZERO - -fpu_error_or_IRQA: - pta its_IRQ, tr0 - beqi/l r4, EVENT_INTERRUPT, tr0 -#ifdef CONFIG_SH_FPU - movi do_fpu_state_restore, r6 -#else - movi do_exception_error, r6 -#endif - ptabs r6, tr0 - blink tr0, ZERO - -fpu_error_or_IRQB: - pta its_IRQ, tr0 - beqi/l r4, EVENT_INTERRUPT, tr0 -#ifdef CONFIG_SH_FPU - movi do_fpu_state_restore, r6 -#else - movi do_exception_error, r6 -#endif - ptabs r6, tr0 - blink tr0, ZERO - -its_IRQ: - movi do_IRQ, r6 - ptabs r6, tr0 - blink tr0, ZERO - -/* - * system_call/unknown_trap third level handler: - * - * Inputs: - * (r2) fault/interrupt code, entry number (TRAP = 11) - * (r3) struct pt_regs *, original register's frame pointer - * (r4) Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault) - * (r5) TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr) - * (SP) = r3 - * (LINK) return address: ret_from_exception - * (*r3) Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7) - * - * Outputs: - * (*r3) Syscall reply (Saved r2) - * (LINK) In case of syscall only it can be scrapped. - * Common second level post handler will be ret_from_syscall. - * Common (non-trace) exit point to that is syscall_ret (saving - * result to r2). Common bad exit point is syscall_bad (returning - * ENOSYS then saved to r2). - * - */ - -unknown_trap: - /* Unknown Trap or User Trace */ - movi do_unknown_trapa, r6 - ptabs r6, tr0 - ld.q r3, FRAME_R(9), r2 /* r2 = #arg << 16 | syscall # */ - andi r2, 0x1ff, r2 /* r2 = syscall # */ - blink tr0, LINK - - pta syscall_ret, tr0 - blink tr0, ZERO - - /* New syscall implementation*/ -system_call: - pta unknown_trap, tr0 - or r5, ZERO, r4 /* TRA (=r5) -> r4 */ - shlri r4, 20, r4 - bnei r4, 1, tr0 /* unknown_trap if not 0x1yzzzz */ - - /* It's a system call */ - st.q r3, FRAME_S(FSYSCALL_ID), r5 /* ID (0x1yzzzz) -> stack */ - andi r5, 0x1ff, r5 /* syscall # -> r5 */ - - STI() - - pta syscall_allowed, tr0 - movi NR_syscalls - 1, r4 /* Last valid */ - bgeu/l r4, r5, tr0 - -syscall_bad: - /* Return ENOSYS ! */ - movi -(ENOSYS), r2 /* Fall-through */ - - .global syscall_ret -syscall_ret: - st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */ - -#ifdef CONFIG_POOR_MANS_STRACE - /* nothing useful in registers at this point */ - - movi evt_debug2, r5 - ori r5, 1, r5 - ptabs r5, tr0 - ld.q SP, FRAME_R(9), r2 - or SP, ZERO, r3 - blink tr0, LINK -#endif - - ld.q SP, FRAME_S(FSPC), r2 - addi r2, 4, r2 /* Move PC, being pre-execution event */ - st.q SP, FRAME_S(FSPC), r2 - pta ret_from_syscall, tr0 - blink tr0, ZERO - - -/* A different return path for ret_from_fork, because we now need - * to call schedule_tail with the later kernels. Because prev is - * loaded into r2 by switch_to() means we can just call it straight away - */ - -.global ret_from_fork -ret_from_fork: - - movi schedule_tail,r5 - ori r5, 1, r5 - ptabs r5, tr0 - blink tr0, LINK - -#ifdef CONFIG_POOR_MANS_STRACE - /* nothing useful in registers at this point */ - - movi evt_debug2, r5 - ori r5, 1, r5 - ptabs r5, tr0 - ld.q SP, FRAME_R(9), r2 - or SP, ZERO, r3 - blink tr0, LINK -#endif - - ld.q SP, FRAME_S(FSPC), r2 - addi r2, 4, r2 /* Move PC, being pre-execution event */ - st.q SP, FRAME_S(FSPC), r2 - pta ret_from_syscall, tr0 - blink tr0, ZERO - - - -syscall_allowed: - /* Use LINK to deflect the exit point, default is syscall_ret */ - pta syscall_ret, tr0 - gettr tr0, LINK - pta syscall_notrace, tr0 - - getcon KCR0, r2 - ld.l r2, TI_FLAGS, r4 - movi (1 << TIF_SYSCALL_TRACE), r6 - and r6, r4, r6 - beq/l r6, ZERO, tr0 - - /* Trace it by calling syscall_trace before and after */ - movi syscall_trace, r4 - ptabs r4, tr0 - blink tr0, LINK - /* Reload syscall number as r5 is trashed by syscall_trace */ - ld.q SP, FRAME_S(FSYSCALL_ID), r5 - andi r5, 0x1ff, r5 - - pta syscall_ret_trace, tr0 - gettr tr0, LINK - -syscall_notrace: - /* Now point to the appropriate 4th level syscall handler */ - movi sys_call_table, r4 - shlli r5, 2, r5 - ldx.l r4, r5, r5 - ptabs r5, tr0 - - /* Prepare original args */ - ld.q SP, FRAME_R(2), r2 - ld.q SP, FRAME_R(3), r3 - ld.q SP, FRAME_R(4), r4 - ld.q SP, FRAME_R(5), r5 - ld.q SP, FRAME_R(6), r6 - ld.q SP, FRAME_R(7), r7 - - /* And now the trick for those syscalls requiring regs * ! */ - or SP, ZERO, r8 - - /* Call it */ - blink tr0, ZERO /* LINK is already properly set */ - -syscall_ret_trace: - /* We get back here only if under trace */ - st.q SP, FRAME_R(9), r2 /* Save return value */ - - movi syscall_trace, LINK - ptabs LINK, tr0 - blink tr0, LINK - - /* This needs to be done after any syscall tracing */ - ld.q SP, FRAME_S(FSPC), r2 - addi r2, 4, r2 /* Move PC, being pre-execution event */ - st.q SP, FRAME_S(FSPC), r2 - - pta ret_from_syscall, tr0 - blink tr0, ZERO /* Resume normal return sequence */ - -/* - * --- Switch to running under a particular ASID and return the previous ASID value - * --- The caller is assumed to have done a cli before calling this. - * - * Input r2 : new ASID - * Output r2 : old ASID - */ - - .global switch_and_save_asid -switch_and_save_asid: - getcon sr, r0 - movi 255, r4 - shlli r4, 16, r4 /* r4 = mask to select ASID */ - and r0, r4, r3 /* r3 = shifted old ASID */ - andi r2, 255, r2 /* mask down new ASID */ - shlli r2, 16, r2 /* align new ASID against SR.ASID */ - andc r0, r4, r0 /* efface old ASID from SR */ - or r0, r2, r0 /* insert the new ASID */ - putcon r0, ssr - movi 1f, r0 - putcon r0, spc - rte - nop -1: - ptabs LINK, tr0 - shlri r3, 16, r2 /* r2 = old ASID */ - blink tr0, r63 - - .global route_to_panic_handler -route_to_panic_handler: - /* Switch to real mode, goto panic_handler, don't return. Useful for - last-chance debugging, e.g. if no output wants to go to the console. - */ - - movi panic_handler - CONFIG_CACHED_MEMORY_OFFSET, r1 - ptabs r1, tr0 - pta 1f, tr1 - gettr tr1, r0 - putcon r0, spc - getcon sr, r0 - movi 1, r1 - shlli r1, 31, r1 - andc r0, r1, r0 - putcon r0, ssr - rte - nop -1: /* Now in real mode */ - blink tr0, r63 - nop - - .global peek_real_address_q -peek_real_address_q: - /* Two args: - r2 : real mode address to peek - r2(out) : result quadword - - This is provided as a cheapskate way of manipulating device - registers for debugging (to avoid the need to onchip_remap the debug - module, and to avoid the need to onchip_remap the watchpoint - controller in a way that identity maps sufficient bits to avoid the - SH5-101 cut2 silicon defect). - - This code is not performance critical - */ - - add.l r2, r63, r2 /* sign extend address */ - getcon sr, r0 /* r0 = saved original SR */ - movi 1, r1 - shlli r1, 28, r1 - or r0, r1, r1 /* r0 with block bit set */ - putcon r1, sr /* now in critical section */ - movi 1, r36 - shlli r36, 31, r36 - andc r1, r36, r1 /* turn sr.mmu off in real mode section */ - - putcon r1, ssr - movi .peek0 - CONFIG_CACHED_MEMORY_OFFSET, r36 /* real mode target address */ - movi 1f, r37 /* virtual mode return addr */ - putcon r36, spc - - synco - rte - nop - -.peek0: /* come here in real mode, don't touch caches!! - still in critical section (sr.bl==1) */ - putcon r0, ssr - putcon r37, spc - /* Here's the actual peek. If the address is bad, all bets are now off - * what will happen (handlers invoked in real-mode = bad news) */ - ld.q r2, 0, r2 - synco - rte /* Back to virtual mode */ - nop - -1: - ptabs LINK, tr0 - blink tr0, r63 - - .global poke_real_address_q -poke_real_address_q: - /* Two args: - r2 : real mode address to poke - r3 : quadword value to write. - - This is provided as a cheapskate way of manipulating device - registers for debugging (to avoid the need to onchip_remap the debug - module, and to avoid the need to onchip_remap the watchpoint - controller in a way that identity maps sufficient bits to avoid the - SH5-101 cut2 silicon defect). - - This code is not performance critical - */ - - add.l r2, r63, r2 /* sign extend address */ - getcon sr, r0 /* r0 = saved original SR */ - movi 1, r1 - shlli r1, 28, r1 - or r0, r1, r1 /* r0 with block bit set */ - putcon r1, sr /* now in critical section */ - movi 1, r36 - shlli r36, 31, r36 - andc r1, r36, r1 /* turn sr.mmu off in real mode section */ - - putcon r1, ssr - movi .poke0-CONFIG_CACHED_MEMORY_OFFSET, r36 /* real mode target address */ - movi 1f, r37 /* virtual mode return addr */ - putcon r36, spc - - synco - rte - nop - -.poke0: /* come here in real mode, don't touch caches!! - still in critical section (sr.bl==1) */ - putcon r0, ssr - putcon r37, spc - /* Here's the actual poke. If the address is bad, all bets are now off - * what will happen (handlers invoked in real-mode = bad news) */ - st.q r2, 0, r3 - synco - rte /* Back to virtual mode */ - nop - -1: - ptabs LINK, tr0 - blink tr0, r63 - -/* - * --- User Access Handling Section - */ - -/* - * User Access support. It all moved to non inlined Assembler - * functions in here. - * - * __kernel_size_t __copy_user(void *__to, const void *__from, - * __kernel_size_t __n) - * - * Inputs: - * (r2) target address - * (r3) source address - * (r4) size in bytes - * - * Ouputs: - * (*r2) target data - * (r2) non-copied bytes - * - * If a fault occurs on the user pointer, bail out early and return the - * number of bytes not copied in r2. - * Strategy : for large blocks, call a real memcpy function which can - * move >1 byte at a time using unaligned ld/st instructions, and can - * manipulate the cache using prefetch + alloco to improve the speed - * further. If a fault occurs in that function, just revert to the - * byte-by-byte approach used for small blocks; this is rare so the - * performance hit for that case does not matter. - * - * For small blocks it's not worth the overhead of setting up and calling - * the memcpy routine; do the copy a byte at a time. - * - */ - .global __copy_user -__copy_user: - pta __copy_user_byte_by_byte, tr1 - movi 16, r0 ! this value is a best guess, should tune it by benchmarking - bge/u r0, r4, tr1 - pta copy_user_memcpy, tr0 - addi SP, -32, SP - /* Save arguments in case we have to fix-up unhandled page fault */ - st.q SP, 0, r2 - st.q SP, 8, r3 - st.q SP, 16, r4 - st.q SP, 24, r35 ! r35 is callee-save - /* Save LINK in a register to reduce RTS time later (otherwise - ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */ - ori LINK, 0, r35 - blink tr0, LINK - - /* Copy completed normally if we get back here */ - ptabs r35, tr0 - ld.q SP, 24, r35 - /* don't restore r2-r4, pointless */ - /* set result=r2 to zero as the copy must have succeeded. */ - or r63, r63, r2 - addi SP, 32, SP - blink tr0, r63 ! RTS - - .global __copy_user_fixup -__copy_user_fixup: - /* Restore stack frame */ - ori r35, 0, LINK - ld.q SP, 24, r35 - ld.q SP, 16, r4 - ld.q SP, 8, r3 - ld.q SP, 0, r2 - addi SP, 32, SP - /* Fall through to original code, in the 'same' state we entered with */ - -/* The slow byte-by-byte method is used if the fast copy traps due to a bad - user address. In that rare case, the speed drop can be tolerated. */ -__copy_user_byte_by_byte: - pta ___copy_user_exit, tr1 - pta ___copy_user1, tr0 - beq/u r4, r63, tr1 /* early exit for zero length copy */ - sub r2, r3, r0 - addi r0, -1, r0 - -___copy_user1: - ld.b r3, 0, r5 /* Fault address 1 */ - - /* Could rewrite this to use just 1 add, but the second comes 'free' - due to load latency */ - addi r3, 1, r3 - addi r4, -1, r4 /* No real fixup required */ -___copy_user2: - stx.b r3, r0, r5 /* Fault address 2 */ - bne r4, ZERO, tr0 - -___copy_user_exit: - or r4, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * __kernel_size_t __clear_user(void *addr, __kernel_size_t size) - * - * Inputs: - * (r2) target address - * (r3) size in bytes - * - * Ouputs: - * (*r2) zero-ed target data - * (r2) non-zero-ed bytes - */ - .global __clear_user -__clear_user: - pta ___clear_user_exit, tr1 - pta ___clear_user1, tr0 - beq/u r3, r63, tr1 - -___clear_user1: - st.b r2, 0, ZERO /* Fault address */ - addi r2, 1, r2 - addi r3, -1, r3 /* No real fixup required */ - bne r3, ZERO, tr0 - -___clear_user_exit: - or r3, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - - -/* - * int __strncpy_from_user(unsigned long __dest, unsigned long __src, - * int __count) - * - * Inputs: - * (r2) target address - * (r3) source address - * (r4) maximum size in bytes - * - * Ouputs: - * (*r2) copied data - * (r2) -EFAULT (in case of faulting) - * copied data (otherwise) - */ - .global __strncpy_from_user -__strncpy_from_user: - pta ___strncpy_from_user1, tr0 - pta ___strncpy_from_user_done, tr1 - or r4, ZERO, r5 /* r5 = original count */ - beq/u r4, r63, tr1 /* early exit if r4==0 */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - -___strncpy_from_user1: - ld.b r3, 0, r7 /* Fault address: only in reading */ - st.b r2, 0, r7 - addi r2, 1, r2 - addi r3, 1, r3 - beq/u ZERO, r7, tr1 - addi r4, -1, r4 /* return real number of copied bytes */ - bne/l ZERO, r4, tr0 - -___strncpy_from_user_done: - sub r5, r4, r6 /* If done, return copied */ - -___strncpy_from_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * extern long __strnlen_user(const char *__s, long __n) - * - * Inputs: - * (r2) source address - * (r3) source size in bytes - * - * Ouputs: - * (r2) -EFAULT (in case of faulting) - * string length (otherwise) - */ - .global __strnlen_user -__strnlen_user: - pta ___strnlen_user_set_reply, tr0 - pta ___strnlen_user1, tr1 - or ZERO, ZERO, r5 /* r5 = counter */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - beq r3, ZERO, tr0 - -___strnlen_user1: - ldx.b r2, r5, r7 /* Fault address: only in reading */ - addi r3, -1, r3 /* No real fixup */ - addi r5, 1, r5 - beq r3, ZERO, tr0 - bne r7, ZERO, tr1 -! The line below used to be active. This meant led to a junk byte lying between each pair -! of entries in the argv & envp structures in memory. Whilst the program saw the right data -! via the argv and envp arguments to main, it meant the 'flat' representation visible through -! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example. -! addi r5, 1, r5 /* Include '\0' */ - -___strnlen_user_set_reply: - or r5, ZERO, r6 /* If done, return counter */ - -___strnlen_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * extern long __get_user_asm_?(void *val, long addr) - * - * Inputs: - * (r2) dest address - * (r3) source address (in User Space) - * - * Ouputs: - * (r2) -EFAULT (faulting) - * 0 (not faulting) - */ - .global __get_user_asm_b -__get_user_asm_b: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_b1: - ld.b r3, 0, r5 /* r5 = data */ - st.b r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_b_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __get_user_asm_w -__get_user_asm_w: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_w1: - ld.w r3, 0, r5 /* r5 = data */ - st.w r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_w_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __get_user_asm_l -__get_user_asm_l: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_l1: - ld.l r3, 0, r5 /* r5 = data */ - st.l r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_l_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __get_user_asm_q -__get_user_asm_q: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_q1: - ld.q r3, 0, r5 /* r5 = data */ - st.q r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_q_exit: - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * extern long __put_user_asm_?(void *pval, long addr) - * - * Inputs: - * (r2) kernel pointer to value - * (r3) dest address (in User Space) - * - * Ouputs: - * (r2) -EFAULT (faulting) - * 0 (not faulting) - */ - .global __put_user_asm_b -__put_user_asm_b: - ld.b r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_b1: - st.b r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_b_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __put_user_asm_w -__put_user_asm_w: - ld.w r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_w1: - st.w r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_w_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __put_user_asm_l -__put_user_asm_l: - ld.l r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_l1: - st.l r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_l_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __put_user_asm_q -__put_user_asm_q: - ld.q r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_q1: - st.q r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_q_exit: - ptabs LINK, tr0 - blink tr0, ZERO - -panic_stash_regs: - /* The idea is : when we get an unhandled panic, we dump the registers - to a known memory location, the just sit in a tight loop. - This allows the human to look at the memory region through the GDB - session (assuming the debug module's SHwy initiator isn't locked up - or anything), to hopefully analyze the cause of the panic. */ - - /* On entry, former r15 (SP) is in DCR - former r0 is at resvec_saved_area + 0 - former r1 is at resvec_saved_area + 8 - former tr0 is at resvec_saved_area + 32 - DCR is the only register whose value is lost altogether. - */ - - movi 0xffffffff80000000, r0 ! phy of dump area - ld.q SP, 0x000, r1 ! former r0 - st.q r0, 0x000, r1 - ld.q SP, 0x008, r1 ! former r1 - st.q r0, 0x008, r1 - st.q r0, 0x010, r2 - st.q r0, 0x018, r3 - st.q r0, 0x020, r4 - st.q r0, 0x028, r5 - st.q r0, 0x030, r6 - st.q r0, 0x038, r7 - st.q r0, 0x040, r8 - st.q r0, 0x048, r9 - st.q r0, 0x050, r10 - st.q r0, 0x058, r11 - st.q r0, 0x060, r12 - st.q r0, 0x068, r13 - st.q r0, 0x070, r14 - getcon dcr, r14 - st.q r0, 0x078, r14 - st.q r0, 0x080, r16 - st.q r0, 0x088, r17 - st.q r0, 0x090, r18 - st.q r0, 0x098, r19 - st.q r0, 0x0a0, r20 - st.q r0, 0x0a8, r21 - st.q r0, 0x0b0, r22 - st.q r0, 0x0b8, r23 - st.q r0, 0x0c0, r24 - st.q r0, 0x0c8, r25 - st.q r0, 0x0d0, r26 - st.q r0, 0x0d8, r27 - st.q r0, 0x0e0, r28 - st.q r0, 0x0e8, r29 - st.q r0, 0x0f0, r30 - st.q r0, 0x0f8, r31 - st.q r0, 0x100, r32 - st.q r0, 0x108, r33 - st.q r0, 0x110, r34 - st.q r0, 0x118, r35 - st.q r0, 0x120, r36 - st.q r0, 0x128, r37 - st.q r0, 0x130, r38 - st.q r0, 0x138, r39 - st.q r0, 0x140, r40 - st.q r0, 0x148, r41 - st.q r0, 0x150, r42 - st.q r0, 0x158, r43 - st.q r0, 0x160, r44 - st.q r0, 0x168, r45 - st.q r0, 0x170, r46 - st.q r0, 0x178, r47 - st.q r0, 0x180, r48 - st.q r0, 0x188, r49 - st.q r0, 0x190, r50 - st.q r0, 0x198, r51 - st.q r0, 0x1a0, r52 - st.q r0, 0x1a8, r53 - st.q r0, 0x1b0, r54 - st.q r0, 0x1b8, r55 - st.q r0, 0x1c0, r56 - st.q r0, 0x1c8, r57 - st.q r0, 0x1d0, r58 - st.q r0, 0x1d8, r59 - st.q r0, 0x1e0, r60 - st.q r0, 0x1e8, r61 - st.q r0, 0x1f0, r62 - st.q r0, 0x1f8, r63 ! bogus, but for consistency's sake... - - ld.q SP, 0x020, r1 ! former tr0 - st.q r0, 0x200, r1 - gettr tr1, r1 - st.q r0, 0x208, r1 - gettr tr2, r1 - st.q r0, 0x210, r1 - gettr tr3, r1 - st.q r0, 0x218, r1 - gettr tr4, r1 - st.q r0, 0x220, r1 - gettr tr5, r1 - st.q r0, 0x228, r1 - gettr tr6, r1 - st.q r0, 0x230, r1 - gettr tr7, r1 - st.q r0, 0x238, r1 - - getcon sr, r1 - getcon ssr, r2 - getcon pssr, r3 - getcon spc, r4 - getcon pspc, r5 - getcon intevt, r6 - getcon expevt, r7 - getcon pexpevt, r8 - getcon tra, r9 - getcon tea, r10 - getcon kcr0, r11 - getcon kcr1, r12 - getcon vbr, r13 - getcon resvec, r14 - - st.q r0, 0x240, r1 - st.q r0, 0x248, r2 - st.q r0, 0x250, r3 - st.q r0, 0x258, r4 - st.q r0, 0x260, r5 - st.q r0, 0x268, r6 - st.q r0, 0x270, r7 - st.q r0, 0x278, r8 - st.q r0, 0x280, r9 - st.q r0, 0x288, r10 - st.q r0, 0x290, r11 - st.q r0, 0x298, r12 - st.q r0, 0x2a0, r13 - st.q r0, 0x2a8, r14 - - getcon SPC,r2 - getcon SSR,r3 - getcon EXPEVT,r4 - /* Prepare to jump to C - physical address */ - movi panic_handler-CONFIG_CACHED_MEMORY_OFFSET, r1 - ori r1, 1, r1 - ptabs r1, tr0 - getcon DCR, SP - blink tr0, ZERO - nop - nop - nop - nop - - - - -/* - * --- Signal Handling Section - */ - -/* - * extern long long _sa_default_rt_restorer - * extern long long _sa_default_restorer - * - * or, better, - * - * extern void _sa_default_rt_restorer(void) - * extern void _sa_default_restorer(void) - * - * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn() - * from user space. Copied into user space by signal management. - * Both must be quad aligned and 2 quad long (4 instructions). - * - */ - .balign 8 - .global sa_default_rt_restorer -sa_default_rt_restorer: - movi 0x10, r9 - shori __NR_rt_sigreturn, r9 - trapa r9 - nop - - .balign 8 - .global sa_default_restorer -sa_default_restorer: - movi 0x10, r9 - shori __NR_sigreturn, r9 - trapa r9 - nop - -/* - * --- __ex_table Section - */ - -/* - * User Access Exception Table. - */ - .section __ex_table, "a" - - .global asm_uaccess_start /* Just a marker */ -asm_uaccess_start: - - .long ___copy_user1, ___copy_user_exit - .long ___copy_user2, ___copy_user_exit - .long ___clear_user1, ___clear_user_exit - .long ___strncpy_from_user1, ___strncpy_from_user_exit - .long ___strnlen_user1, ___strnlen_user_exit - .long ___get_user_asm_b1, ___get_user_asm_b_exit - .long ___get_user_asm_w1, ___get_user_asm_w_exit - .long ___get_user_asm_l1, ___get_user_asm_l_exit - .long ___get_user_asm_q1, ___get_user_asm_q_exit - .long ___put_user_asm_b1, ___put_user_asm_b_exit - .long ___put_user_asm_w1, ___put_user_asm_w_exit - .long ___put_user_asm_l1, ___put_user_asm_l_exit - .long ___put_user_asm_q1, ___put_user_asm_q_exit - - .global asm_uaccess_end /* Just a marker */ -asm_uaccess_end: - - - - -/* - * --- .text.init Section - */ - - .section .text.init, "ax" - -/* - * void trap_init (void) - * - */ - .global trap_init -trap_init: - addi SP, -24, SP /* Room to save r28/r29/r30 */ - st.q SP, 0, r28 - st.q SP, 8, r29 - st.q SP, 16, r30 - - /* Set VBR and RESVEC */ - movi LVBR_block, r19 - andi r19, -4, r19 /* reset MMUOFF + reserved */ - /* For RESVEC exceptions we force the MMU off, which means we need the - physical address. */ - movi LRESVEC_block-CONFIG_CACHED_MEMORY_OFFSET, r20 - andi r20, -4, r20 /* reset reserved */ - ori r20, 1, r20 /* set MMUOFF */ - putcon r19, VBR - putcon r20, RESVEC - - /* Sanity check */ - movi LVBR_block_end, r21 - andi r21, -4, r21 - movi BLOCK_SIZE, r29 /* r29 = expected size */ - or r19, ZERO, r30 - add r19, r29, r19 - - /* - * Ugly, but better loop forever now than crash afterwards. - * We should print a message, but if we touch LVBR or - * LRESVEC blocks we should not be surprised if we get stuck - * in trap_init(). - */ - pta trap_init_loop, tr1 - gettr tr1, r28 /* r28 = trap_init_loop */ - sub r21, r30, r30 /* r30 = actual size */ - - /* - * VBR/RESVEC handlers overlap by being bigger than - * allowed. Very bad. Just loop forever. - * (r28) panic/loop address - * (r29) expected size - * (r30) actual size - */ -trap_init_loop: - bne r19, r21, tr1 - - /* Now that exception vectors are set up reset SR.BL */ - getcon SR, r22 - movi SR_UNBLOCK_EXC, r23 - and r22, r23, r22 - putcon r22, SR - - addi SP, 24, SP - ptabs LINK, tr0 - blink tr0, ZERO - diff --git a/arch/sh64/kernel/fpu.c b/arch/sh64/kernel/fpu.c deleted file mode 100644 index 8ad4ed6a6c9b..000000000000 --- a/arch/sh64/kernel/fpu.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/fpu.c - * - * Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli - * Copyright (C) 2002 STMicroelectronics Limited - * Author : Stuart Menefy - * - * Started from SH4 version: - * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka - * - */ - -#include <linux/sched.h> -#include <linux/signal.h> -#include <asm/processor.h> -#include <asm/user.h> -#include <asm/io.h> - -/* - * Initially load the FPU with signalling NANS. This bit pattern - * has the property that no matter whether considered as single or as - * double precision, it still represents a signalling NAN. - */ -#define sNAN64 0xFFFFFFFFFFFFFFFFULL -#define sNAN32 0xFFFFFFFFUL - -static union sh_fpu_union init_fpuregs = { - .hard = { - .fp_regs = { [0 ... 63] = sNAN32 }, - .fpscr = FPSCR_INIT - } -}; - -inline void fpsave(struct sh_fpu_hard_struct *fpregs) -{ - asm volatile("fst.p %0, (0*8), fp0\n\t" - "fst.p %0, (1*8), fp2\n\t" - "fst.p %0, (2*8), fp4\n\t" - "fst.p %0, (3*8), fp6\n\t" - "fst.p %0, (4*8), fp8\n\t" - "fst.p %0, (5*8), fp10\n\t" - "fst.p %0, (6*8), fp12\n\t" - "fst.p %0, (7*8), fp14\n\t" - "fst.p %0, (8*8), fp16\n\t" - "fst.p %0, (9*8), fp18\n\t" - "fst.p %0, (10*8), fp20\n\t" - "fst.p %0, (11*8), fp22\n\t" - "fst.p %0, (12*8), fp24\n\t" - "fst.p %0, (13*8), fp26\n\t" - "fst.p %0, (14*8), fp28\n\t" - "fst.p %0, (15*8), fp30\n\t" - "fst.p %0, (16*8), fp32\n\t" - "fst.p %0, (17*8), fp34\n\t" - "fst.p %0, (18*8), fp36\n\t" - "fst.p %0, (19*8), fp38\n\t" - "fst.p %0, (20*8), fp40\n\t" - "fst.p %0, (21*8), fp42\n\t" - "fst.p %0, (22*8), fp44\n\t" - "fst.p %0, (23*8), fp46\n\t" - "fst.p %0, (24*8), fp48\n\t" - "fst.p %0, (25*8), fp50\n\t" - "fst.p %0, (26*8), fp52\n\t" - "fst.p %0, (27*8), fp54\n\t" - "fst.p %0, (28*8), fp56\n\t" - "fst.p %0, (29*8), fp58\n\t" - "fst.p %0, (30*8), fp60\n\t" - "fst.p %0, (31*8), fp62\n\t" - - "fgetscr fr63\n\t" - "fst.s %0, (32*8), fr63\n\t" - : /* no output */ - : "r" (fpregs) - : "memory"); -} - - -static inline void -fpload(struct sh_fpu_hard_struct *fpregs) -{ - asm volatile("fld.p %0, (0*8), fp0\n\t" - "fld.p %0, (1*8), fp2\n\t" - "fld.p %0, (2*8), fp4\n\t" - "fld.p %0, (3*8), fp6\n\t" - "fld.p %0, (4*8), fp8\n\t" - "fld.p %0, (5*8), fp10\n\t" - "fld.p %0, (6*8), fp12\n\t" - "fld.p %0, (7*8), fp14\n\t" - "fld.p %0, (8*8), fp16\n\t" - "fld.p %0, (9*8), fp18\n\t" - "fld.p %0, (10*8), fp20\n\t" - "fld.p %0, (11*8), fp22\n\t" - "fld.p %0, (12*8), fp24\n\t" - "fld.p %0, (13*8), fp26\n\t" - "fld.p %0, (14*8), fp28\n\t" - "fld.p %0, (15*8), fp30\n\t" - "fld.p %0, (16*8), fp32\n\t" - "fld.p %0, (17*8), fp34\n\t" - "fld.p %0, (18*8), fp36\n\t" - "fld.p %0, (19*8), fp38\n\t" - "fld.p %0, (20*8), fp40\n\t" - "fld.p %0, (21*8), fp42\n\t" - "fld.p %0, (22*8), fp44\n\t" - "fld.p %0, (23*8), fp46\n\t" - "fld.p %0, (24*8), fp48\n\t" - "fld.p %0, (25*8), fp50\n\t" - "fld.p %0, (26*8), fp52\n\t" - "fld.p %0, (27*8), fp54\n\t" - "fld.p %0, (28*8), fp56\n\t" - "fld.p %0, (29*8), fp58\n\t" - "fld.p %0, (30*8), fp60\n\t" - - "fld.s %0, (32*8), fr63\n\t" - "fputscr fr63\n\t" - - "fld.p %0, (31*8), fp62\n\t" - : /* no output */ - : "r" (fpregs) ); -} - -void fpinit(struct sh_fpu_hard_struct *fpregs) -{ - *fpregs = init_fpuregs.hard; -} - -asmlinkage void -do_fpu_error(unsigned long ex, struct pt_regs *regs) -{ - struct task_struct *tsk = current; - - regs->pc += 4; - - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; - force_sig(SIGFPE, tsk); -} - - -asmlinkage void -do_fpu_state_restore(unsigned long ex, struct pt_regs *regs) -{ - void die(const char *str, struct pt_regs *regs, long err); - - if (! user_mode(regs)) - die("FPU used in kernel", regs, ex); - - regs->sr &= ~SR_FD; - - if (last_task_used_math == current) - return; - - grab_fpu(); - if (last_task_used_math != NULL) { - /* Other processes fpu state, save away */ - fpsave(&last_task_used_math->thread.fpu.hard); - } - last_task_used_math = current; - if (used_math()) { - fpload(¤t->thread.fpu.hard); - } else { - /* First time FPU user. */ - fpload(&init_fpuregs.hard); - set_used_math(); - } - release_fpu(); -} - diff --git a/arch/sh64/kernel/head.S b/arch/sh64/kernel/head.S deleted file mode 100644 index 186406d3ad9c..000000000000 --- a/arch/sh64/kernel/head.S +++ /dev/null @@ -1,372 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/head.S - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * - * benedict.gaster@superh.com: 2nd May 2002 - * Moved definition of empty_zero_page to its own section allowing - * it to be placed at an absolute address known at load time. - * - * lethal@linux-sh.org: 9th May 2003 - * Kill off GLOBAL_NAME() usage. - * - * lethal@linux-sh.org: 8th May 2004 - * Add early SCIF console DTLB mapping. - */ - - -#include <asm/page.h> -#include <asm/mmu_context.h> -#include <asm/cache.h> -#include <asm/tlb.h> -#include <asm/processor.h> -#include <asm/registers.h> -#include <asm/thread_info.h> - -/* - * MMU defines: TLB boundaries. - */ - -#define MMUIR_FIRST ITLB_FIXED -#define MMUIR_END ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP -#define MMUIR_STEP TLB_STEP - -#define MMUDR_FIRST DTLB_FIXED -#define MMUDR_END DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP -#define MMUDR_STEP TLB_STEP - -/* Safety check : CONFIG_CACHED_MEMORY_OFFSET has to be a multiple of 512Mb */ -#if (CONFIG_CACHED_MEMORY_OFFSET & ((1UL<<29)-1)) -#error "CONFIG_CACHED_MEMORY_OFFSET must be a multiple of 512Mb" -#endif - -/* - * MMU defines: Fixed TLBs. - */ -/* Deal safely with the case where the base of RAM is not 512Mb aligned */ - -#define ALIGN_512M_MASK (0xffffffffe0000000) -#define ALIGNED_EFFECTIVE ((CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START) & ALIGN_512M_MASK) -#define ALIGNED_PHYSICAL (CONFIG_MEMORY_START & ALIGN_512M_MASK) - -#define MMUIR_TEXT_H (0x0000000000000003 | ALIGNED_EFFECTIVE) - /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ - -#define MMUIR_TEXT_L (0x000000000000009a | ALIGNED_PHYSICAL) - /* 512 Mb, Cacheable, Write-back, execute, Not User, Ph. Add. */ - -#define MMUDR_CACHED_H 0x0000000000000003 | ALIGNED_EFFECTIVE - /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ -#define MMUDR_CACHED_L 0x000000000000015a | ALIGNED_PHYSICAL - /* 512 Mb, Cacheable, Write-back, read/write, Not User, Ph. Add. */ - -#ifdef CONFIG_ICACHE_DISABLED -#define ICCR0_INIT_VAL ICCR0_OFF /* ICACHE off */ -#else -#define ICCR0_INIT_VAL ICCR0_ON | ICCR0_ICI /* ICE + ICI */ -#endif -#define ICCR1_INIT_VAL ICCR1_NOLOCK /* No locking */ - -#if defined (CONFIG_DCACHE_DISABLED) -#define OCCR0_INIT_VAL OCCR0_OFF /* D-cache: off */ -#elif defined (CONFIG_DCACHE_WRITE_THROUGH) -#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WT /* D-cache: on, */ - /* WT, invalidate */ -#elif defined (CONFIG_DCACHE_WRITE_BACK) -#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WB /* D-cache: on, */ - /* WB, invalidate */ -#else -#error preprocessor flag CONFIG_DCACHE_... not recognized! -#endif - -#define OCCR1_INIT_VAL OCCR1_NOLOCK /* No locking */ - - .section .empty_zero_page, "aw" - .global empty_zero_page - -empty_zero_page: - .long 1 /* MOUNT_ROOT_RDONLY */ - .long 0 /* RAMDISK_FLAGS */ - .long 0x0200 /* ORIG_ROOT_DEV */ - .long 1 /* LOADER_TYPE */ - .long 0x00800000 /* INITRD_START */ - .long 0x00800000 /* INITRD_SIZE */ - .long 0 - - .text - .balign 4096,0,4096 - - .section .data, "aw" - .balign PAGE_SIZE - - .section .data, "aw" - .balign PAGE_SIZE - - .global swapper_pg_dir -swapper_pg_dir: - .space PAGE_SIZE, 0 - - .global empty_bad_page -empty_bad_page: - .space PAGE_SIZE, 0 - - .global empty_bad_pte_table -empty_bad_pte_table: - .space PAGE_SIZE, 0 - - .global fpu_in_use -fpu_in_use: .quad 0 - - - .section .text.head, "ax" - .balign L1_CACHE_BYTES -/* - * Condition at the entry of __stext: - * . Reset state: - * . SR.FD = 1 (FPU disabled) - * . SR.BL = 1 (Exceptions disabled) - * . SR.MD = 1 (Privileged Mode) - * . SR.MMU = 0 (MMU Disabled) - * . SR.CD = 0 (CTC User Visible) - * . SR.IMASK = Undefined (Interrupt Mask) - * - * Operations supposed to be performed by __stext: - * . prevent speculative fetch onto device memory while MMU is off - * . reflect as much as possible SH5 ABI (r15, r26, r27, r18) - * . first, save CPU state and set it to something harmless - * . any CPU detection and/or endianness settings (?) - * . initialize EMI/LMI (but not TMU/RTC/INTC/SCIF): TBD - * . set initial TLB entries for cached and uncached regions - * (no fine granularity paging) - * . set initial cache state - * . enable MMU and caches - * . set CPU to a consistent state - * . registers (including stack pointer and current/KCR0) - * . NOT expecting to set Exception handling nor VBR/RESVEC/DCR - * at this stage. This is all to later Linux initialization steps. - * . initialize FPU - * . clear BSS - * . jump into start_kernel() - * . be prepared to hopeless start_kernel() returns. - * - */ - .global _stext -_stext: - /* - * Prevent speculative fetch on device memory due to - * uninitialized target registers. - */ - ptabs/u ZERO, tr0 - ptabs/u ZERO, tr1 - ptabs/u ZERO, tr2 - ptabs/u ZERO, tr3 - ptabs/u ZERO, tr4 - ptabs/u ZERO, tr5 - ptabs/u ZERO, tr6 - ptabs/u ZERO, tr7 - synci - - /* - * Read/Set CPU state. After this block: - * r29 = Initial SR - */ - getcon SR, r29 - movi SR_HARMLESS, r20 - putcon r20, SR - - /* - * Initialize EMI/LMI. To Be Done. - */ - - /* - * CPU detection and/or endianness settings (?). To Be Done. - * Pure PIC code here, please ! Just save state into r30. - * After this block: - * r30 = CPU type/Platform Endianness - */ - - /* - * Set initial TLB entries for cached and uncached regions. - * Note: PTA/BLINK is PIC code, PTABS/BLINK isn't ! - */ - /* Clear ITLBs */ - pta clear_ITLB, tr1 - movi MMUIR_FIRST, r21 - movi MMUIR_END, r22 -clear_ITLB: - putcfg r21, 0, ZERO /* Clear MMUIR[n].PTEH.V */ - addi r21, MMUIR_STEP, r21 - bne r21, r22, tr1 - - /* Clear DTLBs */ - pta clear_DTLB, tr1 - movi MMUDR_FIRST, r21 - movi MMUDR_END, r22 -clear_DTLB: - putcfg r21, 0, ZERO /* Clear MMUDR[n].PTEH.V */ - addi r21, MMUDR_STEP, r21 - bne r21, r22, tr1 - - /* Map one big (512Mb) page for ITLB */ - movi MMUIR_FIRST, r21 - movi MMUIR_TEXT_L, r22 /* PTEL first */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 1, r22 /* Set MMUIR[0].PTEL */ - movi MMUIR_TEXT_H, r22 /* PTEH last */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 0, r22 /* Set MMUIR[0].PTEH */ - - /* Map one big CACHED (512Mb) page for DTLB */ - movi MMUDR_FIRST, r21 - movi MMUDR_CACHED_L, r22 /* PTEL first */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 1, r22 /* Set MMUDR[0].PTEL */ - movi MMUDR_CACHED_H, r22 /* PTEH last */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ - -#ifdef CONFIG_EARLY_PRINTK - /* - * Setup a DTLB translation for SCIF phys. - */ - addi r21, MMUDR_STEP, r21 - movi 0x0a03, r22 /* SCIF phys */ - shori 0x0148, r22 - putcfg r21, 1, r22 /* PTEL first */ - movi 0xfa03, r22 /* 0xfa030000, fixed SCIF virt */ - shori 0x0003, r22 - putcfg r21, 0, r22 /* PTEH last */ -#endif - - /* - * Set cache behaviours. - */ - /* ICache */ - movi ICCR_BASE, r21 - movi ICCR0_INIT_VAL, r22 - movi ICCR1_INIT_VAL, r23 - putcfg r21, ICCR_REG0, r22 - putcfg r21, ICCR_REG1, r23 - - /* OCache */ - movi OCCR_BASE, r21 - movi OCCR0_INIT_VAL, r22 - movi OCCR1_INIT_VAL, r23 - putcfg r21, OCCR_REG0, r22 - putcfg r21, OCCR_REG1, r23 - - - /* - * Enable Caches and MMU. Do the first non-PIC jump. - * Now head.S global variables, constants and externs - * can be used. - */ - getcon SR, r21 - movi SR_ENABLE_MMU, r22 - or r21, r22, r21 - putcon r21, SSR - movi hyperspace, r22 - ori r22, 1, r22 /* Make it SHmedia, not required but..*/ - putcon r22, SPC - synco - rte /* And now go into the hyperspace ... */ -hyperspace: /* ... that's the next instruction ! */ - - /* - * Set CPU to a consistent state. - * r31 = FPU support flag - * tr0/tr7 in use. Others give a chance to loop somewhere safe - */ - movi start_kernel, r32 - ori r32, 1, r32 - - ptabs r32, tr0 /* r32 = _start_kernel address */ - pta/u hopeless, tr1 - pta/u hopeless, tr2 - pta/u hopeless, tr3 - pta/u hopeless, tr4 - pta/u hopeless, tr5 - pta/u hopeless, tr6 - pta/u hopeless, tr7 - gettr tr1, r28 /* r28 = hopeless address */ - - /* Set initial stack pointer */ - movi init_thread_union, SP - putcon SP, KCR0 /* Set current to init_task */ - movi THREAD_SIZE, r22 /* Point to the end */ - add SP, r22, SP - - /* - * Initialize FPU. - * Keep FPU flag in r31. After this block: - * r31 = FPU flag - */ - movi fpu_in_use, r31 /* Temporary */ - -#ifdef CONFIG_SH_FPU - getcon SR, r21 - movi SR_ENABLE_FPU, r22 - and r21, r22, r22 - putcon r22, SR /* Try to enable */ - getcon SR, r22 - xor r21, r22, r21 - shlri r21, 15, r21 /* Supposedly 0/1 */ - st.q r31, 0 , r21 /* Set fpu_in_use */ -#else - movi 0, r21 - st.q r31, 0 , r21 /* Set fpu_in_use */ -#endif - or r21, ZERO, r31 /* Set FPU flag at last */ - -#ifndef CONFIG_SH_NO_BSS_INIT -/* Don't clear BSS if running on slow platforms such as an RTL simulation, - remote memory via SHdebug link, etc. For these the memory can be guaranteed - to be all zero on boot anyway. */ - /* - * Clear bss - */ - pta clear_quad, tr1 - movi __bss_start, r22 - movi _end, r23 -clear_quad: - st.q r22, 0, ZERO - addi r22, 8, r22 - bne r22, r23, tr1 /* Both quad aligned, see vmlinux.lds.S */ -#endif - pta/u hopeless, tr1 - - /* Say bye to head.S but be prepared to wrongly get back ... */ - blink tr0, LINK - - /* If we ever get back here through LINK/tr1-tr7 */ - pta/u hopeless, tr7 - -hopeless: - /* - * Something's badly wrong here. Loop endlessly, - * there's nothing more we can do about it. - * - * Note on hopeless: it can be jumped into invariably - * before or after jumping into hyperspace. The only - * requirement is to be PIC called (PTA) before and - * any way (PTA/PTABS) after. According to Virtual - * to Physical mapping a simulator/emulator can easily - * tell where we came here from just looking at hopeless - * (PC) address. - * - * For debugging purposes: - * (r28) hopeless/loop address - * (r29) Original SR - * (r30) CPU type/Platform endianness - * (r31) FPU Support - * (r32) _start_kernel address - */ - blink tr7, ZERO - - diff --git a/arch/sh64/kernel/init_task.c b/arch/sh64/kernel/init_task.c deleted file mode 100644 index deee8bfd3270..000000000000 --- a/arch/sh64/kernel/init_task.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/init_task.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ -#include <linux/rwsem.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/init_task.h> -#include <linux/mqueue.h> -#include <linux/fs.h> -#include <asm/uaccess.h> -#include <asm/pgtable.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); - -struct pt_regs fake_swapper_regs; - -/* - * Initial thread structure. - * - * We need to make sure that this is THREAD_SIZE-byte aligned due - * to the way process stacks are handled. This is done by having a - * special "init_task" linker map entry.. - */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = - { INIT_THREAD_INFO(init_task) }; - -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -struct task_struct init_task = INIT_TASK(init_task); - diff --git a/arch/sh64/kernel/irq.c b/arch/sh64/kernel/irq.c deleted file mode 100644 index 9412b7166700..000000000000 --- a/arch/sh64/kernel/irq.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/irq.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ - -/* - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include <linux/errno.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/rwsem.h> -#include <linux/sched.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/smp.h> -#include <linux/init.h> -#include <linux/seq_file.h> -#include <linux/bitops.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/smp.h> -#include <asm/pgalloc.h> -#include <asm/delay.h> -#include <asm/irq.h> -#include <linux/irq.h> - -void ack_bad_irq(unsigned int irq) -{ - printk("unexpected IRQ trap at irq %02x\n", irq); -} - -#if defined(CONFIG_PROC_FS) -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v, j; - struct irqaction * action; - unsigned long flags; - - if (i == 0) { - seq_puts(p, " "); - for_each_online_cpu(j) - seq_printf(p, "CPU%d ",j); - seq_putc(p, '\n'); - } - - if (i < NR_IRQS) { - spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; - if (!action) - goto unlock; - seq_printf(p, "%3d: ",i); - seq_printf(p, "%10u ", kstat_irqs(i)); - seq_printf(p, " %14s", irq_desc[i].chip->typename); - seq_printf(p, " %s", action->name); - - for (action=action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - seq_putc(p, '\n'); -unlock: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } - return 0; -} -#endif - -/* - * do_NMI handles all Non-Maskable Interrupts. - */ -asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs) -{ - if (regs->sr & 0x40000000) - printk("unexpected NMI trap in system mode\n"); - else - printk("unexpected NMI trap in user mode\n"); - - /* No statistics */ -} - -/* - * do_IRQ handles all normal device IRQ's. - */ -asmlinkage int do_IRQ(unsigned long vector_num, struct pt_regs * regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - int irq; - - irq_enter(); - - irq = irq_demux(vector_num); - - if (irq >= 0) { - __do_IRQ(irq); - } else { - printk("unexpected IRQ trap at vector %03lx\n", vector_num); - } - - irq_exit(); - - set_irq_regs(old_regs); - return 1; -} - diff --git a/arch/sh64/kernel/irq_intc.c b/arch/sh64/kernel/irq_intc.c deleted file mode 100644 index 3b63a93198f2..000000000000 --- a/arch/sh64/kernel/irq_intc.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/irq_intc.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - * Interrupt Controller support for SH5 INTC. - * Per-interrupt selective. IRLM=0 (Fixed priority) is not - * supported being useless without a cascaded interrupt - * controller. - * - */ - -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/bitops.h> /* this includes also <asm/registers.h */ - /* which is required to remap register */ - /* names used into __asm__ blocks... */ - -#include <asm/hardware.h> -#include <asm/platform.h> -#include <asm/page.h> -#include <asm/io.h> -#include <asm/irq.h> - -/* - * Maybe the generic Peripheral block could move to a more - * generic include file. INTC Block will be defined here - * and only here to make INTC self-contained in a single - * file. - */ -#define INTC_BLOCK_OFFSET 0x01000000 - -/* Base */ -#define INTC_BASE PHYS_PERIPHERAL_BLOCK + \ - INTC_BLOCK_OFFSET - -/* Address */ -#define INTC_ICR_SET (intc_virt + 0x0) -#define INTC_ICR_CLEAR (intc_virt + 0x8) -#define INTC_INTPRI_0 (intc_virt + 0x10) -#define INTC_INTSRC_0 (intc_virt + 0x50) -#define INTC_INTSRC_1 (intc_virt + 0x58) -#define INTC_INTREQ_0 (intc_virt + 0x60) -#define INTC_INTREQ_1 (intc_virt + 0x68) -#define INTC_INTENB_0 (intc_virt + 0x70) -#define INTC_INTENB_1 (intc_virt + 0x78) -#define INTC_INTDSB_0 (intc_virt + 0x80) -#define INTC_INTDSB_1 (intc_virt + 0x88) - -#define INTC_ICR_IRLM 0x1 -#define INTC_INTPRI_PREGS 8 /* 8 Priority Registers */ -#define INTC_INTPRI_PPREG 8 /* 8 Priorities per Register */ - - -/* - * Mapper between the vector ordinal and the IRQ number - * passed to kernel/device drivers. - */ -int intc_evt_to_irq[(0xE20/0x20)+1] = { - -1, -1, -1, -1, -1, -1, -1, -1, /* 0x000 - 0x0E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0x100 - 0x1E0 */ - 0, 0, 0, 0, 0, 1, 0, 0, /* 0x200 - 0x2E0 */ - 2, 0, 0, 3, 0, 0, 0, -1, /* 0x300 - 0x3E0 */ - 32, 33, 34, 35, 36, 37, 38, -1, /* 0x400 - 0x4E0 */ - -1, -1, -1, 63, -1, -1, -1, -1, /* 0x500 - 0x5E0 */ - -1, -1, 18, 19, 20, 21, 22, -1, /* 0x600 - 0x6E0 */ - 39, 40, 41, 42, -1, -1, -1, -1, /* 0x700 - 0x7E0 */ - 4, 5, 6, 7, -1, -1, -1, -1, /* 0x800 - 0x8E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0x900 - 0x9E0 */ - 12, 13, 14, 15, 16, 17, -1, -1, /* 0xA00 - 0xAE0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0xB00 - 0xBE0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0xC00 - 0xCE0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0xD00 - 0xDE0 */ - -1, -1 /* 0xE00 - 0xE20 */ -}; - -/* - * Opposite mapper. - */ -static int IRQ_to_vectorN[NR_INTC_IRQS] = { - 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */ - -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */ - 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */ - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */ - 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */ - -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */ - -}; - -static unsigned long intc_virt; - -static unsigned int startup_intc_irq(unsigned int irq); -static void shutdown_intc_irq(unsigned int irq); -static void enable_intc_irq(unsigned int irq); -static void disable_intc_irq(unsigned int irq); -static void mask_and_ack_intc(unsigned int); -static void end_intc_irq(unsigned int irq); - -static struct hw_interrupt_type intc_irq_type = { - .typename = "INTC", - .startup = startup_intc_irq, - .shutdown = shutdown_intc_irq, - .enable = enable_intc_irq, - .disable = disable_intc_irq, - .ack = mask_and_ack_intc, - .end = end_intc_irq -}; - -static int irlm; /* IRL mode */ - -static unsigned int startup_intc_irq(unsigned int irq) -{ - enable_intc_irq(irq); - return 0; /* never anything pending */ -} - -static void shutdown_intc_irq(unsigned int irq) -{ - disable_intc_irq(irq); -} - -static void enable_intc_irq(unsigned int irq) -{ - unsigned long reg; - unsigned long bitmask; - - if ((irq <= IRQ_IRL3) && (irlm == NO_PRIORITY)) - printk("Trying to use straight IRL0-3 with an encoding platform.\n"); - - if (irq < 32) { - reg = INTC_INTENB_0; - bitmask = 1 << irq; - } else { - reg = INTC_INTENB_1; - bitmask = 1 << (irq - 32); - } - - ctrl_outl(bitmask, reg); -} - -static void disable_intc_irq(unsigned int irq) -{ - unsigned long reg; - unsigned long bitmask; - - if (irq < 32) { - reg = INTC_INTDSB_0; - bitmask = 1 << irq; - } else { - reg = INTC_INTDSB_1; - bitmask = 1 << (irq - 32); - } - - ctrl_outl(bitmask, reg); -} - -static void mask_and_ack_intc(unsigned int irq) -{ - disable_intc_irq(irq); -} - -static void end_intc_irq(unsigned int irq) -{ - enable_intc_irq(irq); -} - -/* For future use, if we ever support IRLM=0) */ -void make_intc_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].chip = &intc_irq_type; - disable_intc_irq(irq); -} - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) -int intc_irq_describe(char* p, int irq) -{ - if (irq < NR_INTC_IRQS) - return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20); - else - return 0; -} -#endif - -void __init init_IRQ(void) -{ - unsigned long long __dummy0, __dummy1=~0x00000000100000f0; - unsigned long reg; - unsigned long data; - int i; - - intc_virt = onchip_remap(INTC_BASE, 1024, "INTC"); - if (!intc_virt) { - panic("Unable to remap INTC\n"); - } - - - /* Set default: per-line enable/disable, priority driven ack/eoi */ - for (i = 0; i < NR_INTC_IRQS; i++) { - if (platform_int_priority[i] != NO_PRIORITY) { - irq_desc[i].chip = &intc_irq_type; - } - } - - - /* Disable all interrupts and set all priorities to 0 to avoid trouble */ - ctrl_outl(-1, INTC_INTDSB_0); - ctrl_outl(-1, INTC_INTDSB_1); - - for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8) - ctrl_outl( NO_PRIORITY, reg); - - - /* Set IRLM */ - /* If all the priorities are set to 'no priority', then - * assume we are using encoded mode. - */ - irlm = platform_int_priority[IRQ_IRL0] + platform_int_priority[IRQ_IRL1] + \ - platform_int_priority[IRQ_IRL2] + platform_int_priority[IRQ_IRL3]; - - if (irlm == NO_PRIORITY) { - /* IRLM = 0 */ - reg = INTC_ICR_CLEAR; - i = IRQ_INTA; - printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); - } else { - /* IRLM = 1 */ - reg = INTC_ICR_SET; - i = IRQ_IRL0; - } - ctrl_outl(INTC_ICR_IRLM, reg); - - /* Set interrupt priorities according to platform description */ - for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { - data |= platform_int_priority[i] << ((i % INTC_INTPRI_PPREG) * 4); - if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { - /* Upon the 7th, set Priority Register */ - ctrl_outl(data, reg); - data = 0; - reg += 8; - } - } - -#ifdef CONFIG_SH_CAYMAN - { - extern void init_cayman_irq(void); - - init_cayman_irq(); - } -#endif - - /* - * And now let interrupts come in. - * sti() is not enough, we need to - * lower priority, too. - */ - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "and %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); -} diff --git a/arch/sh64/kernel/led.c b/arch/sh64/kernel/led.c deleted file mode 100644 index e35d3f667fb4..000000000000 --- a/arch/sh64/kernel/led.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * arch/sh64/kernel/led.c - * - * Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com> - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Flash the LEDs - */ -#include <linux/stddef.h> -#include <linux/sched.h> - -void mach_led(int pos, int val); - -/* acts like an actual heart beat -- ie thump-thump-pause... */ -void heartbeat(void) -{ - static unsigned int cnt = 0, period = 0, dist = 0; - - if (cnt == 0 || cnt == dist) { - mach_led(-1, 1); - } else if (cnt == 7 || cnt == dist + 7) { - mach_led(-1, 0); - } - - if (++cnt > period) { - cnt = 0; - - /* - * The hyperbolic function below modifies the heartbeat period - * length in dependency of the current (5min) load. It goes - * through the points f(0)=126, f(1)=86, f(5)=51, f(inf)->30. - */ - period = ((672 << FSHIFT) / (5 * avenrun[0] + - (7 << FSHIFT))) + 30; - dist = period / 4; - } -} - diff --git a/arch/sh64/kernel/module.c b/arch/sh64/kernel/module.c deleted file mode 100644 index 2598f6b88b44..000000000000 --- a/arch/sh64/kernel/module.c +++ /dev/null @@ -1,161 +0,0 @@ -/* Kernel module help for sh64. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Copyright 2004 SuperH (UK) Ltd - Author: Richard Curnow - - Based on the sh version, and on code from the sh64-specific parts of - modutils, originally written by Richard Curnow and Ben Gaster. - -*/ -#include <linux/moduleloader.h> -#include <linux/elf.h> -#include <linux/vmalloc.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/kernel.h> - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - return vmalloc(size); -} - - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ -} - -/* We don't need anything special. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) -{ - return 0; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - Elf32_Addr relocation; - uint32_t *location; - int align; - int is_shmedia; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - relocation = sym->st_value + rel[i].r_addend; - align = (int)location & 3; - - /* For text addresses, bit2 of the st_other field indicates - * whether the symbol is SHmedia (1) or SHcompact (0). If - * SHmedia, the LSB of the symbol needs to be asserted - * for the CPU to be in SHmedia mode when it starts executing - * the branch target. */ - is_shmedia = (sym->st_other & 4) ? 1 : 0; - if (is_shmedia) { - relocation |= 1; - } - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_SH_DIR32: - DEBUGP("R_SH_DIR32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - *location += relocation; - break; - case R_SH_REL32: - DEBUGP("R_SH_REL32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - relocation -= (Elf32_Addr) location; - *location += relocation; - break; - case R_SH_IMM_LOW16: - DEBUGP("R_SH_IMM_LOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - *location = (*location & ~0x3fffc00) | - ((relocation & 0xffff) << 10); - break; - case R_SH_IMM_MEDLOW16: - DEBUGP("R_SH_IMM_MEDLOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - *location = (*location & ~0x3fffc00) | - (((relocation >> 16) & 0xffff) << 10); - break; - case R_SH_IMM_LOW16_PCREL: - DEBUGP("R_SH_IMM_LOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - relocation -= (Elf32_Addr) location; - *location = (*location & ~0x3fffc00) | - ((relocation & 0xffff) << 10); - break; - case R_SH_IMM_MEDLOW16_PCREL: - DEBUGP("R_SH_IMM_MEDLOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - relocation -= (Elf32_Addr) location; - *location = (*location & ~0x3fffc00) | - (((relocation >> 16) & 0xffff) << 10); - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} - -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: REL RELOCATION unsupported\n", - me->name); - return -ENOEXEC; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) -{ - return 0; -} - -void module_arch_cleanup(struct module *mod) -{ -} - diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c deleted file mode 100644 index b4d9534d2b0e..000000000000 --- a/arch/sh64/kernel/pci_sh5.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Support functions for the SH5 PCI hardware. - */ - -#include <linux/kernel.h> -#include <linux/rwsem.h> -#include <linux/smp.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/types.h> -#include <asm/pci.h> -#include <linux/irq.h> - -#include <asm/io.h> -#include <asm/hardware.h> -#include "pci_sh5.h" - -static unsigned long pcicr_virt; -unsigned long pciio_virt; - -static void __init pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - printk("PCI: IDE base address fixup for %s\n", pci_name(d)); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); - -char * __devinit pcibios_setup(char *str) -{ - return str; -} - -/* Rounds a number UP to the nearest power of two. Used for - * sizing the PCI window. - */ -static u32 __init r2p2(u32 num) -{ - int i = 31; - u32 tmp = num; - - if (num == 0) - return 0; - - do { - if (tmp & (1 << 31)) - break; - i--; - tmp <<= 1; - } while (i >= 0); - - tmp = 1 << i; - /* If the original number isn't a power of 2, round it up */ - if (tmp != num) - tmp <<= 1; - - return tmp; -} - -extern unsigned long long memory_start, memory_end; - -int __init sh5pci_init(unsigned memStart, unsigned memSize) -{ - u32 lsr0; - u32 uval; - - pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR"); - if (!pcicr_virt) { - panic("Unable to remap PCICR\n"); - } - - pciio_virt = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO"); - if (!pciio_virt) { - panic("Unable to remap PCIIO\n"); - } - - pr_debug("Register base addres is 0x%08lx\n", pcicr_virt); - - /* Clear snoop registers */ - SH5PCI_WRITE(CSCR0, 0); - SH5PCI_WRITE(CSCR1, 0); - - pr_debug("Wrote to reg\n"); - - /* Switch off interrupts */ - SH5PCI_WRITE(INTM, 0); - SH5PCI_WRITE(AINTM, 0); - SH5PCI_WRITE(PINTM, 0); - - /* Set bus active, take it out of reset */ - uval = SH5PCI_READ(CR); - - /* Set command Register */ - SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | CR_PFCS | CR_BMAM); - - uval=SH5PCI_READ(CR); - pr_debug("CR is actually 0x%08x\n",uval); - - /* Allow it to be a master */ - /* NB - WE DISABLE I/O ACCESS to stop overlap */ - /* set WAIT bit to enable stepping, an attempt to improve stability */ - SH5PCI_WRITE_SHORT(CSR_CMD, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_WAIT); - - /* - ** Set translation mapping memory in order to convert the address - ** used for the main bus, to the PCI internal address. - */ - SH5PCI_WRITE(MBR,0x40000000); - - /* Always set the max size 512M */ - SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024)); - - /* - ** I/O addresses are mapped at internal PCI specific address - ** as is described into the configuration bridge table. - ** These are changed to 0, to allow cards that have legacy - ** io such as vga to function correctly. We set the SH5 IOBAR to - ** 256K, which is a bit big as we can only have 64K of address space - */ - - SH5PCI_WRITE(IOBR,0x0); - - pr_debug("PCI:Writing 0x%08x to IOBR\n",0); - - /* Set up a 256K window. Totally pointless waste of address space */ - SH5PCI_WRITE(IOBMR,0); - pr_debug("PCI:Writing 0x%08x to IOBMR\n",0); - - /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec. Ideally, - * we would want to map the I/O region somewhere, but it is so big this is not - * that easy! - */ - SH5PCI_WRITE(CSR_IBAR0,~0); - /* Set memory size value */ - memSize = memory_end - memory_start; - - /* Now we set up the mbars so the PCI bus can see the memory of the machine */ - if (memSize < (1024 * 1024)) { - printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%x?\n", memSize); - return -EINVAL; - } - - /* Set LSR 0 */ - lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 : ((r2p2(memSize) - 0x100000) | 0x1); - SH5PCI_WRITE(LSR0, lsr0); - - pr_debug("PCI:Writing 0x%08x to LSR0\n",lsr0); - - /* Set MBAR 0 */ - SH5PCI_WRITE(CSR_MBAR0, memory_start); - SH5PCI_WRITE(LAR0, memory_start); - - SH5PCI_WRITE(CSR_MBAR1,0); - SH5PCI_WRITE(LAR1,0); - SH5PCI_WRITE(LSR1,0); - - pr_debug("PCI:Writing 0x%08llx to CSR_MBAR0\n",memory_start); - pr_debug("PCI:Writing 0x%08llx to LAR0\n",memory_start); - - /* Enable the PCI interrupts on the device */ - SH5PCI_WRITE(INTM, ~0); - SH5PCI_WRITE(AINTM, ~0); - SH5PCI_WRITE(PINTM, ~0); - - pr_debug("Switching on all error interrupts\n"); - - return(0); -} - -static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 *val) -{ - SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - - switch (size) { - case 1: - *val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3)); - break; - case 2: - *val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2)); - break; - case 4: - *val = SH5PCI_READ(PDR); - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) -{ - SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - - switch (size) { - case 1: - SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); - break; - case 2: - SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); - break; - case 4: - SH5PCI_WRITE(PDR, val); - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops pci_config_ops = { - .read = sh5pci_read, - .write = sh5pci_write, -}; - -/* Everything hangs off this */ -static struct pci_bus *pci_root_bus; - - -static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) -{ - pr_debug("swizzle for dev %d on bus %d slot %d pin is %d\n", - dev->devfn,dev->bus->number, PCI_SLOT(dev->devfn),*pin); - return PCI_SLOT(dev->devfn); -} - -static inline u8 bridge_swizzle(u8 pin, u8 slot) -{ - return (((pin-1) + slot) % 4) + 1; -} - -u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp) -{ - if (dev->bus->number != 0) { - u8 pin = *pinp; - do { - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - /* Move up the chain of bridges. */ - dev = dev->bus->self; - } while (dev->bus->self); - *pinp = pin; - - /* The slot is the slot of the last bridge. */ - } - - return PCI_SLOT(dev->devfn); -} - -/* This needs to be shunted out of here into the board specific bit */ - -static int __init map_cayman_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int result = -1; - - /* The complication here is that the PCI IRQ lines from the Cayman's 2 - 5V slots get into the CPU via a different path from the IRQ lines - from the 3 3.3V slots. Thus, we have to detect whether the card's - interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling' - at the point where we cross from 5V to 3.3V is not the normal case. - - The added complication is that we don't know that the 5V slots are - always bus 2, because a card containing a PCI-PCI bridge may be - plugged into a 3.3V slot, and this changes the bus numbering. - - Also, the Cayman has an intermediate PCI bus that goes a custom - expansion board header (and to the secondary bridge). This bus has - never been used in practice. - - The 1ary onboard PCI-PCI bridge is device 3 on bus 0 - The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of the 1ary bridge. - */ - - struct slot_pin { - int slot; - int pin; - } path[4]; - int i=0; - - while (dev->bus->number > 0) { - - slot = path[i].slot = PCI_SLOT(dev->devfn); - pin = path[i].pin = bridge_swizzle(pin, slot); - dev = dev->bus->self; - i++; - if (i > 3) panic("PCI path to root bus too long!\n"); - } - - slot = PCI_SLOT(dev->devfn); - /* This is the slot on bus 0 through which the device is eventually - reachable. */ - - /* Now work back up. */ - if ((slot < 3) || (i == 0)) { - /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final - swizzle now. */ - result = IRQ_INTA + bridge_swizzle(pin, slot) - 1; - } else { - i--; - slot = path[i].slot; - pin = path[i].pin; - if (slot > 0) { - panic("PCI expansion bus device found - not handled!\n"); - } else { - if (i > 0) { - /* 5V slots */ - i--; - slot = path[i].slot; - pin = path[i].pin; - /* 'pin' was swizzled earlier wrt slot, don't do it again. */ - result = IRQ_P2INTA + (pin - 1); - } else { - /* IRQ for 2ary PCI-PCI bridge : unused */ - result = -1; - } - } - } - - return result; -} - -static irqreturn_t pcish5_err_irq(int irq, void *dev_id) -{ - struct pt_regs *regs = get_irq_regs(); - unsigned pci_int, pci_air, pci_cir, pci_aint; - - pci_int = SH5PCI_READ(INT); - pci_cir = SH5PCI_READ(CIR); - pci_air = SH5PCI_READ(AIR); - - if (pci_int) { - printk("PCI INTERRUPT (at %08llx)!\n", regs->pc); - printk("PCI INT -> 0x%x\n", pci_int & 0xffff); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - SH5PCI_WRITE(INT, ~0); - } - - pci_aint = SH5PCI_READ(AINT); - if (pci_aint) { - printk("PCI ARB INTERRUPT!\n"); - printk("PCI AINT -> 0x%x\n", pci_aint); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - SH5PCI_WRITE(AINT, ~0); - } - - return IRQ_HANDLED; -} - -static irqreturn_t pcish5_serr_irq(int irq, void *dev_id) -{ - printk("SERR IRQ\n"); - - return IRQ_NONE; -} - -static void __init -pcibios_size_bridge(struct pci_bus *bus, struct resource *ior, - struct resource *memr) -{ - struct resource io_res, mem_res; - struct pci_dev *dev; - struct pci_dev *bridge = bus->self; - struct list_head *ln; - - if (!bridge) - return; /* host bridge, nothing to do */ - - /* set reasonable default locations for pcibios_align_resource */ - io_res.start = PCIBIOS_MIN_IO; - mem_res.start = PCIBIOS_MIN_MEM; - - io_res.end = io_res.start; - mem_res.end = mem_res.start; - - /* Collect information about how our direct children are layed out. */ - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - int i; - dev = pci_dev_b(ln); - - /* Skip bridges for now */ - if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI) - continue; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource res; - unsigned long size; - - memcpy(&res, &dev->resource[i], sizeof(res)); - size = res.end - res.start + 1; - - if (res.flags & IORESOURCE_IO) { - res.start = io_res.end; - pcibios_align_resource(dev, &res, size, 0); - io_res.end = res.start + size; - } else if (res.flags & IORESOURCE_MEM) { - res.start = mem_res.end; - pcibios_align_resource(dev, &res, size, 0); - mem_res.end = res.start + size; - } - } - } - - /* And for all of the subordinate busses. */ - for (ln=bus->children.next; ln != &bus->children; ln=ln->next) - pcibios_size_bridge(pci_bus_b(ln), &io_res, &mem_res); - - /* turn the ending locations into sizes (subtract start) */ - io_res.end -= io_res.start; - mem_res.end -= mem_res.start; - - /* Align the sizes up by bridge rules */ - io_res.end = ALIGN(io_res.end, 4*1024) - 1; - mem_res.end = ALIGN(mem_res.end, 1*1024*1024) - 1; - - /* Adjust the bridge's allocation requirements */ - bridge->resource[0].end = bridge->resource[0].start + io_res.end; - bridge->resource[1].end = bridge->resource[1].start + mem_res.end; - - bridge->resource[PCI_BRIDGE_RESOURCES].end = - bridge->resource[PCI_BRIDGE_RESOURCES].start + io_res.end; - bridge->resource[PCI_BRIDGE_RESOURCES+1].end = - bridge->resource[PCI_BRIDGE_RESOURCES+1].start + mem_res.end; - - /* adjust parent's resource requirements */ - if (ior) { - ior->end = ALIGN(ior->end, 4*1024); - ior->end += io_res.end; - } - - if (memr) { - memr->end = ALIGN(memr->end, 1*1024*1024); - memr->end += mem_res.end; - } -} - -static void __init pcibios_size_bridges(void) -{ - struct resource io_res, mem_res; - - memset(&io_res, 0, sizeof(io_res)); - memset(&mem_res, 0, sizeof(mem_res)); - - pcibios_size_bridge(pci_root_bus, &io_res, &mem_res); -} - -static int __init pcibios_init(void) -{ - if (request_irq(IRQ_ERR, pcish5_err_irq, - IRQF_DISABLED, "PCI Error",NULL) < 0) { - printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n"); - return -EINVAL; - } - - if (request_irq(IRQ_SERR, pcish5_serr_irq, - IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) { - printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n"); - return -EINVAL; - } - - /* The pci subsystem needs to know where memory is and how much - * of it there is. I've simply made these globals. A better mechanism - * is probably needed. - */ - sh5pci_init(__pa(memory_start), - __pa(memory_end) - __pa(memory_start)); - - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); - pcibios_size_bridges(); - pci_assign_unassigned_resources(); - pci_fixup_irqs(no_swizzle, map_cayman_irq); - - return 0; -} - -subsys_initcall(pcibios_init); - -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - struct pci_dev *dev = bus->self; - int i; - -#if 1 - if(dev) { - for(i=0; i<3; i++) { - bus->resource[i] = - &dev->resource[PCI_BRIDGE_RESOURCES+i]; - bus->resource[i]->name = bus->name; - } - bus->resource[0]->flags |= IORESOURCE_IO; - bus->resource[1]->flags |= IORESOURCE_MEM; - - /* For now, propagate host limits to the bus; - * we'll adjust them later. */ - -#if 1 - bus->resource[0]->end = 64*1024 - 1 ; - bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1; - bus->resource[0]->start = PCIBIOS_MIN_IO; - bus->resource[1]->start = PCIBIOS_MIN_MEM; -#else - bus->resource[0]->end = 0; - bus->resource[1]->end = 0; - bus->resource[0]->start =0; - bus->resource[1]->start = 0; -#endif - /* Turn off downstream PF memory address range by default */ - bus->resource[2]->start = 1024*1024; - bus->resource[2]->end = bus->resource[2]->start - 1; - } -#endif - -} - diff --git a/arch/sh64/kernel/pci_sh5.h b/arch/sh64/kernel/pci_sh5.h deleted file mode 100644 index c71159dd04b9..000000000000 --- a/arch/sh64/kernel/pci_sh5.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Definitions for the SH5 PCI hardware. - */ - -/* Product ID */ -#define PCISH5_PID 0x350d - -/* vendor ID */ -#define PCISH5_VID 0x1054 - -/* Configuration types */ -#define ST_TYPE0 0x00 /* Configuration cycle type 0 */ -#define ST_TYPE1 0x01 /* Configuration cycle type 1 */ - -/* VCR data */ -#define PCISH5_VCR_STATUS 0x00 -#define PCISH5_VCR_VERSION 0x08 - -/* -** ICR register offsets and bits -*/ -#define PCISH5_ICR_CR 0x100 /* PCI control register values */ -#define CR_PBAM (1<<12) -#define CR_PFCS (1<<11) -#define CR_FTO (1<<10) -#define CR_PFE (1<<9) -#define CR_TBS (1<<8) -#define CR_SPUE (1<<7) -#define CR_BMAM (1<<6) -#define CR_HOST (1<<5) -#define CR_CLKEN (1<<4) -#define CR_SOCS (1<<3) -#define CR_IOCS (1<<2) -#define CR_RSTCTL (1<<1) -#define CR_CFINT (1<<0) -#define CR_LOCK_MASK 0xa5000000 - -#define PCISH5_ICR_INT 0x114 /* Interrupt registert values */ -#define INT_MADIM (1<<2) - -#define PCISH5_ICR_LSR0 0X104 /* Local space register values */ -#define PCISH5_ICR_LSR1 0X108 /* Local space register values */ -#define PCISH5_ICR_LAR0 0x10c /* Local address register values */ -#define PCISH5_ICR_LAR1 0x110 /* Local address register values */ -#define PCISH5_ICR_INTM 0x118 /* Interrupt mask register values */ -#define PCISH5_ICR_AIR 0x11c /* Interrupt error address information register values */ -#define PCISH5_ICR_CIR 0x120 /* Interrupt error command information register values */ -#define PCISH5_ICR_AINT 0x130 /* Interrupt error arbiter interrupt register values */ -#define PCISH5_ICR_AINTM 0x134 /* Interrupt error arbiter interrupt mask register values */ -#define PCISH5_ICR_BMIR 0x138 /* Interrupt error info register of bus master values */ -#define PCISH5_ICR_PAR 0x1c0 /* Pio address register values */ -#define PCISH5_ICR_MBR 0x1c4 /* Memory space bank register values */ -#define PCISH5_ICR_IOBR 0x1c8 /* I/O space bank register values */ -#define PCISH5_ICR_PINT 0x1cc /* power management interrupt register values */ -#define PCISH5_ICR_PINTM 0x1d0 /* power management interrupt mask register values */ -#define PCISH5_ICR_MBMR 0x1d8 /* memory space bank mask register values */ -#define PCISH5_ICR_IOBMR 0x1dc /* I/O space bank mask register values */ -#define PCISH5_ICR_CSCR0 0x210 /* PCI cache snoop control register 0 */ -#define PCISH5_ICR_CSCR1 0x214 /* PCI cache snoop control register 1 */ -#define PCISH5_ICR_PDR 0x220 /* Pio data register values */ - -/* These are configs space registers */ -#define PCISH5_ICR_CSR_VID 0x000 /* Vendor id */ -#define PCISH5_ICR_CSR_DID 0x002 /* Device id */ -#define PCISH5_ICR_CSR_CMD 0x004 /* Command register */ -#define PCISH5_ICR_CSR_STATUS 0x006 /* Stautus */ -#define PCISH5_ICR_CSR_IBAR0 0x010 /* I/O base address register */ -#define PCISH5_ICR_CSR_MBAR0 0x014 /* First Memory base address register */ -#define PCISH5_ICR_CSR_MBAR1 0x018 /* Second Memory base address register */ - - - -/* Base address of registers */ -#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000) -#define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000) -/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */ - -/* Register selection macro */ -#define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x)) -/* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */ - -/* Write I/O functions */ -#define SH5PCI_WRITE(reg,val) ctrl_outl((u32)(val),PCISH5_ICR_REG(reg)) -#define SH5PCI_WRITE_SHORT(reg,val) ctrl_outw((u16)(val),PCISH5_ICR_REG(reg)) -#define SH5PCI_WRITE_BYTE(reg,val) ctrl_outb((u8)(val),PCISH5_ICR_REG(reg)) - -/* Read I/O functions */ -#define SH5PCI_READ(reg) ctrl_inl(PCISH5_ICR_REG(reg)) -#define SH5PCI_READ_SHORT(reg) ctrl_inw(PCISH5_ICR_REG(reg)) -#define SH5PCI_READ_BYTE(reg) ctrl_inb(PCISH5_ICR_REG(reg)) - -/* Set PCI config bits */ -#define SET_CONFIG_BITS(bus,devfn,where) ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000) - -/* Set PCI command register */ -#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) - -/* Size converters */ -#define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18) -#define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18) - - diff --git a/arch/sh64/kernel/pcibios.c b/arch/sh64/kernel/pcibios.c deleted file mode 100644 index 945920bc24db..000000000000 --- a/arch/sh64/kernel/pcibios.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * $Id: pcibios.c,v 1.1 2001/08/24 12:38:19 dwmw2 Exp $ - * - * arch/sh/kernel/pcibios.c - * - * Copyright (C) 2002 STMicroelectronics Limited - * Author : David J. McKay - * - * Copyright (C) 2004 Richard Curnow, SuperH UK Limited - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * This is GPL'd. - * - * Provided here are generic versions of: - * pcibios_update_resource() - * pcibios_align_resource() - * pcibios_enable_device() - * pcibios_set_master() - * pcibios_update_irq() - * - * These functions are collected here to reduce duplication of common - * code amongst the many platform-specific PCI support code files. - * - * Platform-specific files are expected to provide: - * pcibios_fixup_bus() - * pcibios_init() - * pcibios_setup() - * pcibios_fixup_pbus_ranges() - */ - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/init.h> - -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= IORESOURCE_ROM_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", pci_name(dev), resource, - new, check); - } -} - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - */ -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) -{ - if (res->flags & IORESOURCE_IO) { - resource_size_t start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - -static void pcibios_enable_bridge(struct pci_dev *dev) -{ - struct pci_bus *bus = dev->subordinate; - u16 cmd, old_cmd; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - - if (bus->resource[0]->flags & IORESOURCE_IO) { - cmd |= PCI_COMMAND_IO; - } - if ((bus->resource[1]->flags & IORESOURCE_MEM) || - (bus->resource[2]->flags & IORESOURCE_PREFETCH)) { - cmd |= PCI_COMMAND_MEMORY; - } - - if (cmd != old_cmd) { - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - - printk("PCI bridge %s, command register -> %04x\n", - pci_name(dev), cmd); - -} - - - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - pcibios_enable_bridge(dev); - } - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - if (!(mask & (1 << idx))) - continue; - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check and set - * the latency timer as it may not be properly set. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c deleted file mode 100644 index 0761af4d2a42..000000000000 --- a/arch/sh64/kernel/process.c +++ /dev/null @@ -1,691 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/process.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - * Started from SH3/4 version: - * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima - * - * In turn started from i386 version: - * Copyright (C) 1995 Linus Torvalds - * - */ - -/* - * This file handles the architecture-dependent parts of process handling.. - */ -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/ptrace.h> -#include <linux/reboot.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/proc_fs.h> -#include <asm/uaccess.h> -#include <asm/pgtable.h> - -struct task_struct *last_task_used_math = NULL; - -static int hlt_counter = 1; - -#define HARD_IDLE_TIMEOUT (HZ / 3) - -void disable_hlt(void) -{ - hlt_counter++; -} - -void enable_hlt(void) -{ - hlt_counter--; -} - -static int __init nohlt_setup(char *__unused) -{ - hlt_counter = 1; - return 1; -} - -static int __init hlt_setup(char *__unused) -{ - hlt_counter = 0; - return 1; -} - -__setup("nohlt", nohlt_setup); -__setup("hlt", hlt_setup); - -static inline void hlt(void) -{ - __asm__ __volatile__ ("sleep" : : : "memory"); -} - -/* - * The idle loop on a uniprocessor SH.. - */ -void cpu_idle(void) -{ - /* endless idle loop with no priority at all */ - while (1) { - if (hlt_counter) { - while (!need_resched()) - cpu_relax(); - } else { - local_irq_disable(); - while (!need_resched()) { - local_irq_enable(); - hlt(); - local_irq_disable(); - } - local_irq_enable(); - } - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } - -} - -void machine_restart(char * __unused) -{ - extern void phys_stext(void); - - phys_stext(); -} - -void machine_halt(void) -{ - for (;;); -} - -void machine_power_off(void) -{ - extern void enter_deep_standby(void); - - enter_deep_standby(); -} - -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - -void show_regs(struct pt_regs * regs) -{ - unsigned long long ah, al, bh, bl, ch, cl; - - printk("\n"); - - ah = (regs->pc) >> 32; - al = (regs->pc) & 0xffffffff; - bh = (regs->regs[18]) >> 32; - bl = (regs->regs[18]) & 0xffffffff; - ch = (regs->regs[15]) >> 32; - cl = (regs->regs[15]) & 0xffffffff; - printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->sr) >> 32; - al = (regs->sr) & 0xffffffff; - asm volatile ("getcon " __TEA ", %0" : "=r" (bh)); - asm volatile ("getcon " __TEA ", %0" : "=r" (bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __KCR0 ", %0" : "=r" (ch)); - asm volatile ("getcon " __KCR0 ", %0" : "=r" (cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[0]) >> 32; - al = (regs->regs[0]) & 0xffffffff; - bh = (regs->regs[1]) >> 32; - bl = (regs->regs[1]) & 0xffffffff; - ch = (regs->regs[2]) >> 32; - cl = (regs->regs[2]) & 0xffffffff; - printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[3]) >> 32; - al = (regs->regs[3]) & 0xffffffff; - bh = (regs->regs[4]) >> 32; - bl = (regs->regs[4]) & 0xffffffff; - ch = (regs->regs[5]) >> 32; - cl = (regs->regs[5]) & 0xffffffff; - printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[6]) >> 32; - al = (regs->regs[6]) & 0xffffffff; - bh = (regs->regs[7]) >> 32; - bl = (regs->regs[7]) & 0xffffffff; - ch = (regs->regs[8]) >> 32; - cl = (regs->regs[8]) & 0xffffffff; - printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[9]) >> 32; - al = (regs->regs[9]) & 0xffffffff; - bh = (regs->regs[10]) >> 32; - bl = (regs->regs[10]) & 0xffffffff; - ch = (regs->regs[11]) >> 32; - cl = (regs->regs[11]) & 0xffffffff; - printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[12]) >> 32; - al = (regs->regs[12]) & 0xffffffff; - bh = (regs->regs[13]) >> 32; - bl = (regs->regs[13]) & 0xffffffff; - ch = (regs->regs[14]) >> 32; - cl = (regs->regs[14]) & 0xffffffff; - printk("R12 : %08Lx%08Lx R13 : %08Lx%08Lx R14 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[16]) >> 32; - al = (regs->regs[16]) & 0xffffffff; - bh = (regs->regs[17]) >> 32; - bl = (regs->regs[17]) & 0xffffffff; - ch = (regs->regs[19]) >> 32; - cl = (regs->regs[19]) & 0xffffffff; - printk("R16 : %08Lx%08Lx R17 : %08Lx%08Lx R19 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[20]) >> 32; - al = (regs->regs[20]) & 0xffffffff; - bh = (regs->regs[21]) >> 32; - bl = (regs->regs[21]) & 0xffffffff; - ch = (regs->regs[22]) >> 32; - cl = (regs->regs[22]) & 0xffffffff; - printk("R20 : %08Lx%08Lx R21 : %08Lx%08Lx R22 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[23]) >> 32; - al = (regs->regs[23]) & 0xffffffff; - bh = (regs->regs[24]) >> 32; - bl = (regs->regs[24]) & 0xffffffff; - ch = (regs->regs[25]) >> 32; - cl = (regs->regs[25]) & 0xffffffff; - printk("R23 : %08Lx%08Lx R24 : %08Lx%08Lx R25 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[26]) >> 32; - al = (regs->regs[26]) & 0xffffffff; - bh = (regs->regs[27]) >> 32; - bl = (regs->regs[27]) & 0xffffffff; - ch = (regs->regs[28]) >> 32; - cl = (regs->regs[28]) & 0xffffffff; - printk("R26 : %08Lx%08Lx R27 : %08Lx%08Lx R28 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[29]) >> 32; - al = (regs->regs[29]) & 0xffffffff; - bh = (regs->regs[30]) >> 32; - bl = (regs->regs[30]) & 0xffffffff; - ch = (regs->regs[31]) >> 32; - cl = (regs->regs[31]) & 0xffffffff; - printk("R29 : %08Lx%08Lx R30 : %08Lx%08Lx R31 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[32]) >> 32; - al = (regs->regs[32]) & 0xffffffff; - bh = (regs->regs[33]) >> 32; - bl = (regs->regs[33]) & 0xffffffff; - ch = (regs->regs[34]) >> 32; - cl = (regs->regs[34]) & 0xffffffff; - printk("R32 : %08Lx%08Lx R33 : %08Lx%08Lx R34 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[35]) >> 32; - al = (regs->regs[35]) & 0xffffffff; - bh = (regs->regs[36]) >> 32; - bl = (regs->regs[36]) & 0xffffffff; - ch = (regs->regs[37]) >> 32; - cl = (regs->regs[37]) & 0xffffffff; - printk("R35 : %08Lx%08Lx R36 : %08Lx%08Lx R37 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[38]) >> 32; - al = (regs->regs[38]) & 0xffffffff; - bh = (regs->regs[39]) >> 32; - bl = (regs->regs[39]) & 0xffffffff; - ch = (regs->regs[40]) >> 32; - cl = (regs->regs[40]) & 0xffffffff; - printk("R38 : %08Lx%08Lx R39 : %08Lx%08Lx R40 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[41]) >> 32; - al = (regs->regs[41]) & 0xffffffff; - bh = (regs->regs[42]) >> 32; - bl = (regs->regs[42]) & 0xffffffff; - ch = (regs->regs[43]) >> 32; - cl = (regs->regs[43]) & 0xffffffff; - printk("R41 : %08Lx%08Lx R42 : %08Lx%08Lx R43 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[44]) >> 32; - al = (regs->regs[44]) & 0xffffffff; - bh = (regs->regs[45]) >> 32; - bl = (regs->regs[45]) & 0xffffffff; - ch = (regs->regs[46]) >> 32; - cl = (regs->regs[46]) & 0xffffffff; - printk("R44 : %08Lx%08Lx R45 : %08Lx%08Lx R46 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[47]) >> 32; - al = (regs->regs[47]) & 0xffffffff; - bh = (regs->regs[48]) >> 32; - bl = (regs->regs[48]) & 0xffffffff; - ch = (regs->regs[49]) >> 32; - cl = (regs->regs[49]) & 0xffffffff; - printk("R47 : %08Lx%08Lx R48 : %08Lx%08Lx R49 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[50]) >> 32; - al = (regs->regs[50]) & 0xffffffff; - bh = (regs->regs[51]) >> 32; - bl = (regs->regs[51]) & 0xffffffff; - ch = (regs->regs[52]) >> 32; - cl = (regs->regs[52]) & 0xffffffff; - printk("R50 : %08Lx%08Lx R51 : %08Lx%08Lx R52 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[53]) >> 32; - al = (regs->regs[53]) & 0xffffffff; - bh = (regs->regs[54]) >> 32; - bl = (regs->regs[54]) & 0xffffffff; - ch = (regs->regs[55]) >> 32; - cl = (regs->regs[55]) & 0xffffffff; - printk("R53 : %08Lx%08Lx R54 : %08Lx%08Lx R55 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[56]) >> 32; - al = (regs->regs[56]) & 0xffffffff; - bh = (regs->regs[57]) >> 32; - bl = (regs->regs[57]) & 0xffffffff; - ch = (regs->regs[58]) >> 32; - cl = (regs->regs[58]) & 0xffffffff; - printk("R56 : %08Lx%08Lx R57 : %08Lx%08Lx R58 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[59]) >> 32; - al = (regs->regs[59]) & 0xffffffff; - bh = (regs->regs[60]) >> 32; - bl = (regs->regs[60]) & 0xffffffff; - ch = (regs->regs[61]) >> 32; - cl = (regs->regs[61]) & 0xffffffff; - printk("R59 : %08Lx%08Lx R60 : %08Lx%08Lx R61 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[62]) >> 32; - al = (regs->regs[62]) & 0xffffffff; - bh = (regs->tregs[0]) >> 32; - bl = (regs->tregs[0]) & 0xffffffff; - ch = (regs->tregs[1]) >> 32; - cl = (regs->tregs[1]) & 0xffffffff; - printk("R62 : %08Lx%08Lx T0 : %08Lx%08Lx T1 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->tregs[2]) >> 32; - al = (regs->tregs[2]) & 0xffffffff; - bh = (regs->tregs[3]) >> 32; - bl = (regs->tregs[3]) & 0xffffffff; - ch = (regs->tregs[4]) >> 32; - cl = (regs->tregs[4]) & 0xffffffff; - printk("T2 : %08Lx%08Lx T3 : %08Lx%08Lx T4 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->tregs[5]) >> 32; - al = (regs->tregs[5]) & 0xffffffff; - bh = (regs->tregs[6]) >> 32; - bl = (regs->tregs[6]) & 0xffffffff; - ch = (regs->tregs[7]) >> 32; - cl = (regs->tregs[7]) & 0xffffffff; - printk("T5 : %08Lx%08Lx T6 : %08Lx%08Lx T7 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - /* - * If we're in kernel mode, dump the stack too.. - */ - if (!user_mode(regs)) { - void show_stack(struct task_struct *tsk, unsigned long *sp); - unsigned long sp = regs->regs[15] & 0xffffffff; - struct task_struct *tsk = get_current(); - - tsk->thread.kregs = regs; - - show_stack(tsk, (unsigned long *)sp); - } -} - -struct task_struct * alloc_task_struct(void) -{ - /* Get task descriptor pages */ - return (struct task_struct *) - __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)); -} - -void free_task_struct(struct task_struct *p) -{ - free_pages((unsigned long) p, get_order(THREAD_SIZE)); -} - -/* - * Create a kernel thread - */ -ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) -{ - do_exit(fn(arg)); -} - -/* - * 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 freed until both the parent and the child have exited. - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - regs.regs[2] = (unsigned long)arg; - regs.regs[3] = (unsigned long)fn; - - regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = (1 << 30); - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, - ®s, 0, NULL, NULL); -} - -/* - * Free current thread data structures etc.. - */ -void exit_thread(void) -{ - /* See arch/sparc/kernel/process.c for the precedent for doing this -- RPC. - - The SH-5 FPU save/restore approach relies on last_task_used_math - pointing to a live task_struct. When another task tries to use the - FPU for the 1st time, the FPUDIS trap handling (see - arch/sh64/kernel/fpu.c) will save the existing FPU state to the - FP regs field within last_task_used_math before re-loading the new - task's FPU state (or initialising it if the FPU has been used - before). So if last_task_used_math is stale, and its page has already been - re-allocated for another use, the consequences are rather grim. Unless we - null it here, there is no other path through which it would get safely - nulled. */ - -#ifdef CONFIG_SH_FPU - if (last_task_used_math == current) { - last_task_used_math = NULL; - } -#endif -} - -void flush_thread(void) -{ - - /* Called by fs/exec.c (flush_old_exec) to remove traces of a - * previously running executable. */ -#ifdef CONFIG_SH_FPU - if (last_task_used_math == current) { - last_task_used_math = NULL; - } - /* Force FPU state to be reinitialised after exec */ - clear_used_math(); -#endif - - /* if we are a kernel thread, about to change to user thread, - * update kreg - */ - if(current->thread.kregs==&fake_swapper_regs) { - current->thread.kregs = - ((struct pt_regs *)(THREAD_SIZE + (unsigned long) current) - 1); - current->thread.uregs = current->thread.kregs; - } -} - -void release_thread(struct task_struct *dead_task) -{ - /* do nothing */ -} - -/* Fill in the fpu structure for a core dump.. */ -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -{ -#ifdef CONFIG_SH_FPU - int fpvalid; - struct task_struct *tsk = current; - - fpvalid = !!tsk_used_math(tsk); - if (fpvalid) { - if (current == last_task_used_math) { - grab_fpu(); - fpsave(&tsk->thread.fpu.hard); - release_fpu(); - last_task_used_math = 0; - regs->sr |= SR_FD; - } - - memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); - } - - return fpvalid; -#else - return 0; /* Task didn't use the fpu at all. */ -#endif -} - -asmlinkage void ret_from_fork(void); - -int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) -{ - struct pt_regs *childregs; - unsigned long long se; /* Sign extension */ - -#ifdef CONFIG_SH_FPU - if(last_task_used_math == current) { - grab_fpu(); - fpsave(¤t->thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } -#endif - /* Copy from sh version */ - childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; - - *childregs = *regs; - - if (user_mode(regs)) { - childregs->regs[15] = usp; - p->thread.uregs = childregs; - } else { - childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; - } - - childregs->regs[9] = 0; /* Set return value for child */ - childregs->sr |= SR_FD; /* Invalidate FPU flag */ - - p->thread.sp = (unsigned long) childregs; - p->thread.pc = (unsigned long) ret_from_fork; - - /* - * Sign extend the edited stack. - * Note that thread.pc and thread.pc will stay - * 32-bit wide and context switch must take care - * of NEFF sign extension. - */ - - se = childregs->regs[15]; - se = (se & NEFF_SIGN) ? (se | NEFF_MASK) : se; - childregs->regs[15] = se; - - return 0; -} - -asmlinkage int sys_fork(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); -} - -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - if (!newsp) - newsp = pregs->regs[15]; - return do_fork(clone_flags, newsp, pregs, 0, 0, 0); -} - -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(char *ufilename, char **uargv, - char **uenvp, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - int error; - char *filename; - - lock_kernel(); - filename = getname((char __user *)ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename, - (char __user * __user *)uargv, - (char __user * __user *)uenvp, - pregs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); -out: - unlock_kernel(); - return error; -} - -/* - * These bracket the sleeping functions.. - */ -extern void interruptible_sleep_on(wait_queue_head_t *q); - -#define mid_sched ((unsigned long) interruptible_sleep_on) - -static int in_sh64_switch_to(unsigned long pc) -{ - extern char __sh64_switch_to_end; - /* For a sleeping task, the PC is somewhere in the middle of the function, - so we don't have to worry about masking the LSB off */ - return (pc >= (unsigned long) sh64_switch_to) && - (pc < (unsigned long) &__sh64_switch_to_end); -} - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long schedule_fp; - unsigned long sh64_switch_to_fp; - unsigned long schedule_caller_pc; - unsigned long pc; - - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - /* - * The same comment as on the Alpha applies here, too ... - */ - pc = thread_saved_pc(p); - -#ifdef CONFIG_FRAME_POINTER - if (in_sh64_switch_to(pc)) { - sh64_switch_to_fp = (long) p->thread.sp; - /* r14 is saved at offset 4 in the sh64_switch_to frame */ - schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4); - - /* and the caller of 'schedule' is (currently!) saved at offset 24 - in the frame of schedule (from disasm) */ - schedule_caller_pc = *(unsigned long *) (long)(schedule_fp + 24); - return schedule_caller_pc; - } -#endif - return pc; -} - -/* Provide a /proc/asids file that lists out the - ASIDs currently associated with the processes. (If the DM.PC register is - examined through the debug link, this shows ASID + PC. To make use of this, - the PID->ASID relationship needs to be known. This is primarily for - debugging.) - */ - -#if defined(CONFIG_SH64_PROC_ASIDS) -static int -asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) -{ - int len=0; - struct task_struct *p; - read_lock(&tasklist_lock); - for_each_process(p) { - int pid = p->pid; - struct mm_struct *mm; - if (!pid) continue; - mm = p->mm; - if (mm) { - unsigned long asid, context; - context = mm->context; - asid = (context & 0xff); - len += sprintf(buf+len, "%5d : %02lx\n", pid, asid); - } else { - len += sprintf(buf+len, "%5d : (none)\n", pid); - } - } - read_unlock(&tasklist_lock); - *eof = 1; - return len; -} - -static int __init register_proc_asids(void) -{ - create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); - return 0; -} -__initcall(register_proc_asids); -#endif diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c deleted file mode 100644 index 8a2d339cf760..000000000000 --- a/arch/sh64/kernel/ptrace.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/ptrace.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - * Started from SH3/4 version: - * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka - * - * Original x86 implementation: - * By Ross Biro 1/23/92 - * edited by Linus Torvalds - * - */ - -#include <linux/kernel.h> -#include <linux/rwsem.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/signal.h> -#include <linux/syscalls.h> - -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/pgtable.h> -#include <asm/system.h> -#include <asm/processor.h> -#include <asm/mmu_context.h> - -/* This mask defines the bits of the SR which the user is not allowed to - change, which are everything except S, Q, M, PR, SZ, FR. */ -#define SR_MASK (0xffff8cfd) - -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -/* - * This routine will get a word from the user area in the process kernel stack. - */ -static inline int get_stack_long(struct task_struct *task, int offset) -{ - unsigned char *stack; - - stack = (unsigned char *)(task->thread.uregs); - stack += offset; - return (*((int *)stack)); -} - -static inline unsigned long -get_fpu_long(struct task_struct *task, unsigned long addr) -{ - unsigned long tmp; - struct pt_regs *regs; - regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; - - if (!tsk_used_math(task)) { - if (addr == offsetof(struct user_fpu_struct, fpscr)) { - tmp = FPSCR_INIT; - } else { - tmp = 0xffffffffUL; /* matches initial value in fpu.c */ - } - return tmp; - } - - if (last_task_used_math == task) { - grab_fpu(); - fpsave(&task->thread.fpu.hard); - release_fpu(); - last_task_used_math = 0; - regs->sr |= SR_FD; - } - - tmp = ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)]; - return tmp; -} - -/* - * This routine will put a word into the user area in the process kernel stack. - */ -static inline int put_stack_long(struct task_struct *task, int offset, - unsigned long data) -{ - unsigned char *stack; - - stack = (unsigned char *)(task->thread.uregs); - stack += offset; - *(unsigned long *) stack = data; - return 0; -} - -static inline int -put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) -{ - struct pt_regs *regs; - - regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; - - if (!tsk_used_math(task)) { - fpinit(&task->thread.fpu.hard); - set_stopped_child_used_math(task); - } else if (last_task_used_math == task) { - grab_fpu(); - fpsave(&task->thread.fpu.hard); - release_fpu(); - last_task_used_math = 0; - regs->sr |= SR_FD; - } - - ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)] = data; - return 0; -} - - -long arch_ptrace(struct task_struct *child, long request, long addr, long data) -{ - int ret; - - switch (request) { - /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - - /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - ret = -EIO; - if ((addr & 3) || addr < 0) - break; - - if (addr < sizeof(struct pt_regs)) - tmp = get_stack_long(child, addr); - else if ((addr >= offsetof(struct user, fpu)) && - (addr < offsetof(struct user, u_fpvalid))) { - tmp = get_fpu_long(child, addr - offsetof(struct user, fpu)); - } else if (addr == offsetof(struct user, u_fpvalid)) { - tmp = !!tsk_used_math(child); - } else { - break; - } - ret = put_user(tmp, (unsigned long *)data); - break; - } - - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - - case PTRACE_POKEUSR: - /* write the word at location addr in the USER area. We must - disallow any changes to certain SR bits or u_fpvalid, since - this could crash the kernel or result in a security - loophole. */ - ret = -EIO; - if ((addr & 3) || addr < 0) - break; - - if (addr < sizeof(struct pt_regs)) { - /* Ignore change of top 32 bits of SR */ - if (addr == offsetof (struct pt_regs, sr)+4) - { - ret = 0; - break; - } - /* If lower 32 bits of SR, ignore non-user bits */ - if (addr == offsetof (struct pt_regs, sr)) - { - long cursr = get_stack_long(child, addr); - data &= ~(SR_MASK); - data |= (cursr & SR_MASK); - } - ret = put_stack_long(child, addr, data); - } - else if ((addr >= offsetof(struct user, fpu)) && - (addr < offsetof(struct user, u_fpvalid))) { - ret = put_fpu_long(child, addr - offsetof(struct user, fpu), data); - } - break; - - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - ret = -EIO; - if (!valid_signal(data)) - break; - 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; - wake_up_process(child); - ret = 0; - break; - } - -/* - * 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: { - ret = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - break; - child->exit_code = SIGKILL; - wake_up_process(child); - break; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - struct pt_regs *regs; - - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - if ((child->ptrace & PT_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->ptrace |= PT_DTRACE; - } - - regs = child->thread.uregs; - - regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ - - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - break; - } - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - return ret; -} - -asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) -{ - extern void poke_real_address_q(unsigned long long addr, unsigned long long data); -#define WPC_DBRMODE 0x0d104008 - static int first_call = 1; - - lock_kernel(); - if (first_call) { - /* Set WPC.DBRMODE to 0. This makes all debug events get - * delivered through RESVEC, i.e. into the handlers in entry.S. - * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE - * would normally be left set to 1, which makes debug events get - * delivered through DBRVEC, i.e. into the remote gdb's - * handlers. This prevents ptrace getting them, and confuses - * the remote gdb.) */ - printk("DBRMODE set to 0 to permit native debugging\n"); - poke_real_address_q(WPC_DBRMODE, 0); - first_call = 0; - } - unlock_kernel(); - - return sys_ptrace(request, pid, addr, data); -} - -asmlinkage void syscall_trace(void) -{ - struct task_struct *tsk = current; - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - if (!(tsk->ptrace & PT_PTRACED)) - return; - - 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 (tsk->exit_code) { - send_sig(tsk->exit_code, tsk, 1); - tsk->exit_code = 0; - } -} - -/* Called with interrupts disabled */ -asmlinkage void do_single_step(unsigned long long vec, struct pt_regs *regs) -{ - /* This is called after a single step exception (DEBUGSS). - There is no need to change the PC, as it is a post-execution - exception, as entry.S does not do anything to the PC for DEBUGSS. - We need to clear the Single Step setting in SR to avoid - continually stepping. */ - local_irq_enable(); - regs->sr &= ~SR_SSTEP; - force_sig(SIGTRAP, current); -} - -/* Called with interrupts disabled */ -asmlinkage void do_software_break_point(unsigned long long vec, - struct pt_regs *regs) -{ - /* We need to forward step the PC, to counteract the backstep done - in signal.c. */ - local_irq_enable(); - force_sig(SIGTRAP, current); - regs->pc += 4; -} - -/* - * 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.. */ -} diff --git a/arch/sh64/kernel/semaphore.c b/arch/sh64/kernel/semaphore.c deleted file mode 100644 index 72c16533436e..000000000000 --- a/arch/sh64/kernel/semaphore.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Just taken from alpha implementation. - * This can't work well, perhaps. - */ -/* - * Generic semaphore code. Buyer beware. Do your own - * specific changes in <asm/semaphore-helper.h> - */ - -#include <linux/errno.h> -#include <linux/rwsem.h> -#include <linux/sched.h> -#include <linux/wait.h> -#include <linux/init.h> -#include <asm/semaphore.h> -#include <asm/semaphore-helper.h> - -spinlock_t semaphore_wake_lock; - -/* - * Semaphores are implemented using a two-way counter: - * The "count" variable is decremented for each process - * that tries to sleep, while the "waking" variable is - * incremented when the "up()" code goes to wake up waiting - * processes. - * - * Notably, the inline "up()" and "down()" functions can - * efficiently test if they need to do any extra work (up - * needs to do something only if count was negative before - * the increment operation. - * - * waking_non_zero() (from asm/semaphore.h) must execute - * atomically. - * - * When __up() is called, the count was negative before - * incrementing it, and we need to wake up somebody. - * - * This routine adds one to the count of processes that need to - * wake up and exit. ALL waiting processes actually wake up but - * only the one that gets to the "waking" field first will gate - * through and acquire the semaphore. The others will go back - * to sleep. - * - * Note that these functions are only called when there is - * contention on the lock, and as such all this is the - * "non-critical" part of the whole semaphore business. The - * critical part is the inline stuff in <asm/semaphore.h> - * where we want to avoid any extra jumps and calls. - */ -void __up(struct semaphore *sem) -{ - wake_one_more(sem); - wake_up(&sem->wait); -} - -/* - * Perform the "down" function. Return zero for semaphore acquired, - * return negative for signalled out of the function. - * - * If called from __down, the return is ignored and the wait loop is - * not interruptible. This means that a task waiting on a semaphore - * using "down()" cannot be killed until someone does an "up()" on - * the semaphore. - * - * If called from __down_interruptible, the return value gets checked - * upon return. If the return value is negative then the task continues - * with the negative value in the return register (it can be tested by - * the caller). - * - * Either form may be used in conjunction with "up()". - * - */ - -#define DOWN_VAR \ - struct task_struct *tsk = current; \ - wait_queue_t wait; \ - init_waitqueue_entry(&wait, tsk); - -#define DOWN_HEAD(task_state) \ - \ - \ - tsk->state = (task_state); \ - add_wait_queue(&sem->wait, &wait); \ - \ - /* \ - * Ok, we're set up. sem->count is known to be less than zero \ - * so we must wait. \ - * \ - * We can let go the lock for purposes of waiting. \ - * We re-acquire it after awaking so as to protect \ - * all semaphore operations. \ - * \ - * If "up()" is called before we call waking_non_zero() then \ - * we will catch it right away. If it is called later then \ - * we will have to go through a wakeup cycle to catch it. \ - * \ - * Multiple waiters contend for the semaphore lock to see \ - * who gets to gate through and who has to wait some more. \ - */ \ - for (;;) { - -#define DOWN_TAIL(task_state) \ - tsk->state = (task_state); \ - } \ - tsk->state = TASK_RUNNING; \ - remove_wait_queue(&sem->wait, &wait); - -void __sched __down(struct semaphore * sem) -{ - DOWN_VAR - DOWN_HEAD(TASK_UNINTERRUPTIBLE) - if (waking_non_zero(sem)) - break; - schedule(); - DOWN_TAIL(TASK_UNINTERRUPTIBLE) -} - -int __sched __down_interruptible(struct semaphore * sem) -{ - int ret = 0; - DOWN_VAR - DOWN_HEAD(TASK_INTERRUPTIBLE) - - ret = waking_non_zero_interruptible(sem, tsk); - if (ret) - { - if (ret == 1) - /* ret != 0 only if we get interrupted -arca */ - ret = 0; - break; - } - schedule(); - DOWN_TAIL(TASK_INTERRUPTIBLE) - return ret; -} - -int __down_trylock(struct semaphore * sem) -{ - return waking_non_zero_trylock(sem); -} diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c deleted file mode 100644 index 2b7264c0c6f7..000000000000 --- a/arch/sh64/kernel/setup.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/setup.c - * - * sh64 Arch Support - * - * This file handles the architecture-dependent parts of initialization - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * benedict.gaster@superh.com: 2nd May 2002 - * Modified to use the empty_zero_page to pass command line arguments. - * - * benedict.gaster@superh.com: 3rd May 2002 - * Added support for ramdisk, removing statically linked romfs at the same time. - * - * lethal@linux-sh.org: 15th May 2003 - * Added generic procfs cpuinfo reporting. Make boards just export their name. - * - * lethal@linux-sh.org: 25th May 2003 - * Added generic get_cpu_subtype() for subtype reporting from cpu_data->type. - * - */ -#include <linux/errno.h> -#include <linux/rwsem.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 <linux/user.h> -#include <linux/a.out.h> -#include <linux/screen_info.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/seq_file.h> -#include <linux/blkdev.h> -#include <linux/bootmem.h> -#include <linux/console.h> -#include <linux/root_dev.h> -#include <linux/cpu.h> -#include <linux/initrd.h> -#include <linux/pfn.h> -#include <asm/processor.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/platform.h> -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/sections.h> -#include <asm/setup.h> -#include <asm/smp.h> - -struct screen_info screen_info; - -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ -#endif - -extern int root_mountflags; -extern char *get_system_type(void); -extern void platform_setup(void); -extern void platform_monitor(void); -extern void platform_reserve(void); -extern int sh64_cache_init(void); -extern int sh64_tlb_init(void); - -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 - -static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, }; -unsigned long long memory_start = CONFIG_MEMORY_START; -unsigned long long memory_end = CONFIG_MEMORY_START + (CONFIG_MEMORY_SIZE_IN_MB * 1024 * 1024); - -struct sh_cpuinfo boot_cpu_data; - -static inline void parse_mem_cmdline (char ** cmdline_p) -{ - char c = ' ', *to = command_line, *from = COMMAND_LINE; - int len = 0; - - /* Save unparsed command line copy for /proc/cmdline */ - memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); - boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; - - for (;;) { - /* - * "mem=XXX[kKmM]" defines a size of memory. - */ - if (c == ' ' && !memcmp(from, "mem=", 4)) { - if (to != command_line) - to--; - { - unsigned long mem_size; - - mem_size = memparse(from+4, &from); - memory_end = memory_start + mem_size; - } - } - c = *(from++); - if (!c) - break; - if (COMMAND_LINE_SIZE <= ++len) - break; - *(to++) = c; - } - *to = '\0'; - - *cmdline_p = command_line; -} - -static void __init sh64_cpu_type_detect(void) -{ - extern unsigned long long peek_real_address_q(unsigned long long addr); - unsigned long long cir; - /* Do peeks in real mode to avoid having to set up a mapping for the - WPC registers. On SH5-101 cut2, such a mapping would be exposed to - an address translation erratum which would make it hard to set up - correctly. */ - cir = peek_real_address_q(0x0d000008); - - if ((cir & 0xffff) == 0x5103) { - boot_cpu_data.type = CPU_SH5_103; - } else if (((cir >> 32) & 0xffff) == 0x51e2) { - /* CPU.VCR aliased at CIR address on SH5-101 */ - boot_cpu_data.type = CPU_SH5_101; - } else { - boot_cpu_data.type = CPU_SH_NONE; - } -} - -void __init setup_arch(char **cmdline_p) -{ - unsigned long bootmap_size, i; - unsigned long first_pfn, start_pfn, last_pfn, pages; - -#ifdef CONFIG_EARLY_PRINTK - extern void enable_early_printk(void); - - /* - * Setup Early SCIF console - */ - enable_early_printk(); -#endif - - /* - * Setup TLB mappings - */ - sh64_tlb_init(); - - /* - * Caches are already initialized by the time we get here, so we just - * fill in cpu_data info for the caches. - */ - sh64_cache_init(); - - platform_setup(); - platform_monitor(); - - sh64_cpu_type_detect(); - - ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); - -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif - - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; - init_mm.start_code = (unsigned long) _text; - init_mm.end_code = (unsigned long) _etext; - init_mm.end_data = (unsigned long) _edata; - init_mm.brk = (unsigned long) _end; - - code_resource.start = __pa(_text); - code_resource.end = __pa(_etext)-1; - data_resource.start = __pa(_etext); - data_resource.end = __pa(_edata)-1; - - parse_mem_cmdline(cmdline_p); - - /* - * Find the lowest and highest page frame numbers we have available - */ - first_pfn = PFN_DOWN(memory_start); - last_pfn = PFN_DOWN(memory_end); - pages = last_pfn - first_pfn; - - /* - * Partially used pages are not usable - thus - * we are rounding upwards: - */ - start_pfn = PFN_UP(__pa(_end)); - - /* - * Find a proper area for the bootmem bitmap. After this - * bootstrap step all allocations (until the page allocator - * is intact) must be done via bootmem_alloc(). - */ - bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, - first_pfn, - last_pfn); - /* - * Round it up. - */ - bootmap_size = PFN_PHYS(PFN_UP(bootmap_size)); - - /* - * Register fully available RAM pages with the bootmem allocator. - */ - free_bootmem_node(NODE_DATA(0), PFN_PHYS(first_pfn), PFN_PHYS(pages)); - - /* - * Reserve all kernel sections + bootmem bitmap + a guard page. - */ - reserve_bootmem_node(NODE_DATA(0), PFN_PHYS(first_pfn), - (PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE) - PFN_PHYS(first_pfn)); - - /* - * Reserve platform dependent sections - */ - platform_reserve(); - -#ifdef CONFIG_BLK_DEV_INITRD - if (LOADER_TYPE && INITRD_START) { - if (INITRD_START + INITRD_SIZE <= (PFN_PHYS(last_pfn))) { - reserve_bootmem_node(NODE_DATA(0), INITRD_START + __MEMORY_START, INITRD_SIZE); - - initrd_start = (long) INITRD_START + PAGE_OFFSET + __MEMORY_START; - initrd_end = initrd_start + INITRD_SIZE; - } else { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - (long) INITRD_START + INITRD_SIZE, - PFN_PHYS(last_pfn)); - initrd_start = 0; - } - } -#endif - - /* - * Claim all RAM, ROM, and I/O resources. - */ - - /* Kernel RAM */ - request_resource(&iomem_resource, &code_resource); - request_resource(&iomem_resource, &data_resource); - - /* Other KRAM space */ - for (i = 0; i < STANDARD_KRAM_RESOURCES - 2; i++) - request_resource(&iomem_resource, - &platform_parms.kram_res_p[i]); - - /* XRAM space */ - for (i = 0; i < STANDARD_XRAM_RESOURCES; i++) - request_resource(&iomem_resource, - &platform_parms.xram_res_p[i]); - - /* ROM space */ - for (i = 0; i < STANDARD_ROM_RESOURCES; i++) - request_resource(&iomem_resource, - &platform_parms.rom_res_p[i]); - - /* I/O space */ - for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, - &platform_parms.io_res_p[i]); - - -#ifdef CONFIG_VT -#if defined(CONFIG_VGA_CONSOLE) - conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; -#endif -#endif - - printk("Hardware FPU: %s\n", fpu_in_use ? "enabled" : "disabled"); - - paging_init(); -} - -void __xchg_called_with_bad_pointer(void) -{ - printk(KERN_EMERG "xchg() called with bad pointer !\n"); -} - -static struct cpu cpu[1]; - -static int __init topology_init(void) -{ - return register_cpu(cpu, 0); -} - -subsys_initcall(topology_init); - -/* - * Get CPU information - */ -static const char *cpu_name[] = { - [CPU_SH5_101] = "SH5-101", - [CPU_SH5_103] = "SH5-103", - [CPU_SH_NONE] = "Unknown", -}; - -const char *get_cpu_subtype(void) -{ - return cpu_name[boot_cpu_data.type]; -} - -#ifdef CONFIG_PROC_FS -static int show_cpuinfo(struct seq_file *m,void *v) -{ - unsigned int cpu = smp_processor_id(); - - if (!cpu) - seq_printf(m, "machine\t\t: %s\n", get_system_type()); - - seq_printf(m, "processor\t: %d\n", cpu); - seq_printf(m, "cpu family\t: SH-5\n"); - seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype()); - - seq_printf(m, "icache size\t: %dK-bytes\n", - (boot_cpu_data.icache.ways * - boot_cpu_data.icache.sets * - boot_cpu_data.icache.linesz) >> 10); - seq_printf(m, "dcache size\t: %dK-bytes\n", - (boot_cpu_data.dcache.ways * - boot_cpu_data.dcache.sets * - boot_cpu_data.dcache.linesz) >> 10); - seq_printf(m, "itlb entries\t: %d\n", boot_cpu_data.itlb.entries); - seq_printf(m, "dtlb entries\t: %d\n", boot_cpu_data.dtlb.entries); - -#define PRINT_CLOCK(name, value) \ - seq_printf(m, name " clock\t: %d.%02dMHz\n", \ - ((value) / 1000000), ((value) % 1000000)/10000) - - PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock); - PRINT_CLOCK("bus", boot_cpu_data.bus_clock); - PRINT_CLOCK("module", boot_cpu_data.module_clock); - - seq_printf(m, "bogomips\t: %lu.%02lu\n\n", - (loops_per_jiffy*HZ+2500)/500000, - ((loops_per_jiffy*HZ+2500)/5000) % 100); - - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - return (void*)(*pos == 0); -} -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - return NULL; -} -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, -}; -#endif /* CONFIG_PROC_FS */ diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c deleted file mode 100644 index b1705acc8e64..000000000000 --- a/arch/sh64/kernel/sh_ksyms.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/sh_ksyms.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include <linux/rwsem.h> -#include <linux/module.h> -#include <linux/smp.h> -#include <linux/user.h> -#include <linux/elfcore.h> -#include <linux/sched.h> -#include <linux/in6.h> -#include <linux/interrupt.h> -#include <linux/screen_info.h> - -#include <asm/semaphore.h> -#include <asm/processor.h> -#include <asm/uaccess.h> -#include <asm/checksum.h> -#include <asm/io.h> -#include <asm/delay.h> -#include <asm/irq.h> - -extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); - -/* platform dependent support */ -EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(kernel_thread); - -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy_nocheck); - -#ifdef CONFIG_VT -EXPORT_SYMBOL(screen_info); -#endif - -EXPORT_SYMBOL(__down); -EXPORT_SYMBOL(__down_trylock); -EXPORT_SYMBOL(__up); -EXPORT_SYMBOL(__put_user_asm_l); -EXPORT_SYMBOL(__get_user_asm_l); -EXPORT_SYMBOL(__copy_user); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(udelay); -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(ndelay); -EXPORT_SYMBOL(__ndelay); -EXPORT_SYMBOL(flush_dcache_page); -EXPORT_SYMBOL(sh64_page_clear); - -/* Ugh. These come in from libgcc.a at link time. */ -#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) - -DECLARE_EXPORT(__sdivsi3); -DECLARE_EXPORT(__muldi3); -DECLARE_EXPORT(__udivsi3); diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c deleted file mode 100644 index 79fc48cf54c6..000000000000 --- a/arch/sh64/kernel/signal.c +++ /dev/null @@ -1,750 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/signal.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - * Started from sh version. - * - */ -#include <linux/rwsem.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/errno.h> -#include <linux/wait.h> -#include <linux/personality.h> -#include <linux/freezer.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/stddef.h> -#include <asm/ucontext.h> -#include <asm/uaccess.h> -#include <asm/pgtable.h> - - -#define REG_RET 9 -#define REG_ARG1 2 -#define REG_ARG2 3 -#define REG_ARG3 4 -#define REG_SP 15 -#define REG_PR 18 -#define REF_REG_RET regs->regs[REG_RET] -#define REF_REG_SP regs->regs[REG_SP] -#define DEREF_REG_PR regs->regs[REG_PR] - -#define DEBUG_SIG 0 - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ - -asmlinkage int -sys_sigsuspend(old_sigset_t mask, - unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs * regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - REF_REG_RET = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - regs->pc += 4; /* because sys_sigreturn decrements the pc */ - if (do_signal(regs, &saveset)) { - /* pc now points at signal handler. Need to decrement - it because entry.S will increment it. */ - regs->pc -= 4; - return -EINTR; - } - } -} - -asmlinkage int -sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, - unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, - struct pt_regs * regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - REF_REG_RET = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - regs->pc += 4; /* because sys_sigreturn decrements the pc */ - if (do_signal(regs, &saveset)) { - /* pc now points at signal handler. Need to decrement - it because entry.S will increment it. */ - regs->pc -= 4; - return -EINTR; - } - } -} - -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -asmlinkage int -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, - struct pt_regs * regs) -{ - return do_sigaltstack(uss, uoss, REF_REG_SP); -} - - -/* - * Do a signal return; undo the signal stack. - */ - -struct sigframe -{ - struct sigcontext sc; - unsigned long extramask[_NSIG_WORDS-1]; - long long retcode[2]; -}; - -struct rt_sigframe -{ - struct siginfo __user *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; - long long retcode[2]; -}; - -#ifdef CONFIG_SH_FPU -static inline int -restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{ - int err = 0; - int fpvalid; - - err |= __get_user (fpvalid, &sc->sc_fpvalid); - conditional_used_math(fpvalid); - if (! fpvalid) - return err; - - if (current == last_task_used_math) { - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - err |= __copy_from_user(¤t->thread.fpu.hard, &sc->sc_fpregs[0], - (sizeof(long long) * 32) + (sizeof(int) * 1)); - - return err; -} - -static inline int -setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{ - int err = 0; - int fpvalid; - - fpvalid = !!used_math(); - err |= __put_user(fpvalid, &sc->sc_fpvalid); - if (! fpvalid) - return err; - - if (current == last_task_used_math) { - grab_fpu(); - fpsave(¤t->thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - err |= __copy_to_user(&sc->sc_fpregs[0], ¤t->thread.fpu.hard, - (sizeof(long long) * 32) + (sizeof(int) * 1)); - clear_used_math(); - - return err; -} -#else -static inline int -restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{} -static inline int -setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{} -#endif - -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p) -{ - unsigned int err = 0; - unsigned long long current_sr, new_sr; -#define SR_MASK 0xffff8cfd - -#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) - - COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]); - COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]); - COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); - COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]); - COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]); - COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]); - COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]); - COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]); - COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]); - COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]); - COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]); - COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]); - COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]); - COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]); - COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]); - COPY(regs[60]); COPY(regs[61]); COPY(regs[62]); - COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]); - COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]); - - /* Prevent the signal handler manipulating SR in a way that can - crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be - modified */ - current_sr = regs->sr; - err |= __get_user(new_sr, &sc->sc_sr); - regs->sr &= SR_MASK; - regs->sr |= (new_sr & ~SR_MASK); - - COPY(pc); - -#undef COPY - - /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr - * has been restored above.) */ - err |= restore_sigcontext_fpu(regs, sc); - - regs->syscall_nr = -1; /* disable syscall checks */ - err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]); - return err; -} - -asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs * regs) -{ - struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP; - sigset_t set; - long long ret; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __copy_from_user(&set.sig[1], &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(regs, &frame->sc, &ret)) - goto badframe; - regs->pc -= 4; - - return (int) ret; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs * regs) -{ - struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP; - sigset_t set; - stack_t __user st; - long long ret; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret)) - goto badframe; - regs->pc -= 4; - - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) - goto badframe; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - do_sigaltstack(&st, NULL, REF_REG_SP); - - return (int) ret; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -/* - * Set up a signal frame. - */ - -static int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - unsigned long mask) -{ - int err = 0; - - /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */ - err |= setup_sigcontext_fpu(regs, sc); - -#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) - - COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]); - COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]); - COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); - COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]); - COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]); - COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]); - COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]); - COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]); - COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]); - COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]); - COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]); - COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]); - COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]); - COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]); - COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]); - COPY(regs[60]); COPY(regs[61]); COPY(regs[62]); - COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]); - COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]); - COPY(sr); COPY(pc); - -#undef COPY - - err |= __put_user(mask, &sc->oldmask); - - return err; -} - -/* - * Determine which stack to use.. - */ -static inline void __user * -get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) -{ - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) - sp = current->sas_ss_sp + current->sas_ss_size; - - return (void __user *)((sp - frame_size) & -8ul); -} - -void sa_default_restorer(void); /* See comments below */ -void sa_default_rt_restorer(void); /* See comments below */ - -static void setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - struct sigframe __user *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); } - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; - - /* - * On SH5 all edited pointers are subject to NEFF - */ - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - } else { - /* - * Different approach on SH5. - * . Endianness independent asm code gets placed in entry.S . - * This is limited to four ASM instructions corresponding - * to two long longs in size. - * . err checking is done on the else branch only - * . flush_icache_range() is called upon __put_user() only - * . all edited pointers are subject to NEFF - * . being code, linker turns ShMedia bit on, always - * dereference index -1. - */ - DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - - if (__copy_to_user(frame->retcode, - (unsigned long long)sa_default_restorer & (~1), 16) != 0) - goto give_sigsegv; - - /* Cohere the trampoline with the I-cache. */ - flush_cache_sigtramp(DEREF_REG_PR-1, DEREF_REG_PR-1+16); - } - - /* - * Set up registers for signal handler. - * All edited pointers are subject to NEFF. - */ - regs->regs[REG_SP] = (unsigned long) frame; - regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? - (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; - regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ - - /* FIXME: - The glibc profiling support for SH-5 needs to be passed a sigcontext - so it can retrieve the PC. At some point during 2003 the glibc - support was changed to receive the sigcontext through the 2nd - argument, but there are still versions of libc.so in use that use - the 3rd argument. Until libc.so is stabilised, pass the sigcontext - through both 2nd and 3rd arguments. - */ - - regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; - regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; - - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; - - set_fs(USER_DS); - -#if DEBUG_SIG - /* Broken %016Lx */ - printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", - signal, - current->comm, current->pid, frame, - regs->pc >> 32, regs->pc & 0xffffffff, - DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); -#endif - - return; - -give_sigsegv: - force_sigsegv(sig, current); -} - -static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, info); - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user((void *)current->sas_ss_sp, - &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->regs[REG_SP]), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, - regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; - - /* - * On SH5 all edited pointers are subject to NEFF - */ - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - } else { - /* - * Different approach on SH5. - * . Endianness independent asm code gets placed in entry.S . - * This is limited to four ASM instructions corresponding - * to two long longs in size. - * . err checking is done on the else branch only - * . flush_icache_range() is called upon __put_user() only - * . all edited pointers are subject to NEFF - * . being code, linker turns ShMedia bit on, always - * dereference index -1. - */ - - DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - - if (__copy_to_user(frame->retcode, - (unsigned long long)sa_default_rt_restorer & (~1), 16) != 0) - goto give_sigsegv; - - flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); - } - - /* - * Set up registers for signal handler. - * All edited pointers are subject to NEFF. - */ - regs->regs[REG_SP] = (unsigned long) frame; - regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? - (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; - regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ - regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; - regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; - - set_fs(USER_DS); - -#if DEBUG_SIG - /* Broken %016Lx */ - printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", - signal, - current->comm, current->pid, frame, - regs->pc >> 32, regs->pc & 0xffffffff, - DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); -#endif - - return; - -give_sigsegv: - force_sigsegv(sig, current); -} - -/* - * OK, we're invoking a handler - */ - -static void -handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - sigset_t *oldset, struct pt_regs * regs) -{ - /* Are we from a system call? */ - if (regs->syscall_nr >= 0) { - /* If so, check system call restarting.. */ - switch (regs->regs[REG_RET]) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - regs->regs[REG_RET] = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->regs[REG_RET] = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - /* Decode syscall # */ - regs->regs[REG_RET] = regs->syscall_nr; - regs->pc -= 4; - } - } - - /* Set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(sig, ka, info, oldset, regs); - else - setup_frame(sig, ka, oldset, regs); - - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); -} - -/* - * 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. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) -{ - siginfo_t info; - int signr; - struct k_sigaction ka; - - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return 1; - - if (try_to_freeze()) - goto no_signal; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else if (!oldset) - oldset = ¤t->blocked; - - signr = get_signal_to_deliver(&info, &ka, regs, 0); - - if (signr > 0) { - /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, oldset, regs); - - /* - * If a signal was successfully delivered, the saved sigmask - * is in its frame, and we can clear the TIF_RESTORE_SIGMASK - * flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - return 1; - } - -no_signal: - /* Did we come from a system call? */ - if (regs->syscall_nr >= 0) { - /* Restart the system call - no handlers present */ - switch (regs->regs[REG_RET]) { - case -ERESTARTNOHAND: - case -ERESTARTSYS: - case -ERESTARTNOINTR: - /* Decode Syscall # */ - regs->regs[REG_RET] = regs->syscall_nr; - regs->pc -= 4; - break; - - case -ERESTART_RESTARTBLOCK: - regs->regs[REG_RET] = __NR_restart_syscall; - regs->pc -= 4; - break; - } - } - - /* No signal to deliver -- 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); - } - - return 0; -} diff --git a/arch/sh64/kernel/switchto.S b/arch/sh64/kernel/switchto.S deleted file mode 100644 index 45b2d90eed7d..000000000000 --- a/arch/sh64/kernel/switchto.S +++ /dev/null @@ -1,198 +0,0 @@ -/* - * arch/sh64/kernel/switchto.S - * - * sh64 context switch - * - * Copyright (C) 2004 Richard Curnow - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. -*/ - - .section .text..SHmedia32,"ax" - .little - - .balign 32 - - .type sh64_switch_to,@function - .global sh64_switch_to - .global __sh64_switch_to_end -sh64_switch_to: - -/* Incoming args - r2 - prev - r3 - &prev->thread - r4 - next - r5 - &next->thread - - Outgoing results - r2 - last (=prev) : this just stays in r2 throughout - - Want to create a full (struct pt_regs) on the stack to allow backtracing - functions to work. However, we only need to populate the callee-save - register slots in this structure; since we're a function our ancestors must - have themselves preserved all caller saved state in the stack. This saves - some wasted effort since we won't need to look at the values. - - In particular, all caller-save registers are immediately available for - scratch use. - -*/ - -#define FRAME_SIZE (76*8 + 8) - - movi FRAME_SIZE, r0 - sub.l r15, r0, r15 - ! Do normal-style register save to support backtrace - - st.l r15, 0, r18 ! save link reg - st.l r15, 4, r14 ! save fp - add.l r15, r63, r14 ! setup frame pointer - - ! hopefully this looks normal to the backtrace now. - - addi.l r15, 8, r1 ! base of pt_regs - addi.l r1, 24, r0 ! base of pt_regs.regs - addi.l r0, (63*8), r8 ! base of pt_regs.trregs - - /* Note : to be fixed? - struct pt_regs is really designed for holding the state on entry - to an exception, i.e. pc,sr,regs etc. However, for the context - switch state, some of this is not required. But the unwinder takes - struct pt_regs * as an arg so we have to build this structure - to allow unwinding switched tasks in show_state() */ - - st.q r0, ( 9*8), r9 - st.q r0, (10*8), r10 - st.q r0, (11*8), r11 - st.q r0, (12*8), r12 - st.q r0, (13*8), r13 - st.q r0, (14*8), r14 ! for unwind, want to look as though we took a trap at - ! the point where the process is left in suspended animation, i.e. current - ! fp here, not the saved one. - st.q r0, (16*8), r16 - - st.q r0, (24*8), r24 - st.q r0, (25*8), r25 - st.q r0, (26*8), r26 - st.q r0, (27*8), r27 - st.q r0, (28*8), r28 - st.q r0, (29*8), r29 - st.q r0, (30*8), r30 - st.q r0, (31*8), r31 - st.q r0, (32*8), r32 - st.q r0, (33*8), r33 - st.q r0, (34*8), r34 - st.q r0, (35*8), r35 - - st.q r0, (44*8), r44 - st.q r0, (45*8), r45 - st.q r0, (46*8), r46 - st.q r0, (47*8), r47 - st.q r0, (48*8), r48 - st.q r0, (49*8), r49 - st.q r0, (50*8), r50 - st.q r0, (51*8), r51 - st.q r0, (52*8), r52 - st.q r0, (53*8), r53 - st.q r0, (54*8), r54 - st.q r0, (55*8), r55 - st.q r0, (56*8), r56 - st.q r0, (57*8), r57 - st.q r0, (58*8), r58 - st.q r0, (59*8), r59 - - ! do this early as pta->gettr has no pipeline forwarding (=> 5 cycle latency) - ! Use a local label to avoid creating a symbol that will confuse the ! - ! backtrace - pta .Lsave_pc, tr0 - - gettr tr5, r45 - gettr tr6, r46 - gettr tr7, r47 - st.q r8, (5*8), r45 - st.q r8, (6*8), r46 - st.q r8, (7*8), r47 - - ! Now switch context - gettr tr0, r9 - st.l r3, 0, r15 ! prev->thread.sp - st.l r3, 8, r1 ! prev->thread.kregs - st.l r3, 4, r9 ! prev->thread.pc - st.q r1, 0, r9 ! save prev->thread.pc into pt_regs->pc - - ! Load PC for next task (init value or save_pc later) - ld.l r5, 4, r18 ! next->thread.pc - ! Switch stacks - ld.l r5, 0, r15 ! next->thread.sp - ptabs r18, tr0 - - ! Update current - ld.l r4, 4, r9 ! next->thread_info (2nd element of next task_struct) - putcon r9, kcr0 ! current = next->thread_info - - ! go to save_pc for a reschedule, or the initial thread.pc for a new process - blink tr0, r63 - - ! Restore (when we come back to a previously saved task) -.Lsave_pc: - addi.l r15, 32, r0 ! r0 = next's regs - addi.l r0, (63*8), r8 ! r8 = next's tr_regs - - ld.q r8, (5*8), r45 - ld.q r8, (6*8), r46 - ld.q r8, (7*8), r47 - ptabs r45, tr5 - ptabs r46, tr6 - ptabs r47, tr7 - - ld.q r0, ( 9*8), r9 - ld.q r0, (10*8), r10 - ld.q r0, (11*8), r11 - ld.q r0, (12*8), r12 - ld.q r0, (13*8), r13 - ld.q r0, (14*8), r14 - ld.q r0, (16*8), r16 - - ld.q r0, (24*8), r24 - ld.q r0, (25*8), r25 - ld.q r0, (26*8), r26 - ld.q r0, (27*8), r27 - ld.q r0, (28*8), r28 - ld.q r0, (29*8), r29 - ld.q r0, (30*8), r30 - ld.q r0, (31*8), r31 - ld.q r0, (32*8), r32 - ld.q r0, (33*8), r33 - ld.q r0, (34*8), r34 - ld.q r0, (35*8), r35 - - ld.q r0, (44*8), r44 - ld.q r0, (45*8), r45 - ld.q r0, (46*8), r46 - ld.q r0, (47*8), r47 - ld.q r0, (48*8), r48 - ld.q r0, (49*8), r49 - ld.q r0, (50*8), r50 - ld.q r0, (51*8), r51 - ld.q r0, (52*8), r52 - ld.q r0, (53*8), r53 - ld.q r0, (54*8), r54 - ld.q r0, (55*8), r55 - ld.q r0, (56*8), r56 - ld.q r0, (57*8), r57 - ld.q r0, (58*8), r58 - ld.q r0, (59*8), r59 - - ! epilogue - ld.l r15, 0, r18 - ld.l r15, 4, r14 - ptabs r18, tr0 - movi FRAME_SIZE, r0 - add r15, r0, r15 - blink tr0, r63 -__sh64_switch_to_end: -.LFE1: - .size sh64_switch_to,.LFE1-sh64_switch_to - diff --git a/arch/sh64/kernel/sys_sh64.c b/arch/sh64/kernel/sys_sh64.c deleted file mode 100644 index de0a303ba26f..000000000000 --- a/arch/sh64/kernel/sys_sh64.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/sys_sh64.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/SH5 - * platform. - * - * Mostly taken from i386 version. - * - */ - -#include <linux/errno.h> -#include <linux/rwsem.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/smp.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/stat.h> -#include <linux/mman.h> -#include <linux/file.h> -#include <linux/utsname.h> -#include <linux/syscalls.h> -#include <linux/ipc.h> -#include <asm/uaccess.h> -#include <asm/ptrace.h> -#include <asm/unistd.h> - -#define REG_3 3 - -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -#ifdef NEW_PIPE_IMPLEMENTATION -asmlinkage int sys_pipe(unsigned long * fildes, - unsigned long dummy_r3, - unsigned long dummy_r4, - unsigned long dummy_r5, - unsigned long dummy_r6, - unsigned long dummy_r7, - struct pt_regs * regs) /* r8 = pt_regs forced by entry.S */ -{ - int fd[2]; - int ret; - - ret = do_pipe(fd); - if (ret == 0) - /* - *********************************************************************** - * To avoid the copy_to_user we prefer to break the ABIs convention, * - * packing the valid pair of file IDs into a single register (r3); * - * while r2 is the return code as defined by the sh5-ABIs. * - * BE CAREFUL: pipe stub, into glibc, must be aware of this solution * - *********************************************************************** - -#ifdef __LITTLE_ENDIAN__ - regs->regs[REG_3] = (((unsigned long long) fd[1]) << 32) | ((unsigned long long) fd[0]); -#else - regs->regs[REG_3] = (((unsigned long long) fd[0]) << 32) | ((unsigned long long) fd[1]); -#endif - - */ - /* although not very clever this is endianess independent */ - regs->regs[REG_3] = (unsigned long long) *((unsigned long long *) fd); - - return ret; -} - -#else -asmlinkage int sys_pipe(unsigned long * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - -#endif - -/* - * To avoid cache alias, we map the shard page with same color. - */ -#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1)) - -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) -{ - struct vm_area_struct *vma; - - if (flags & MAP_FIXED) { - /* We do not accept a shared mapping if it would violate - * cache aliasing constraints. - */ - if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1))) - return -EINVAL; - return addr; - } - - if (len > TASK_SIZE) - return -ENOMEM; - if (!addr) - addr = TASK_UNMAPPED_BASE; - - if (flags & MAP_PRIVATE) - addr = PAGE_ALIGN(addr); - else - addr = COLOUR_ALIGN(addr); - - for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { - /* At this point: (!vma || addr < vma->vm_end). */ - if (TASK_SIZE - len < addr) - return -ENOMEM; - if (!vma || addr + len <= vma->vm_start) - return addr; - addr = vma->vm_end; - if (!(flags & MAP_PRIVATE)) - addr = COLOUR_ALIGN(addr); - } -} - -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - -asmlinkage int old_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - int fd, unsigned long off) -{ - if (off & ~PAGE_MASK) - return -EINVAL; - return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); -} - -/* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ -asmlinkage int sys_ipc(uint call, int first, int second, - int third, void __user *ptr, long fifth) -{ - int version, ret; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - - if (call <= SEMCTL) - switch (call) { - case SEMOP: - return sys_semtimedop(first, (struct sembuf __user *)ptr, - second, NULL); - case SEMTIMEDOP: - return sys_semtimedop(first, (struct sembuf __user *)ptr, - second, - (const struct timespec __user *)fifth); - case SEMGET: - return sys_semget (first, second, third); - case SEMCTL: { - union semun fourth; - if (!ptr) - return -EINVAL; - if (get_user(fourth.__pad, (void * __user *) ptr)) - return -EFAULT; - return sys_semctl (first, second, third, fourth); - } - default: - return -EINVAL; - } - - if (call <= MSGCTL) - switch (call) { - case MSGSND: - return sys_msgsnd (first, (struct msgbuf __user *) ptr, - second, third); - case MSGRCV: - switch (version) { - case 0: { - struct ipc_kludge tmp; - if (!ptr) - return -EINVAL; - - if (copy_from_user(&tmp, - (struct ipc_kludge __user *) ptr, - sizeof (tmp))) - return -EFAULT; - return sys_msgrcv (first, tmp.msgp, second, - tmp.msgtyp, third); - } - default: - return sys_msgrcv (first, - (struct msgbuf __user *) ptr, - second, fifth, third); - } - case MSGGET: - return sys_msgget ((key_t) first, second); - case MSGCTL: - return sys_msgctl (first, second, - (struct msqid_ds __user *) ptr); - default: - return -EINVAL; - } - if (call <= SHMCTL) - switch (call) { - case SHMAT: - switch (version) { - default: { - ulong raddr; - ret = do_shmat (first, (char __user *) ptr, - second, &raddr); - if (ret) - return ret; - return put_user (raddr, (ulong __user *) third); - } - case 1: /* iBCS2 emulator entry point */ - if (!segment_eq(get_fs(), get_ds())) - return -EINVAL; - return do_shmat (first, (char __user *) ptr, - second, (ulong *) third); - } - case SHMDT: - return sys_shmdt ((char __user *)ptr); - case SHMGET: - return sys_shmget (first, second, third); - case SHMCTL: - return sys_shmctl (first, second, - (struct shmid_ds __user *) ptr); - default: - return -EINVAL; - } - - return -EINVAL; -} - -asmlinkage int sys_uname(struct old_utsname * name) -{ - int err; - if (!name) - return -EFAULT; - down_read(&uts_sem); - err = copy_to_user(name, utsname(), sizeof (*name)); - up_read(&uts_sem); - return err?-EFAULT:0; -} - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, char *const argv[], char *const envp[]) -{ - register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve); - register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename; - register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv; - register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp; - __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)" - : "=r" (__sc0) - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); - __asm__ __volatile__ ("!dummy %0 %1 %2 %3" - : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory"); - return __sc0; -} diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S deleted file mode 100644 index abb94c05d07a..000000000000 --- a/arch/sh64/kernel/syscalls.S +++ /dev/null @@ -1,381 +0,0 @@ -/* - * arch/sh64/kernel/syscalls.S - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2004 - 2007 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include <linux/sys.h> - - .section .data, "aw" - .balign 32 - -/* - * System calls jump table - */ - .globl sys_call_table -sys_call_table: - .long sys_restart_syscall /* 0 - old "setup()" system call */ - .long sys_exit - .long sys_fork - .long sys_read - .long sys_write - .long sys_open /* 5 */ - .long sys_close - .long sys_waitpid - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long sys_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod /* 15 */ - .long sys_lchown16 - .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat - .long sys_lseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_oldumount - .long sys_setuid16 - .long sys_getuid16 - .long sys_stime /* 25 */ - .long sh64_ptrace - .long sys_alarm - .long sys_fstat - .long sys_pause - .long sys_utime /* 30 */ - .long sys_ni_syscall /* old stty syscall holder */ - .long sys_ni_syscall /* old gtty syscall holder */ - .long sys_access - .long sys_nice - .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* old prof syscall holder */ - .long sys_brk /* 45 */ - .long sys_setgid16 - .long sys_getgid16 - .long sys_signal - .long sys_geteuid16 - .long sys_getegid16 /* 50 */ - .long sys_acct - .long sys_umount /* recycled never used phys( */ - .long sys_ni_syscall /* old lock syscall holder */ - .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ - .long sys_setpgid - .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_ni_syscall /* sys_olduname */ - .long sys_umask /* 60 */ - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp /* 65 */ - .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid16 /* 70 */ - .long sys_setregid16 - .long sys_sigsuspend - .long sys_sigpending - .long sys_sethostname - .long sys_setrlimit /* 75 */ - .long sys_old_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups16 /* 80 */ - .long sys_setgroups16 - .long sys_ni_syscall /* sys_oldselect */ - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long old_readdir - .long old_mmap /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown16 /* 95 */ - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* old profil syscall holder */ - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_ni_syscall /* ioperm */ - .long sys_socketcall /* Obsolete implementation of socket syscall */ - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_uname - .long sys_ni_syscall /* 110 */ /* iopl */ - .long sys_vhangup - .long sys_ni_syscall /* idle */ - .long sys_ni_syscall /* vm86old */ - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc /* Obsolete ipc syscall implementation */ - .long sys_fsync - .long sys_sigreturn - .long sys_clone /* 120 */ - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall /* sys_modify_ldt */ - .long sys_adjtimex - .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* old "create_module" */ - .long sys_init_module - .long sys_delete_module - .long sys_ni_syscall /* 130: old "get_kernel_syms" */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush - .long sys_sysfs /* 135 */ - .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 - .long sys_llseek /* 140 */ - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync - .long sys_readv /* 145 */ - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl - .long sys_mlock /* 150 */ - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam - .long sys_sched_getparam /* 155 */ - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max - .long sys_sched_get_priority_min /* 160 */ - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_mremap - .long sys_setresuid16 - .long sys_getresuid16 /* 165 */ - .long sys_ni_syscall /* vm86 */ - .long sys_ni_syscall /* old "query_module" */ - .long sys_poll - .long sys_nfsservctl - .long sys_setresgid16 /* 170 */ - .long sys_getresgid16 - .long sys_prctl - .long sys_rt_sigreturn - .long sys_rt_sigaction - .long sys_rt_sigprocmask /* 175 */ - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend - .long sys_pread64 /* 180 */ - .long sys_pwrite64 - .long sys_chown16 - .long sys_getcwd - .long sys_capget - .long sys_capset /* 185 */ - .long sys_sigaltstack - .long sys_sendfile - .long sys_ni_syscall /* streams1 */ - .long sys_ni_syscall /* streams2 */ - .long sys_vfork /* 190 */ - .long sys_getrlimit - .long sys_mmap2 - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 /* 195 */ - .long sys_lstat64 - .long sys_fstat64 - .long sys_lchown - .long sys_getuid - .long sys_getgid /* 200 */ - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid - .long sys_getgroups /* 205 */ - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid - .long sys_setresgid /* 210 */ - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid - .long sys_setfsuid /* 215 */ - .long sys_setfsgid - .long sys_pivot_root - .long sys_mincore - .long sys_madvise - /* Broken-out socket family (maintain backwards compatibility in syscall - numbering with 2.4) */ - .long sys_socket /* 220 */ - .long sys_bind - .long sys_connect - .long sys_listen - .long sys_accept - .long sys_getsockname /* 225 */ - .long sys_getpeername - .long sys_socketpair - .long sys_send - .long sys_sendto - .long sys_recv /* 230*/ - .long sys_recvfrom - .long sys_shutdown - .long sys_setsockopt - .long sys_getsockopt - .long sys_sendmsg /* 235 */ - .long sys_recvmsg - /* Broken-out IPC family (maintain backwards compatibility in syscall - numbering with 2.4) */ - .long sys_semop - .long sys_semget - .long sys_semctl - .long sys_msgsnd /* 240 */ - .long sys_msgrcv - .long sys_msgget - .long sys_msgctl - .long sys_shmat - .long sys_shmdt /* 245 */ - .long sys_shmget - .long sys_shmctl - /* Rest of syscalls listed in 2.4 i386 unistd.h */ - .long sys_getdents64 - .long sys_fcntl64 - .long sys_ni_syscall /* 250 reserved for TUX */ - .long sys_ni_syscall /* Reserved for Security */ - .long sys_gettid - .long sys_readahead - .long sys_setxattr - .long sys_lsetxattr /* 255 */ - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr - .long sys_fgetxattr - .long sys_listxattr /* 260 */ - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr - .long sys_lremovexattr - .long sys_fremovexattr /* 265 */ - .long sys_tkill - .long sys_sendfile64 - .long sys_futex - .long sys_sched_setaffinity - .long sys_sched_getaffinity /* 270 */ - .long sys_ni_syscall - .long sys_ni_syscall - .long sys_io_setup - .long sys_io_destroy - .long sys_io_getevents /* 275 */ - .long sys_io_submit - .long sys_io_cancel - .long sys_fadvise64 - .long sys_ni_syscall - .long sys_exit_group /* 280 */ - /* Rest of new 2.6 syscalls */ - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl - .long sys_epoll_wait - .long sys_remap_file_pages /* 285 */ - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime - .long sys_timer_gettime - .long sys_timer_getoverrun /* 290 */ - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime - .long sys_clock_getres - .long sys_clock_nanosleep /* 295 */ - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill - .long sys_utimes - .long sys_fadvise64_64 /* 300 */ - .long sys_ni_syscall /* Reserved for vserver */ - .long sys_ni_syscall /* Reserved for mbind */ - .long sys_ni_syscall /* get_mempolicy */ - .long sys_ni_syscall /* set_mempolicy */ - .long sys_mq_open /* 305 */ - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive - .long sys_mq_notify - .long sys_mq_getsetattr /* 310 */ - .long sys_ni_syscall /* Reserved for kexec */ - .long sys_waitid - .long sys_add_key - .long sys_request_key - .long sys_keyctl /* 315 */ - .long sys_ioprio_set - .long sys_ioprio_get - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch /* 320 */ - .long sys_ni_syscall - .long sys_migrate_pages - .long sys_openat - .long sys_mkdirat - .long sys_mknodat /* 325 */ - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 - .long sys_unlinkat - .long sys_renameat /* 330 */ - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat - .long sys_fchmodat - .long sys_faccessat /* 335 */ - .long sys_pselect6 - .long sys_ppoll - .long sys_unshare - .long sys_set_robust_list - .long sys_get_robust_list /* 340 */ - .long sys_splice - .long sys_sync_file_range - .long sys_tee - .long sys_vmsplice - .long sys_move_pages /* 345 */ - .long sys_getcpu - .long sys_epoll_pwait - .long sys_utimensat - .long sys_signalfd - .long sys_timerfd /* 350 */ - .long sys_eventfd - .long sys_fallocate diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c deleted file mode 100644 index 06f3c179e345..000000000000 --- a/arch/sh64/kernel/time.c +++ /dev/null @@ -1,593 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/time.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2003 Richard Curnow - * - * Original TMU/RTC code taken from sh version. - * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka - * Some code taken from i386 version. - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - */ - -#include <linux/errno.h> -#include <linux/rwsem.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/delay.h> -#include <linux/init.h> -#include <linux/profile.h> -#include <linux/smp.h> -#include <linux/module.h> -#include <linux/bcd.h> - -#include <asm/registers.h> /* required by inline __asm__ stmt. */ - -#include <asm/processor.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/delay.h> - -#include <linux/timex.h> -#include <linux/irq.h> -#include <asm/hardware.h> - -#define TMU_TOCR_INIT 0x00 -#define TMU0_TCR_INIT 0x0020 -#define TMU_TSTR_INIT 1 -#define TMU_TSTR_OFF 0 - -/* RCR1 Bits */ -#define RCR1_CF 0x80 /* Carry Flag */ -#define RCR1_CIE 0x10 /* Carry Interrupt Enable */ -#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */ -#define RCR1_AF 0x01 /* Alarm Flag */ - -/* RCR2 Bits */ -#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */ -#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */ -#define RCR2_RTCEN 0x08 /* ENable RTC */ -#define RCR2_ADJ 0x04 /* ADJustment (30-second) */ -#define RCR2_RESET 0x02 /* Reset bit */ -#define RCR2_START 0x01 /* Start bit */ - -/* Clock, Power and Reset Controller */ -#define CPRC_BLOCK_OFF 0x01010000 -#define CPRC_BASE PHYS_PERIPHERAL_BLOCK + CPRC_BLOCK_OFF - -#define FRQCR (cprc_base+0x0) -#define WTCSR (cprc_base+0x0018) -#define STBCR (cprc_base+0x0030) - -/* Time Management Unit */ -#define TMU_BLOCK_OFF 0x01020000 -#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF -#define TMU0_BASE tmu_base + 0x8 + (0xc * 0x0) -#define TMU1_BASE tmu_base + 0x8 + (0xc * 0x1) -#define TMU2_BASE tmu_base + 0x8 + (0xc * 0x2) - -#define TMU_TOCR tmu_base+0x0 /* Byte access */ -#define TMU_TSTR tmu_base+0x4 /* Byte access */ - -#define TMU0_TCOR TMU0_BASE+0x0 /* Long access */ -#define TMU0_TCNT TMU0_BASE+0x4 /* Long access */ -#define TMU0_TCR TMU0_BASE+0x8 /* Word access */ - -/* Real Time Clock */ -#define RTC_BLOCK_OFF 0x01040000 -#define RTC_BASE PHYS_PERIPHERAL_BLOCK + RTC_BLOCK_OFF - -#define R64CNT rtc_base+0x00 -#define RSECCNT rtc_base+0x04 -#define RMINCNT rtc_base+0x08 -#define RHRCNT rtc_base+0x0c -#define RWKCNT rtc_base+0x10 -#define RDAYCNT rtc_base+0x14 -#define RMONCNT rtc_base+0x18 -#define RYRCNT rtc_base+0x1c /* 16bit */ -#define RSECAR rtc_base+0x20 -#define RMINAR rtc_base+0x24 -#define RHRAR rtc_base+0x28 -#define RWKAR rtc_base+0x2c -#define RDAYAR rtc_base+0x30 -#define RMONAR rtc_base+0x34 -#define RCR1 rtc_base+0x38 -#define RCR2 rtc_base+0x3c - -#define TICK_SIZE (tick_nsec / 1000) - -static unsigned long tmu_base, rtc_base; -unsigned long cprc_base; - -/* Variables to allow interpolation of time of day to resolution better than a - * jiffy. */ - -/* This is effectively protected by xtime_lock */ -static unsigned long ctc_last_interrupt; -static unsigned long long usecs_per_jiffy = 1000000/HZ; /* Approximation */ - -#define CTC_JIFFY_SCALE_SHIFT 40 - -/* 2**CTC_JIFFY_SCALE_SHIFT / ctc_ticks_per_jiffy */ -static unsigned long long scaled_recip_ctc_ticks_per_jiffy; - -/* Estimate number of microseconds that have elapsed since the last timer tick, - by scaling the delta that has occurred in the CTC register. - - WARNING WARNING WARNING : This algorithm relies on the CTC decrementing at - the CPU clock rate. If the CPU sleeps, the CTC stops counting. Bear this - in mind if enabling SLEEP_WORKS in process.c. In that case, this algorithm - probably needs to use TMU.TCNT0 instead. This will work even if the CPU is - sleeping, though will be coarser. - - FIXME : What if usecs_per_tick is moving around too much, e.g. if an adjtime - is running or if the freq or tick arguments of adjtimex are modified after - we have calibrated the scaling factor? This will result in either a jump at - the end of a tick period, or a wrap backwards at the start of the next one, - if the application is reading the time of day often enough. I think we - ought to do better than this. For this reason, usecs_per_jiffy is left - separated out in the calculation below. This allows some future hook into - the adjtime-related stuff in kernel/timer.c to remove this hazard. - -*/ - -static unsigned long usecs_since_tick(void) -{ - unsigned long long current_ctc; - long ctc_ticks_since_interrupt; - unsigned long long ull_ctc_ticks_since_interrupt; - unsigned long result; - - unsigned long long mul1_out; - unsigned long long mul1_out_high; - unsigned long long mul2_out_low, mul2_out_high; - - /* Read CTC register */ - asm ("getcon cr62, %0" : "=r" (current_ctc)); - /* Note, the CTC counts down on each CPU clock, not up. - Note(2), use long type to get correct wraparound arithmetic when - the counter crosses zero. */ - ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc; - ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt; - - /* Inline assembly to do 32x32x32->64 multiplier */ - asm volatile ("mulu.l %1, %2, %0" : - "=r" (mul1_out) : - "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy)); - - mul1_out_high = mul1_out >> 32; - - asm volatile ("mulu.l %1, %2, %0" : - "=r" (mul2_out_low) : - "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy)); - -#if 1 - asm volatile ("mulu.l %1, %2, %0" : - "=r" (mul2_out_high) : - "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy)); -#endif - - result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT); - - return result; -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - unsigned long usec, sec; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - usec = usecs_since_tick(); - sec = xtime.tv_sec; - usec += xtime.tv_nsec / 1000; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! - */ - nsec -= 1000 * usecs_since_tick(); - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - - return 0; -} -EXPORT_SYMBOL(do_settimeofday); - -static int set_rtc_time(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - - ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */ - - cmos_minutes = ctrl_inb(RMINCNT); - BCD_TO_BIN(cmos_minutes); - - /* - * 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 - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - ctrl_outb(real_seconds, RSECCNT); - ctrl_outb(real_minutes, RMINCNT); - } else { - printk(KERN_WARNING - "set_rtc_time: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */ - - return retval; -} - -/* last time the RTC clock got updated */ -static long last_rtc_update = 0; - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static inline void do_timer_interrupt(void) -{ - unsigned long long current_ctc; - asm ("getcon cr62, %0" : "=r" (current_ctc)); - ctc_last_interrupt = (unsigned long) current_ctc; - - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - if (current->pid) - profile_tick(CPU_PROFILING); - -#ifdef CONFIG_HEARTBEAT - { - extern void heartbeat(void); - - heartbeat(); - } -#endif - - /* - * If we have an externally synchronized Linux clock, then update - * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - 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_time(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - } -} - -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - unsigned long timer_status; - - /* Clear UNF bit */ - timer_status = ctrl_inw(TMU0_TCR); - timer_status &= ~0x100; - ctrl_outw(timer_status, TMU0_TCR); - - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_lock(&xtime_lock); - do_timer_interrupt(); - write_unlock(&xtime_lock); - - return IRQ_HANDLED; -} - -static unsigned long get_rtc_time(void) -{ - unsigned int sec, min, hr, wk, day, mon, yr, yr100; - - again: - do { - ctrl_outb(0, RCR1); /* Clear CF-bit */ - sec = ctrl_inb(RSECCNT); - min = ctrl_inb(RMINCNT); - hr = ctrl_inb(RHRCNT); - wk = ctrl_inb(RWKCNT); - day = ctrl_inb(RDAYCNT); - mon = ctrl_inb(RMONCNT); - yr = ctrl_inw(RYRCNT); - yr100 = (yr >> 8); - yr &= 0xff; - } while ((ctrl_inb(RCR1) & RCR1_CF) != 0); - - BCD_TO_BIN(yr100); - BCD_TO_BIN(yr); - BCD_TO_BIN(mon); - BCD_TO_BIN(day); - BCD_TO_BIN(hr); - BCD_TO_BIN(min); - BCD_TO_BIN(sec); - - if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 || - hr > 23 || min > 59 || sec > 59) { - printk(KERN_ERR - "SH RTC: invalid value, resetting to 1 Jan 2000\n"); - ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */ - ctrl_outb(0, RSECCNT); - ctrl_outb(0, RMINCNT); - ctrl_outb(0, RHRCNT); - ctrl_outb(6, RWKCNT); - ctrl_outb(1, RDAYCNT); - ctrl_outb(1, RMONCNT); - ctrl_outw(0x2000, RYRCNT); - ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start */ - goto again; - } - - return mktime(yr100 * 100 + yr, mon, day, hr, min, sec); -} - -static __init unsigned int get_cpu_hz(void) -{ - unsigned int count; - unsigned long __dummy; - unsigned long ctc_val_init, ctc_val; - - /* - ** Regardless the toolchain, force the compiler to use the - ** arbitrary register r3 as a clock tick counter. - ** NOTE: r3 must be in accordance with sh64_rtc_interrupt() - */ - register unsigned long long __rtc_irq_flag __asm__ ("r3"); - - local_irq_enable(); - do {} while (ctrl_inb(R64CNT) != 0); - ctrl_outb(RCR1_CIE, RCR1); /* Enable carry interrupt */ - - /* - * r3 is arbitrary. CDC does not support "=z". - */ - ctc_val_init = 0xffffffff; - ctc_val = ctc_val_init; - - asm volatile("gettr tr0, %1\n\t" - "putcon %0, " __CTC "\n\t" - "and %2, r63, %2\n\t" - "pta $+4, tr0\n\t" - "beq/l %2, r63, tr0\n\t" - "ptabs %1, tr0\n\t" - "getcon " __CTC ", %0\n\t" - : "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag) - : "0" (0)); - local_irq_disable(); - /* - * SH-3: - * CPU clock = 4 stages * loop - * tst rm,rm if id ex - * bt/s 1b if id ex - * add #1,rd if id ex - * (if) pipe line stole - * tst rm,rm if id ex - * .... - * - * - * SH-4: - * CPU clock = 6 stages * loop - * I don't know why. - * .... - * - * SH-5: - * Use CTC register to count. This approach returns the right value - * even if the I-cache is disabled (e.g. whilst debugging.) - * - */ - - count = ctc_val_init - ctc_val; /* CTC counts down */ - -#if defined (CONFIG_SH_SIMULATOR) - /* - * Let's pretend we are a 5MHz SH-5 to avoid a too - * little timer interval. Also to keep delay - * calibration within a reasonable time. - */ - return 5000000; -#else - /* - * This really is count by the number of clock cycles - * by the ratio between a complete R64CNT - * wrap-around (128) and CUI interrupt being raised (64). - */ - return count*2; -#endif -} - -static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id) -{ - struct pt_regs *regs = get_irq_regs(); - - ctrl_outb(0, RCR1); /* Disable Carry Interrupts */ - regs->regs[3] = 1; /* Using r3 */ - - return IRQ_HANDLED; -} - -static struct irqaction irq0 = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "timer", -}; -static struct irqaction irq1 = { - .handler = sh64_rtc_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "rtc", -}; - -void __init time_init(void) -{ - unsigned int cpu_clock, master_clock, bus_clock, module_clock; - unsigned long interval; - unsigned long frqcr, ifc, pfc; - static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 }; -#define bfc_table ifc_table /* Same */ -#define pfc_table ifc_table /* Same */ - - tmu_base = onchip_remap(TMU_BASE, 1024, "TMU"); - if (!tmu_base) { - panic("Unable to remap TMU\n"); - } - - rtc_base = onchip_remap(RTC_BASE, 1024, "RTC"); - if (!rtc_base) { - panic("Unable to remap RTC\n"); - } - - cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC"); - if (!cprc_base) { - panic("Unable to remap CPRC\n"); - } - - xtime.tv_sec = get_rtc_time(); - xtime.tv_nsec = 0; - - setup_irq(TIMER_IRQ, &irq0); - setup_irq(RTC_IRQ, &irq1); - - /* Check how fast it is.. */ - cpu_clock = get_cpu_hz(); - - /* Note careful order of operations to maintain reasonable precision and avoid overflow. */ - scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) / (unsigned long long)(cpu_clock / HZ)); - - disable_irq(RTC_IRQ); - - printk("CPU clock: %d.%02dMHz\n", - (cpu_clock / 1000000), (cpu_clock % 1000000)/10000); - { - unsigned short bfc; - frqcr = ctrl_inl(FRQCR); - ifc = ifc_table[(frqcr>> 6) & 0x0007]; - bfc = bfc_table[(frqcr>> 3) & 0x0007]; - pfc = pfc_table[(frqcr>> 12) & 0x0007]; - master_clock = cpu_clock * ifc; - bus_clock = master_clock/bfc; - } - - printk("Bus clock: %d.%02dMHz\n", - (bus_clock/1000000), (bus_clock % 1000000)/10000); - module_clock = master_clock/pfc; - printk("Module clock: %d.%02dMHz\n", - (module_clock/1000000), (module_clock % 1000000)/10000); - interval = (module_clock/(HZ*4)); - - printk("Interval = %ld\n", interval); - - current_cpu_data.cpu_clock = cpu_clock; - current_cpu_data.master_clock = master_clock; - current_cpu_data.bus_clock = bus_clock; - current_cpu_data.module_clock = module_clock; - - /* Start TMU0 */ - ctrl_outb(TMU_TSTR_OFF, TMU_TSTR); - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); - ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); - ctrl_outl(interval, TMU0_TCOR); - ctrl_outl(interval, TMU0_TCNT); - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); -} - -void enter_deep_standby(void) -{ - /* Disable watchdog timer */ - ctrl_outl(0xa5000000, WTCSR); - /* Configure deep standby on sleep */ - ctrl_outl(0x03, STBCR); - -#ifdef CONFIG_SH_ALPHANUMERIC - { - extern void mach_alphanum(int position, unsigned char value); - extern void mach_alphanum_brightness(int setting); - char halted[] = "Halted. "; - int i; - mach_alphanum_brightness(6); /* dimmest setting above off */ - for (i=0; i<8; i++) { - mach_alphanum(i, halted[i]); - } - asm __volatile__ ("synco"); - } -#endif - - asm __volatile__ ("sleep"); - asm __volatile__ ("synci"); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); - panic("Unexpected wakeup!\n"); -} diff --git a/arch/sh64/kernel/traps.c b/arch/sh64/kernel/traps.c deleted file mode 100644 index f32df3831f45..000000000000 --- a/arch/sh64/kernel/traps.c +++ /dev/null @@ -1,982 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/traps.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - */ - -/* - * 'Traps.c' handles hardware traps and faults after we have saved some - * state in 'entry.S'. - */ -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/kallsyms.h> -#include <linux/interrupt.h> -#include <linux/sysctl.h> -#include <linux/module.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/atomic.h> -#include <asm/processor.h> -#include <asm/pgtable.h> - -#undef DEBUG_EXCEPTION -#ifdef DEBUG_EXCEPTION -/* implemented in ../lib/dbg.c */ -extern void show_excp_regs(char *fname, int trapnr, int signr, - struct pt_regs *regs); -#else -#define show_excp_regs(a, b, c, d) -#endif - -static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, - unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk); - -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \ -{ \ - do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \ -} - -spinlock_t die_lock; - -void die(const char * str, struct pt_regs * regs, long err) -{ - console_verbose(); - spin_lock_irq(&die_lock); - printk("%s: %lx\n", str, (err & 0xffffff)); - show_regs(regs); - spin_unlock_irq(&die_lock); - do_exit(SIGSEGV); -} - -static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) - die(str, regs, err); -} - -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) { - const struct exception_table_entry *fixup; - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return; - } - die(str, regs, err); - } -} - -DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) -DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current) - - -/* Implement misaligned load/store handling for kernel (and optionally for user - mode too). Limitation : only SHmedia mode code is handled - there is no - handling at all for misaligned accesses occurring in SHcompact code yet. */ - -static int misaligned_fixup(struct pt_regs *regs); - -asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs) -{ - if (misaligned_fixup(regs) < 0) { - do_unhandled_exception(7, SIGSEGV, "address error(load)", - "do_address_error_load", - error_code, regs, current); - } - return; -} - -asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs) -{ - if (misaligned_fixup(regs) < 0) { - do_unhandled_exception(8, SIGSEGV, "address error(store)", - "do_address_error_store", - error_code, regs, current); - } - return; -} - -#if defined(CONFIG_SH64_ID2815_WORKAROUND) - -#define OPCODE_INVALID 0 -#define OPCODE_USER_VALID 1 -#define OPCODE_PRIV_VALID 2 - -/* getcon/putcon - requires checking which control register is referenced. */ -#define OPCODE_CTRL_REG 3 - -/* Table of valid opcodes for SHmedia mode. - Form a 10-bit value by concatenating the major/minor opcodes i.e. - opcode[31:26,20:16]. The 6 MSBs of this value index into the following - array. The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to - LSBs==4'b0000 etc). */ -static unsigned long shmedia_opcode_table[64] = { - 0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015, - 0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000, - 0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000, - 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000 -}; - -void do_reserved_inst(unsigned long error_code, struct pt_regs *regs) -{ - /* Workaround SH5-101 cut2 silicon defect #2815 : - in some situations, inter-mode branches from SHcompact -> SHmedia - which should take ITLBMISS or EXECPROT exceptions at the target - falsely take RESINST at the target instead. */ - - unsigned long opcode = 0x6ff4fff0; /* guaranteed reserved opcode */ - unsigned long pc, aligned_pc; - int get_user_error; - int trapnr = 12; - int signr = SIGILL; - char *exception_name = "reserved_instruction"; - - pc = regs->pc; - if ((pc & 3) == 1) { - /* SHmedia : check for defect. This requires executable vmas - to be readable too. */ - aligned_pc = pc & ~3; - if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { - get_user_error = -EFAULT; - } else { - get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); - } - if (get_user_error >= 0) { - unsigned long index, shift; - unsigned long major, minor, combined; - unsigned long reserved_field; - reserved_field = opcode & 0xf; /* These bits are currently reserved as zero in all valid opcodes */ - major = (opcode >> 26) & 0x3f; - minor = (opcode >> 16) & 0xf; - combined = (major << 4) | minor; - index = major; - shift = minor << 1; - if (reserved_field == 0) { - int opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3; - switch (opcode_state) { - case OPCODE_INVALID: - /* Trap. */ - break; - case OPCODE_USER_VALID: - /* Restart the instruction : the branch to the instruction will now be from an RTE - not from SHcompact so the silicon defect won't be triggered. */ - return; - case OPCODE_PRIV_VALID: - if (!user_mode(regs)) { - /* Should only ever get here if a module has - SHcompact code inside it. If so, the same fix up is needed. */ - return; /* same reason */ - } - /* Otherwise, user mode trying to execute a privileged instruction - - fall through to trap. */ - break; - case OPCODE_CTRL_REG: - /* If in privileged mode, return as above. */ - if (!user_mode(regs)) return; - /* In user mode ... */ - if (combined == 0x9f) { /* GETCON */ - unsigned long regno = (opcode >> 20) & 0x3f; - if (regno >= 62) { - return; - } - /* Otherwise, reserved or privileged control register, => trap */ - } else if (combined == 0x1bf) { /* PUTCON */ - unsigned long regno = (opcode >> 4) & 0x3f; - if (regno >= 62) { - return; - } - /* Otherwise, reserved or privileged control register, => trap */ - } else { - /* Trap */ - } - break; - default: - /* Fall through to trap. */ - break; - } - } - /* fall through to normal resinst processing */ - } else { - /* Error trying to read opcode. This typically means a - real fault, not a RESINST any more. So change the - codes. */ - trapnr = 87; - exception_name = "address error (exec)"; - signr = SIGSEGV; - } - } - - do_unhandled_exception(trapnr, signr, exception_name, "do_reserved_inst", error_code, regs, current); -} - -#else /* CONFIG_SH64_ID2815_WORKAROUND */ - -/* If the workaround isn't needed, this is just a straightforward reserved - instruction */ -DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) - -#endif /* CONFIG_SH64_ID2815_WORKAROUND */ - -/* Called with interrupts disabled */ -asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs) -{ - PLS(); - show_excp_regs(__FUNCTION__, -1, -1, regs); - die_if_kernel("exception", regs, ex); -} - -int do_unknown_trapa(unsigned long scId, struct pt_regs *regs) -{ - /* Syscall debug */ - printk("System call ID error: [0x1#args:8 #syscall:16 0x%lx]\n", scId); - - die_if_kernel("unknown trapa", regs, scId); - - return -ENOSYS; -} - -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ -#ifdef CONFIG_KALLSYMS - extern void sh64_unwind(struct pt_regs *regs); - struct pt_regs *regs; - - regs = tsk ? tsk->thread.kregs : NULL; - - sh64_unwind(regs); -#else - printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n"); -#endif -} - -void show_task(unsigned long *sp) -{ - show_stack(NULL, sp); -} - -void dump_stack(void) -{ - show_task(NULL); -} -/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */ -EXPORT_SYMBOL(dump_stack); - -static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, - unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk) -{ - show_excp_regs(fn_name, trapnr, signr, regs); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = trapnr; - - if (user_mode(regs)) - force_sig(signr, tsk); - - die_if_no_fixup(str, regs, error_code); -} - -static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int from_user_mode) -{ - int get_user_error; - unsigned long aligned_pc; - unsigned long opcode; - - if ((pc & 3) == 1) { - /* SHmedia */ - aligned_pc = pc & ~3; - if (from_user_mode) { - if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { - get_user_error = -EFAULT; - } else { - get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); - *result_opcode = opcode; - } - return get_user_error; - } else { - /* If the fault was in the kernel, we can either read - * this directly, or if not, we fault. - */ - *result_opcode = *(unsigned long *) aligned_pc; - return 0; - } - } else if ((pc & 1) == 0) { - /* SHcompact */ - /* TODO : provide handling for this. We don't really support - user-mode SHcompact yet, and for a kernel fault, this would - have to come from a module built for SHcompact. */ - return -EFAULT; - } else { - /* misaligned */ - return -EFAULT; - } -} - -static int address_is_sign_extended(__u64 a) -{ - __u64 b; -#if (NEFF == 32) - b = (__u64)(__s64)(__s32)(a & 0xffffffffUL); - return (b == a) ? 1 : 0; -#else -#error "Sign extend check only works for NEFF==32" -#endif -} - -static int generate_and_check_address(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - __u64 *address) -{ - /* return -1 for fault, 0 for OK */ - - __u64 base_address, addr; - int basereg; - - basereg = (opcode >> 20) & 0x3f; - base_address = regs->regs[basereg]; - if (displacement_not_indexed) { - __s64 displacement; - displacement = (opcode >> 10) & 0x3ff; - displacement = ((displacement << 54) >> 54); /* sign extend */ - addr = (__u64)((__s64)base_address + (displacement << width_shift)); - } else { - __u64 offset; - int offsetreg; - offsetreg = (opcode >> 10) & 0x3f; - offset = regs->regs[offsetreg]; - addr = base_address + offset; - } - - /* Check sign extended */ - if (!address_is_sign_extended(addr)) { - return -1; - } - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - /* Check accessible. For misaligned access in the kernel, assume the - address is always accessible (and if not, just fault when the - load/store gets done.) */ - if (user_mode(regs)) { - if (addr >= TASK_SIZE) { - return -1; - } - /* Do access_ok check later - it depends on whether it's a load or a store. */ - } -#endif - - *address = addr; - return 0; -} - -/* Default value as for sh */ -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) -static int user_mode_unaligned_fixup_count = 10; -static int user_mode_unaligned_fixup_enable = 1; -#endif - -static int kernel_mode_unaligned_fixup_count = 32; - -static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result) -{ - unsigned short x; - unsigned char *p, *q; - p = (unsigned char *) (int) address; - q = (unsigned char *) &x; - q[0] = p[0]; - q[1] = p[1]; - - if (do_sign_extend) { - *result = (__u64)(__s64) *(short *) &x; - } else { - *result = (__u64) x; - } -} - -static void misaligned_kernel_word_store(__u64 address, __u64 value) -{ - unsigned short x; - unsigned char *p, *q; - p = (unsigned char *) (int) address; - q = (unsigned char *) &x; - - x = (__u16) value; - p[0] = q[0]; - p[1] = q[1]; -} - -static int misaligned_load(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - int do_sign_extend) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int destreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - destreg = (opcode >> 4) & 0x3f; -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - if (user_mode(regs)) { - __u64 buffer; - - if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL<<width_shift)) { - return -1; - } - - if (__copy_user(&buffer, (const void *)(int)address, (1 << width_shift)) > 0) { - return -1; /* fault */ - } - switch (width_shift) { - case 1: - if (do_sign_extend) { - regs->regs[destreg] = (__u64)(__s64) *(__s16 *) &buffer; - } else { - regs->regs[destreg] = (__u64) *(__u16 *) &buffer; - } - break; - case 2: - regs->regs[destreg] = (__u64)(__s64) *(__s32 *) &buffer; - break; - case 3: - regs->regs[destreg] = buffer; - break; - default: - printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - } else -#endif - { - /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */ - __u64 lo, hi; - - switch (width_shift) { - case 1: - misaligned_kernel_word_load(address, do_sign_extend, ®s->regs[destreg]); - break; - case 2: - asm ("ldlo.l %1, 0, %0" : "=r" (lo) : "r" (address)); - asm ("ldhi.l %1, 3, %0" : "=r" (hi) : "r" (address)); - regs->regs[destreg] = lo | hi; - break; - case 3: - asm ("ldlo.q %1, 0, %0" : "=r" (lo) : "r" (address)); - asm ("ldhi.q %1, 7, %0" : "=r" (hi) : "r" (address)); - regs->regs[destreg] = lo | hi; - break; - - default: - printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - } - - return 0; - -} - -static int misaligned_store(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int srcreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - srcreg = (opcode >> 4) & 0x3f; -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - if (user_mode(regs)) { - __u64 buffer; - - if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<<width_shift)) { - return -1; - } - - switch (width_shift) { - case 1: - *(__u16 *) &buffer = (__u16) regs->regs[srcreg]; - break; - case 2: - *(__u32 *) &buffer = (__u32) regs->regs[srcreg]; - break; - case 3: - buffer = regs->regs[srcreg]; - break; - default: - printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - - if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) { - return -1; /* fault */ - } - } else -#endif - { - /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */ - __u64 val = regs->regs[srcreg]; - - switch (width_shift) { - case 1: - misaligned_kernel_word_store(address, val); - break; - case 2: - asm ("stlo.l %1, 0, %0" : : "r" (val), "r" (address)); - asm ("sthi.l %1, 3, %0" : : "r" (val), "r" (address)); - break; - case 3: - asm ("stlo.q %1, 0, %0" : : "r" (val), "r" (address)); - asm ("sthi.q %1, 7, %0" : : "r" (val), "r" (address)); - break; - - default: - printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - } - - return 0; - -} - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) -/* Never need to fix up misaligned FPU accesses within the kernel since that's a real - error. */ -static int misaligned_fpu_load(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - int do_paired_load) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int destreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - destreg = (opcode >> 4) & 0x3f; - if (user_mode(regs)) { - __u64 buffer; - __u32 buflo, bufhi; - - if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL<<width_shift)) { - return -1; - } - - if (__copy_user(&buffer, (const void *)(int)address, (1 << width_shift)) > 0) { - return -1; /* fault */ - } - /* 'current' may be the current owner of the FPU state, so - context switch the registers into memory so they can be - indexed by register number. */ - if (last_task_used_math == current) { - grab_fpu(); - fpsave(¤t->thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - buflo = *(__u32*) &buffer; - bufhi = *(1 + (__u32*) &buffer); - - switch (width_shift) { - case 2: - current->thread.fpu.hard.fp_regs[destreg] = buflo; - break; - case 3: - if (do_paired_load) { - current->thread.fpu.hard.fp_regs[destreg] = buflo; - current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; - } else { -#if defined(CONFIG_LITTLE_ENDIAN) - current->thread.fpu.hard.fp_regs[destreg] = bufhi; - current->thread.fpu.hard.fp_regs[destreg+1] = buflo; -#else - current->thread.fpu.hard.fp_regs[destreg] = buflo; - current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; -#endif - } - break; - default: - printk("Unexpected width_shift %d in misaligned_fpu_load, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - return 0; - } else { - die ("Misaligned FPU load inside kernel", regs, 0); - return -1; - } - - -} - -static int misaligned_fpu_store(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - int do_paired_load) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int srcreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - srcreg = (opcode >> 4) & 0x3f; - if (user_mode(regs)) { - __u64 buffer; - /* Initialise these to NaNs. */ - __u32 buflo=0xffffffffUL, bufhi=0xffffffffUL; - - if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<<width_shift)) { - return -1; - } - - /* 'current' may be the current owner of the FPU state, so - context switch the registers into memory so they can be - indexed by register number. */ - if (last_task_used_math == current) { - grab_fpu(); - fpsave(¤t->thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - switch (width_shift) { - case 2: - buflo = current->thread.fpu.hard.fp_regs[srcreg]; - break; - case 3: - if (do_paired_load) { - buflo = current->thread.fpu.hard.fp_regs[srcreg]; - bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; - } else { -#if defined(CONFIG_LITTLE_ENDIAN) - bufhi = current->thread.fpu.hard.fp_regs[srcreg]; - buflo = current->thread.fpu.hard.fp_regs[srcreg+1]; -#else - buflo = current->thread.fpu.hard.fp_regs[srcreg]; - bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; -#endif - } - break; - default: - printk("Unexpected width_shift %d in misaligned_fpu_store, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - - *(__u32*) &buffer = buflo; - *(1 + (__u32*) &buffer) = bufhi; - if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) { - return -1; /* fault */ - } - return 0; - } else { - die ("Misaligned FPU load inside kernel", regs, 0); - return -1; - } -} -#endif - -static int misaligned_fixup(struct pt_regs *regs) -{ - unsigned long opcode; - int error; - int major, minor; - -#if !defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - /* Never fixup user mode misaligned accesses without this option enabled. */ - return -1; -#else - if (!user_mode_unaligned_fixup_enable) return -1; -#endif - - error = read_opcode(regs->pc, &opcode, user_mode(regs)); - if (error < 0) { - return error; - } - major = (opcode >> 26) & 0x3f; - minor = (opcode >> 16) & 0xf; - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) { - --user_mode_unaligned_fixup_count; - /* Only do 'count' worth of these reports, to remove a potential DoS against syslog */ - printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", - current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); - } else -#endif - if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) { - --kernel_mode_unaligned_fixup_count; - if (in_interrupt()) { - printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n", - (__u32)regs->pc, opcode); - } else { - printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", - current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); - } - } - - - switch (major) { - case (0x84>>2): /* LD.W */ - error = misaligned_load(regs, opcode, 1, 1, 1); - break; - case (0xb0>>2): /* LD.UW */ - error = misaligned_load(regs, opcode, 1, 1, 0); - break; - case (0x88>>2): /* LD.L */ - error = misaligned_load(regs, opcode, 1, 2, 1); - break; - case (0x8c>>2): /* LD.Q */ - error = misaligned_load(regs, opcode, 1, 3, 0); - break; - - case (0xa4>>2): /* ST.W */ - error = misaligned_store(regs, opcode, 1, 1); - break; - case (0xa8>>2): /* ST.L */ - error = misaligned_store(regs, opcode, 1, 2); - break; - case (0xac>>2): /* ST.Q */ - error = misaligned_store(regs, opcode, 1, 3); - break; - - case (0x40>>2): /* indexed loads */ - switch (minor) { - case 0x1: /* LDX.W */ - error = misaligned_load(regs, opcode, 0, 1, 1); - break; - case 0x5: /* LDX.UW */ - error = misaligned_load(regs, opcode, 0, 1, 0); - break; - case 0x2: /* LDX.L */ - error = misaligned_load(regs, opcode, 0, 2, 1); - break; - case 0x3: /* LDX.Q */ - error = misaligned_load(regs, opcode, 0, 3, 0); - break; - default: - error = -1; - break; - } - break; - - case (0x60>>2): /* indexed stores */ - switch (minor) { - case 0x1: /* STX.W */ - error = misaligned_store(regs, opcode, 0, 1); - break; - case 0x2: /* STX.L */ - error = misaligned_store(regs, opcode, 0, 2); - break; - case 0x3: /* STX.Q */ - error = misaligned_store(regs, opcode, 0, 3); - break; - default: - error = -1; - break; - } - break; - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - case (0x94>>2): /* FLD.S */ - error = misaligned_fpu_load(regs, opcode, 1, 2, 0); - break; - case (0x98>>2): /* FLD.P */ - error = misaligned_fpu_load(regs, opcode, 1, 3, 1); - break; - case (0x9c>>2): /* FLD.D */ - error = misaligned_fpu_load(regs, opcode, 1, 3, 0); - break; - case (0x1c>>2): /* floating indexed loads */ - switch (minor) { - case 0x8: /* FLDX.S */ - error = misaligned_fpu_load(regs, opcode, 0, 2, 0); - break; - case 0xd: /* FLDX.P */ - error = misaligned_fpu_load(regs, opcode, 0, 3, 1); - break; - case 0x9: /* FLDX.D */ - error = misaligned_fpu_load(regs, opcode, 0, 3, 0); - break; - default: - error = -1; - break; - } - break; - case (0xb4>>2): /* FLD.S */ - error = misaligned_fpu_store(regs, opcode, 1, 2, 0); - break; - case (0xb8>>2): /* FLD.P */ - error = misaligned_fpu_store(regs, opcode, 1, 3, 1); - break; - case (0xbc>>2): /* FLD.D */ - error = misaligned_fpu_store(regs, opcode, 1, 3, 0); - break; - case (0x3c>>2): /* floating indexed stores */ - switch (minor) { - case 0x8: /* FSTX.S */ - error = misaligned_fpu_store(regs, opcode, 0, 2, 0); - break; - case 0xd: /* FSTX.P */ - error = misaligned_fpu_store(regs, opcode, 0, 3, 1); - break; - case 0x9: /* FSTX.D */ - error = misaligned_fpu_store(regs, opcode, 0, 3, 0); - break; - default: - error = -1; - break; - } - break; -#endif - - default: - /* Fault */ - error = -1; - break; - } - - if (error < 0) { - return error; - } else { - regs->pc += 4; /* Skip the instruction that's just been emulated */ - return 0; - } - -} - -static ctl_table unaligned_table[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "kernel_reports", - .data = &kernel_mode_unaligned_fixup_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - { - .ctl_name = CTL_UNNUMBERED, - .procname = "user_reports", - .data = &user_mode_unaligned_fixup_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "user_enable", - .data = &user_mode_unaligned_fixup_enable, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec}, -#endif - {} -}; - -static ctl_table unaligned_root[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "unaligned_fixup", - .mode = 0555, - unaligned_table - }, - {} -}; - -static ctl_table sh64_root[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "sh64", - .mode = 0555, - .child = unaligned_root - }, - {} -}; -static struct ctl_table_header *sysctl_header; -static int __init init_sysctl(void) -{ - sysctl_header = register_sysctl_table(sh64_root); - return 0; -} - -__initcall(init_sysctl); - - -asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) -{ - u64 peek_real_address_q(u64 addr); - u64 poke_real_address_q(u64 addr, u64 val); - unsigned long long DM_EXP_CAUSE_PHY = 0x0c100010; - unsigned long long exp_cause; - /* It's not worth ioremapping the debug module registers for the amount - of access we make to them - just go direct to their physical - addresses. */ - exp_cause = peek_real_address_q(DM_EXP_CAUSE_PHY); - if (exp_cause & ~4) { - printk("DM.EXP_CAUSE had unexpected bits set (=%08lx)\n", - (unsigned long)(exp_cause & 0xffffffff)); - } - show_state(); - /* Clear all DEBUGINT causes */ - poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); -} diff --git a/arch/sh64/kernel/unwind.c b/arch/sh64/kernel/unwind.c deleted file mode 100644 index 1214c78e3584..000000000000 --- a/arch/sh64/kernel/unwind.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * arch/sh64/kernel/unwind.c - * - * Copyright (C) 2004 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/kallsyms.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <asm/page.h> -#include <asm/ptrace.h> -#include <asm/processor.h> -#include <asm/io.h> - -static u8 regcache[63]; - -/* - * Finding the previous stack frame isn't horribly straightforward as it is - * on some other platforms. In the sh64 case, we don't have "linked" stack - * frames, so we need to do a bit of work to determine the previous frame, - * and in turn, the previous r14/r18 pair. - * - * There are generally a few cases which determine where we can find out - * the r14/r18 values. In the general case, this can be determined by poking - * around the prologue of the symbol PC is in (note that we absolutely must - * have frame pointer support as well as the kernel symbol table mapped, - * otherwise we can't even get this far). - * - * In other cases, such as the interrupt/exception path, we can poke around - * the sp/fp. - * - * Notably, this entire approach is somewhat error prone, and in the event - * that the previous frame cannot be determined, that's all we can do. - * Either way, this still leaves us with a more correct backtrace then what - * we would be able to come up with by walking the stack (which is garbage - * for anything beyond the first frame). - * -- PFM. - */ -static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc, - unsigned long *pprev_fp, unsigned long *pprev_pc, - struct pt_regs *regs) -{ - const char *sym; - char namebuf[128]; - unsigned long offset; - unsigned long prologue = 0; - unsigned long fp_displacement = 0; - unsigned long fp_prev = 0; - unsigned long offset_r14 = 0, offset_r18 = 0; - int i, found_prologue_end = 0; - - sym = kallsyms_lookup(pc, NULL, &offset, NULL, namebuf); - if (!sym) - return -EINVAL; - - prologue = pc - offset; - if (!prologue) - return -EINVAL; - - /* Validate fp, to avoid risk of dereferencing a bad pointer later. - Assume 128Mb since that's the amount of RAM on a Cayman. Modify - when there is an SH-5 board with more. */ - if ((fp < (unsigned long) phys_to_virt(__MEMORY_START)) || - (fp >= (unsigned long)(phys_to_virt(__MEMORY_START)) + 128*1024*1024) || - ((fp & 7) != 0)) { - return -EINVAL; - } - - /* - * Depth to walk, depth is completely arbitrary. - */ - for (i = 0; i < 100; i++, prologue += sizeof(unsigned long)) { - unsigned long op; - u8 major, minor; - u8 src, dest, disp; - - op = *(unsigned long *)prologue; - - major = (op >> 26) & 0x3f; - src = (op >> 20) & 0x3f; - minor = (op >> 16) & 0xf; - disp = (op >> 10) & 0x3f; - dest = (op >> 4) & 0x3f; - - /* - * Stack frame creation happens in a number of ways.. in the - * general case when the stack frame is less than 511 bytes, - * it's generally created by an addi or addi.l: - * - * addi/addi.l r15, -FRAME_SIZE, r15 - * - * in the event that the frame size is bigger than this, it's - * typically created using a movi/sub pair as follows: - * - * movi FRAME_SIZE, rX - * sub r15, rX, r15 - */ - - switch (major) { - case (0x00 >> 2): - switch (minor) { - case 0x8: /* add.l */ - case 0x9: /* add */ - /* Look for r15, r63, r14 */ - if (src == 15 && disp == 63 && dest == 14) - found_prologue_end = 1; - - break; - case 0xa: /* sub.l */ - case 0xb: /* sub */ - if (src != 15 || dest != 15) - continue; - - fp_displacement -= regcache[disp]; - fp_prev = fp - fp_displacement; - break; - } - break; - case (0xa8 >> 2): /* st.l */ - if (src != 15) - continue; - - switch (dest) { - case 14: - if (offset_r14 || fp_displacement == 0) - continue; - - offset_r14 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); - offset_r14 *= sizeof(unsigned long); - offset_r14 += fp_displacement; - break; - case 18: - if (offset_r18 || fp_displacement == 0) - continue; - - offset_r18 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); - offset_r18 *= sizeof(unsigned long); - offset_r18 += fp_displacement; - break; - } - - break; - case (0xcc >> 2): /* movi */ - if (dest >= 63) { - printk(KERN_NOTICE "%s: Invalid dest reg %d " - "specified in movi handler. Failed " - "opcode was 0x%lx: ", __FUNCTION__, - dest, op); - - continue; - } - - /* Sign extend */ - regcache[dest] = - ((((s64)(u64)op >> 10) & 0xffff) << 54) >> 54; - break; - case (0xd0 >> 2): /* addi */ - case (0xd4 >> 2): /* addi.l */ - /* Look for r15, -FRAME_SIZE, r15 */ - if (src != 15 || dest != 15) - continue; - - /* Sign extended frame size.. */ - fp_displacement += - (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); - fp_prev = fp - fp_displacement; - break; - } - - if (found_prologue_end && offset_r14 && (offset_r18 || *pprev_pc) && fp_prev) - break; - } - - if (offset_r14 == 0 || fp_prev == 0) { - if (!offset_r14) - pr_debug("Unable to find r14 offset\n"); - if (!fp_prev) - pr_debug("Unable to find previous fp\n"); - - return -EINVAL; - } - - /* For innermost leaf function, there might not be a offset_r18 */ - if (!*pprev_pc && (offset_r18 == 0)) - return -EINVAL; - - *pprev_fp = *(unsigned long *)(fp_prev + offset_r14); - - if (offset_r18) - *pprev_pc = *(unsigned long *)(fp_prev + offset_r18); - - *pprev_pc &= ~1; - - return 0; -} - -/* Don't put this on the stack since we'll want to call sh64_unwind - * when we're close to underflowing the stack anyway. */ -static struct pt_regs here_regs; - -extern const char syscall_ret; -extern const char ret_from_syscall; -extern const char ret_from_exception; -extern const char ret_from_irq; - -static void sh64_unwind_inner(struct pt_regs *regs); - -static void unwind_nested (unsigned long pc, unsigned long fp) -{ - if ((fp >= __MEMORY_START) && - ((fp & 7) == 0)) { - sh64_unwind_inner((struct pt_regs *) fp); - } -} - -static void sh64_unwind_inner(struct pt_regs *regs) -{ - unsigned long pc, fp; - int ofs = 0; - int first_pass; - - pc = regs->pc & ~1; - fp = regs->regs[14]; - - first_pass = 1; - for (;;) { - int cond; - unsigned long next_fp, next_pc; - - if (pc == ((unsigned long) &syscall_ret & ~1)) { - printk("SYSCALL\n"); - unwind_nested(pc,fp); - return; - } - - if (pc == ((unsigned long) &ret_from_syscall & ~1)) { - printk("SYSCALL (PREEMPTED)\n"); - unwind_nested(pc,fp); - return; - } - - /* In this case, the PC is discovered by lookup_prev_stack_frame but - it has 4 taken off it to look like the 'caller' */ - if (pc == ((unsigned long) &ret_from_exception & ~1)) { - printk("EXCEPTION\n"); - unwind_nested(pc,fp); - return; - } - - if (pc == ((unsigned long) &ret_from_irq & ~1)) { - printk("IRQ\n"); - unwind_nested(pc,fp); - return; - } - - cond = ((pc >= __MEMORY_START) && (fp >= __MEMORY_START) && - ((pc & 3) == 0) && ((fp & 7) == 0)); - - pc -= ofs; - - printk("[<%08lx>] ", pc); - print_symbol("%s\n", pc); - - if (first_pass) { - /* If the innermost frame is a leaf function, it's - * possible that r18 is never saved out to the stack. - */ - next_pc = regs->regs[18]; - } else { - next_pc = 0; - } - - if (lookup_prev_stack_frame(fp, pc, &next_fp, &next_pc, regs) == 0) { - ofs = sizeof(unsigned long); - pc = next_pc & ~1; - fp = next_fp; - } else { - printk("Unable to lookup previous stack frame\n"); - break; - } - first_pass = 0; - } - - printk("\n"); - -} - -void sh64_unwind(struct pt_regs *regs) -{ - if (!regs) { - /* - * Fetch current regs if we have no other saved state to back - * trace from. - */ - regs = &here_regs; - - __asm__ __volatile__ ("ori r14, 0, %0" : "=r" (regs->regs[14])); - __asm__ __volatile__ ("ori r15, 0, %0" : "=r" (regs->regs[15])); - __asm__ __volatile__ ("ori r18, 0, %0" : "=r" (regs->regs[18])); - - __asm__ __volatile__ ("gettr tr0, %0" : "=r" (regs->tregs[0])); - __asm__ __volatile__ ("gettr tr1, %0" : "=r" (regs->tregs[1])); - __asm__ __volatile__ ("gettr tr2, %0" : "=r" (regs->tregs[2])); - __asm__ __volatile__ ("gettr tr3, %0" : "=r" (regs->tregs[3])); - __asm__ __volatile__ ("gettr tr4, %0" : "=r" (regs->tregs[4])); - __asm__ __volatile__ ("gettr tr5, %0" : "=r" (regs->tregs[5])); - __asm__ __volatile__ ("gettr tr6, %0" : "=r" (regs->tregs[6])); - __asm__ __volatile__ ("gettr tr7, %0" : "=r" (regs->tregs[7])); - - __asm__ __volatile__ ( - "pta 0f, tr0\n\t" - "blink tr0, %0\n\t" - "0: nop" - : "=r" (regs->pc) - ); - } - - printk("\nCall Trace:\n"); - sh64_unwind_inner(regs); -} - diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S deleted file mode 100644 index f533a064da5f..000000000000 --- a/arch/sh64/kernel/vmlinux.lds.S +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh5/vmlinux.lds.S - * - * ld script to make ST50 Linux kernel - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * benedict.gaster@superh.com: 2nd May 2002 - * Add definition of empty_zero_page to be the first page of kernel image. - * - * benedict.gaster@superh.com: 3rd May 2002 - * Added support for ramdisk, removing statically linked romfs at the same time. - * - * lethal@linux-sh.org: 9th May 2003 - * Kill off GLOBAL_NAME() usage and other CDC-isms. - * - * lethal@linux-sh.org: 19th May 2003 - * Remove support for ancient toolchains. - */ - -#include <asm/page.h> -#include <asm/cache.h> -#include <asm/processor.h> -#include <asm/thread_info.h> - -#define LOAD_OFFSET CONFIG_CACHED_MEMORY_OFFSET -#include <asm-generic/vmlinux.lds.h> - -OUTPUT_ARCH(sh:sh5) - -#define C_PHYS(x) AT (ADDR(x) - LOAD_OFFSET) - -ENTRY(__start) -SECTIONS -{ - . = CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START + PAGE_SIZE; - _text = .; /* Text and read-only data */ - text = .; /* Text and read-only data */ - - .empty_zero_page : C_PHYS(.empty_zero_page) { - *(.empty_zero_page) - } = 0 - - .text : C_PHYS(.text) { - *(.text.head) - TEXT_TEXT - *(.text64) - *(.text..SHmedia32) - SCHED_TEXT - LOCK_TEXT - *(.fixup) - *(.gnu.warning) -#ifdef CONFIG_LITTLE_ENDIAN - } = 0x6ff0fff0 -#else - } = 0xf0fff06f -#endif - - /* We likely want __ex_table to be Cache Line aligned */ - . = ALIGN(L1_CACHE_BYTES); /* Exception table */ - __start___ex_table = .; - __ex_table : C_PHYS(__ex_table) { *(__ex_table) } - __stop___ex_table = .; - - _etext = .; /* End of text section */ - - NOTES - - RODATA - - .data : C_PHYS(.data) { /* Data */ - DATA_DATA - CONSTRUCTORS - } - - . = ALIGN(PAGE_SIZE); - .data.page_aligned : C_PHYS(.data.page_aligned) { *(.data.page_aligned) } - - PERCPU(PAGE_SIZE) - - . = ALIGN(L1_CACHE_BYTES); - .data.cacheline_aligned : C_PHYS(.data.cacheline_aligned) { *(.data.cacheline_aligned) } - - _edata = .; /* End of data section */ - - . = ALIGN(THREAD_SIZE); /* init_task: structure size aligned */ - .data.init_task : C_PHYS(.data.init_task) { *(.data.init_task) } - - . = ALIGN(PAGE_SIZE); /* Init code and data */ - __init_begin = .; - _sinittext = .; - .init.text : C_PHYS(.init.text) { *(.init.text) } - _einittext = .; - .init.data : C_PHYS(.init.data) { *(.init.data) } - . = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */ - __setup_start = .; - .init.setup : C_PHYS(.init.setup) { *(.init.setup) } - __setup_end = .; - __initcall_start = .; - .initcall.init : C_PHYS(.initcall.init) { - INITCALLS - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : C_PHYS(.con_initcall.init) { *(.con_initcall.init) } - __con_initcall_end = .; - SECURITY_INIT - -#ifdef CONFIG_BLK_DEV_INITRD - __initramfs_start = .; - .init.ramfs : C_PHYS(.init.ramfs) { *(.init.ramfs) } - __initramfs_end = .; -#endif - - . = ALIGN(PAGE_SIZE); - __init_end = .; - - /* Align to the biggest single data representation, head and tail */ - . = ALIGN(8); - __bss_start = .; /* BSS */ - .bss : C_PHYS(.bss) { - *(.bss) - } - . = ALIGN(8); - _end = . ; - - /* Sections to be discarded */ - /DISCARD/ : { - *(.exit.text) - *(.exit.data) - *(.exitcall.exit) - } - - STABS_DEBUG - DWARF_DEBUG -} |