diff options
Diffstat (limited to 'arch/cris/arch-v32/kernel')
-rw-r--r-- | arch/cris/arch-v32/kernel/Makefile | 18 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/cache.c | 34 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/cacheflush.S | 100 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/crisksyms.c | 26 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/debugport.c | 232 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/entry.S | 909 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/fasttimer.c | 793 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/head.S | 439 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/irq.c | 520 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/kgdb.c | 1593 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/kgdb_asm.S | 552 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/process.c | 180 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/ptrace.c | 492 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/setup.c | 163 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/signal.c | 541 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/time.c | 345 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/traps.c | 196 |
17 files changed, 0 insertions, 7133 deletions
diff --git a/arch/cris/arch-v32/kernel/Makefile b/arch/cris/arch-v32/kernel/Makefile deleted file mode 100644 index 2db7e4f7c1fa..000000000000 --- a/arch/cris/arch-v32/kernel/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the linux kernel. -# - -extra-y := head.o - - -obj-y := entry.o traps.o irq.o debugport.o \ - process.o ptrace.o setup.o signal.o traps.o time.o \ - cache.o cacheflush.o - -obj-$(CONFIG_ETRAX_KGDB) += kgdb.o kgdb_asm.o -obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o -obj-$(CONFIG_MODULES) += crisksyms.o - -clean: - diff --git a/arch/cris/arch-v32/kernel/cache.c b/arch/cris/arch-v32/kernel/cache.c deleted file mode 100644 index a080d2fa4803..000000000000 --- a/arch/cris/arch-v32/kernel/cache.c +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/module.h> -#include <asm/io.h> -#include <arch/cache.h> -#include <arch/hwregs/dma.h> - -/* This file is used to workaround a cache bug, Guinness TR 106. */ - -inline void flush_dma_descr(struct dma_descr_data *descr, int flush_buf) -{ - /* Flush descriptor to make sure we get correct in_eop and after. */ - asm volatile ("ftagd [%0]" :: "r" (descr)); - /* Flush buffer pointed out by descriptor. */ - if (flush_buf) - cris_flush_cache_range(phys_to_virt((unsigned)descr->buf), - (unsigned)(descr->after - descr->buf)); -} -EXPORT_SYMBOL(flush_dma_descr); - -void flush_dma_list(struct dma_descr_data *descr) -{ - while (1) { - flush_dma_descr(descr, 1); - if (descr->eol) - break; - descr = phys_to_virt((unsigned)descr->next); - } -} -EXPORT_SYMBOL(flush_dma_list); - -/* From cacheflush.S */ -EXPORT_SYMBOL(cris_flush_cache); -/* From cacheflush.S */ -EXPORT_SYMBOL(cris_flush_cache_range); diff --git a/arch/cris/arch-v32/kernel/cacheflush.S b/arch/cris/arch-v32/kernel/cacheflush.S deleted file mode 100644 index 2a54d793f96c..000000000000 --- a/arch/cris/arch-v32/kernel/cacheflush.S +++ /dev/null @@ -1,100 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - .global cris_flush_cache_range - .type cris_flush_cache_range, @function -cris_flush_cache_range: - move.d 1024, $r12 - cmp.d $r11, $r12 - bhi cris_flush_1KB - nop - add.d $r10, $r11 - ftagd [$r10] -cris_flush_last: - addq 32, $r10 - cmp.d $r11, $r10 - blt cris_flush_last - ftagd [$r10] - ret - nop -cris_flush_1KB: - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ftagd [$r10] - addq 32, $r10 - ba cris_flush_cache_range - sub.d $r12, $r11 - .size cris_flush_cache_range, . - cris_flush_cache_range - - .global cris_flush_cache - .type cris_flush_cache, @function -cris_flush_cache: - moveq 0, $r10 -cris_flush_line: - move.d 16*1024, $r11 - addq 16, $r10 - cmp.d $r10, $r11 - blt cris_flush_line - fidxd [$r10] - ret - nop - .size cris_flush_cache, . - cris_flush_cache - diff --git a/arch/cris/arch-v32/kernel/crisksyms.c b/arch/cris/arch-v32/kernel/crisksyms.c deleted file mode 100644 index 8cc8ad1cb532..000000000000 --- a/arch/cris/arch-v32/kernel/crisksyms.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/module.h> -#include <linux/irq.h> -#include <arch/dma.h> -#include <arch/intmem.h> -#include <mach/pinmux.h> - -/* Functions for allocating DMA channels */ -EXPORT_SYMBOL(crisv32_request_dma); -EXPORT_SYMBOL(crisv32_free_dma); - -/* Functions for handling internal RAM */ -EXPORT_SYMBOL(crisv32_intmem_alloc); -EXPORT_SYMBOL(crisv32_intmem_free); -EXPORT_SYMBOL(crisv32_intmem_phys_to_virt); -EXPORT_SYMBOL(crisv32_intmem_virt_to_phys); - -/* Functions for handling pinmux */ -EXPORT_SYMBOL(crisv32_pinmux_alloc); -EXPORT_SYMBOL(crisv32_pinmux_alloc_fixed); -EXPORT_SYMBOL(crisv32_pinmux_dealloc); -EXPORT_SYMBOL(crisv32_pinmux_dealloc_fixed); - -/* Functions masking/unmasking interrupts */ -EXPORT_SYMBOL(crisv32_mask_irq); -EXPORT_SYMBOL(crisv32_unmask_irq); diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c deleted file mode 100644 index 69247fd2090a..000000000000 --- a/arch/cris/arch-v32/kernel/debugport.c +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2003, Axis Communications AB. - */ - -#include <linux/console.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/string.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/reg_map.h> -#include <hwregs/ser_defs.h> -#include <hwregs/dma_defs.h> -#include <mach/pinmux.h> - -struct dbg_port -{ - unsigned char nbr; - unsigned long instance; - unsigned int started; - unsigned long baudrate; - unsigned char parity; - unsigned int bits; -}; - -struct dbg_port ports[] = -{ - { - 0, - regi_ser0, - 0, - 115200, - 'N', - 8 - }, - { - 1, - regi_ser1, - 0, - 115200, - 'N', - 8 - }, - { - 2, - regi_ser2, - 0, - 115200, - 'N', - 8 - }, - { - 3, - regi_ser3, - 0, - 115200, - 'N', - 8 - }, -#if CONFIG_ETRAX_SERIAL_PORTS == 5 - { - 4, - regi_ser4, - 0, - 115200, - 'N', - 8 - }, -#endif -}; - -static struct dbg_port *port = -#if defined(CONFIG_ETRAX_DEBUG_PORT0) - &ports[0]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT1) - &ports[1]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT2) - &ports[2]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT3) - &ports[3]; -#else - NULL; -#endif - -#ifdef CONFIG_ETRAX_KGDB -static struct dbg_port *kgdb_port = -#if defined(CONFIG_ETRAX_KGDB_PORT0) - &ports[0]; -#elif defined(CONFIG_ETRAX_KGDB_PORT1) - &ports[1]; -#elif defined(CONFIG_ETRAX_KGDB_PORT2) - &ports[2]; -#elif defined(CONFIG_ETRAX_KGDB_PORT3) - &ports[3]; -#elif defined(CONFIG_ETRAX_KGDB_PORT4) - &ports[4]; -#else - NULL; -#endif -#endif - -static void start_port(struct dbg_port *p) -{ - /* Set up serial port registers */ - reg_ser_rw_tr_ctrl tr_ctrl = {0}; - reg_ser_rw_tr_dma_en tr_dma_en = {0}; - - reg_ser_rw_rec_ctrl rec_ctrl = {0}; - reg_ser_rw_tr_baud_div tr_baud_div = {0}; - reg_ser_rw_rec_baud_div rec_baud_div = {0}; - - if (!p || p->started) - return; - - p->started = 1; - - if (p->nbr == 1) - crisv32_pinmux_alloc_fixed(pinmux_ser1); - else if (p->nbr == 2) - crisv32_pinmux_alloc_fixed(pinmux_ser2); - else if (p->nbr == 3) - crisv32_pinmux_alloc_fixed(pinmux_ser3); -#if CONFIG_ETRAX_SERIAL_PORTS == 5 - else if (p->nbr == 4) - crisv32_pinmux_alloc_fixed(pinmux_ser4); -#endif - - tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493; - tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no; - tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8; - tr_ctrl.en = rec_ctrl.en = 1; - - if (p->parity == 'O') { - tr_ctrl.par_en = regk_ser_yes; - tr_ctrl.par = regk_ser_odd; - rec_ctrl.par_en = regk_ser_yes; - rec_ctrl.par = regk_ser_odd; - } else if (p->parity == 'E') { - tr_ctrl.par_en = regk_ser_yes; - tr_ctrl.par = regk_ser_even; - rec_ctrl.par_en = regk_ser_yes; - rec_ctrl.par = regk_ser_odd; - } - - if (p->bits == 7) { - tr_ctrl.data_bits = regk_ser_bits7; - rec_ctrl.data_bits = regk_ser_bits7; - } - - REG_WR (ser, p->instance, rw_tr_baud_div, tr_baud_div); - REG_WR (ser, p->instance, rw_rec_baud_div, rec_baud_div); - REG_WR (ser, p->instance, rw_tr_dma_en, tr_dma_en); - REG_WR (ser, p->instance, rw_tr_ctrl, tr_ctrl); - REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); -} - -#ifdef CONFIG_ETRAX_KGDB -/* Use polling to get a single character from the kernel debug port */ -int getDebugChar(void) -{ - reg_ser_rs_stat_din stat; - reg_ser_rw_ack_intr ack_intr = { 0 }; - - do { - stat = REG_RD(ser, kgdb_port->instance, rs_stat_din); - } while (!stat.dav); - - /* Ack the data_avail interrupt. */ - ack_intr.dav = 1; - REG_WR(ser, kgdb_port->instance, rw_ack_intr, ack_intr); - - return stat.data; -} - -/* Use polling to put a single character to the kernel debug port */ -void putDebugChar(int val) -{ - reg_ser_r_stat_din stat; - do { - stat = REG_RD(ser, kgdb_port->instance, r_stat_din); - } while (!stat.tr_rdy); - REG_WR_INT(ser, kgdb_port->instance, rw_dout, val); -} -#endif /* CONFIG_ETRAX_KGDB */ - -static void __init early_putch(int c) -{ - reg_ser_r_stat_din stat; - /* Wait until transmitter is ready and send. */ - do - stat = REG_RD(ser, port->instance, r_stat_din); - while (!stat.tr_rdy); - REG_WR_INT(ser, port->instance, rw_dout, c); -} - -static void __init -early_console_write(struct console *con, const char *s, unsigned n) -{ - extern void reset_watchdog(void); - int i; - - /* Send data. */ - for (i = 0; i < n; i++) { - /* TODO: the '\n' -> '\n\r' translation should be done at the - receiver. Remove it when the serial driver removes it. */ - if (s[i] == '\n') - early_putch('\r'); - early_putch(s[i]); - reset_watchdog(); - } -} - -static struct console early_console_dev __initdata = { - .name = "early", - .write = early_console_write, - .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1 -}; - -/* Register console for printk's, etc. */ -int __init init_etrax_debug(void) -{ - start_port(port); - - /* Register an early console if a debug port was chosen. */ - register_console(&early_console_dev); - -#ifdef CONFIG_ETRAX_KGDB - start_port(kgdb_port); -#endif /* CONFIG_ETRAX_KGDB */ - return 0; -} diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S deleted file mode 100644 index 0793a52b2c34..000000000000 --- a/arch/cris/arch-v32/kernel/entry.S +++ /dev/null @@ -1,909 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2000-2003 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * Tobias Anderberg (tobiasa@axis.com), CRISv32 port. - * - * Code for the system-call and fault low-level handling routines. - * - * NOTE: This code handles signal-recognition, which happens every time - * after a timer-interrupt and after each system call. - * - * Stack layout in 'ret_from_system_call': - * ptrace needs to have all regs on the stack. - * if the order here is changed, it needs to be - * updated in fork.c:copy_process, signal.c:do_signal, - * ptrace.c and ptrace.h - * - */ - -#include <linux/linkage.h> -#include <linux/sys.h> -#include <asm/unistd.h> -#include <asm/errno.h> -#include <asm/thread_info.h> -#include <asm/asm-offsets.h> - -#include <hwregs/asm/reg_map_asm.h> -#include <hwregs/asm/intr_vect_defs_asm.h> - - ;; Exported functions. - .globl system_call - .globl ret_from_intr - .globl ret_from_fork - .globl ret_from_kernel_thread - .globl resume - .globl multiple_interrupt - .globl nmi_interrupt - .globl spurious_interrupt - .globl do_sigtrap - .globl gdb_handle_exception - .globl sys_call_table - - ; Check if preemptive kernel scheduling should be done. -#ifdef CONFIG_PREEMPT -_resume_kernel: - di - ; Load current task struct. - movs.w -8192, $r0 ; THREAD_SIZE = 8192 - and.d $sp, $r0 - - addoq +TI_preempt_count, $r0, $acr - move.d [$acr], $r10 ; Preemption disabled? - bne _Rexit - nop - -_need_resched: - addoq +TI_flags, $r0, $acr - move.d [$acr], $r10 - btstq TIF_NEED_RESCHED, $r10 ; Check if need_resched is set. - bpl _Rexit - nop - - ; Do preemptive kernel scheduling. - jsr preempt_schedule_irq - nop - - ; Load new task struct. - movs.w -8192, $r0 ; THREAD_SIZE = 8192. - and.d $sp, $r0 - - ; One more time with new task. - ba _need_resched - nop -#else -#define _resume_kernel _Rexit -#endif - - ; Called at exit from fork. schedule_tail must be called to drop - ; spinlock if CONFIG_PREEMPT. - .type ret_from_fork,@function -ret_from_fork: - jsr schedule_tail - nop - ba ret_from_sys_call - nop - .size ret_from_fork, . - ret_from_fork - - .type ret_from_kernel_thread,@function -ret_from_kernel_thread: - jsr schedule_tail - nop - move.d $r2, $r10 - jsr $r1 - nop - moveq 0, $r9 ; no syscall restarts, TYVM... - ba ret_from_sys_call - nop - .size ret_from_kernel_thread, . - ret_from_kernel_thread - - .type ret_from_intr,@function -ret_from_intr: - moveq 0, $r9 ; not a syscall - - ;; Check for resched if preemptive kernel, or if we're going back to - ;; user-mode. This test matches the user_regs(regs) macro. Don't simply - ;; test CCS since that doesn't necessarily reflect what mode we'll - ;; return into. - addoq +PT_ccs, $sp, $acr - move.d [$acr], $r0 - btstq 16, $r0 ; User-mode flag. - bpl _resume_kernel - .size ret_from_intr, . - ret_from_intr + 2 ; +2 includes the dslot. - - ; Note that di below is in delay slot. - .type _resume_userspace,@function -_resume_userspace: - di ; So need_resched and sigpending don't change. - - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - addoq +TI_flags, $r0, $acr ; current->work - move.d [$acr], $r10 - and.d _TIF_WORK_MASK, $r10 ; Work to be done on return? - bne _work_pending - nop - ba _Rexit - nop - .size _resume_userspace, . - _resume_userspace - - ;; The system_call is called by a BREAK instruction, which looks pretty - ;; much like any other exception. - ;; - ;; System calls can't be made from interrupts but we still stack ERP - ;; to have a complete stack frame. - ;; - ;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12, - ;; r13,mof,srp - ;; - ;; This function looks on the _surface_ like spaghetti programming, but it's - ;; really designed so that the fast-path does not force cache-loading of - ;; non-used instructions. Only the non-common cases cause the outlined code - ;; to run.. - - .type system_call,@function -system_call: - ;; Stack-frame similar to the irq heads, which is reversed in - ;; ret_from_sys_call. - - sub.d 92, $sp ; Skip EDA. - movem $r13, [$sp] - move.d $sp, $r8 - addq 14*4, $r8 - move.d $acr, $r0 - move $srs, $r1 - move $mof, $r2 - move $spc, $r3 - move $ccs, $r4 - move $srp, $r5 - move $erp, $r6 - move.d $r9, $r7 ; Store syscall number in EXS - subq 4, $sp - movem $r7, [$r8] - ei ; Enable interrupts while processing syscalls. - move.d $r10, [$sp] - - ; Set S-bit when kernel debugging to keep hardware breakpoints active. -#ifdef CONFIG_ETRAX_KGDB - move $ccs, $r0 - or.d (1<<9), $r0 - move $r0, $ccs -#endif - - movs.w -ENOSYS, $r0 - addoq +PT_r10, $sp, $acr - move.d $r0, [$acr] - - ;; Check if this process is syscall-traced. - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - addoq +TI_flags, $r0, $acr - move.d [$acr], $r0 - btstq TIF_SYSCALL_TRACE, $r0 - bmi _syscall_trace_entry - nop - -_syscall_traced: - ;; Check for sanity in the requested syscall number. - cmpu.w NR_syscalls, $r9 - bhs ret_from_sys_call - lslq 2, $r9 ; Multiply by 4, in the delay slot. - - ;; The location on the stack for the register structure is passed as a - ;; seventh argument. Some system calls need this. - move.d $sp, $r0 - subq 4, $sp - move.d $r0, [$sp] - - ;; The registers carrying parameters (R10-R13) are intact. The optional - ;; fifth and sixth parameters is in MOF and SRP respectively. Put them - ;; back on the stack. - subq 4, $sp - move $srp, [$sp] - subq 4, $sp - move $mof, [$sp] - - ;; Actually to the system call. - addo.d +sys_call_table, $r9, $acr - move.d [$acr], $acr - jsr $acr - nop - - addq 3*4, $sp ; Pop the mof, srp and regs parameters. - addoq +PT_r10, $sp, $acr - move.d $r10, [$acr] ; Save the return value. - - moveq 1, $r9 ; "Parameter" to ret_from_sys_call to - ; show it was a sys call. - - ;; Fall through into ret_from_sys_call to return. - -ret_from_sys_call: - ;; R9 is a parameter: - ;; >= 1 from syscall - ;; 0 from irq - - ;; Get the current task-struct pointer. - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - di ; Make sure need_resched and sigpending don't change. - - addoq +TI_flags, $r0, $acr - move.d [$acr], $r1 - and.d _TIF_ALLWORK_MASK, $r1 - bne _syscall_exit_work - nop - .size system_call, . - system_call - - .type _Rexit,@function -_Rexit: -#if defined(CONFIG_TRACE_IRQFLAGS) - addoq +PT_ccs, $sp, $acr - move.d [$acr], $r0 - btstq 15, $r0 ; I1 - bpl 1f - nop - jsr trace_hardirqs_on - nop -1: -#endif - - ;; This epilogue MUST match the prologues in multiple_interrupt, irq.h - ;; and ptregs.h. - addq 4, $sp ; Skip orig_r10. - movem [$sp+], $r13 ; Registers R0-R13. - move.d [$sp+], $acr - move [$sp], $srs - addq 4, $sp - move [$sp+], $mof - move [$sp+], $spc - move [$sp+], $ccs - move [$sp+], $srp - move [$sp+], $erp - addq 8, $sp ; Skip EXS, EDA. - jump $erp - rfe ; Restore condition code stack in delay-slot. - .size _Rexit, . - _Rexit - - ;; We get here after doing a syscall if extra work might need to be done - ;; perform syscall exit tracing if needed. - - .type _syscall_exit_work,@function -_syscall_exit_work: - ;; R0 contains current at this point and irq's are disabled. - - addoq +TI_flags, $r0, $acr - move.d [$acr], $r1 - btstq TIF_SYSCALL_TRACE, $r1 - bpl _work_pending - nop - ei - move.d $r9, $r1 ; Preserve R9. - jsr do_syscall_trace - nop - move.d $r1, $r9 - ba _resume_userspace - nop - .size _syscall_exit_work, . - _syscall_exit_work - - .type _work_pending,@function -_work_pending: - addoq +TI_flags, $r0, $acr - move.d [$acr], $r12 ; The thread_info_flags parameter. - move.d $sp, $r11 ; The regs param. - jsr do_work_pending - move.d $r9, $r10 ; The syscall/irq param. - - ba _Rexit - nop - .size _work_pending, . - _work_pending - - ;; We get here as a sidetrack when we've entered a syscall with the - ;; trace-bit set. We need to call do_syscall_trace and then continue - ;; with the call. - -_syscall_trace_entry: - ;; PT_r10 in the frame contains -ENOSYS as required, at this point. - - jsr do_syscall_trace - nop - - ;; Now re-enter the syscall code to do the syscall itself. We need to - ;; restore R9 here to contain the wanted syscall, and the other - ;; parameter-bearing registers. - addoq +PT_r9, $sp, $acr - move.d [$acr], $r9 - addoq +PT_orig_r10, $sp, $acr - move.d [$acr], $r10 ; PT_r10 is already -ENOSYS. - addoq +PT_r11, $sp, $acr - move.d [$acr], $r11 - addoq +PT_r12, $sp, $acr - move.d [$acr], $r12 - addoq +PT_r13, $sp, $acr - move.d [$acr], $r13 - addoq +PT_mof, $sp, $acr - move [$acr], $mof - addoq +PT_srp, $sp, $acr - move [$acr], $srp - - ba _syscall_traced - nop - - ;; Resume performs the actual task-switching, by switching stack - ;; pointers. Input arguments are: - ;; - ;; R10 = prev - ;; R11 = next - ;; R12 = thread offset in task struct. - ;; - ;; Returns old current in R10. - - .type resume,@function -resume: - subq 4, $sp ; Make space for srp. - - add.d $r12, $r10 ; R10 = current tasks tss. - addoq +THREAD_ccs, $r10, $acr - move $srp, [$sp] ; Keep old/new PC on the stack. - move $ccs, [$acr] ; Save IRQ enable state. - di - - addoq +THREAD_usp, $r10, $acr - subq 10*4, $sp ; Make room for R9. - move $usp, [$acr] ; Save user-mode stackpointer. - - ;; See copy_thread for the reason why register R9 is saved. - movem $r9, [$sp] ; Save non-scratch registers and R9. - - addoq +THREAD_ksp, $r10, $acr - move.d $sp, $r10 ; Return last running task in R10. - move.d $sp, [$acr] ; Save kernel SP for old task. - - and.d -8192, $r10 ; Get thread_info from stackpointer. - addoq +TI_task, $r10, $acr - add.d $r12, $r11 ; Find the new tasks tss. - move.d [$acr], $r10 ; Get task. - addoq +THREAD_ksp, $r11, $acr - move.d [$acr], $sp ; Switch to new stackframe. - addoq +THREAD_usp, $r11, $acr - movem [$sp+], $r9 ; Restore non-scratch registers and R9. - - move [$acr], $usp ; Restore user-mode stackpointer. - - addoq +THREAD_ccs, $r11, $acr - move.d [$sp+], $r11 - jump $r11 ; Restore PC. - move [$acr], $ccs ; Restore IRQ enable status. - .size resume, . - resume - -nmi_interrupt: - -;; If we receive a watchdog interrupt while it is not expected, then set -;; up a canonical frame and dump register contents before dying. - - ;; This prologue MUST match the one in irq.h and the struct in ptregs.h! - subq 12, $sp ; Skip EXS, EDA. - move $nrp, [$sp] - subq 4, $sp - move $srp, [$sp] - subq 4, $sp - move $ccs, [$sp] - subq 4, $sp - move $spc, [$sp] - subq 4, $sp - move $mof, [$sp] - subq 4, $sp - move $srs, [$sp] - subq 4, $sp - move.d $acr, [$sp] - subq 14*4, $sp ; Make room for R0-R13. - movem $r13, [$sp] ; Push R0-R13. - subq 4, $sp - move.d $r10, [$sp] ; Push orig_r10. - move.d REG_ADDR(intr_vect, regi_irq, r_nmi), $r0 - move.d [$r0], $r0 - btstq REG_BIT(intr_vect, r_nmi, watchdog), $r0 - bpl 1f - nop - jsr handle_watchdog_bite ; In time.c. - move.d $sp, $r10 ; Pointer to registers -1: btstq REG_BIT(intr_vect, r_nmi, ext), $r0 - bpl 1f - nop - jsr handle_nmi - move.d $sp, $r10 ; Pointer to registers -1: addq 4, $sp ; Skip orig_r10 - movem [$sp+], $r13 - move.d [$sp+], $acr - move [$sp], $srs - addq 4, $sp - move [$sp+], $mof - move [$sp+], $spc - move [$sp+], $ccs - move [$sp+], $srp - move [$sp+], $nrp - addq 8, $sp ; Skip EXS, EDA. - jump $nrp - rfn - - .comm cause_of_death, 4 ;; Don't declare this anywhere. - -spurious_interrupt: - di - jump hard_reset_now - nop - - ;; This handles the case when multiple interrupts arrive at the same - ;; time. Jump to the first set interrupt bit in a priority fashion. The - ;; hardware will call the unserved interrupts after the handler - ;; finishes. - .type multiple_interrupt, @function -multiple_interrupt: - ;; This prologue MUST match the one in irq.h and the struct in ptregs.h! - subq 12, $sp ; Skip EXS, EDA. - move $erp, [$sp] - subq 4, $sp - move $srp, [$sp] - subq 4, $sp - move $ccs, [$sp] - subq 4, $sp - move $spc, [$sp] - subq 4, $sp - move $mof, [$sp] - subq 4, $sp - move $srs, [$sp] - subq 4, $sp - move.d $acr, [$sp] - subq 14*4, $sp ; Make room for R0-R13. - movem $r13, [$sp] ; Push R0-R13. - subq 4, $sp - move.d $r10, [$sp] ; Push orig_r10. - -; Set S-bit when kernel debugging to keep hardware breakpoints active. -#ifdef CONFIG_ETRAX_KGDB - move $ccs, $r0 - or.d (1<<9), $r0 - move $r0, $ccs -#endif - - jsr crisv32_do_multiple - move.d $sp, $r10 - jump ret_from_intr - nop - .size multiple_interrupt, . - multiple_interrupt - -do_sigtrap: - ;; Sigtraps the process that executed the BREAK instruction. Creates a - ;; frame that Rexit expects. - subq 4, $sp - move $eda, [$sp] - subq 4, $sp - move $exs, [$sp] - subq 4, $sp - move $erp, [$sp] - subq 4, $sp - move $srp, [$sp] - subq 4, $sp - move $ccs, [$sp] - subq 4, $sp - move $spc, [$sp] - subq 4, $sp - move $mof, [$sp] - subq 4, $sp - move $srs, [$sp] - subq 4, $sp - move.d $acr, [$sp] - di ; Need to disable irq's at this point. - subq 14*4, $sp ; Make room for r0-r13. - movem $r13, [$sp] ; Push the r0-r13 registers. - subq 4, $sp - move.d $r10, [$sp] ; Push orig_r10. - - movs.w -8192, $r9 ; THREAD_SIZE == 8192 - and.d $sp, $r9 - - ;; thread_info as first parameter - move.d $r9, $r10 - moveq 5, $r11 ; SIGTRAP as second argument. - jsr ugdb_trap_user - nop - jump ret_from_intr ; Use the return routine for interrupts. - nop - -gdb_handle_exception: - subq 4, $sp - move.d $r0, [$sp] -#ifdef CONFIG_ETRAX_KGDB - move $ccs, $r0 ; U-flag not affected by previous insns. - btstq 16, $r0 ; Test the U-flag. - bmi _ugdb_handle_exception ; Go to user mode debugging. - nop ; Empty delay-slot (cannot pop R0 here). - ba kgdb_handle_exception ; Go to kernel debugging. - move.d [$sp+], $r0 ; Restore R0 in delay slot. -#endif - -_ugdb_handle_exception: - ba do_sigtrap ; SIGTRAP the offending process. - move.d [$sp+], $r0 ; Restore R0 in delay slot. - - .data - - .section .rodata,"a" -sys_call_table: - .long sys_restart_syscall ; 0 - old "setup()" system call, used - ; for restarting. - .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 sys_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 /* old sys_olduname holder */ - .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_select /* was old_select in Linux/E100 */ - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long sys_old_readdir - .long sys_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 /* sys_ioperm in i386 */ - .long sys_socketcall - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_ni_syscall /* old sys_uname holder */ - .long sys_ni_syscall /* sys_iopl in i386 */ - .long sys_vhangup - .long sys_ni_syscall /* old "idle" system call */ - .long sys_ni_syscall /* vm86old in i386 */ - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc - .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 /* sys_vm86 */ - .long sys_ni_syscall /* Old sys_query_module */ - .long sys_poll - .long sys_ni_syscall /* Old 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 - .long sys_getdents64 /* 220 */ - .long sys_fcntl64 - .long sys_ni_syscall /* reserved for TUX */ - .long sys_ni_syscall - .long sys_gettid - .long sys_readahead /* 225 */ - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr /* 230 */ - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr /* 235 */ - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill - .long sys_sendfile64 - .long sys_futex /* 240 */ - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_ni_syscall /* sys_set_thread_area */ - .long sys_ni_syscall /* sys_get_thread_area */ - .long sys_io_setup /* 245 */ - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel - .long sys_fadvise64 /* 250 */ - .long sys_ni_syscall - .long sys_exit_group - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl /* 255 */ - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime /* 260 */ - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime /* 265 */ - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill /* 270 */ - .long sys_utimes - .long sys_fadvise64_64 - .long sys_ni_syscall /* sys_vserver */ - .long sys_ni_syscall /* sys_mbind */ - .long sys_ni_syscall /* 275 sys_get_mempolicy */ - .long sys_ni_syscall /* sys_set_mempolicy */ - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive /* 280 */ - .long sys_mq_notify - .long sys_mq_getsetattr - .long sys_ni_syscall /* reserved for kexec */ - .long sys_waitid - .long sys_ni_syscall /* 285 */ /* available */ - .long sys_add_key - .long sys_request_key - .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get /* 290 */ - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_migrate_pages - .long sys_openat /* 295 */ - .long sys_mkdirat - .long sys_mknodat - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 /* 300 */ - .long sys_unlinkat - .long sys_renameat - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat /* 305 */ - .long sys_fchmodat - .long sys_faccessat - .long sys_pselect6 - .long sys_ppoll - .long sys_unshare /* 310 */ - .long sys_set_robust_list - .long sys_get_robust_list - .long sys_splice - .long sys_sync_file_range - .long sys_tee /* 315 */ - .long sys_vmsplice - .long sys_move_pages - .long sys_getcpu - .long sys_epoll_pwait - .long sys_utimensat /* 320 */ - .long sys_signalfd - .long sys_timerfd_create - .long sys_eventfd - .long sys_fallocate - .long sys_timerfd_settime /* 325 */ - .long sys_timerfd_gettime - .long sys_signalfd4 - .long sys_eventfd2 - .long sys_epoll_create1 - .long sys_dup3 /* 330 */ - .long sys_pipe2 - .long sys_inotify_init1 - .long sys_preadv - .long sys_pwritev - .long sys_setns /* 335 */ - .long sys_name_to_handle_at - .long sys_open_by_handle_at - .long sys_rt_tgsigqueueinfo - .long sys_perf_event_open - .long sys_recvmmsg /* 340 */ - .long sys_accept4 - .long sys_fanotify_init - .long sys_fanotify_mark - .long sys_prlimit64 - .long sys_clock_adjtime /* 345 */ - .long sys_syncfs - .long sys_sendmmsg - .long sys_process_vm_readv - .long sys_process_vm_writev - .long sys_kcmp /* 350 */ - .long sys_finit_module - .long sys_sched_setattr - .long sys_sched_getattr - .long sys_renameat2 - .long sys_seccomp /* 355 */ - .long sys_getrandom - .long sys_memfd_create - .long sys_bpf - .long sys_execveat - - /* - * NOTE!! This doesn't have to be exact - we just have - * to make sure we have _enough_ of the "sys_ni_syscall" - * entries. Don't panic if you notice that this hasn't - * been shrunk every time we add a new system call. - */ - - .rept NR_syscalls - (.-sys_call_table) / 4 - .long sys_ni_syscall - .endr - diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c deleted file mode 100644 index 7452c70f61ff..000000000000 --- a/arch/cris/arch-v32/kernel/fasttimer.c +++ /dev/null @@ -1,793 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/fasttimer.c - * - * Fast timers for ETRAX FS - * - * Copyright (C) 2000-2006 Axis Communications AB, Lund, Sweden - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/vmalloc.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/delay.h> - -#include <asm/irq.h> - -#include <hwregs/reg_map.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/timer_defs.h> -#include <asm/fasttimer.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -/* - * timer0 is running at 100MHz and generating jiffies timer ticks - * at 100 or 1000 HZ. - * fasttimer gives an API that gives timers that expire "between" the jiffies - * giving microsecond resolution (10 ns). - * fasttimer uses reg_timer_rw_trig register to get interrupt when - * r_time reaches a certain value. - */ - - -#define DEBUG_LOG_INCLUDED -#define FAST_TIMER_LOG -/* #define FAST_TIMER_TEST */ - -#define FAST_TIMER_SANITY_CHECKS - -#ifdef FAST_TIMER_SANITY_CHECKS -static int sanity_failed; -#endif - -#define D1(x) -#define D2(x) -#define DP(x) - -static unsigned int fast_timer_running; -static unsigned int fast_timers_added; -static unsigned int fast_timers_started; -static unsigned int fast_timers_expired; -static unsigned int fast_timers_deleted; -static unsigned int fast_timer_is_init; -static unsigned int fast_timer_ints; - -struct fast_timer *fast_timer_list = NULL; - -#ifdef DEBUG_LOG_INCLUDED -#define DEBUG_LOG_MAX 128 -static const char * debug_log_string[DEBUG_LOG_MAX]; -static unsigned long debug_log_value[DEBUG_LOG_MAX]; -static unsigned int debug_log_cnt; -static unsigned int debug_log_cnt_wrapped; - -#define DEBUG_LOG(string, value) \ -{ \ - unsigned long log_flags; \ - local_irq_save(log_flags); \ - debug_log_string[debug_log_cnt] = (string); \ - debug_log_value[debug_log_cnt] = (unsigned long)(value); \ - if (++debug_log_cnt >= DEBUG_LOG_MAX) \ - { \ - debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \ - debug_log_cnt_wrapped = 1; \ - } \ - local_irq_restore(log_flags); \ -} -#else -#define DEBUG_LOG(string, value) -#endif - - -#define NUM_TIMER_STATS 16 -#ifdef FAST_TIMER_LOG -struct fast_timer timer_added_log[NUM_TIMER_STATS]; -struct fast_timer timer_started_log[NUM_TIMER_STATS]; -struct fast_timer timer_expired_log[NUM_TIMER_STATS]; -#endif - -int timer_div_settings[NUM_TIMER_STATS]; -int timer_delay_settings[NUM_TIMER_STATS]; - -struct work_struct fast_work; - -static void -timer_trig_handler(struct work_struct *work); - - - -/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ -inline void do_gettimeofday_fast(struct fasttime_t *tv) -{ - tv->tv_jiff = jiffies; - tv->tv_usec = GET_JIFFIES_USEC(); -} - -inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1) -{ - /* Compare jiffies. Takes care of wrapping */ - if (time_before(t0->tv_jiff, t1->tv_jiff)) - return -1; - else if (time_after(t0->tv_jiff, t1->tv_jiff)) - return 1; - - /* Compare us */ - if (t0->tv_usec < t1->tv_usec) - return -1; - else if (t0->tv_usec > t1->tv_usec) - return 1; - return 0; -} - -/* Called with ints off */ -inline void start_timer_trig(unsigned long delay_us) -{ - reg_timer_rw_ack_intr ack_intr = { 0 }; - reg_timer_rw_intr_mask intr_mask; - reg_timer_rw_trig trig; - reg_timer_rw_trig_cfg trig_cfg = { 0 }; - reg_timer_r_time r_time0; - reg_timer_r_time r_time1; - unsigned char trig_wrap; - unsigned char time_wrap; - - r_time0 = REG_RD(timer, regi_timer0, r_time); - - D1(printk("start_timer_trig : %d us freq: %i div: %i\n", - delay_us, freq_index, div)); - /* Clear trig irq */ - intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); - intr_mask.trig = 0; - REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); - - /* Set timer values and check if trigger wraps. */ - /* r_time is 100MHz (10 ns resolution) */ - trig_wrap = (trig = r_time0 + delay_us*(1000/10)) < r_time0; - - timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = trig; - timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; - - /* Ack interrupt */ - ack_intr.trig = 1; - REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); - - /* Start timer */ - REG_WR(timer, regi_timer0, rw_trig, trig); - trig_cfg.tmr = regk_timer_time; - REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); - - /* Check if we have already passed the trig time */ - r_time1 = REG_RD(timer, regi_timer0, r_time); - time_wrap = r_time1 < r_time0; - - if ((trig_wrap && !time_wrap) || (r_time1 < trig)) { - /* No, Enable trig irq */ - intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); - intr_mask.trig = 1; - REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); - fast_timers_started++; - fast_timer_running = 1; - } else { - /* We have passed the time, disable trig point, ack intr */ - trig_cfg.tmr = regk_timer_off; - REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); - REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); - /* call the int routine */ - INIT_WORK(&fast_work, timer_trig_handler); - schedule_work(&fast_work); - } - -} - -/* In version 1.4 this function takes 27 - 50 us */ -void start_one_shot_timer(struct fast_timer *t, - fast_timer_function_type *function, - unsigned long data, - unsigned long delay_us, - const char *name) -{ - unsigned long flags; - struct fast_timer *tmp; - - D1(printk("sft %s %d us\n", name, delay_us)); - - local_irq_save(flags); - - do_gettimeofday_fast(&t->tv_set); - tmp = fast_timer_list; - -#ifdef FAST_TIMER_SANITY_CHECKS - /* Check so this is not in the list already... */ - while (tmp != NULL) { - if (tmp == t) { - printk(KERN_DEBUG - "timer name: %s data: 0x%08lX already " - "in list!\n", name, data); - sanity_failed++; - goto done; - } else - tmp = tmp->next; - } - tmp = fast_timer_list; -#endif - - t->delay_us = delay_us; - t->function = function; - t->data = data; - t->name = name; - - t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; - t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ; - if (t->tv_expires.tv_usec > 1000000) { - t->tv_expires.tv_usec -= 1000000; - t->tv_expires.tv_jiff += HZ; - } -#ifdef FAST_TIMER_LOG - timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; -#endif - fast_timers_added++; - - /* Check if this should timeout before anything else */ - if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) { - /* Put first in list and modify the timer value */ - t->prev = NULL; - t->next = fast_timer_list; - if (fast_timer_list) - fast_timer_list->prev = t; - fast_timer_list = t; -#ifdef FAST_TIMER_LOG - timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; -#endif - start_timer_trig(delay_us); - } else { - /* Put in correct place in list */ - while (tmp->next && - fasttime_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0) - tmp = tmp->next; - /* Insert t after tmp */ - t->prev = tmp; - t->next = tmp->next; - if (tmp->next) - { - tmp->next->prev = t; - } - tmp->next = t; - } - - D2(printk("start_one_shot_timer: %d us done\n", delay_us)); - -done: - local_irq_restore(flags); -} /* start_one_shot_timer */ - -static inline int fast_timer_pending (const struct fast_timer * t) -{ - return (t->next != NULL) || (t->prev != NULL) || (t == fast_timer_list); -} - -static inline int detach_fast_timer (struct fast_timer *t) -{ - struct fast_timer *next, *prev; - if (!fast_timer_pending(t)) - return 0; - next = t->next; - prev = t->prev; - if (next) - next->prev = prev; - if (prev) - prev->next = next; - else - fast_timer_list = next; - fast_timers_deleted++; - return 1; -} - -int del_fast_timer(struct fast_timer * t) -{ - unsigned long flags; - int ret; - - local_irq_save(flags); - ret = detach_fast_timer(t); - t->next = t->prev = NULL; - local_irq_restore(flags); - return ret; -} /* del_fast_timer */ - - -/* Interrupt routines or functions called in interrupt context */ - -/* Timer interrupt handler for trig interrupts */ - -static irqreturn_t -timer_trig_interrupt(int irq, void *dev_id) -{ - reg_timer_r_masked_intr masked_intr; - /* Check if the timer interrupt is for us (a trig int) */ - masked_intr = REG_RD(timer, regi_timer0, r_masked_intr); - if (!masked_intr.trig) - return IRQ_NONE; - timer_trig_handler(NULL); - return IRQ_HANDLED; -} - -static void timer_trig_handler(struct work_struct *work) -{ - reg_timer_rw_ack_intr ack_intr = { 0 }; - reg_timer_rw_intr_mask intr_mask; - reg_timer_rw_trig_cfg trig_cfg = { 0 }; - struct fast_timer *t; - fast_timer_function_type *f; - unsigned long d; - unsigned long flags; - - /* We keep interrupts disabled not only when we modify the - * fast timer list, but any time we hold a reference to a - * timer in the list, since del_fast_timer may be called - * from (another) interrupt context. Thus, the only time - * when interrupts are enabled is when calling the timer - * callback function. - */ - local_irq_save(flags); - - /* Clear timer trig interrupt */ - intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); - intr_mask.trig = 0; - REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); - - /* First stop timer, then ack interrupt */ - /* Stop timer */ - trig_cfg.tmr = regk_timer_off; - REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); - - /* Ack interrupt */ - ack_intr.trig = 1; - REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); - - fast_timer_running = 0; - fast_timer_ints++; - - t = fast_timer_list; - while (t) { - struct fasttime_t tv; - - /* Has it really expired? */ - do_gettimeofday_fast(&tv); - D1(printk(KERN_DEBUG - "t: %is %06ius\n", tv.tv_jiff, tv.tv_usec)); - - if (fasttime_cmp(&t->tv_expires, &tv) <= 0) { - /* Yes it has expired */ -#ifdef FAST_TIMER_LOG - timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t; -#endif - fast_timers_expired++; - - /* Remove this timer before call, since it may reuse the timer */ - if (t->prev) - t->prev->next = t->next; - else - fast_timer_list = t->next; - if (t->next) - t->next->prev = t->prev; - t->prev = NULL; - t->next = NULL; - - /* Save function callback data before enabling - * interrupts, since the timer may be removed and we - * don't know how it was allocated (e.g. ->function - * and ->data may become overwritten after deletion - * if the timer was stack-allocated). - */ - f = t->function; - d = t->data; - - if (f != NULL) { - /* Run the callback function with interrupts - * enabled. */ - local_irq_restore(flags); - f(d); - local_irq_save(flags); - } else - DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints); - } else { - /* Timer is to early, let's set it again using the normal routines */ - D1(printk(".\n")); - } - - t = fast_timer_list; - if (t != NULL) { - /* Start next timer.. */ - long us = 0; - struct fasttime_t tv; - - do_gettimeofday_fast(&tv); - - /* time_after_eq takes care of wrapping */ - if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff)) - us = ((t->tv_expires.tv_jiff - tv.tv_jiff) * - 1000000 / HZ + t->tv_expires.tv_usec - - tv.tv_usec); - - if (us > 0) { - if (!fast_timer_running) { -#ifdef FAST_TIMER_LOG - timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; -#endif - start_timer_trig(us); - } - break; - } else { - /* Timer already expired, let's handle it better late than never. - * The normal loop handles it - */ - D1(printk("e! %d\n", us)); - } - } - } - - local_irq_restore(flags); - - if (!t) - D1(printk("ttrig stop!\n")); -} - -static void wake_up_func(unsigned long data) -{ - wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data; - wake_up(sleep_wait_p); -} - - -/* Useful API */ - -void schedule_usleep(unsigned long us) -{ - struct fast_timer t; - wait_queue_head_t sleep_wait; - init_waitqueue_head(&sleep_wait); - - D1(printk("schedule_usleep(%d)\n", us)); - start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, - "usleep"); - /* Uninterruptible sleep on the fast timer. (The condition is - * somewhat redundant since the timer is what wakes us up.) */ - wait_event(sleep_wait, !fast_timer_pending(&t)); - - D1(printk("done schedule_usleep(%d)\n", us)); -} - -#ifdef CONFIG_PROC_FS -/* This value is very much based on testing */ -#define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300) - -static int proc_fasttimer_show(struct seq_file *m, void *v) -{ - unsigned long flags; - int i = 0; - int num_to_show; - struct fasttime_t tv; - struct fast_timer *t, *nextt; - - do_gettimeofday_fast(&tv); - - seq_printf(m, "Fast timers added: %i\n", fast_timers_added); - seq_printf(m, "Fast timers started: %i\n", fast_timers_started); - seq_printf(m, "Fast timer interrupts: %i\n", fast_timer_ints); - seq_printf(m, "Fast timers expired: %i\n", fast_timers_expired); - seq_printf(m, "Fast timers deleted: %i\n", fast_timers_deleted); - seq_printf(m, "Fast timer running: %s\n", - fast_timer_running ? "yes" : "no"); - seq_printf(m, "Current time: %lu.%06lu\n", - (unsigned long)tv.tv_jiff, - (unsigned long)tv.tv_usec); -#ifdef FAST_TIMER_SANITY_CHECKS - seq_printf(m, "Sanity failed: %i\n", sanity_failed); -#endif - seq_putc(m, '\n'); - -#ifdef DEBUG_LOG_INCLUDED - { - int end_i = debug_log_cnt; - i = 0; - - if (debug_log_cnt_wrapped) - i = debug_log_cnt; - - while ((i != end_i || debug_log_cnt_wrapped)) { - seq_printf(m, debug_log_string[i], debug_log_value[i]); - if (seq_has_overflowed(m)) - return 0; - i = (i+1) % DEBUG_LOG_MAX; - } - } - seq_putc(m, '\n'); -#endif - - num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started: - NUM_TIMER_STATS); - seq_printf(m, "Timers started: %i\n", fast_timers_started); - for (i = 0; i < num_to_show; i++) { - int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS; - -#if 1 //ndef FAST_TIMER_LOG - seq_printf(m, "div: %i delay: %i\n", - timer_div_settings[cur], - timer_delay_settings[cur]); -#endif -#ifdef FAST_TIMER_LOG - t = &timer_started_log[cur]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; -#endif - } - seq_putc(m, '\n'); - -#ifdef FAST_TIMER_LOG - num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added: - NUM_TIMER_STATS); - seq_printf(m, "Timers added: %i\n", fast_timers_added); - for (i = 0; i < num_to_show; i++) { - t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - } - seq_putc(m, '\n'); - - num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired: - NUM_TIMER_STATS); - seq_printf(m, "Timers expired: %i\n", fast_timers_expired); - for (i = 0; i < num_to_show; i++){ - t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - } - seq_putc(m, '\n'); -#endif - - seq_puts(m, "Active timers:\n"); - local_irq_save(flags); - t = fast_timer_list; - while (t != NULL){ - nextt = t->next; - local_irq_restore(flags); - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - local_irq_save(flags); - if (t->next != nextt) - printk("timer removed!\n"); - t = nextt; - } - local_irq_restore(flags); - return 0; -} - -static int proc_fasttimer_open(struct inode *inode, struct file *file) -{ - return single_open_size(file, proc_fasttimer_show, PDE_DATA(inode), BIG_BUF_SIZE); -} - -static const struct file_operations proc_fasttimer_fops = { - .open = proc_fasttimer_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#endif /* PROC_FS */ - -#ifdef FAST_TIMER_TEST -static volatile unsigned long i = 0; -static volatile int num_test_timeout = 0; -static struct fast_timer tr[10]; -static int exp_num[10]; - -static struct fasttime_t tv_exp[100]; - -static void test_timeout(unsigned long data) -{ - do_gettimeofday_fast(&tv_exp[data]); - exp_num[data] = num_test_timeout; - - num_test_timeout++; -} - -static void test_timeout1(unsigned long data) -{ - do_gettimeofday_fast(&tv_exp[data]); - exp_num[data] = num_test_timeout; - if (data < 7) - { - start_one_shot_timer(&tr[i], test_timeout1, i, 1000, "timeout1"); - i++; - } - num_test_timeout++; -} - -DP( -static char buf0[2000]; -static char buf1[2000]; -static char buf2[2000]; -static char buf3[2000]; -static char buf4[2000]; -); - -static char buf5[6000]; -static int j_u[1000]; - -static void fast_timer_test(void) -{ - int prev_num; - int j; - - struct fasttime_t tv, tv0, tv1, tv2; - - printk("fast_timer_test() start\n"); - do_gettimeofday_fast(&tv); - - for (j = 0; j < 1000; j++) - { - j_u[j] = GET_JIFFIES_USEC(); - } - for (j = 0; j < 100; j++) - { - do_gettimeofday_fast(&tv_exp[j]); - } - printk(KERN_DEBUG "fast_timer_test() %is %06i\n", tv.tv_jiff, tv.tv_usec); - - for (j = 0; j < 1000; j++) - { - printk(KERN_DEBUG "%i %i %i %i %i\n", - j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]); - j += 4; - } - for (j = 0; j < 100; j++) - { - printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n", - tv_exp[j].tv_jiff, tv_exp[j].tv_usec, - tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec, - tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec, - tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec, - tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec); - j += 4; - } - do_gettimeofday_fast(&tv0); - start_one_shot_timer(&tr[i], test_timeout, i, 50000, "test0"); - DP(proc_fasttimer_read(buf0, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 70000, "test1"); - DP(proc_fasttimer_read(buf1, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 40000, "test2"); - DP(proc_fasttimer_read(buf2, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 60000, "test3"); - DP(proc_fasttimer_read(buf3, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout1, i, 55000, "test4xx"); - DP(proc_fasttimer_read(buf4, NULL, 0, 0, 0)); - i++; - do_gettimeofday_fast(&tv1); - - proc_fasttimer_read(buf5, NULL, 0, 0, 0); - - prev_num = num_test_timeout; - while (num_test_timeout < i) - { - if (num_test_timeout != prev_num) - prev_num = num_test_timeout; - } - do_gettimeofday_fast(&tv2); - printk(KERN_INFO "Timers started %is %06i\n", - tv0.tv_jiff, tv0.tv_usec); - printk(KERN_INFO "Timers started at %is %06i\n", - tv1.tv_jiff, tv1.tv_usec); - printk(KERN_INFO "Timers done %is %06i\n", - tv2.tv_jiff, tv2.tv_usec); - DP(printk("buf0:\n"); - printk(buf0); - printk("buf1:\n"); - printk(buf1); - printk("buf2:\n"); - printk(buf2); - printk("buf3:\n"); - printk(buf3); - printk("buf4:\n"); - printk(buf4); - ); - printk("buf5:\n"); - printk(buf5); - - printk("timers set:\n"); - for(j = 0; j<i; j++) - { - struct fast_timer *t = &tr[j]; - printk("%-10s set: %6is %06ius exp: %6is %06ius " - "data: 0x%08X func: 0x%08X\n", - t->name, - t->tv_set.tv_jiff, - t->tv_set.tv_usec, - t->tv_expires.tv_jiff, - t->tv_expires.tv_usec, - t->data, - t->function - ); - - printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", - t->delay_us, - tv_exp[j].tv_jiff, - tv_exp[j].tv_usec, - exp_num[j], - (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) * - 1000000 + tv_exp[j].tv_usec - - t->tv_expires.tv_usec); - } - proc_fasttimer_read(buf5, NULL, 0, 0, 0); - printk("buf5 after all done:\n"); - printk(buf5); - printk("fast_timer_test() done\n"); -} -#endif - - -int fast_timer_init(void) -{ - /* For some reason, request_irq() hangs when called froom time_init() */ - if (!fast_timer_is_init) - { - printk("fast_timer_init()\n"); - -#ifdef CONFIG_PROC_FS - proc_create("fasttimer", 0, NULL, &proc_fasttimer_fops); -#endif /* PROC_FS */ - if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt, - IRQF_SHARED, - "fast timer int", &fast_timer_list)) - printk(KERN_ERR "err: fasttimer irq\n"); - fast_timer_is_init = 1; -#ifdef FAST_TIMER_TEST - printk("do test\n"); - fast_timer_test(); -#endif - } - return 0; -} -__initcall(fast_timer_init); diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S deleted file mode 100644 index 92f9fb1f6845..000000000000 --- a/arch/cris/arch-v32/kernel/head.S +++ /dev/null @@ -1,439 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * CRISv32 kernel startup code. - * - * Copyright (C) 2003, Axis Communications AB - */ - -#include <linux/init.h> - -#define ASSEMBLER_MACROS_ONLY - -/* - * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so - * -traditional must not be used when assembling this file. - */ -#include <arch/memmap.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/intr_vect.h> -#include <hwregs/asm/mmu_defs_asm.h> -#include <hwregs/asm/reg_map_asm.h> -#include <mach/startup.inc> - -#define CRAMFS_MAGIC 0x28cd3d45 -#define JHEAD_MAGIC 0x1FF528A6 -#define JHEAD_SIZE 8 -#define RAM_INIT_MAGIC 0x56902387 -#define COMMAND_LINE_MAGIC 0x87109563 -#define NAND_BOOT_MAGIC 0x9a9db001 - - ;; NOTE: R8 and R9 carry information from the decompressor (if the - ;; kernel was compressed). They must not be used in the code below - ;; until they are read! - - ;; Exported symbols. - .global etrax_irv - .global romfs_start - .global romfs_length - .global romfs_in_flash - .global nand_boot - .global swapper_pg_dir - - __HEAD -tstart: - ;; This is the entry point of the kernel. The CPU is currently in - ;; supervisor mode. - ;; - ;; 0x00000000 if flash. - ;; 0x40004000 if DRAM. - ;; - di - - START_CLOCKS - - SETUP_WAIT_STATES - - GIO_INIT - - ;; Setup and enable the MMU. Use same configuration for both the data - ;; and the instruction MMU. - ;; - ;; Note; 3 cycles is needed for a bank-select to take effect. Further; - ;; bank 1 is the instruction MMU, bank 2 is the data MMU. - -#ifdef CONFIG_CRIS_MACH_ARTPEC3 - move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ - | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ - | REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5) \ - | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 -#else - move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ - | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ - | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 -#endif - - ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00. - move.d REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4) \ - | REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1 - - ;; Enable certain page protections and setup linear mapping - ;; for f,e,c,b,4,0. - - ;; ARTPEC-3: - ;; c,d used for linear kernel mapping, up to 512 MB - ;; e used for vmalloc - ;; f unused, but page mapped to get page faults - - ;; ETRAX FS: - ;; c used for linear kernel mapping, up to 256 MB - ;; d used for vmalloc - ;; e,f used for memory-mapped NOR flash - -#ifdef CONFIG_CRIS_MACH_ARTPEC3 - move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ - | REG_STATE(mmu, rw_mm_cfg, acc, on) \ - | REG_STATE(mmu, rw_mm_cfg, ex, on) \ - | REG_STATE(mmu, rw_mm_cfg, inv, on) \ - | REG_STATE(mmu, rw_mm_cfg, seg_f, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_e, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_d, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_a, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2 -#else - move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ - | REG_STATE(mmu, rw_mm_cfg, acc, on) \ - | REG_STATE(mmu, rw_mm_cfg, ex, on) \ - | REG_STATE(mmu, rw_mm_cfg, inv, on) \ - | REG_STATE(mmu, rw_mm_cfg, seg_f, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_e, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_d, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_a, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \ - | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \ - | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2 -#endif - - ;; Update instruction MMU. - move 1, $srs - nop - nop - nop - move $r0, $s2 ; kbase_hi. - move $r1, $s1 ; kbase_lo. - move $r2, $s0 ; mm_cfg, virtual memory configuration. - - ;; Update data MMU. - move 2, $srs - nop - nop - nop - move $r0, $s2 ; kbase_hi. - move $r1, $s1 ; kbase_lo - move $r2, $s0 ; mm_cfg, virtual memory configuration. - - ;; Enable data and instruction MMU. - move 0, $srs - moveq 0xf, $r0 ; IMMU, DMMU, DCache, Icache on - nop - nop - nop - move $r0, $s0 - nop - nop - nop - - ; Check if starting from DRAM (network->RAM boot or unpacked - ; compressed kernel), or directly from flash. - lapcq ., $r0 - and.d 0x7fffffff, $r0 ; Mask off the non-cache bit. - cmp.d 0x10000, $r0 ; Arbitrary, something above this code. - blo _inflash0 - nop - - jump _inram ; Jump to cached RAM. - nop - - ;; Jumpgate. -_inflash0: - jump _inflash - nop - - ;; Put the following in a section so that storage for it can be - ;; reclaimed after init is finished. - __INIT - -_inflash: - - ;; Initialize DRAM. - cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized? - beq _dram_initialized - nop - -#if defined CONFIG_ETRAXFS -#include "../mach-fs/dram_init.S" -#elif defined CONFIG_CRIS_MACH_ARTPEC3 -#include "../mach-a3/dram_init.S" -#else -#error Only ETRAXFS and ARTPEC-3 supported! -#endif - - -_dram_initialized: - ;; Copy the text and data section to DRAM. This depends on that the - ;; variables used below are correctly set up by the linker script. - ;; The calculated value stored in R4 is used below. - ;; Leave the cramfs file system (piggybacked after the kernel) in flash. - moveq 0, $r0 ; Source. - move.d text_start, $r1 ; Destination. - move.d __vmlinux_end, $r2 - move.d $r2, $r4 - sub.d $r1, $r4 -1: move.w [$r0+], $r3 - move.w $r3, [$r1+] - cmp.d $r2, $r1 - blo 1b - nop - - ;; Check for cramfs. - moveq 0, $r0 - move.d romfs_length, $r1 - move.d $r0, [$r1] - move.d [$r4], $r0 ; cramfs_super.magic - cmp.d CRAMFS_MAGIC, $r0 - bne 1f - nop - - ;; Set length and start of cramfs, set romfs_in_flash flag - addoq +4, $r4, $acr - move.d [$acr], $r0 - move.d romfs_length, $r1 - move.d $r0, [$r1] - add.d 0xf0000000, $r4 ; Add cached flash start in virtual memory. - move.d romfs_start, $r1 - move.d $r4, [$r1] -1: moveq 1, $r0 - move.d romfs_in_flash, $r1 - move.d $r0, [$r1] - - jump _start_it ; Jump to cached code. - nop - -_inram: - ;; Check if booting from NAND flash; if so, set appropriate flags - ;; and move on. - cmp.d NAND_BOOT_MAGIC, $r12 - bne move_cramfs ; not nand, jump - moveq 1, $r0 - move.d nand_boot, $r1 ; tell axisflashmap we're booting from NAND - move.d $r0, [$r1] - moveq 0, $r0 ; tell axisflashmap romfs is not in - move.d romfs_in_flash, $r1 ; (directly accessed) flash - move.d $r0, [$r1] - jump _start_it ; continue with boot - nop - -move_cramfs: - ;; kernel is in DRAM. - ;; Must figure out if there is a piggybacked rootfs image or not. - ;; Set romfs_length to 0 => no rootfs image available by default. - moveq 0, $r0 - move.d romfs_length, $r1 - move.d $r0, [$r1] - - ;; The kernel could have been unpacked to DRAM by the loader, but - ;; the cramfs image could still be in the flash immediately - ;; following the compressed kernel image. The loader passes the address - ;; of the byte succeeding the last compressed byte in the flash in - ;; register R9 when starting the kernel. - cmp.d 0x0ffffff8, $r9 - bhs _no_romfs_in_flash ; R9 points outside the flash area. - nop - ;; cramfs rootfs might to be in flash. Check for it. - move.d [$r9], $r0 ; cramfs_super.magic - cmp.d CRAMFS_MAGIC, $r0 - bne _no_romfs_in_flash - nop - - ;; found cramfs in flash. set address and size, and romfs_in_flash flag. - addoq +4, $r9, $acr - move.d [$acr], $r0 - move.d romfs_length, $r1 - move.d $r0, [$r1] - add.d 0xf0000000, $r9 ; Add cached flash start in virtual memory. - move.d romfs_start, $r1 - move.d $r9, [$r1] - moveq 1, $r0 - move.d romfs_in_flash, $r1 - move.d $r0, [$r1] - - jump _start_it ; Jump to cached code. - nop - -_no_romfs_in_flash: - ;; No romfs in flash, so look for cramfs, or jffs2 with jhead, - ;; after kernel in RAM, as is the case with network->RAM boot. - ;; For cramfs, partition starts with magic and length. - ;; For jffs2, a jhead is prepended which contains with magic and length. - ;; The jhead is not part of the jffs2 partition however. - move.d __bss_start, $r0 - move.d [$r0], $r1 - cmp.d CRAMFS_MAGIC, $r1 ; cramfs magic? - beq 2f ; yes, jump - nop - cmp.d JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic? - bne 4f ; no, skip copy - nop - addq 4, $r0 ; location of jffs2 size - move.d [$r0+], $r2 ; fetch jffs2 size -> r2 - ; r0 now points to start of jffs2 - ba 3f - nop -2: - addoq +4, $r0, $acr ; location of cramfs size - move.d [$acr], $r2 ; fetch cramfs size -> r2 - ; r0 still points to start of cramfs -3: - ;; Now, move the root fs to after kernel's BSS - - move.d _end, $r1 ; start of cramfs -> r1 - move.d romfs_start, $r3 - move.d $r1, [$r3] ; store at romfs_start (for axisflashmap) - move.d romfs_length, $r3 - move.d $r2, [$r3] ; store size at romfs_length - - add.d $r2, $r0 ; copy from end and downwards - add.d $r2, $r1 - - lsrq 1, $r2 ; Size is in bytes, we copy words. - addq 1, $r2 -1: - move.w [$r0], $r3 - move.w $r3, [$r1] - subq 2, $r0 - subq 2, $r1 - subq 1, $r2 - bne 1b - nop - -4: - ;; BSS move done. - ;; Clear romfs_in_flash flag, as we now know romfs is in DRAM - ;; Also clear nand_boot flag; if we got here, we know we've not - ;; booted from NAND flash. - moveq 0, $r0 - move.d romfs_in_flash, $r1 - move.d $r0, [$r1] - moveq 0, $r0 - move.d nand_boot, $r1 - move.d $r0, [$r1] - - jump _start_it ; Jump to cached code. - nop - -_start_it: - - ;; Check if kernel command line is supplied - cmp.d COMMAND_LINE_MAGIC, $r10 - bne no_command_line - nop - - move.d 256, $r13 - move.d cris_command_line, $r10 - or.d 0x80000000, $r11 ; Make it virtual -1: - move.b [$r11+], $r1 - move.b $r1, [$r10+] - subq 1, $r13 - bne 1b - nop - -no_command_line: - - ;; The kernel stack contains a task structure for each task. This - ;; the initial kernel stack is in the same page as the init_task, - ;; but starts at the top of the page, i.e. + 8192 bytes. - move.d init_thread_union + 8192, $sp - move.d ebp_start, $r0 ; Defined in linker-script. - move $r0, $ebp - move.d etrax_irv, $r1 ; Set the exception base register and pointer. - move.d $r0, [$r1] - - ;; Clear the BSS region from _bss_start to _end. - move.d __bss_start, $r0 - move.d _end, $r1 -1: clear.d [$r0+] - cmp.d $r1, $r0 - blo 1b - nop - - ; Initialize registers to increase determinism - move.d __bss_start, $r0 - movem [$r0], $r13 - -#ifdef CONFIG_ETRAX_L2CACHE - jsr l2cache_init - nop -#endif - - jump start_kernel ; Jump to start_kernel() in init/main.c. - nop - - .data -etrax_irv: - .dword 0 - -; Variables for communication with the Axis flash map driver (axisflashmap), -; and for setting up memory in arch/cris/kernel/setup.c . - -; romfs_start is set to the start of the root file system, if it exists -; in directly accessible memory (i.e. NOR Flash when booting from Flash, -; or RAM when booting directly from a network-downloaded RAM image) -romfs_start: - .dword 0 - -; romfs_length is set to the size of the root file system image, if it exists -; in directly accessible memory (see romfs_start). Otherwise it is set to 0. -romfs_length: - .dword 0 - -; romfs_in_flash is set to 1 if the root file system resides in directly -; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot -; or NAND flash boot. -romfs_in_flash: - .dword 0 - -; nand_boot is set to 1 when the kernel has been booted from NAND flash -nand_boot: - .dword 0 - -swapper_pg_dir = 0xc0002000 - - .section ".init.data", "aw" - -#if defined CONFIG_ETRAXFS -#include "../mach-fs/hw_settings.S" -#elif defined CONFIG_CRIS_MACH_ARTPEC3 -#include "../mach-a3/hw_settings.S" -#else -#error Only ETRAXFS and ARTPEC-3 supported! -#endif diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c deleted file mode 100644 index 414afd543232..000000000000 --- a/arch/cris/arch-v32/kernel/irq.c +++ /dev/null @@ -1,520 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2003, Axis Communications AB. - */ - -#include <asm/irq.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/smp.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/profile.h> -#include <linux/of.h> -#include <linux/of_irq.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#include <linux/threads.h> -#include <linux/spinlock.h> -#include <linux/kernel_stat.h> -#include <hwregs/reg_map.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/intr_vect.h> -#include <hwregs/intr_vect_defs.h> - -#define CPU_FIXED -1 - -/* IRQ masks (refer to comment for crisv32_do_multiple) */ -#if TIMER0_INTR_VECT - FIRST_IRQ < 32 -#define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ)) -#undef TIMER_VECT1 -#else -#define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ - 32)) -#define TIMER_VECT1 -#endif -#ifdef CONFIG_ETRAX_KGDB -#if defined(CONFIG_ETRAX_KGDB_PORT0) -#define IGNOREMASK (1 << (SER0_INTR_VECT - FIRST_IRQ)) -#elif defined(CONFIG_ETRAX_KGDB_PORT1) -#define IGNOREMASK (1 << (SER1_INTR_VECT - FIRST_IRQ)) -#elif defined(CONFIG_ETRAX_KGDB_PORT2) -#define IGNOREMASK (1 << (SER2_INTR_VECT - FIRST_IRQ)) -#elif defined(CONFIG_ETRAX_KGDB_PORT3) -#define IGNOREMASK (1 << (SER3_INTR_VECT - FIRST_IRQ)) -#endif -#endif - -DEFINE_SPINLOCK(irq_lock); - -struct cris_irq_allocation -{ - int cpu; /* The CPU to which the IRQ is currently allocated. */ - cpumask_t mask; /* The CPUs to which the IRQ may be allocated. */ -}; - -struct cris_irq_allocation irq_allocations[NR_REAL_IRQS] = - { [0 ... NR_REAL_IRQS - 1] = {0, CPU_MASK_ALL} }; - -static unsigned long irq_regs[NR_CPUS] = -{ - regi_irq, -}; - -#if NR_REAL_IRQS > 32 -#define NBR_REGS 2 -#else -#define NBR_REGS 1 -#endif - -unsigned long cpu_irq_counters[NR_CPUS]; -unsigned long irq_counters[NR_REAL_IRQS]; - -/* From irq.c. */ -extern void weird_irq(void); - -/* From entry.S. */ -extern void system_call(void); -extern void nmi_interrupt(void); -extern void multiple_interrupt(void); -extern void gdb_handle_exception(void); -extern void i_mmu_refill(void); -extern void i_mmu_invalid(void); -extern void i_mmu_access(void); -extern void i_mmu_execute(void); -extern void d_mmu_refill(void); -extern void d_mmu_invalid(void); -extern void d_mmu_access(void); -extern void d_mmu_write(void); - -/* From kgdb.c. */ -extern void kgdb_init(void); -extern void breakpoint(void); - -/* From traps.c. */ -extern void breakh_BUG(void); - -/* - * Build the IRQ handler stubs using macros from irq.h. - */ -#ifdef CONFIG_CRIS_MACH_ARTPEC3 -BUILD_TIMER_IRQ(0x31, 0) -#else -BUILD_IRQ(0x31) -#endif -BUILD_IRQ(0x32) -BUILD_IRQ(0x33) -BUILD_IRQ(0x34) -BUILD_IRQ(0x35) -BUILD_IRQ(0x36) -BUILD_IRQ(0x37) -BUILD_IRQ(0x38) -BUILD_IRQ(0x39) -BUILD_IRQ(0x3a) -BUILD_IRQ(0x3b) -BUILD_IRQ(0x3c) -BUILD_IRQ(0x3d) -BUILD_IRQ(0x3e) -BUILD_IRQ(0x3f) -BUILD_IRQ(0x40) -BUILD_IRQ(0x41) -BUILD_IRQ(0x42) -BUILD_IRQ(0x43) -BUILD_IRQ(0x44) -BUILD_IRQ(0x45) -BUILD_IRQ(0x46) -BUILD_IRQ(0x47) -BUILD_IRQ(0x48) -BUILD_IRQ(0x49) -BUILD_IRQ(0x4a) -#ifdef CONFIG_ETRAXFS -BUILD_TIMER_IRQ(0x4b, 0) -#else -BUILD_IRQ(0x4b) -#endif -BUILD_IRQ(0x4c) -BUILD_IRQ(0x4d) -BUILD_IRQ(0x4e) -BUILD_IRQ(0x4f) -BUILD_IRQ(0x50) -#if MACH_IRQS > 32 -BUILD_IRQ(0x51) -BUILD_IRQ(0x52) -BUILD_IRQ(0x53) -BUILD_IRQ(0x54) -BUILD_IRQ(0x55) -BUILD_IRQ(0x56) -BUILD_IRQ(0x57) -BUILD_IRQ(0x58) -BUILD_IRQ(0x59) -BUILD_IRQ(0x5a) -BUILD_IRQ(0x5b) -BUILD_IRQ(0x5c) -BUILD_IRQ(0x5d) -BUILD_IRQ(0x5e) -BUILD_IRQ(0x5f) -BUILD_IRQ(0x60) -BUILD_IRQ(0x61) -BUILD_IRQ(0x62) -BUILD_IRQ(0x63) -BUILD_IRQ(0x64) -BUILD_IRQ(0x65) -BUILD_IRQ(0x66) -BUILD_IRQ(0x67) -BUILD_IRQ(0x68) -BUILD_IRQ(0x69) -BUILD_IRQ(0x6a) -BUILD_IRQ(0x6b) -BUILD_IRQ(0x6c) -BUILD_IRQ(0x6d) -BUILD_IRQ(0x6e) -BUILD_IRQ(0x6f) -BUILD_IRQ(0x70) -#endif - -/* Pointers to the low-level handlers. */ -static void (*interrupt[MACH_IRQS])(void) = { - IRQ0x31_interrupt, IRQ0x32_interrupt, IRQ0x33_interrupt, - IRQ0x34_interrupt, IRQ0x35_interrupt, IRQ0x36_interrupt, - IRQ0x37_interrupt, IRQ0x38_interrupt, IRQ0x39_interrupt, - IRQ0x3a_interrupt, IRQ0x3b_interrupt, IRQ0x3c_interrupt, - IRQ0x3d_interrupt, IRQ0x3e_interrupt, IRQ0x3f_interrupt, - IRQ0x40_interrupt, IRQ0x41_interrupt, IRQ0x42_interrupt, - IRQ0x43_interrupt, IRQ0x44_interrupt, IRQ0x45_interrupt, - IRQ0x46_interrupt, IRQ0x47_interrupt, IRQ0x48_interrupt, - IRQ0x49_interrupt, IRQ0x4a_interrupt, IRQ0x4b_interrupt, - IRQ0x4c_interrupt, IRQ0x4d_interrupt, IRQ0x4e_interrupt, - IRQ0x4f_interrupt, IRQ0x50_interrupt, -#if MACH_IRQS > 32 - IRQ0x51_interrupt, IRQ0x52_interrupt, IRQ0x53_interrupt, - IRQ0x54_interrupt, IRQ0x55_interrupt, IRQ0x56_interrupt, - IRQ0x57_interrupt, IRQ0x58_interrupt, IRQ0x59_interrupt, - IRQ0x5a_interrupt, IRQ0x5b_interrupt, IRQ0x5c_interrupt, - IRQ0x5d_interrupt, IRQ0x5e_interrupt, IRQ0x5f_interrupt, - IRQ0x60_interrupt, IRQ0x61_interrupt, IRQ0x62_interrupt, - IRQ0x63_interrupt, IRQ0x64_interrupt, IRQ0x65_interrupt, - IRQ0x66_interrupt, IRQ0x67_interrupt, IRQ0x68_interrupt, - IRQ0x69_interrupt, IRQ0x6a_interrupt, IRQ0x6b_interrupt, - IRQ0x6c_interrupt, IRQ0x6d_interrupt, IRQ0x6e_interrupt, - IRQ0x6f_interrupt, IRQ0x70_interrupt, -#endif -}; - -void -block_irq(int irq, int cpu) -{ - int intr_mask; - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - /* Remember, 1 let thru, 0 block. */ - if (irq - FIRST_IRQ < 32) { - intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], - rw_mask, 0); - intr_mask &= ~(1 << (irq - FIRST_IRQ)); - REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, - 0, intr_mask); - } else { - intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], - rw_mask, 1); - intr_mask &= ~(1 << (irq - FIRST_IRQ - 32)); - REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, - 1, intr_mask); - } - spin_unlock_irqrestore(&irq_lock, flags); -} - -void -unblock_irq(int irq, int cpu) -{ - int intr_mask; - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - /* Remember, 1 let thru, 0 block. */ - if (irq - FIRST_IRQ < 32) { - intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], - rw_mask, 0); - intr_mask |= (1 << (irq - FIRST_IRQ)); - REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, - 0, intr_mask); - } else { - intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], - rw_mask, 1); - intr_mask |= (1 << (irq - FIRST_IRQ - 32)); - REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, - 1, intr_mask); - } - spin_unlock_irqrestore(&irq_lock, flags); -} - -/* Find out which CPU the irq should be allocated to. */ -static int irq_cpu(int irq) -{ - int cpu; - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - cpu = irq_allocations[irq - FIRST_IRQ].cpu; - - /* Fixed interrupts stay on the local CPU. */ - if (cpu == CPU_FIXED) - { - spin_unlock_irqrestore(&irq_lock, flags); - return smp_processor_id(); - } - - - /* Let the interrupt stay if possible */ - if (cpumask_test_cpu(cpu, &irq_allocations[irq - FIRST_IRQ].mask)) - goto out; - - /* IRQ must be moved to another CPU. */ - cpu = cpumask_first(&irq_allocations[irq - FIRST_IRQ].mask); - irq_allocations[irq - FIRST_IRQ].cpu = cpu; -out: - spin_unlock_irqrestore(&irq_lock, flags); - return cpu; -} - -void crisv32_mask_irq(int irq) -{ - int cpu; - - for (cpu = 0; cpu < NR_CPUS; cpu++) - block_irq(irq, cpu); -} - -void crisv32_unmask_irq(int irq) -{ - unblock_irq(irq, irq_cpu(irq)); -} - - -static void enable_crisv32_irq(struct irq_data *data) -{ - crisv32_unmask_irq(data->irq); -} - -static void disable_crisv32_irq(struct irq_data *data) -{ - crisv32_mask_irq(data->irq); -} - -static int set_affinity_crisv32_irq(struct irq_data *data, - const struct cpumask *dest, bool force) -{ - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - irq_allocations[data->irq - FIRST_IRQ].mask = *dest; - spin_unlock_irqrestore(&irq_lock, flags); - return 0; -} - -static struct irq_chip crisv32_irq_type = { - .name = "CRISv32", - .irq_shutdown = disable_crisv32_irq, - .irq_enable = enable_crisv32_irq, - .irq_disable = disable_crisv32_irq, - .irq_set_affinity = set_affinity_crisv32_irq, -}; - -void -set_exception_vector(int n, irqvectptr addr) -{ - etrax_irv->v[n] = (irqvectptr) addr; -} - -extern void do_IRQ(int irq, struct pt_regs * regs); - -void -crisv32_do_IRQ(int irq, int block, struct pt_regs* regs) -{ - /* Interrupts that may not be moved to another CPU may - * skip blocking. This is currently only valid for the - * timer IRQ and the IPI and is used for the timer - * interrupt to avoid watchdog starvation. - */ - if (!block) { - do_IRQ(irq, regs); - return; - } - - block_irq(irq, smp_processor_id()); - do_IRQ(irq, regs); - - unblock_irq(irq, irq_cpu(irq)); -} - -/* If multiple interrupts occur simultaneously we get a multiple - * interrupt from the CPU and software has to sort out which - * interrupts that happened. There are two special cases here: - * - * 1. Timer interrupts may never be blocked because of the - * watchdog (refer to comment in include/asr/arch/irq.h) - * 2. GDB serial port IRQs are unhandled here and will be handled - * as a single IRQ when it strikes again because the GDB - * stubb wants to save the registers in its own fashion. - */ -void -crisv32_do_multiple(struct pt_regs* regs) -{ - int cpu; - int mask; - int masked[NBR_REGS]; - int bit; - int i; - - cpu = smp_processor_id(); - - /* An extra irq_enter here to prevent softIRQs to run after - * each do_IRQ. This will decrease the interrupt latency. - */ - irq_enter(); - - for (i = 0; i < NBR_REGS; i++) { - /* Get which IRQs that happened. */ - masked[i] = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], - r_masked_vect, i); - - /* Calculate new IRQ mask with these IRQs disabled. */ - mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i); - mask &= ~masked[i]; - - /* Timer IRQ is never masked */ -#ifdef TIMER_VECT1 - if ((i == 1) && (masked[0] & TIMER_MASK)) - mask |= TIMER_MASK; -#else - if ((i == 0) && (masked[0] & TIMER_MASK)) - mask |= TIMER_MASK; -#endif - /* Block all the IRQs */ - REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask); - - /* Check for timer IRQ and handle it special. */ -#ifdef TIMER_VECT1 - if ((i == 1) && (masked[i] & TIMER_MASK)) { - masked[i] &= ~TIMER_MASK; - do_IRQ(TIMER0_INTR_VECT, regs); - } -#else - if ((i == 0) && (masked[i] & TIMER_MASK)) { - masked[i] &= ~TIMER_MASK; - do_IRQ(TIMER0_INTR_VECT, regs); - } -#endif - } - -#ifdef IGNORE_MASK - /* Remove IRQs that can't be handled as multiple. */ - masked[0] &= ~IGNORE_MASK; -#endif - - /* Handle the rest of the IRQs. */ - for (i = 0; i < NBR_REGS; i++) { - for (bit = 0; bit < 32; bit++) { - if (masked[i] & (1 << bit)) - do_IRQ(bit + FIRST_IRQ + i*32, regs); - } - } - - /* Unblock all the IRQs. */ - for (i = 0; i < NBR_REGS; i++) { - mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i); - mask |= masked[i]; - REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask); - } - - /* This irq_exit() will trigger the soft IRQs. */ - irq_exit(); -} - -static int crisv32_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw_irq_num) -{ - irq_set_chip_and_handler(virq, &crisv32_irq_type, handle_simple_irq); - - return 0; -} - -static struct irq_domain_ops crisv32_irq_ops = { - .map = crisv32_irq_map, - .xlate = irq_domain_xlate_onecell, -}; - -/* - * This is called by start_kernel. It fixes the IRQ masks and setup the - * interrupt vector table to point to bad_interrupt pointers. - */ -void __init -init_IRQ(void) -{ - int i; - int j; - reg_intr_vect_rw_mask vect_mask = {0}; - struct device_node *np; - struct irq_domain *domain; - - /* Clear all interrupts masks. */ - for (i = 0; i < NBR_REGS; i++) - REG_WR_VECT(intr_vect, regi_irq, rw_mask, i, vect_mask); - - for (i = 0; i < 256; i++) - etrax_irv->v[i] = weird_irq; - - np = of_find_compatible_node(NULL, NULL, "axis,crisv32-intc"); - domain = irq_domain_add_legacy(np, NBR_INTR_VECT - FIRST_IRQ, - FIRST_IRQ, FIRST_IRQ, - &crisv32_irq_ops, NULL); - BUG_ON(!domain); - irq_set_default_host(domain); - of_node_put(np); - - for (i = FIRST_IRQ, j = 0; j < NBR_INTR_VECT && j < MACH_IRQS; i++, j++) - set_exception_vector(i, interrupt[j]); - - /* Mark Timer and IPI IRQs as CPU local */ - irq_allocations[TIMER0_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED; - irq_set_status_flags(TIMER0_INTR_VECT, IRQ_PER_CPU); - irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED; - irq_set_status_flags(IPI_INTR_VECT, IRQ_PER_CPU); - - set_exception_vector(0x00, nmi_interrupt); - set_exception_vector(0x30, multiple_interrupt); - - /* Set up handler for various MMU bus faults. */ - set_exception_vector(0x04, i_mmu_refill); - set_exception_vector(0x05, i_mmu_invalid); - set_exception_vector(0x06, i_mmu_access); - set_exception_vector(0x07, i_mmu_execute); - set_exception_vector(0x08, d_mmu_refill); - set_exception_vector(0x09, d_mmu_invalid); - set_exception_vector(0x0a, d_mmu_access); - set_exception_vector(0x0b, d_mmu_write); - -#ifdef CONFIG_BUG - /* Break 14 handler, used to implement cheap BUG(). */ - set_exception_vector(0x1e, breakh_BUG); -#endif - - /* The system-call trap is reached by "break 13". */ - set_exception_vector(0x1d, system_call); - - /* Exception handlers for debugging, both user-mode and kernel-mode. */ - - /* Break 8. */ - set_exception_vector(0x18, gdb_handle_exception); - /* Hardware single step. */ - set_exception_vector(0x3, gdb_handle_exception); - /* Hardware breakpoint. */ - set_exception_vector(0xc, gdb_handle_exception); - -#ifdef CONFIG_ETRAX_KGDB - kgdb_init(); - /* Everything is set up; now trap the kernel. */ - breakpoint(); -#endif -} - diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c deleted file mode 100644 index 3d6f516763a5..000000000000 --- a/arch/cris/arch-v32/kernel/kgdb.c +++ /dev/null @@ -1,1593 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * arch/cris/arch-v32/kernel/kgdb.c - * - * CRIS v32 version by Orjan Friberg, Axis Communications AB. - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), - * - * Originally written by Glenn Engel, Lake Stevens Instrument Division - * - * Contributed by HP Systems - * - * Modified for SPARC by Stu Grossman, Cygnus Support. - * - * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse - * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de> - * - * Copyright (C) 1995 Andreas Busse - */ - -/* FIXME: Check the documentation. */ - -/* - * kgdb usage notes: - * ----------------- - * - * If you select CONFIG_ETRAX_KGDB in the configuration, the kernel will be - * built with different gcc flags: "-g" is added to get debug infos, and - * "-fomit-frame-pointer" is omitted to make debugging easier. Since the - * resulting kernel will be quite big (approx. > 7 MB), it will be stripped - * before compresion. Such a kernel will behave just as usually, except if - * given a "debug=<device>" command line option. (Only serial devices are - * allowed for <device>, i.e. no printers or the like; possible values are - * machine depedend and are the same as for the usual debug device, the one - * for logging kernel messages.) If that option is given and the device can be - * initialized, the kernel will connect to the remote gdb in trap_init(). The - * serial parameters are fixed to 8N1 and 115200 bps, for easyness of - * implementation. - * - * To start a debugging session, start that gdb with the debugging kernel - * image (the one with the symbols, vmlinux.debug) named on the command line. - * This file will be used by gdb to get symbol and debugging infos about the - * kernel. Next, select remote debug mode by - * target remote <device> - * where <device> is the name of the serial device over which the debugged - * machine is connected. Maybe you have to adjust the baud rate by - * set remotebaud <rate> - * or also other parameters with stty: - * shell stty ... </dev/... - * If the kernel to debug has already booted, it waited for gdb and now - * connects, and you'll see a breakpoint being reported. If the kernel isn't - * running yet, start it now. The order of gdb and the kernel doesn't matter. - * Another thing worth knowing about in the getting-started phase is how to - * debug the remote protocol itself. This is activated with - * set remotedebug 1 - * gdb will then print out each packet sent or received. You'll also get some - * messages about the gdb stub on the console of the debugged machine. - * - * If all that works, you can use lots of the usual debugging techniques on - * the kernel, e.g. inspecting and changing variables/memory, setting - * breakpoints, single stepping and so on. It's also possible to interrupt the - * debugged kernel by pressing C-c in gdb. Have fun! :-) - * - * The gdb stub is entered (and thus the remote gdb gets control) in the - * following situations: - * - * - If breakpoint() is called. This is just after kgdb initialization, or if - * a breakpoint() call has been put somewhere into the kernel source. - * (Breakpoints can of course also be set the usual way in gdb.) - * In eLinux, we call breakpoint() in init/main.c after IRQ initialization. - * - * - If there is a kernel exception, i.e. bad_super_trap() or die_if_kernel() - * are entered. All the CPU exceptions are mapped to (more or less..., see - * the hard_trap_info array below) appropriate signal, which are reported - * to gdb. die_if_kernel() is usually called after some kind of access - * error and thus is reported as SIGSEGV. - * - * - When panic() is called. This is reported as SIGABRT. - * - * - If C-c is received over the serial line, which is treated as - * SIGINT. - * - * Of course, all these signals are just faked for gdb, since there is no - * signal concept as such for the kernel. It also isn't possible --obviously-- - * to set signal handlers from inside gdb, or restart the kernel with a - * signal. - * - * Current limitations: - * - * - While the kernel is stopped, interrupts are disabled for safety reasons - * (i.e., variables not changing magically or the like). But this also - * means that the clock isn't running anymore, and that interrupts from the - * hardware may get lost/not be served in time. This can cause some device - * errors... - * - * - When single-stepping, only one instruction of the current thread is - * executed, but interrupts are allowed for that time and will be serviced - * if pending. Be prepared for that. - * - * - All debugging happens in kernel virtual address space. There's no way to - * access physical memory not mapped in kernel space, or to access user - * space. A way to work around this is using get_user_long & Co. in gdb - * expressions, but only for the current process. - * - * - Interrupting the kernel only works if interrupts are currently allowed, - * and the interrupt of the serial line isn't blocked by some other means - * (IPL too high, disabled, ...) - * - * - The gdb stub is currently not reentrant, i.e. errors that happen therein - * (e.g. accessing invalid memory) may not be caught correctly. This could - * be removed in future by introducing a stack of struct registers. - * - */ - -/* - * To enable debugger support, two things need to happen. One, a - * call to kgdb_init() is necessary in order to allow any breakpoints - * or error conditions to be properly intercepted and reported to gdb. - * Two, a breakpoint needs to be generated to begin communication. This - * is most easily accomplished by a call to breakpoint(). - * - * The following gdb commands are supported: - * - * command function Return value - * - * g return the value of the CPU registers hex data or ENN - * G set the value of the CPU registers OK or ENN - * - * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN - * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN - * - * c Resume at current address SNN ( signal NN) - * cAA..AA Continue at address AA..AA SNN - * - * s Step one instruction SNN - * sAA..AA Step one instruction from AA..AA SNN - * - * k kill - * - * ? What was the last sigval ? SNN (signal NN) - * - * bBB..BB Set baud rate to BB..BB OK or BNN, then sets - * baud rate - * - * All commands and responses are sent with a packet which includes a - * checksum. A packet consists of - * - * $<packet info>#<checksum>. - * - * where - * <packet info> :: <characters representing the command or response> - * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> - * - * When a packet is received, it is first acknowledged with either '+' or '-'. - * '+' indicates a successful transfer. '-' indicates a failed transfer. - * - * Example: - * - * Host: Reply: - * $m0,10#2a +$00010203040506070809101112131415#42 - * - */ - - -#include <linux/string.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/linkage.h> -#include <linux/reboot.h> - -#include <asm/setup.h> -#include <asm/ptrace.h> - -#include <asm/irq.h> -#include <hwregs/reg_map.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/intr_vect_defs.h> -#include <hwregs/ser_defs.h> - -/* From entry.S. */ -extern void gdb_handle_exception(void); -/* From kgdb_asm.S. */ -extern void kgdb_handle_exception(void); - -static int kgdb_started = 0; - -/********************************* Register image ****************************/ - -typedef -struct register_image -{ - /* Offset */ - unsigned int r0; /* 0x00 */ - unsigned int r1; /* 0x04 */ - unsigned int r2; /* 0x08 */ - unsigned int r3; /* 0x0C */ - unsigned int r4; /* 0x10 */ - unsigned int r5; /* 0x14 */ - unsigned int r6; /* 0x18 */ - unsigned int r7; /* 0x1C */ - unsigned int r8; /* 0x20; Frame pointer (if any) */ - unsigned int r9; /* 0x24 */ - unsigned int r10; /* 0x28 */ - unsigned int r11; /* 0x2C */ - unsigned int r12; /* 0x30 */ - unsigned int r13; /* 0x34 */ - unsigned int sp; /* 0x38; R14, Stack pointer */ - unsigned int acr; /* 0x3C; R15, Address calculation register. */ - - unsigned char bz; /* 0x40; P0, 8-bit zero register */ - unsigned char vr; /* 0x41; P1, Version register (8-bit) */ - unsigned int pid; /* 0x42; P2, Process ID */ - unsigned char srs; /* 0x46; P3, Support register select (8-bit) */ - unsigned short wz; /* 0x47; P4, 16-bit zero register */ - unsigned int exs; /* 0x49; P5, Exception status */ - unsigned int eda; /* 0x4D; P6, Exception data address */ - unsigned int mof; /* 0x51; P7, Multiply overflow register */ - unsigned int dz; /* 0x55; P8, 32-bit zero register */ - unsigned int ebp; /* 0x59; P9, Exception base pointer */ - unsigned int erp; /* 0x5D; P10, Exception return pointer. Contains the PC we are interested in. */ - unsigned int srp; /* 0x61; P11, Subroutine return pointer */ - unsigned int nrp; /* 0x65; P12, NMI return pointer */ - unsigned int ccs; /* 0x69; P13, Condition code stack */ - unsigned int usp; /* 0x6D; P14, User mode stack pointer */ - unsigned int spc; /* 0x71; P15, Single step PC */ - unsigned int pc; /* 0x75; Pseudo register (for the most part set to ERP). */ - -} registers; - -typedef -struct bp_register_image -{ - /* Support register bank 0. */ - unsigned int s0_0; - unsigned int s1_0; - unsigned int s2_0; - unsigned int s3_0; - unsigned int s4_0; - unsigned int s5_0; - unsigned int s6_0; - unsigned int s7_0; - unsigned int s8_0; - unsigned int s9_0; - unsigned int s10_0; - unsigned int s11_0; - unsigned int s12_0; - unsigned int s13_0; - unsigned int s14_0; - unsigned int s15_0; - - /* Support register bank 1. */ - unsigned int s0_1; - unsigned int s1_1; - unsigned int s2_1; - unsigned int s3_1; - unsigned int s4_1; - unsigned int s5_1; - unsigned int s6_1; - unsigned int s7_1; - unsigned int s8_1; - unsigned int s9_1; - unsigned int s10_1; - unsigned int s11_1; - unsigned int s12_1; - unsigned int s13_1; - unsigned int s14_1; - unsigned int s15_1; - - /* Support register bank 2. */ - unsigned int s0_2; - unsigned int s1_2; - unsigned int s2_2; - unsigned int s3_2; - unsigned int s4_2; - unsigned int s5_2; - unsigned int s6_2; - unsigned int s7_2; - unsigned int s8_2; - unsigned int s9_2; - unsigned int s10_2; - unsigned int s11_2; - unsigned int s12_2; - unsigned int s13_2; - unsigned int s14_2; - unsigned int s15_2; - - /* Support register bank 3. */ - unsigned int s0_3; /* BP_CTRL */ - unsigned int s1_3; /* BP_I0_START */ - unsigned int s2_3; /* BP_I0_END */ - unsigned int s3_3; /* BP_D0_START */ - unsigned int s4_3; /* BP_D0_END */ - unsigned int s5_3; /* BP_D1_START */ - unsigned int s6_3; /* BP_D1_END */ - unsigned int s7_3; /* BP_D2_START */ - unsigned int s8_3; /* BP_D2_END */ - unsigned int s9_3; /* BP_D3_START */ - unsigned int s10_3; /* BP_D3_END */ - unsigned int s11_3; /* BP_D4_START */ - unsigned int s12_3; /* BP_D4_END */ - unsigned int s13_3; /* BP_D5_START */ - unsigned int s14_3; /* BP_D5_END */ - unsigned int s15_3; /* BP_RESERVED */ - -} support_registers; - -enum register_name -{ - R0, R1, R2, R3, - R4, R5, R6, R7, - R8, R9, R10, R11, - R12, R13, SP, ACR, - - BZ, VR, PID, SRS, - WZ, EXS, EDA, MOF, - DZ, EBP, ERP, SRP, - NRP, CCS, USP, SPC, - PC, - - S0, S1, S2, S3, - S4, S5, S6, S7, - S8, S9, S10, S11, - S12, S13, S14, S15 - -}; - -/* The register sizes of the registers in register_name. An unimplemented register - is designated by size 0 in this array. */ -static int register_size[] = -{ - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - - 1, 1, 4, 1, - 2, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - - 4, - - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4 - -}; - -/* Contains the register image of the kernel. - (Global so that they can be reached from assembler code.) */ -registers reg; -support_registers sreg; - -/************** Prototypes for local library functions ***********************/ - -/* Copy of strcpy from libc. */ -static char *gdb_cris_strcpy(char *s1, const char *s2); - -/* Copy of strlen from libc. */ -static int gdb_cris_strlen(const char *s); - -/* Copy of memchr from libc. */ -static void *gdb_cris_memchr(const void *s, int c, int n); - -/* Copy of strtol from libc. Does only support base 16. */ -static int gdb_cris_strtol(const char *s, char **endptr, int base); - -/********************** Prototypes for local functions. **********************/ - -/* Write a value to a specified register regno in the register image - of the current thread. */ -static int write_register(int regno, char *val); - -/* Read a value from a specified register in the register image. Returns the - status of the read operation. The register value is returned in valptr. */ -static int read_register(char regno, unsigned int *valptr); - -/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */ -int getDebugChar(void); - -/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */ -void putDebugChar(int val); - -/* Convert the memory, pointed to by mem into hexadecimal representation. - Put the result in buf, and return a pointer to the last character - in buf (null). */ -static char *mem2hex(char *buf, unsigned char *mem, int count); - -/* Put the content of the array, in binary representation, pointed to by buf - into memory pointed to by mem, and return a pointer to - the character after the last byte written. */ -static unsigned char *bin2mem(unsigned char *mem, unsigned char *buf, int count); - -/* Await the sequence $<data>#<checksum> and store <data> in the array buffer - returned. */ -static void getpacket(char *buffer); - -/* Send $<data>#<checksum> from the <data> in the array buffer. */ -static void putpacket(char *buffer); - -/* Build and send a response packet in order to inform the host the - stub is stopped. */ -static void stub_is_stopped(int sigval); - -/* All expected commands are sent from remote.c. Send a response according - to the description in remote.c. Not static since it needs to be reached - from assembler code. */ -void handle_exception(int sigval); - -/* Performs a complete re-start from scratch. ETRAX specific. */ -static void kill_restart(void); - -/******************** Prototypes for global functions. ***********************/ - -/* The string str is prepended with the GDB printout token and sent. */ -void putDebugString(const unsigned char *str, int len); - -/* A static breakpoint to be used at startup. */ -void breakpoint(void); - -/* Avoid warning as the internal_stack is not used in the C-code. */ -#define USEDVAR(name) { if (name) { ; } } -#define USEDFUN(name) { void (*pf)(void) = (void *)name; USEDVAR(pf) } - -/********************************** Packet I/O ******************************/ -/* BUFMAX defines the maximum number of characters in - inbound/outbound buffers */ -/* FIXME: How do we know it's enough? */ -#define BUFMAX 512 - -/* Run-length encoding maximum length. Send 64 at most. */ -#define RUNLENMAX 64 - -/* The inbound/outbound buffers used in packet I/O */ -static char input_buffer[BUFMAX]; -static char output_buffer[BUFMAX]; - -/* Error and warning messages. */ -enum error_type -{ - SUCCESS, E01, E02, E03, E04, E05, E06, E07, E08 -}; - -static char *error_message[] = -{ - "", - "E01 Set current or general thread - H[c,g] - internal error.", - "E02 Change register content - P - cannot change read-only register.", - "E03 Thread is not alive.", /* T, not used. */ - "E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.", - "E05 Change register content - P - the register is not implemented..", - "E06 Change memory content - M - internal error.", - "E07 Change register content - P - the register is not stored on the stack", - "E08 Invalid parameter" -}; - -/********************************** Breakpoint *******************************/ -/* Use an internal stack in the breakpoint and interrupt response routines. - FIXME: How do we know the size of this stack is enough? - Global so it can be reached from assembler code. */ -#define INTERNAL_STACK_SIZE 1024 -char internal_stack[INTERNAL_STACK_SIZE]; - -/* Due to the breakpoint return pointer, a state variable is needed to keep - track of whether it is a static (compiled) or dynamic (gdb-invoked) - breakpoint to be handled. A static breakpoint uses the content of register - ERP as it is whereas a dynamic breakpoint requires subtraction with 2 - in order to execute the instruction. The first breakpoint is static; all - following are assumed to be dynamic. */ -static int dynamic_bp = 0; - -/********************************* String library ****************************/ -/* Single-step over library functions creates trap loops. */ - -/* Copy char s2[] to s1[]. */ -static char* -gdb_cris_strcpy(char *s1, const char *s2) -{ - char *s = s1; - - for (s = s1; (*s++ = *s2++) != '\0'; ) - ; - return s1; -} - -/* Find length of s[]. */ -static int -gdb_cris_strlen(const char *s) -{ - const char *sc; - - for (sc = s; *sc != '\0'; sc++) - ; - return (sc - s); -} - -/* Find first occurrence of c in s[n]. */ -static void* -gdb_cris_memchr(const void *s, int c, int n) -{ - const unsigned char uc = c; - const unsigned char *su; - - for (su = s; 0 < n; ++su, --n) - if (*su == uc) - return (void *)su; - return NULL; -} -/******************************* Standard library ****************************/ -/* Single-step over library functions creates trap loops. */ -/* Convert string to long. */ -static int -gdb_cris_strtol(const char *s, char **endptr, int base) -{ - char *s1; - char *sd; - int x = 0; - - for (s1 = (char*)s; (sd = gdb_cris_memchr(hex_asc, *s1, base)) != NULL; ++s1) - x = x * base + (sd - hex_asc); - - if (endptr) { - /* Unconverted suffix is stored in endptr unless endptr is NULL. */ - *endptr = s1; - } - - return x; -} - -/********************************* Register image ****************************/ - -/* Write a value to a specified register in the register image of the current - thread. Returns status code SUCCESS, E02, E05 or E08. */ -static int -write_register(int regno, char *val) -{ - int status = SUCCESS; - - if (regno >= R0 && regno <= ACR) { - /* Consecutive 32-bit registers. */ - if (hex2bin((unsigned char *)®.r0 + (regno - R0) * sizeof(unsigned int), - val, sizeof(unsigned int))) - status = E08; - - } else if (regno == BZ || regno == VR || regno == WZ || regno == DZ) { - /* Read-only registers. */ - status = E02; - - } else if (regno == PID) { - /* 32-bit register. (Even though we already checked SRS and WZ, we cannot - combine this with the EXS - SPC write since SRS and WZ have different size.) */ - if (hex2bin((unsigned char *)®.pid, val, sizeof(unsigned int))) - status = E08; - - } else if (regno == SRS) { - /* 8-bit register. */ - if (hex2bin((unsigned char *)®.srs, val, sizeof(unsigned char))) - status = E08; - - } else if (regno >= EXS && regno <= SPC) { - /* Consecutive 32-bit registers. */ - if (hex2bin((unsigned char *)®.exs + (regno - EXS) * sizeof(unsigned int), - val, sizeof(unsigned int))) - status = E08; - - } else if (regno == PC) { - /* Pseudo-register. Treat as read-only. */ - status = E02; - - } else if (regno >= S0 && regno <= S15) { - /* 32-bit registers. */ - if (hex2bin((unsigned char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int), - val, sizeof(unsigned int))) - status = E08; - } else { - /* Non-existing register. */ - status = E05; - } - return status; -} - -/* Read a value from a specified register in the register image. Returns the - value in the register or -1 for non-implemented registers. */ -static int -read_register(char regno, unsigned int *valptr) -{ - int status = SUCCESS; - - /* We read the zero registers from the register struct (instead of just returning 0) - to catch errors. */ - - if (regno >= R0 && regno <= ACR) { - /* Consecutive 32-bit registers. */ - *valptr = *(unsigned int *)((char *)®.r0 + (regno - R0) * sizeof(unsigned int)); - - } else if (regno == BZ || regno == VR) { - /* Consecutive 8-bit registers. */ - *valptr = (unsigned int)(*(unsigned char *) - ((char *)®.bz + (regno - BZ) * sizeof(char))); - - } else if (regno == PID) { - /* 32-bit register. */ - *valptr = *(unsigned int *)((char *)®.pid); - - } else if (regno == SRS) { - /* 8-bit register. */ - *valptr = (unsigned int)(*(unsigned char *)((char *)®.srs)); - - } else if (regno == WZ) { - /* 16-bit register. */ - *valptr = (unsigned int)(*(unsigned short *)(char *)®.wz); - - } else if (regno >= EXS && regno <= PC) { - /* Consecutive 32-bit registers. */ - *valptr = *(unsigned int *)((char *)®.exs + (regno - EXS) * sizeof(unsigned int)); - - } else if (regno >= S0 && regno <= S15) { - /* Consecutive 32-bit registers, located elsewhere. */ - *valptr = *(unsigned int *)((char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int)); - - } else { - /* Non-existing register. */ - status = E05; - } - return status; - -} - -/********************************** Packet I/O ******************************/ -/* Convert the memory, pointed to by mem into hexadecimal representation. - Put the result in buf, and return a pointer to the last character - in buf (null). */ - -static char * -mem2hex(char *buf, unsigned char *mem, int count) -{ - int i; - int ch; - - if (mem == NULL) { - /* Invalid address, caught by 'm' packet handler. */ - for (i = 0; i < count; i++) { - *buf++ = '0'; - *buf++ = '0'; - } - } else { - /* Valid mem address. */ - for (i = 0; i < count; i++) { - ch = *mem++; - buf = hex_byte_pack(buf, ch); - } - } - /* Terminate properly. */ - *buf = '\0'; - return buf; -} - -/* Same as mem2hex, but puts it in network byte order. */ -static char * -mem2hex_nbo(char *buf, unsigned char *mem, int count) -{ - int i; - int ch; - - mem += count - 1; - for (i = 0; i < count; i++) { - ch = *mem--; - buf = hex_byte_pack(buf, ch); - } - - /* Terminate properly. */ - *buf = '\0'; - return buf; -} - -/* Put the content of the array, in binary representation, pointed to by buf - into memory pointed to by mem, and return a pointer to the character after - the last byte written. - Gdb will escape $, #, and the escape char (0x7d). */ -static unsigned char* -bin2mem(unsigned char *mem, unsigned char *buf, int count) -{ - int i; - unsigned char *next; - for (i = 0; i < count; i++) { - /* Check for any escaped characters. Be paranoid and - only unescape chars that should be escaped. */ - if (*buf == 0x7d) { - next = buf + 1; - if (*next == 0x3 || *next == 0x4 || *next == 0x5D) { - /* #, $, ESC */ - buf++; - *buf += 0x20; - } - } - *mem++ = *buf++; - } - return mem; -} - -/* Await the sequence $<data>#<checksum> and store <data> in the array buffer - returned. */ -static void -getpacket(char *buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - char ch; - - do { - while((ch = getDebugChar ()) != '$') - /* Wait for the start character $ and ignore all other characters */; - checksum = 0; - xmitcsum = -1; - count = 0; - /* Read until a # or the end of the buffer is reached */ - while (count < BUFMAX) { - ch = getDebugChar(); - if (ch == '#') - break; - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - - if (count >= BUFMAX) - continue; - - buffer[count] = 0; - - if (ch == '#') { - xmitcsum = hex_to_bin(getDebugChar()) << 4; - xmitcsum += hex_to_bin(getDebugChar()); - if (checksum != xmitcsum) { - /* Wrong checksum */ - putDebugChar('-'); - } else { - /* Correct checksum */ - putDebugChar('+'); - /* If sequence characters are received, reply with them */ - if (buffer[2] == ':') { - putDebugChar(buffer[0]); - putDebugChar(buffer[1]); - /* Remove the sequence characters from the buffer */ - count = gdb_cris_strlen(buffer); - for (i = 3; i <= count; i++) - buffer[i - 3] = buffer[i]; - } - } - } - } while (checksum != xmitcsum); -} - -/* Send $<data>#<checksum> from the <data> in the array buffer. */ - -static void -putpacket(char *buffer) -{ - int checksum; - int runlen; - int encode; - - do { - char *src = buffer; - putDebugChar('$'); - checksum = 0; - while (*src) { - /* Do run length encoding */ - putDebugChar(*src); - checksum += *src; - runlen = 0; - while (runlen < RUNLENMAX && *src == src[runlen]) { - runlen++; - } - if (runlen > 3) { - /* Got a useful amount */ - putDebugChar ('*'); - checksum += '*'; - encode = runlen + ' ' - 4; - putDebugChar(encode); - checksum += encode; - src += runlen; - } else { - src++; - } - } - putDebugChar('#'); - putDebugChar(hex_asc_hi(checksum)); - putDebugChar(hex_asc_lo(checksum)); - } while(kgdb_started && (getDebugChar() != '+')); -} - -/* The string str is prepended with the GDB printout token and sent. Required - in traditional implementations. */ -void -putDebugString(const unsigned char *str, int len) -{ - /* Move SPC forward if we are single-stepping. */ - asm("spchere:"); - asm("move $spc, $r10"); - asm("cmp.d spchere, $r10"); - asm("bne nosstep"); - asm("nop"); - asm("move.d spccont, $r10"); - asm("move $r10, $spc"); - asm("nosstep:"); - - output_buffer[0] = 'O'; - mem2hex(&output_buffer[1], (unsigned char *)str, len); - putpacket(output_buffer); - - asm("spccont:"); -} - -/********************************** Handle exceptions ************************/ -/* Build and send a response packet in order to inform the host the - stub is stopped. TAAn...:r...;n...:r...;n...:r...; - AA = signal number - n... = register number (hex) - r... = register contents - n... = `thread' - r... = thread process ID. This is a hex integer. - n... = other string not starting with valid hex digit. - gdb should ignore this n,r pair and go on to the next. - This way we can extend the protocol. */ -static void -stub_is_stopped(int sigval) -{ - char *ptr = output_buffer; - unsigned int reg_cont; - - /* Send trap type (converted to signal) */ - - *ptr++ = 'T'; - ptr = hex_byte_pack(ptr, sigval); - - if (((reg.exs & 0xff00) >> 8) == 0xc) { - - /* Some kind of hardware watchpoint triggered. Find which one - and determine its type (read/write/access). */ - int S, bp, trig_bits = 0, rw_bits = 0; - int trig_mask = 0; - unsigned int *bp_d_regs = &sreg.s3_3; - /* In a lot of cases, the stopped data address will simply be EDA. - In some cases, we adjust it to match the watched data range. - (We don't want to change the actual EDA though). */ - unsigned int stopped_data_address; - /* The S field of EXS. */ - S = (reg.exs & 0xffff0000) >> 16; - - if (S & 1) { - /* Instruction watchpoint. */ - /* FIXME: Check against, and possibly adjust reported EDA. */ - } else { - /* Data watchpoint. Find the one that triggered. */ - for (bp = 0; bp < 6; bp++) { - - /* Dx_RD, Dx_WR in the S field of EXS for this BP. */ - int bitpos_trig = 1 + bp * 2; - /* Dx_BPRD, Dx_BPWR in BP_CTRL for this BP. */ - int bitpos_config = 2 + bp * 4; - - /* Get read/write trig bits for this BP. */ - trig_bits = (S & (3 << bitpos_trig)) >> bitpos_trig; - - /* Read/write config bits for this BP. */ - rw_bits = (sreg.s0_3 & (3 << bitpos_config)) >> bitpos_config; - if (trig_bits) { - /* Sanity check: the BP shouldn't trigger for accesses - that it isn't configured for. */ - if ((rw_bits == 0x1 && trig_bits != 0x1) || - (rw_bits == 0x2 && trig_bits != 0x2)) - panic("Invalid r/w trigging for this BP"); - - /* Mark this BP as trigged for future reference. */ - trig_mask |= (1 << bp); - - if (reg.eda >= bp_d_regs[bp * 2] && - reg.eda <= bp_d_regs[bp * 2 + 1]) { - /* EDA within range for this BP; it must be the one - we're looking for. */ - stopped_data_address = reg.eda; - break; - } - } - } - if (bp < 6) { - /* Found a trigged BP with EDA within its configured data range. */ - } else if (trig_mask) { - /* Something triggered, but EDA doesn't match any BP's range. */ - for (bp = 0; bp < 6; bp++) { - /* Dx_BPRD, Dx_BPWR in BP_CTRL for this BP. */ - int bitpos_config = 2 + bp * 4; - - /* Read/write config bits for this BP (needed later). */ - rw_bits = (sreg.s0_3 & (3 << bitpos_config)) >> bitpos_config; - - if (trig_mask & (1 << bp)) { - /* EDA within 31 bytes of the configured start address? */ - if (reg.eda + 31 >= bp_d_regs[bp * 2]) { - /* Changing the reported address to match - the start address of the first applicable BP. */ - stopped_data_address = bp_d_regs[bp * 2]; - break; - } else { - /* We continue since we might find another useful BP. */ - printk("EDA doesn't match trigged BP's range"); - } - } - } - } - - /* No match yet? */ - BUG_ON(bp >= 6); - /* Note that we report the type according to what the BP is configured - for (otherwise we'd never report an 'awatch'), not according to how - it trigged. We did check that the trigged bits match what the BP is - configured for though. */ - if (rw_bits == 0x1) { - /* read */ - strncpy(ptr, "rwatch", 6); - ptr += 6; - } else if (rw_bits == 0x2) { - /* write */ - strncpy(ptr, "watch", 5); - ptr += 5; - } else if (rw_bits == 0x3) { - /* access */ - strncpy(ptr, "awatch", 6); - ptr += 6; - } else { - panic("Invalid r/w bits for this BP."); - } - - *ptr++ = ':'; - /* Note that we don't read_register(EDA, ...) */ - ptr = mem2hex_nbo(ptr, (unsigned char *)&stopped_data_address, register_size[EDA]); - *ptr++ = ';'; - } - } - /* Only send PC, frame and stack pointer. */ - read_register(PC, ®_cont); - ptr = hex_byte_pack(ptr, PC); - *ptr++ = ':'; - ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[PC]); - *ptr++ = ';'; - - read_register(R8, ®_cont); - ptr = hex_byte_pack(ptr, R8); - *ptr++ = ':'; - ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[R8]); - *ptr++ = ';'; - - read_register(SP, ®_cont); - ptr = hex_byte_pack(ptr, SP); - *ptr++ = ':'; - ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[SP]); - *ptr++ = ';'; - - /* Send ERP as well; this will save us an entire register fetch in some cases. */ - read_register(ERP, ®_cont); - ptr = hex_byte_pack(ptr, ERP); - *ptr++ = ':'; - ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[ERP]); - *ptr++ = ';'; - - /* null-terminate and send it off */ - *ptr = 0; - putpacket(output_buffer); -} - -/* Returns the size of an instruction that has a delay slot. */ - -int insn_size(unsigned long pc) -{ - unsigned short opcode = *(unsigned short *)pc; - int size = 0; - - switch ((opcode & 0x0f00) >> 8) { - case 0x0: - case 0x9: - case 0xb: - size = 2; - break; - case 0xe: - case 0xf: - size = 6; - break; - case 0xd: - /* Could be 4 or 6; check more bits. */ - if ((opcode & 0xff) == 0xff) - size = 4; - else - size = 6; - break; - default: - panic("Couldn't find size of opcode 0x%x at 0x%lx\n", opcode, pc); - } - - return size; -} - -void register_fixup(int sigval) -{ - /* Compensate for ACR push at the beginning of exception handler. */ - reg.sp += 4; - - /* Standard case. */ - reg.pc = reg.erp; - if (reg.erp & 0x1) { - /* Delay slot bit set. Report as stopped on proper instruction. */ - if (reg.spc) { - /* Rely on SPC if set. */ - reg.pc = reg.spc; - } else { - /* Calculate the PC from the size of the instruction - that the delay slot we're in belongs to. */ - reg.pc += insn_size(reg.erp & ~1) - 1 ; - } - } - - if ((reg.exs & 0x3) == 0x0) { - /* Bits 1 - 0 indicate the type of memory operation performed - by the interrupted instruction. 0 means no memory operation, - and EDA is undefined in that case. We zero it to avoid confusion. */ - reg.eda = 0; - } - - if (sigval == SIGTRAP) { - /* Break 8, single step or hardware breakpoint exception. */ - - /* Check IDX field of EXS. */ - if (((reg.exs & 0xff00) >> 8) == 0x18) { - - /* Break 8. */ - - /* Static (compiled) breakpoints must return to the next instruction - in order to avoid infinite loops (default value of ERP). Dynamic - (gdb-invoked) must subtract the size of the break instruction from - the ERP so that the instruction that was originally in the break - instruction's place will be run when we return from the exception. */ - if (!dynamic_bp) { - /* Assuming that all breakpoints are dynamic from now on. */ - dynamic_bp = 1; - } else { - - /* Only if not in a delay slot. */ - if (!(reg.erp & 0x1)) { - reg.erp -= 2; - reg.pc -= 2; - } - } - - } else if (((reg.exs & 0xff00) >> 8) == 0x3) { - /* Single step. */ - /* Don't fiddle with S1. */ - - } else if (((reg.exs & 0xff00) >> 8) == 0xc) { - - /* Hardware watchpoint exception. */ - - /* SPC has been updated so that we will get a single step exception - when we return, but we don't want that. */ - reg.spc = 0; - - /* Don't fiddle with S1. */ - } - - } else if (sigval == SIGINT) { - /* Nothing special. */ - } -} - -static void insert_watchpoint(char type, int addr, int len) -{ - /* Breakpoint/watchpoint types (GDB terminology): - 0 = memory breakpoint for instructions - (not supported; done via memory write instead) - 1 = hardware breakpoint for instructions (supported) - 2 = write watchpoint (supported) - 3 = read watchpoint (supported) - 4 = access watchpoint (supported) */ - - if (type < '1' || type > '4') { - output_buffer[0] = 0; - return; - } - - /* Read watchpoints are set as access watchpoints, because of GDB's - inability to deal with pure read watchpoints. */ - if (type == '3') - type = '4'; - - if (type == '1') { - /* Hardware (instruction) breakpoint. */ - /* Bit 0 in BP_CTRL holds the configuration for I0. */ - if (sreg.s0_3 & 0x1) { - /* Already in use. */ - gdb_cris_strcpy(output_buffer, error_message[E04]); - return; - } - /* Configure. */ - sreg.s1_3 = addr; - sreg.s2_3 = (addr + len - 1); - sreg.s0_3 |= 1; - } else { - int bp; - unsigned int *bp_d_regs = &sreg.s3_3; - - /* The watchpoint allocation scheme is the simplest possible. - For example, if a region is watched for read and - a write watch is requested, a new watchpoint will - be used. Also, if a watch for a region that is already - covered by one or more existing watchpoints, a new - watchpoint will be used. */ - - /* First, find a free data watchpoint. */ - for (bp = 0; bp < 6; bp++) { - /* Each data watchpoint's control registers occupy 2 bits - (hence the 3), starting at bit 2 for D0 (hence the 2) - with 4 bits between for each watchpoint (yes, the 4). */ - if (!(sreg.s0_3 & (0x3 << (2 + (bp * 4))))) { - break; - } - } - - if (bp > 5) { - /* We're out of watchpoints. */ - gdb_cris_strcpy(output_buffer, error_message[E04]); - return; - } - - /* Configure the control register first. */ - if (type == '3' || type == '4') { - /* Trigger on read. */ - sreg.s0_3 |= (1 << (2 + bp * 4)); - } - if (type == '2' || type == '4') { - /* Trigger on write. */ - sreg.s0_3 |= (2 << (2 + bp * 4)); - } - - /* Ugly pointer arithmetics to configure the watched range. */ - bp_d_regs[bp * 2] = addr; - bp_d_regs[bp * 2 + 1] = (addr + len - 1); - } - - /* Set the S1 flag to enable watchpoints. */ - reg.ccs |= (1 << (S_CCS_BITNR + CCS_SHIFT)); - gdb_cris_strcpy(output_buffer, "OK"); -} - -static void remove_watchpoint(char type, int addr, int len) -{ - /* Breakpoint/watchpoint types: - 0 = memory breakpoint for instructions - (not supported; done via memory write instead) - 1 = hardware breakpoint for instructions (supported) - 2 = write watchpoint (supported) - 3 = read watchpoint (supported) - 4 = access watchpoint (supported) */ - if (type < '1' || type > '4') { - output_buffer[0] = 0; - return; - } - - /* Read watchpoints are set as access watchpoints, because of GDB's - inability to deal with pure read watchpoints. */ - if (type == '3') - type = '4'; - - if (type == '1') { - /* Hardware breakpoint. */ - /* Bit 0 in BP_CTRL holds the configuration for I0. */ - if (!(sreg.s0_3 & 0x1)) { - /* Not in use. */ - gdb_cris_strcpy(output_buffer, error_message[E04]); - return; - } - /* Deconfigure. */ - sreg.s1_3 = 0; - sreg.s2_3 = 0; - sreg.s0_3 &= ~1; - } else { - int bp; - unsigned int *bp_d_regs = &sreg.s3_3; - /* Try to find a watchpoint that is configured for the - specified range, then check that read/write also matches. */ - - /* Ugly pointer arithmetic, since I cannot rely on a - single switch (addr) as there may be several watchpoints with - the same start address for example. */ - - for (bp = 0; bp < 6; bp++) { - if (bp_d_regs[bp * 2] == addr && - bp_d_regs[bp * 2 + 1] == (addr + len - 1)) { - /* Matching range. */ - int bitpos = 2 + bp * 4; - int rw_bits; - - /* Read/write bits for this BP. */ - rw_bits = (sreg.s0_3 & (0x3 << bitpos)) >> bitpos; - - if ((type == '3' && rw_bits == 0x1) || - (type == '2' && rw_bits == 0x2) || - (type == '4' && rw_bits == 0x3)) { - /* Read/write matched. */ - break; - } - } - } - - if (bp > 5) { - /* No watchpoint matched. */ - gdb_cris_strcpy(output_buffer, error_message[E04]); - return; - } - - /* Found a matching watchpoint. Now, deconfigure it by - both disabling read/write in bp_ctrl and zeroing its - start/end addresses. */ - sreg.s0_3 &= ~(3 << (2 + (bp * 4))); - bp_d_regs[bp * 2] = 0; - bp_d_regs[bp * 2 + 1] = 0; - } - - /* Note that we don't clear the S1 flag here. It's done when continuing. */ - gdb_cris_strcpy(output_buffer, "OK"); -} - - - -/* All expected commands are sent from remote.c. Send a response according - to the description in remote.c. */ -void -handle_exception(int sigval) -{ - /* Avoid warning of not used. */ - - USEDFUN(handle_exception); - USEDVAR(internal_stack[0]); - - register_fixup(sigval); - - /* Send response. */ - stub_is_stopped(sigval); - - for (;;) { - output_buffer[0] = '\0'; - getpacket(input_buffer); - switch (input_buffer[0]) { - case 'g': - /* Read registers: g - Success: Each byte of register data is described by two hex digits. - Registers are in the internal order for GDB, and the bytes - in a register are in the same order the machine uses. - Failure: void. */ - { - char *buf; - /* General and special registers. */ - buf = mem2hex(output_buffer, (char *)®, sizeof(registers)); - /* Support registers. */ - /* -1 because of the null termination that mem2hex adds. */ - mem2hex(buf, - (char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)), - 16 * sizeof(unsigned int)); - break; - } - case 'G': - /* Write registers. GXX..XX - Each byte of register data is described by two hex digits. - Success: OK - Failure: E08. */ - /* General and special registers. */ - if (hex2bin((char *)®, &input_buffer[1], sizeof(registers))) - gdb_cris_strcpy(output_buffer, error_message[E08]); - /* Support registers. */ - else if (hex2bin((char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)), - &input_buffer[1] + sizeof(registers), - 16 * sizeof(unsigned int))) - gdb_cris_strcpy(output_buffer, error_message[E08]); - else - gdb_cris_strcpy(output_buffer, "OK"); - break; - - case 'P': - /* Write register. Pn...=r... - Write register n..., hex value without 0x, with value r..., - which contains a hex value without 0x and two hex digits - for each byte in the register (target byte order). P1f=11223344 means - set register 31 to 44332211. - Success: OK - Failure: E02, E05 */ - { - char *suffix; - int regno = gdb_cris_strtol(&input_buffer[1], &suffix, 16); - int status; - - status = write_register(regno, suffix+1); - - switch (status) { - case E02: - /* Do not support read-only registers. */ - gdb_cris_strcpy(output_buffer, error_message[E02]); - break; - case E05: - /* Do not support non-existing registers. */ - gdb_cris_strcpy(output_buffer, error_message[E05]); - break; - case E08: - /* Invalid parameter. */ - gdb_cris_strcpy(output_buffer, error_message[E08]); - break; - default: - /* Valid register number. */ - gdb_cris_strcpy(output_buffer, "OK"); - break; - } - } - break; - - case 'm': - /* Read from memory. mAA..AA,LLLL - AA..AA is the address and LLLL is the length. - Success: XX..XX is the memory content. Can be fewer bytes than - requested if only part of the data may be read. m6000120a,6c means - retrieve 108 byte from base address 6000120a. - Failure: void. */ - { - char *suffix; - unsigned char *addr = (unsigned char *)gdb_cris_strtol(&input_buffer[1], - &suffix, 16); - int len = gdb_cris_strtol(suffix+1, 0, 16); - - /* Bogus read (i.e. outside the kernel's - segment)? . */ - if (!((unsigned int)addr >= 0xc0000000 && - (unsigned int)addr < 0xd0000000)) - addr = NULL; - - mem2hex(output_buffer, addr, len); - } - break; - - case 'X': - /* Write to memory. XAA..AA,LLLL:XX..XX - AA..AA is the start address, LLLL is the number of bytes, and - XX..XX is the binary data. - Success: OK - Failure: void. */ - case 'M': - /* Write to memory. MAA..AA,LLLL:XX..XX - AA..AA is the start address, LLLL is the number of bytes, and - XX..XX is the hexadecimal data. - Success: OK - Failure: E08. */ - { - char *lenptr; - char *dataptr; - unsigned char *addr = (unsigned char *)gdb_cris_strtol(&input_buffer[1], - &lenptr, 16); - int len = gdb_cris_strtol(lenptr+1, &dataptr, 16); - if (*lenptr == ',' && *dataptr == ':') { - if (input_buffer[0] == 'M') { - if (hex2bin(addr, dataptr + 1, len)) - gdb_cris_strcpy(output_buffer, error_message[E08]); - else - gdb_cris_strcpy(output_buffer, "OK"); - } else /* X */ { - bin2mem(addr, dataptr + 1, len); - gdb_cris_strcpy(output_buffer, "OK"); - } - } else { - gdb_cris_strcpy(output_buffer, error_message[E06]); - } - } - break; - - case 'c': - /* Continue execution. cAA..AA - AA..AA is the address where execution is resumed. If AA..AA is - omitted, resume at the present address. - Success: return to the executing thread. - Failure: will never know. */ - - if (input_buffer[1] != '\0') { - /* FIXME: Doesn't handle address argument. */ - gdb_cris_strcpy(output_buffer, error_message[E04]); - break; - } - - /* Before continuing, make sure everything is set up correctly. */ - - /* Set the SPC to some unlikely value. */ - reg.spc = 0; - /* Set the S1 flag to 0 unless some watchpoint is enabled (since setting - S1 to 0 would also disable watchpoints). (Note that bits 26-31 in BP_CTRL - are reserved, so don't check against those). */ - if ((sreg.s0_3 & 0x3fff) == 0) { - reg.ccs &= ~(1 << (S_CCS_BITNR + CCS_SHIFT)); - } - - return; - - case 's': - /* Step. sAA..AA - AA..AA is the address where execution is resumed. If AA..AA is - omitted, resume at the present address. Success: return to the - executing thread. Failure: will never know. */ - - if (input_buffer[1] != '\0') { - /* FIXME: Doesn't handle address argument. */ - gdb_cris_strcpy(output_buffer, error_message[E04]); - break; - } - - /* Set the SPC to PC, which is where we'll return - (deduced previously). */ - reg.spc = reg.pc; - - /* Set the S1 (first stacked, not current) flag, which will - kick into action when we rfe. */ - reg.ccs |= (1 << (S_CCS_BITNR + CCS_SHIFT)); - return; - - case 'Z': - - /* Insert breakpoint or watchpoint, Ztype,addr,length. - Remote protocol says: A remote target shall return an empty string - for an unrecognized breakpoint or watchpoint packet type. */ - { - char *lenptr; - char *dataptr; - int addr = gdb_cris_strtol(&input_buffer[3], &lenptr, 16); - int len = gdb_cris_strtol(lenptr + 1, &dataptr, 16); - char type = input_buffer[1]; - - insert_watchpoint(type, addr, len); - break; - } - - case 'z': - /* Remove breakpoint or watchpoint, Ztype,addr,length. - Remote protocol says: A remote target shall return an empty string - for an unrecognized breakpoint or watchpoint packet type. */ - { - char *lenptr; - char *dataptr; - int addr = gdb_cris_strtol(&input_buffer[3], &lenptr, 16); - int len = gdb_cris_strtol(lenptr + 1, &dataptr, 16); - char type = input_buffer[1]; - - remove_watchpoint(type, addr, len); - break; - } - - - case '?': - /* The last signal which caused a stop. ? - Success: SAA, where AA is the signal number. - Failure: void. */ - output_buffer[0] = 'S'; - output_buffer[1] = hex_asc_hi(sigval); - output_buffer[2] = hex_asc_lo(sigval); - output_buffer[3] = 0; - break; - - case 'D': - /* Detach from host. D - Success: OK, and return to the executing thread. - Failure: will never know */ - putpacket("OK"); - return; - - case 'k': - case 'r': - /* kill request or reset request. - Success: restart of target. - Failure: will never know. */ - kill_restart(); - break; - - case 'C': - case 'S': - case '!': - case 'R': - case 'd': - /* Continue with signal sig. Csig;AA..AA - Step with signal sig. Ssig;AA..AA - Use the extended remote protocol. ! - Restart the target system. R0 - Toggle debug flag. d - Search backwards. tAA:PP,MM - Not supported: E04 */ - - /* FIXME: What's the difference between not supported - and ignored (below)? */ - gdb_cris_strcpy(output_buffer, error_message[E04]); - break; - - default: - /* The stub should ignore other request and send an empty - response ($#<checksum>). This way we can extend the protocol and GDB - can tell whether the stub it is talking to uses the old or the new. */ - output_buffer[0] = 0; - break; - } - putpacket(output_buffer); - } -} - -void -kgdb_init(void) -{ - reg_intr_vect_rw_mask intr_mask; - reg_ser_rw_intr_mask ser_intr_mask; - - /* Configure the kgdb serial port. */ -#if defined(CONFIG_ETRAX_KGDB_PORT0) - /* Note: no shortcut registered (not handled by multiple_interrupt). - See entry.S. */ - set_exception_vector(SER0_INTR_VECT, kgdb_handle_exception); - /* Enable the ser irq in the global config. */ - intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); - intr_mask.ser0 = 1; - REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); - - ser_intr_mask = REG_RD(ser, regi_ser0, rw_intr_mask); - ser_intr_mask.dav = regk_ser_yes; - REG_WR(ser, regi_ser0, rw_intr_mask, ser_intr_mask); -#elif defined(CONFIG_ETRAX_KGDB_PORT1) - /* Note: no shortcut registered (not handled by multiple_interrupt). - See entry.S. */ - set_exception_vector(SER1_INTR_VECT, kgdb_handle_exception); - /* Enable the ser irq in the global config. */ - intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); - intr_mask.ser1 = 1; - REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); - - ser_intr_mask = REG_RD(ser, regi_ser1, rw_intr_mask); - ser_intr_mask.dav = regk_ser_yes; - REG_WR(ser, regi_ser1, rw_intr_mask, ser_intr_mask); -#elif defined(CONFIG_ETRAX_KGDB_PORT2) - /* Note: no shortcut registered (not handled by multiple_interrupt). - See entry.S. */ - set_exception_vector(SER2_INTR_VECT, kgdb_handle_exception); - /* Enable the ser irq in the global config. */ - intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); - intr_mask.ser2 = 1; - REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); - - ser_intr_mask = REG_RD(ser, regi_ser2, rw_intr_mask); - ser_intr_mask.dav = regk_ser_yes; - REG_WR(ser, regi_ser2, rw_intr_mask, ser_intr_mask); -#elif defined(CONFIG_ETRAX_KGDB_PORT3) - /* Note: no shortcut registered (not handled by multiple_interrupt). - See entry.S. */ - set_exception_vector(SER3_INTR_VECT, kgdb_handle_exception); - /* Enable the ser irq in the global config. */ - intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); - intr_mask.ser3 = 1; - REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); - - ser_intr_mask = REG_RD(ser, regi_ser3, rw_intr_mask); - ser_intr_mask.dav = regk_ser_yes; - REG_WR(ser, regi_ser3, rw_intr_mask, ser_intr_mask); -#endif - -} -/* Performs a complete re-start from scratch. */ -static void -kill_restart(void) -{ - machine_restart(""); -} - -/* Use this static breakpoint in the start-up only. */ - -void -breakpoint(void) -{ - kgdb_started = 1; - dynamic_bp = 0; /* This is a static, not a dynamic breakpoint. */ - __asm__ volatile ("break 8"); /* Jump to kgdb_handle_breakpoint. */ -} - -/****************************** End of file **********************************/ diff --git a/arch/cris/arch-v32/kernel/kgdb_asm.S b/arch/cris/arch-v32/kernel/kgdb_asm.S deleted file mode 100644 index c26ea6b0e334..000000000000 --- a/arch/cris/arch-v32/kernel/kgdb_asm.S +++ /dev/null @@ -1,552 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2004 Axis Communications AB - * - * Code for handling break 8, hardware breakpoint, single step, and serial - * port exceptions for kernel debugging purposes. - */ - -#include <hwregs/intr_vect.h> - - ;; Exported functions. - .globl kgdb_handle_exception - -kgdb_handle_exception: - -;; Create a register image of the caller. -;; -;; First of all, save the ACR on the stack since we need it for address calculations. -;; We put it into the register struct later. - - subq 4, $sp - move.d $acr, [$sp] - -;; Now we are free to use ACR all we want. -;; If we were running this handler with interrupts on, we would have to be careful -;; to save and restore CCS manually, but since we aren't we treat it like every other -;; register. - - move.d reg, $acr - move.d $r0, [$acr] ; Save R0 (start of register struct) - addq 4, $acr - move.d $r1, [$acr] ; Save R1 - addq 4, $acr - move.d $r2, [$acr] ; Save R2 - addq 4, $acr - move.d $r3, [$acr] ; Save R3 - addq 4, $acr - move.d $r4, [$acr] ; Save R4 - addq 4, $acr - move.d $r5, [$acr] ; Save R5 - addq 4, $acr - move.d $r6, [$acr] ; Save R6 - addq 4, $acr - move.d $r7, [$acr] ; Save R7 - addq 4, $acr - move.d $r8, [$acr] ; Save R8 - addq 4, $acr - move.d $r9, [$acr] ; Save R9 - addq 4, $acr - move.d $r10, [$acr] ; Save R10 - addq 4, $acr - move.d $r11, [$acr] ; Save R11 - addq 4, $acr - move.d $r12, [$acr] ; Save R12 - addq 4, $acr - move.d $r13, [$acr] ; Save R13 - addq 4, $acr - move.d $sp, [$acr] ; Save SP (R14) - addq 4, $acr - - ;; The ACR register is already saved on the stack, so pop it from there. - move.d [$sp],$r0 - move.d $r0, [$acr] - addq 4, $acr - - move $bz, [$acr] - addq 1, $acr - move $vr, [$acr] - addq 1, $acr - move $pid, [$acr] - addq 4, $acr - move $srs, [$acr] - addq 1, $acr - move $wz, [$acr] - addq 2, $acr - move $exs, [$acr] - addq 4, $acr - move $eda, [$acr] - addq 4, $acr - move $mof, [$acr] - addq 4, $acr - move $dz, [$acr] - addq 4, $acr - move $ebp, [$acr] - addq 4, $acr - move $erp, [$acr] - addq 4, $acr - move $srp, [$acr] - addq 4, $acr - move $nrp, [$acr] - addq 4, $acr - move $ccs, [$acr] - addq 4, $acr - move $usp, [$acr] - addq 4, $acr - move $spc, [$acr] - addq 4, $acr - -;; Skip the pseudo-PC. - addq 4, $acr - -;; Save the support registers in bank 0 - 3. - clear.d $r1 ; Bank counter - move.d sreg, $acr - -;; Bank 0 - move $r1, $srs - nop - nop - nop - move $s0, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s1, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s2, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s3, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s4, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s5, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s6, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s7, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s8, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s9, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s10, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s11, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s12, $r0 - move.d $r0, [$acr] - addq 4, $acr - - ;; Nothing in S13 - S15, bank 0 - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - -;; Bank 1 and bank 2 have the same layout, hence the loop. - addq 1, $r1 -1: - move $r1, $srs - nop - nop - nop - move $s0, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s1, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s2, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s3, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s4, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s5, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s6, $r0 - move.d $r0, [$acr] - addq 4, $acr - - ;; Nothing in S7 - S15, bank 1 and 2 - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - clear.d [$acr] - addq 4, $acr - - addq 1, $r1 - cmpq 3, $r1 - bne 1b - nop - -;; Bank 3 - move $r1, $srs - nop - nop - nop - move $s0, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s1, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s2, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s3, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s4, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s5, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s6, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s7, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s8, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s9, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s10, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s11, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s12, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s13, $r0 - move.d $r0, [$acr] - addq 4, $acr - move $s14, $r0 - move.d $r0, [$acr] - addq 4, $acr -;; Nothing in S15, bank 3 - clear.d [$acr] - addq 4, $acr - -;; Check what got us here: get IDX field of EXS. - move $exs, $r10 - and.d 0xff00, $r10 - lsrq 8, $r10 -#if defined(CONFIG_ETRAX_KGDB_PORT0) - cmp.d SER0_INTR_VECT, $r10 ; IRQ for serial port 0 - beq sigint - nop -#elif defined(CONFIG_ETRAX_KGDB_PORT1) - cmp.d SER1_INTR_VECT, $r10 ; IRQ for serial port 1 - beq sigint - nop -#elif defined(CONFIG_ETRAX_KGDB_PORT2) - cmp.d SER2_INTR_VECT, $r10 ; IRQ for serial port 2 - beq sigint - nop -#elif defined(CONFIG_ETRAX_KGDB_PORT3) - cmp.d SER3_INTR_VECT, $r10 ; IRQ for serial port 3 - beq sigint - nop -#endif -;; Multiple interrupt must be due to serial break. - cmp.d 0x30, $r10 ; Multiple interrupt - beq sigint - nop -;; Neither of those? Then it's a sigtrap. - ba handle_comm - moveq 5, $r10 ; Set SIGTRAP (delay slot) - -sigint: - ;; Serial interrupt; get character - jsr getDebugChar - nop ; Delay slot - cmp.b 3, $r10 ; \003 (Ctrl-C)? - bne return ; No, get out of here - nop - moveq 2, $r10 ; Set SIGINT - -;; -;; Handle the communication -;; -handle_comm: - move.d internal_stack+1020, $sp ; Use the internal stack which grows upwards - jsr handle_exception ; Interactive routine - nop - -;; -;; Return to the caller -;; -return: - -;; First of all, write the support registers. - clear.d $r1 ; Bank counter - move.d sreg, $acr - -;; Bank 0 - move $r1, $srs - nop - nop - nop - move.d [$acr], $r0 - move $r0, $s0 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s1 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s2 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s3 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s4 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s5 - addq 4, $acr - -;; Nothing in S6 - S7, bank 0. - addq 4, $acr - addq 4, $acr - - move.d [$acr], $r0 - move $r0, $s8 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s9 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s10 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s11 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s12 - addq 4, $acr - -;; Nothing in S13 - S15, bank 0 - addq 4, $acr - addq 4, $acr - addq 4, $acr - -;; Bank 1 and bank 2 have the same layout, hence the loop. - addq 1, $r1 -2: - move $r1, $srs - nop - nop - nop - move.d [$acr], $r0 - move $r0, $s0 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s1 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s2 - addq 4, $acr - -;; S3 (MM_CAUSE) is read-only. - addq 4, $acr - - move.d [$acr], $r0 - move $r0, $s4 - addq 4, $acr - -;; FIXME: Actually write S5/S6? (Affects MM_CAUSE.) - addq 4, $acr - addq 4, $acr - -;; Nothing in S7 - S15, bank 1 and 2 - addq 4, $acr - addq 4, $acr - addq 4, $acr - addq 4, $acr - addq 4, $acr - addq 4, $acr - addq 4, $acr - addq 4, $acr - addq 4, $acr - - addq 1, $r1 - cmpq 3, $r1 - bne 2b - nop - -;; Bank 3 - move $r1, $srs - nop - nop - nop - move.d [$acr], $r0 - move $r0, $s0 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s1 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s2 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s3 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s4 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s5 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s6 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s7 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s8 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s9 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s10 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s11 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s12 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s13 - addq 4, $acr - move.d [$acr], $r0 - move $r0, $s14 - addq 4, $acr - -;; Nothing in S15, bank 3 - addq 4, $acr - -;; Now, move on to the regular register restoration process. - - move.d reg, $acr ; Reset ACR to point at the beginning of the register image - move.d [$acr], $r0 ; Restore R0 - addq 4, $acr - move.d [$acr], $r1 ; Restore R1 - addq 4, $acr - move.d [$acr], $r2 ; Restore R2 - addq 4, $acr - move.d [$acr], $r3 ; Restore R3 - addq 4, $acr - move.d [$acr], $r4 ; Restore R4 - addq 4, $acr - move.d [$acr], $r5 ; Restore R5 - addq 4, $acr - move.d [$acr], $r6 ; Restore R6 - addq 4, $acr - move.d [$acr], $r7 ; Restore R7 - addq 4, $acr - move.d [$acr], $r8 ; Restore R8 - addq 4, $acr - move.d [$acr], $r9 ; Restore R9 - addq 4, $acr - move.d [$acr], $r10 ; Restore R10 - addq 4, $acr - move.d [$acr], $r11 ; Restore R11 - addq 4, $acr - move.d [$acr], $r12 ; Restore R12 - addq 4, $acr - move.d [$acr], $r13 ; Restore R13 - -;; -;; We restore all registers, even though some of them probably haven't changed. -;; - - addq 4, $acr - move.d [$acr], $sp ; Restore SP (R14) - - ;; ACR cannot be restored just yet. - addq 8, $acr - - ;; Skip BZ, VR. - addq 2, $acr - - move [$acr], $pid ; Restore PID - addq 4, $acr - move [$acr], $srs ; Restore SRS - nop - nop - nop - addq 1, $acr - - ;; Skip WZ. - addq 2, $acr - - move [$acr], $exs ; Restore EXS. - addq 4, $acr - move [$acr], $eda ; Restore EDA. - addq 4, $acr - move [$acr], $mof ; Restore MOF. - - ;; Skip DZ. - addq 8, $acr - - move [$acr], $ebp ; Restore EBP. - addq 4, $acr - move [$acr], $erp ; Restore ERP. - addq 4, $acr - move [$acr], $srp ; Restore SRP. - addq 4, $acr - move [$acr], $nrp ; Restore NRP. - addq 4, $acr - move [$acr], $ccs ; Restore CCS like an ordinary register. - addq 4, $acr - move [$acr], $usp ; Restore USP - addq 4, $acr - move [$acr], $spc ; Restore SPC - ; No restoration of pseudo-PC of course. - - move.d reg, $acr ; Reset ACR to point at the beginning of the register image - add.d 15*4, $acr - move.d [$acr], $acr ; Finally, restore ACR. - rete ; Same as jump ERP - rfe ; Shifts CCS diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c deleted file mode 100644 index a02f276d0ed4..000000000000 --- a/arch/cris/arch-v32/kernel/process.c +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2000-2003 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * Mikael Starvik (starvik@axis.com) - * Tobias Anderberg (tobiasa@axis.com), CRISv32 port. - * - * This file handles the architecture-dependent parts of process handling.. - */ - -#include <linux/sched.h> -#include <linux/sched/debug.h> -#include <linux/sched/task.h> -#include <linux/sched/task_stack.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/fs.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/reg_map.h> -#include <hwregs/timer_defs.h> -#include <hwregs/intr_vect_defs.h> -#include <linux/ptrace.h> - -extern void stop_watchdog(void); - -/* We use this if we don't have any better idle routine. */ -void default_idle(void) -{ - local_irq_enable(); - /* Halt until exception. */ - __asm__ volatile("halt"); -} - -/* - * Free current thread data structures etc.. - */ - -extern void deconfigure_bp(long pid); -void exit_thread(struct task_struct *tsk) -{ - deconfigure_bp(tsk->pid); -} - -/* - * If the watchdog is enabled, disable interrupts and enter an infinite loop. - * The watchdog will reset the CPU after 0.1s. If the watchdog isn't enabled - * then enable it and wait. - */ -extern void arch_enable_nmi(void); - -void -hard_reset_now(void) -{ - /* - * Don't declare this variable elsewhere. We don't want any other - * code to know about it than the watchdog handler in entry.S and - * this code, implementing hard reset through the watchdog. - */ -#if defined(CONFIG_ETRAX_WATCHDOG) - extern int cause_of_death; -#endif - - printk("*** HARD RESET ***\n"); - local_irq_disable(); - -#if defined(CONFIG_ETRAX_WATCHDOG) - cause_of_death = 0xbedead; -#else -{ - reg_timer_rw_wd_ctrl wd_ctrl = {0}; - - stop_watchdog(); - - wd_ctrl.key = 16; /* Arbitrary key. */ - wd_ctrl.cnt = 1; /* Minimum time. */ - wd_ctrl.cmd = regk_timer_start; - - arch_enable_nmi(); - REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl); -} -#endif - - while (1) - ; /* Wait for reset. */ -} - -/* - * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. - * It will be unnested during _resume and _ret_from_sys_call when the new thread - * is scheduled. - * - * Also setup the thread switching structure which is used to keep - * thread-specific data during _resumes. - */ - -extern asmlinkage void ret_from_fork(void); -extern asmlinkage void ret_from_kernel_thread(void); - -int -copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p) -{ - struct pt_regs *childregs = task_pt_regs(p); - struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; - - /* - * Put the pt_regs structure at the end of the new kernel stack page and - * fix it up. Note: the task_struct doubles as the kernel stack for the - * task. - */ - if (unlikely(p->flags & PF_KTHREAD)) { - memset(swstack, 0, - sizeof(struct switch_stack) + sizeof(struct pt_regs)); - swstack->r1 = usp; - swstack->r2 = arg; - childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); - swstack->return_ip = (unsigned long) ret_from_kernel_thread; - p->thread.ksp = (unsigned long) swstack; - p->thread.usp = 0; - return 0; - } - *childregs = *current_pt_regs(); /* Struct copy of pt_regs. */ - childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ - - /* Set a new TLS ? - * The TLS is in $mof because it is the 5th argument to sys_clone. - */ - if (p->mm && (clone_flags & CLONE_SETTLS)) { - task_thread_info(p)->tls = childregs->mof; - } - - /* Put the switch stack right below the pt_regs. */ - - /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ - swstack->r9 = 0; - - /* - * We want to return into ret_from_sys_call after the _resume. - * ret_from_fork will call ret_from_sys_call. - */ - swstack->return_ip = (unsigned long) ret_from_fork; - - /* Fix the user-mode and kernel-mode stackpointer. */ - p->thread.usp = usp ?: rdusp(); - p->thread.ksp = (unsigned long) swstack; - - return 0; -} - -unsigned long -get_wchan(struct task_struct *p) -{ - /* TODO */ - return 0; -} -#undef last_sched -#undef first_sched - -void show_regs(struct pt_regs * regs) -{ - unsigned long usp = rdusp(); - - show_regs_print_info(KERN_DEFAULT); - - printk("ERP: %08lx SRP: %08lx CCS: %08lx USP: %08lx MOF: %08lx\n", - regs->erp, regs->srp, regs->ccs, usp, regs->mof); - - printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", - regs->r0, regs->r1, regs->r2, regs->r3); - - printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", - regs->r4, regs->r5, regs->r6, regs->r7); - - printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", - regs->r8, regs->r9, regs->r10, regs->r11); - - printk("r12: %08lx r13: %08lx oR10: %08lx\n", - regs->r12, regs->r13, regs->orig_r10); -} diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c deleted file mode 100644 index ccac1aaadc8a..000000000000 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ /dev/null @@ -1,492 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2000-2007, Axis Communications AB. - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/signal.h> -#include <linux/security.h> - -#include <linux/uaccess.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <arch/hwregs/supp_reg.h> - -/* - * Determines which bits in CCS the user has access to. - * 1 = access, 0 = no access. - */ -#define CCS_MASK 0x00087c00 /* SXNZVC */ - -#define SBIT_USER (1 << (S_CCS_BITNR + CCS_SHIFT)) - -static int put_debugreg(long pid, unsigned int regno, long data); -static long get_debugreg(long pid, unsigned int regno); -static unsigned long get_pseudo_pc(struct task_struct *child); -void deconfigure_bp(long pid); - -extern unsigned long cris_signal_return_page; - -/* - * Get contents of register REGNO in task TASK. - */ -long get_reg(struct task_struct *task, unsigned int regno) -{ - /* USP is a special case, it's not in the pt_regs struct but - * in the tasks thread struct - */ - unsigned long ret; - - if (regno <= PT_EDA) - ret = ((unsigned long *)task_pt_regs(task))[regno]; - else if (regno == PT_USP) - ret = task->thread.usp; - else if (regno == PT_PPC) - ret = get_pseudo_pc(task); - else if (regno <= PT_MAX) - ret = get_debugreg(task->pid, regno); - else - ret = 0; - - return ret; -} - -/* - * Write contents of register REGNO in task TASK. - */ -int put_reg(struct task_struct *task, unsigned int regno, unsigned long data) -{ - if (regno <= PT_EDA) - ((unsigned long *)task_pt_regs(task))[regno] = data; - else if (regno == PT_USP) - task->thread.usp = data; - else if (regno == PT_PPC) { - /* Write pseudo-PC to ERP only if changed. */ - if (data != get_pseudo_pc(task)) - task_pt_regs(task)->erp = data; - } else if (regno <= PT_MAX) - return put_debugreg(task->pid, regno, data); - else - return -1; - return 0; -} - -void user_enable_single_step(struct task_struct *child) -{ - unsigned long tmp; - - /* - * Set up SPC if not set already (in which case we have no other - * choice but to trust it). - */ - if (!get_reg(child, PT_SPC)) { - /* In case we're stopped in a delay slot. */ - tmp = get_reg(child, PT_ERP) & ~1; - put_reg(child, PT_SPC, tmp); - } - tmp = get_reg(child, PT_CCS) | SBIT_USER; - put_reg(child, PT_CCS, tmp); -} - -void user_disable_single_step(struct task_struct *child) -{ - put_reg(child, PT_SPC, 0); - - if (!get_debugreg(child->pid, PT_BP_CTRL)) { - unsigned long tmp; - /* If no h/w bp configured, disable S bit. */ - tmp = get_reg(child, PT_CCS) & ~SBIT_USER; - put_reg(child, PT_CCS, tmp); - } -} - -/* - * Called by kernel/ptrace.c when detaching. - * - * Make sure the single step bit is not set. - */ -void -ptrace_disable(struct task_struct *child) -{ - /* Deconfigure SPC and S-bit. */ - user_disable_single_step(child); - put_reg(child, PT_SPC, 0); - - /* Deconfigure any watchpoints associated with the child. */ - deconfigure_bp(child->pid); -} - - -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret; - unsigned int regno = addr >> 2; - unsigned long __user *datap = (unsigned long __user *)data; - - switch (request) { - /* Read word at location address. */ - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: { - unsigned long tmp; - int copied; - - ret = -EIO; - - /* The signal trampoline page is outside the normal user-addressable - * space but still accessible. This is hack to make it possible to - * access the signal handler code in GDB. - */ - if ((addr & PAGE_MASK) == cris_signal_return_page) { - /* The trampoline page is globally mapped, no page table to traverse.*/ - tmp = *(unsigned long*)addr; - } else { - copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE); - - if (copied != sizeof(tmp)) - break; - } - - ret = put_user(tmp,datap); - break; - } - - /* Read the word at location address in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - ret = -EIO; - if ((addr & 3) || regno > PT_MAX) - break; - - tmp = get_reg(child, regno); - ret = put_user(tmp, datap); - break; - } - - /* Write the word at location address. */ - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - - /* Write the word at location address in the USER area. */ - case PTRACE_POKEUSR: - ret = -EIO; - if ((addr & 3) || regno > PT_MAX) - break; - - if (regno == PT_CCS) { - /* don't allow the tracing process to change stuff like - * interrupt enable, kernel/user bit, dma enables etc. - */ - data &= CCS_MASK; - data |= get_reg(child, PT_CCS) & ~CCS_MASK; - } - if (put_reg(child, regno, data)) - break; - ret = 0; - break; - - /* Get all GP registers from the child. */ - case PTRACE_GETREGS: { - int i; - unsigned long tmp; - - for (i = 0; i <= PT_MAX; i++) { - tmp = get_reg(child, i); - - if (put_user(tmp, datap)) { - ret = -EFAULT; - goto out_tsk; - } - - datap++; - } - - ret = 0; - break; - } - - /* Set all GP registers in the child. */ - case PTRACE_SETREGS: { - int i; - unsigned long tmp; - - for (i = 0; i <= PT_MAX; i++) { - if (get_user(tmp, datap)) { - ret = -EFAULT; - goto out_tsk; - } - - if (i == PT_CCS) { - tmp &= CCS_MASK; - tmp |= get_reg(child, PT_CCS) & ~CCS_MASK; - } - - put_reg(child, i, tmp); - datap++; - } - - ret = 0; - break; - } - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - -out_tsk: - return ret; -} - -void do_syscall_trace(void) -{ - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - - if (!(current->ptrace & PT_PTRACED)) - return; - - /* the 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - 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. - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} - -/* Returns the size of an instruction that has a delay slot. */ - -static int insn_size(struct task_struct *child, unsigned long pc) -{ - unsigned long opcode; - int copied; - int opsize = 0; - - /* Read the opcode at pc (do what PTRACE_PEEKTEXT would do). */ - copied = access_process_vm(child, pc, &opcode, sizeof(opcode), FOLL_FORCE); - if (copied != sizeof(opcode)) - return 0; - - switch ((opcode & 0x0f00) >> 8) { - case 0x0: - case 0x9: - case 0xb: - opsize = 2; - break; - case 0xe: - case 0xf: - opsize = 6; - break; - case 0xd: - /* Could be 4 or 6; check more bits. */ - if ((opcode & 0xff) == 0xff) - opsize = 4; - else - opsize = 6; - break; - default: - panic("ERROR: Couldn't find size of opcode 0x%lx at 0x%lx\n", - opcode, pc); - } - - return opsize; -} - -static unsigned long get_pseudo_pc(struct task_struct *child) -{ - /* Default value for PC is ERP. */ - unsigned long pc = get_reg(child, PT_ERP); - - if (pc & 0x1) { - unsigned long spc = get_reg(child, PT_SPC); - /* Delay slot bit set. Report as stopped on proper - instruction. */ - if (spc) { - /* Rely on SPC if set. FIXME: We might want to check - that EXS indicates we stopped due to a single-step - exception. */ - pc = spc; - } else { - /* Calculate the PC from the size of the instruction - that the delay slot we're in belongs to. */ - pc += insn_size(child, pc & ~1) - 1; - } - } - return pc; -} - -static long bp_owner = 0; - -/* Reachable from exit_thread in signal.c, so not static. */ -void deconfigure_bp(long pid) -{ - int bp; - - /* Only deconfigure if the pid is the owner. */ - if (bp_owner != pid) - return; - - for (bp = 0; bp < 6; bp++) { - unsigned long tmp; - /* Deconfigure start and end address (also gets rid of ownership). */ - put_debugreg(pid, PT_BP + 3 + (bp * 2), 0); - put_debugreg(pid, PT_BP + 4 + (bp * 2), 0); - - /* Deconfigure relevant bits in control register. */ - tmp = get_debugreg(pid, PT_BP_CTRL) & ~(3 << (2 + (bp * 4))); - put_debugreg(pid, PT_BP_CTRL, tmp); - } - /* No owner now. */ - bp_owner = 0; -} - -static int put_debugreg(long pid, unsigned int regno, long data) -{ - int ret = 0; - register int old_srs; - -#ifdef CONFIG_ETRAX_KGDB - /* Ignore write, but pretend it was ok if value is 0 - (we don't want POKEUSR/SETREGS failing unnessecarily). */ - return (data == 0) ? ret : -1; -#endif - - /* Simple owner management. */ - if (!bp_owner) - bp_owner = pid; - else if (bp_owner != pid) { - /* Ignore write, but pretend it was ok if value is 0 - (we don't want POKEUSR/SETREGS failing unnessecarily). */ - return (data == 0) ? ret : -1; - } - - /* Remember old SRS. */ - SPEC_REG_RD(SPEC_REG_SRS, old_srs); - /* Switch to BP bank. */ - SUPP_BANK_SEL(BANK_BP); - - switch (regno - PT_BP) { - case 0: - SUPP_REG_WR(0, data); break; - case 1: - case 2: - if (data) - ret = -1; - break; - case 3: - SUPP_REG_WR(3, data); break; - case 4: - SUPP_REG_WR(4, data); break; - case 5: - SUPP_REG_WR(5, data); break; - case 6: - SUPP_REG_WR(6, data); break; - case 7: - SUPP_REG_WR(7, data); break; - case 8: - SUPP_REG_WR(8, data); break; - case 9: - SUPP_REG_WR(9, data); break; - case 10: - SUPP_REG_WR(10, data); break; - case 11: - SUPP_REG_WR(11, data); break; - case 12: - SUPP_REG_WR(12, data); break; - case 13: - SUPP_REG_WR(13, data); break; - case 14: - SUPP_REG_WR(14, data); break; - default: - ret = -1; - break; - } - - /* Restore SRS. */ - SPEC_REG_WR(SPEC_REG_SRS, old_srs); - /* Just for show. */ - NOP(); - NOP(); - NOP(); - - return ret; -} - -static long get_debugreg(long pid, unsigned int regno) -{ - register int old_srs; - register long data; - - if (pid != bp_owner) { - return 0; - } - - /* Remember old SRS. */ - SPEC_REG_RD(SPEC_REG_SRS, old_srs); - /* Switch to BP bank. */ - SUPP_BANK_SEL(BANK_BP); - - switch (regno - PT_BP) { - case 0: - SUPP_REG_RD(0, data); break; - case 1: - case 2: - /* error return value? */ - data = 0; - break; - case 3: - SUPP_REG_RD(3, data); break; - case 4: - SUPP_REG_RD(4, data); break; - case 5: - SUPP_REG_RD(5, data); break; - case 6: - SUPP_REG_RD(6, data); break; - case 7: - SUPP_REG_RD(7, data); break; - case 8: - SUPP_REG_RD(8, data); break; - case 9: - SUPP_REG_RD(9, data); break; - case 10: - SUPP_REG_RD(10, data); break; - case 11: - SUPP_REG_RD(11, data); break; - case 12: - SUPP_REG_RD(12, data); break; - case 13: - SUPP_REG_RD(13, data); break; - case 14: - SUPP_REG_RD(14, data); break; - default: - /* error return value? */ - data = 0; - } - - /* Restore SRS. */ - SPEC_REG_WR(SPEC_REG_SRS, old_srs); - /* Just for show. */ - NOP(); - NOP(); - NOP(); - - return data; -} diff --git a/arch/cris/arch-v32/kernel/setup.c b/arch/cris/arch-v32/kernel/setup.c deleted file mode 100644 index a36372e35e96..000000000000 --- a/arch/cris/arch-v32/kernel/setup.c +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Display CPU info in /proc/cpuinfo. - * - * Copyright (C) 2003, Axis Communications AB. - */ - -#include <linux/seq_file.h> -#include <linux/proc_fs.h> -#include <linux/delay.h> -#include <linux/param.h> - -#include <linux/i2c.h> -#include <linux/platform_device.h> - -#ifdef CONFIG_PROC_FS - -#define HAS_FPU 0x0001 -#define HAS_MMU 0x0002 -#define HAS_ETHERNET100 0x0004 -#define HAS_TOKENRING 0x0008 -#define HAS_SCSI 0x0010 -#define HAS_ATA 0x0020 -#define HAS_USB 0x0040 -#define HAS_IRQ_BUG 0x0080 -#define HAS_MMU_BUG 0x0100 - -struct cpu_info { - char *cpu_model; - unsigned short rev; - unsigned short cache_size; - unsigned short flags; -}; - -/* Some of these model are here for historical reasons only. */ -static struct cpu_info cpinfo[] = { - {"ETRAX 1", 0, 0, 0}, - {"ETRAX 2", 1, 0, 0}, - {"ETRAX 3", 2, 0, 0}, - {"ETRAX 4", 3, 0, 0}, - {"Simulator", 7, 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA}, - {"ETRAX 100", 8, 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG}, - {"ETRAX 100", 9, 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA}, - - {"ETRAX 100LX", 10, 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB - | HAS_MMU | HAS_MMU_BUG}, - - {"ETRAX 100LX v2", 11, 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB - | HAS_MMU}, -#ifdef CONFIG_ETRAXFS - {"ETRAX FS", 32, 32, HAS_ETHERNET100 | HAS_ATA | HAS_MMU}, -#else - {"ARTPEC-3", 32, 32, HAS_ETHERNET100 | HAS_MMU}, -#endif - {"Unknown", 0, 0, 0} -}; - -int show_cpuinfo(struct seq_file *m, void *v) -{ - int i; - int cpu = (int)v - 1; - unsigned long revision; - struct cpu_info *info; - - info = &cpinfo[ARRAY_SIZE(cpinfo) - 1]; - - revision = rdvr(); - - for (i = 0; i < ARRAY_SIZE(cpinfo); i++) { - if (cpinfo[i].rev == revision) { - info = &cpinfo[i]; - break; - } - } - - seq_printf(m, - "processor\t: %d\n" - "cpu\t\t: CRIS\n" - "cpu revision\t: %lu\n" - "cpu model\t: %s\n" - "cache size\t: %d KB\n" - "fpu\t\t: %s\n" - "mmu\t\t: %s\n" - "mmu DMA bug\t: %s\n" - "ethernet\t: %s Mbps\n" - "token ring\t: %s\n" - "scsi\t\t: %s\n" - "ata\t\t: %s\n" - "usb\t\t: %s\n" - "bogomips\t: %lu.%02lu\n\n", - - cpu, - revision, - info->cpu_model, - info->cache_size, - info->flags & HAS_FPU ? "yes" : "no", - info->flags & HAS_MMU ? "yes" : "no", - info->flags & HAS_MMU_BUG ? "yes" : "no", - info->flags & HAS_ETHERNET100 ? "10/100" : "10", - info->flags & HAS_TOKENRING ? "4/16 Mbps" : "no", - info->flags & HAS_SCSI ? "yes" : "no", - info->flags & HAS_ATA ? "yes" : "no", - info->flags & HAS_USB ? "yes" : "no", - (loops_per_jiffy * HZ + 500) / 500000, - ((loops_per_jiffy * HZ + 500) / 5000) % 100); - - return 0; -} - -#endif /* CONFIG_PROC_FS */ - -void show_etrax_copyright(void) -{ -#ifdef CONFIG_ETRAXFS - printk(KERN_INFO "Linux/CRISv32 port on ETRAX FS " - "(C) 2003, 2004 Axis Communications AB\n"); -#else - printk(KERN_INFO "Linux/CRISv32 port on ARTPEC-3 " - "(C) 2003-2009 Axis Communications AB\n"); -#endif -} - -static struct i2c_board_info __initdata i2c_info[] = { - {I2C_BOARD_INFO("camblock", 0x43)}, - {I2C_BOARD_INFO("tmp100", 0x48)}, - {I2C_BOARD_INFO("tmp100", 0x4A)}, - {I2C_BOARD_INFO("tmp100", 0x4C)}, - {I2C_BOARD_INFO("tmp100", 0x4D)}, - {I2C_BOARD_INFO("tmp100", 0x4E)}, -#ifdef CONFIG_RTC_DRV_PCF8563 - {I2C_BOARD_INFO("pcf8563", 0x51)}, -#endif - {I2C_BOARD_INFO("pca9536", 0x41)}, - {I2C_BOARD_INFO("fnp300", 0x40)}, - {I2C_BOARD_INFO("fnp300", 0x42)}, - {I2C_BOARD_INFO("adc101", 0x54)}, -}; - -static struct i2c_board_info __initdata i2c_info2[] = { - {I2C_BOARD_INFO("camblock", 0x43)}, - {I2C_BOARD_INFO("tmp100", 0x48)}, - {I2C_BOARD_INFO("tmp100", 0x4A)}, - {I2C_BOARD_INFO("tmp100", 0x4C)}, - {I2C_BOARD_INFO("tmp100", 0x4D)}, - {I2C_BOARD_INFO("tmp100", 0x4E)}, - {I2C_BOARD_INFO("pca9536", 0x41)}, - {I2C_BOARD_INFO("fnp300", 0x40)}, - {I2C_BOARD_INFO("fnp300", 0x42)}, - {I2C_BOARD_INFO("adc101", 0x54)}, -}; - -static struct i2c_board_info __initdata i2c_info3[] = { - {I2C_BOARD_INFO("adc101", 0x54)}, -}; - -static int __init etrax_init(void) -{ - i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); - i2c_register_board_info(1, i2c_info2, ARRAY_SIZE(i2c_info2)); - i2c_register_board_info(2, i2c_info3, ARRAY_SIZE(i2c_info3)); - return 0; -} -arch_initcall(etrax_init); diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c deleted file mode 100644 index 4f2e3ba3bf40..000000000000 --- a/arch/cris/arch-v32/kernel/signal.c +++ /dev/null @@ -1,541 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2003, Axis Communications AB. - */ - -#include <linux/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/errno.h> -#include <linux/wait.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/stddef.h> -#include <linux/syscalls.h> -#include <linux/vmalloc.h> - -#include <asm/io.h> -#include <asm/processor.h> -#include <asm/ucontext.h> -#include <linux/uaccess.h> -#include <arch/hwregs/cpu_vect.h> - -extern unsigned long cris_signal_return_page; - -/* - * A syscall in CRIS is really a "break 13" instruction, which is 2 - * bytes. The registers is manipulated so upon return the instruction - * will be executed again. - * - * This relies on that PC points to the instruction after the break call. - */ -#define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->erp -= 2; - -/* Signal frames. */ -struct signal_frame { - struct sigcontext sc; - unsigned long extramask[_NSIG_WORDS - 1]; - unsigned char retcode[8]; /* Trampoline code. */ -}; - -struct rt_signal_frame { - struct siginfo *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; - unsigned char retcode[8]; /* Trampoline code. */ -}; - -void do_signal(int restart, struct pt_regs *regs); -void keep_debug_flags(unsigned long oldccs, unsigned long oldspc, - struct pt_regs *regs); - -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) -{ - unsigned int err = 0; - unsigned long old_usp; - - /* Always make any pending restarted system calls return -EINTR */ - current->restart_block.fn = do_no_restart_syscall; - - /* - * Restore the registers from &sc->regs. sc is already checked - * for VERIFY_READ since the signal_frame was previously - * checked in sys_sigreturn(). - */ - if (__copy_from_user(regs, sc, sizeof(struct pt_regs))) - goto badframe; - - /* Make that the user-mode flag is set. */ - regs->ccs |= (1 << (U_CCS_BITNR + CCS_SHIFT)); - - /* Don't perform syscall restarting */ - regs->exs = -1; - - /* Restore the old USP. */ - err |= __get_user(old_usp, &sc->usp); - wrusp(old_usp); - - return err; - -badframe: - return 1; -} - -asmlinkage int sys_sigreturn(void) -{ - struct pt_regs *regs = current_pt_regs(); - sigset_t set; - struct signal_frame __user *frame; - unsigned long oldspc = regs->spc; - unsigned long oldccs = regs->ccs; - - frame = (struct signal_frame *) rdusp(); - - /* - * Since the signal is stacked on a dword boundary, the frame - * should be dword aligned here as well. It it's not, then the - * user is trying some funny business. - */ - if (((long)frame) & 3) - goto badframe; - - 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; - - set_current_blocked(&set); - - if (restore_sigcontext(regs, &frame->sc)) - goto badframe; - - keep_debug_flags(oldccs, oldspc, regs); - - return regs->r10; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(void) -{ - struct pt_regs *regs = current_pt_regs(); - sigset_t set; - struct rt_signal_frame __user *frame; - unsigned long oldspc = regs->spc; - unsigned long oldccs = regs->ccs; - - frame = (struct rt_signal_frame *) rdusp(); - - /* - * Since the signal is stacked on a dword boundary, the frame - * should be dword aligned here as well. It it's not, then the - * user is trying some funny business. - */ - if (((long)frame) & 3) - goto badframe; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) - goto badframe; - - if (restore_altstack(&frame->uc.uc_stack)) - goto badframe; - - keep_debug_flags(oldccs, oldspc, regs); - - return regs->r10; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -/* Setup a signal frame. */ -static int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - unsigned long mask) -{ - int err; - unsigned long usp; - - err = 0; - usp = rdusp(); - - /* - * Copy the registers. They are located first in sc, so it's - * possible to use sc directly. - */ - err |= __copy_to_user(sc, regs, sizeof(struct pt_regs)); - - err |= __put_user(mask, &sc->oldmask); - err |= __put_user(usp, &sc->usp); - - return err; -} - -/* Figure out where to put the new signal frame - usually on the stack. */ -static inline void __user * -get_sigframe(struct ksignal *ksig, size_t frame_size) -{ - unsigned long sp = sigsp(rdusp(), ksig); - - /* Make sure the frame is dword-aligned. */ - sp &= ~3; - - return (void __user *)(sp - frame_size); -} - -/* Grab and setup a signal frame. - * - * Basically a lot of state-info is stacked, and arranged for the - * user-mode program to return to the kernel using either a trampiline - * which performs the syscall sigreturn(), or a provided user-mode - * trampoline. - */ -static int -setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) -{ - int err; - unsigned long return_ip; - struct signal_frame __user *frame; - - err = 0; - frame = get_sigframe(ksig, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - - if (err) - return -EFAULT; - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - } - - if (err) - return -EFAULT; - - /* - * Set up to return from user-space. If provided, use a stub - * already located in user-space. - */ - if (ksig->ka.sa.sa_flags & SA_RESTORER) { - return_ip = (unsigned long)ksig->ka.sa.sa_restorer; - } else { - /* Trampoline - the desired return ip is in the signal return page. */ - return_ip = cris_signal_return_page; - - /* - * This is movu.w __NR_sigreturn, r9; break 13; - * - * WE DO NOT USE IT ANY MORE! It's only left here for historical - * reasons and because gdb uses it as a signature to notice - * signal handler stack frames. - */ - err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0)); - err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2)); - err |= __put_user(0xe93d, (short __user*)(frame->retcode+4)); - } - - if (err) - return -EFAULT; - - /* - * Set up registers for signal handler. - * - * Where the code enters now. - * Where the code enter later. - * First argument, signo. - */ - regs->erp = (unsigned long) ksig->ka.sa.sa_handler; - regs->srp = return_ip; - regs->r10 = ksig->sig; - - /* Actually move the USP to reflect the stacked frame. */ - wrusp((unsigned long)frame); - - return 0; -} - -static int -setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) -{ - int err; - unsigned long return_ip; - struct rt_signal_frame __user *frame; - - err = 0; - frame = get_sigframe(ksig, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, &ksig->info); - - if (err) - return -EFAULT; - - /* Clear all the bits of the ucontext we don't use. */ - err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); - err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - err |= __save_altstack(&frame->uc.uc_stack, rdusp()); - - if (err) - return -EFAULT; - - /* - * Set up to return from user-space. If provided, use a stub - * already located in user-space. - */ - if (ksig->ka.sa.sa_flags & SA_RESTORER) { - return_ip = (unsigned long) ksig->ka.sa.sa_restorer; - } else { - /* Trampoline - the desired return ip is in the signal return page. */ - return_ip = cris_signal_return_page + 6; - - /* - * This is movu.w __NR_rt_sigreturn, r9; break 13; - * - * WE DO NOT USE IT ANY MORE! It's only left here for historical - * reasons and because gdb uses it as a signature to notice - * signal handler stack frames. - */ - err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0)); - - err |= __put_user(__NR_rt_sigreturn, - (short __user*)(frame->retcode+2)); - - err |= __put_user(0xe93d, (short __user*)(frame->retcode+4)); - } - - if (err) - return -EFAULT; - - /* - * Set up registers for signal handler. - * - * Where the code enters now. - * Where the code enters later. - * First argument is signo. - * Second argument is (siginfo_t *). - * Third argument is unused. - */ - regs->erp = (unsigned long) ksig->ka.sa.sa_handler; - regs->srp = return_ip; - regs->r10 = ksig->sig; - regs->r11 = (unsigned long) &frame->info; - regs->r12 = 0; - - /* Actually move the usp to reflect the stacked frame. */ - wrusp((unsigned long)frame); - - return 0; -} - -/* Invoke a signal handler to, well, handle the signal. */ -static inline void -handle_signal(int canrestart, struct ksignal *ksig, struct pt_regs *regs) -{ - sigset_t *oldset = sigmask_to_save(); - int ret; - - /* Check if this got called from a system call. */ - if (canrestart) { - /* If so, check system call restarting. */ - switch (regs->r10) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - /* - * This means that the syscall should - * only be restarted if there was no - * handler for the signal, and since - * this point isn't reached unless - * there is a handler, there's no need - * to restart. - */ - regs->r10 = -EINTR; - break; - - case -ERESTARTSYS: - /* - * This means restart the syscall if - * there is no handler, or the handler - * was registered with SA_RESTART. - */ - if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { - regs->r10 = -EINTR; - break; - } - - /* Fall through. */ - - case -ERESTARTNOINTR: - /* - * This means that the syscall should - * be called again after the signal - * handler returns. - */ - RESTART_CRIS_SYS(regs); - break; - } - } - - /* Set up the stack frame. */ - if (ksig->ka.sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(ksig, oldset, regs); - else - ret = setup_frame(ksig, oldset, regs); - - signal_setup_done(ret, ksig, 0); -} - -/* - * 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. - * - * Also note that the regs structure given here as an argument, is the latest - * pushed pt_regs. It may or may not be the same as the first pushed registers - * when the initial usermode->kernelmode transition took place. Therefore - * we can use user_mode(regs) to see if we came directly from kernel or user - * mode below. - */ -void -do_signal(int canrestart, struct pt_regs *regs) -{ - struct ksignal ksig; - - canrestart = canrestart && ((int)regs->exs >= 0); - - /* - * The common case should go fast, which is why this point is - * reached from kernel-mode. If that's the case, just return - * without doing anything. - */ - if (!user_mode(regs)) - return; - - if (get_signal(&ksig)) { - /* Whee! Actually deliver the signal. */ - handle_signal(canrestart, &ksig, regs); - return; - } - - /* Got here from a system call? */ - if (canrestart) { - /* Restart the system call - no handlers present. */ - if (regs->r10 == -ERESTARTNOHAND || - regs->r10 == -ERESTARTSYS || - regs->r10 == -ERESTARTNOINTR) { - RESTART_CRIS_SYS(regs); - } - - if (regs->r10 == -ERESTART_RESTARTBLOCK){ - regs->r9 = __NR_restart_syscall; - regs->erp -= 2; - } - } - - /* if there's no signal to deliver, we just put the saved sigmask - * back */ - restore_saved_sigmask(); -} - -asmlinkage void -ugdb_trap_user(struct thread_info *ti, int sig) -{ - if (((user_regs(ti)->exs & 0xff00) >> 8) != SINGLE_STEP_INTR_VECT) { - /* Zero single-step PC if the reason we stopped wasn't a single - step exception. This is to avoid relying on it when it isn't - reliable. */ - user_regs(ti)->spc = 0; - } - /* FIXME: Filter out false h/w breakpoint hits (i.e. EDA - not within any configured h/w breakpoint range). Synchronize with - what already exists for kernel debugging. */ - if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) { - /* Break 8: subtract 2 from ERP unless in a delay slot. */ - if (!(user_regs(ti)->erp & 0x1)) - user_regs(ti)->erp -= 2; - } - sys_kill(ti->task->pid, sig); -} - -void -keep_debug_flags(unsigned long oldccs, unsigned long oldspc, - struct pt_regs *regs) -{ - if (oldccs & (1 << Q_CCS_BITNR)) { - /* Pending single step due to single-stepping the break 13 - in the signal trampoline: keep the Q flag. */ - regs->ccs |= (1 << Q_CCS_BITNR); - /* S flag should be set - complain if it's not. */ - if (!(oldccs & (1 << (S_CCS_BITNR + CCS_SHIFT)))) { - printk("Q flag but no S flag?"); - } - regs->ccs |= (1 << (S_CCS_BITNR + CCS_SHIFT)); - /* Assume the SPC is valid and interesting. */ - regs->spc = oldspc; - - } else if (oldccs & (1 << (S_CCS_BITNR + CCS_SHIFT))) { - /* If a h/w bp was set in the signal handler we need - to keep the S flag. */ - regs->ccs |= (1 << (S_CCS_BITNR + CCS_SHIFT)); - /* Don't keep the old SPC though; if we got here due to - a single-step, the Q flag should have been set. */ - } else if (regs->spc) { - /* If we were single-stepping *before* the signal was taken, - we don't want to restore that state now, because GDB will - have forgotten all about it. */ - regs->spc = 0; - regs->ccs &= ~(1 << (S_CCS_BITNR + CCS_SHIFT)); - } -} - -/* Set up the trampolines on the signal return page. */ -int __init -cris_init_signal(void) -{ - u16* data = kmalloc(PAGE_SIZE, GFP_KERNEL); - - /* This is movu.w __NR_sigreturn, r9; break 13; */ - data[0] = 0x9c5f; - data[1] = __NR_sigreturn; - data[2] = 0xe93d; - /* This is movu.w __NR_rt_sigreturn, r9; break 13; */ - data[3] = 0x9c5f; - data[4] = __NR_rt_sigreturn; - data[5] = 0xe93d; - - /* Map to userspace with appropriate permissions (no write access...) */ - cris_signal_return_page = (unsigned long) - __ioremap_prot(virt_to_phys(data), PAGE_SIZE, PAGE_SIGNAL_TRAMPOLINE); - - return 0; -} - -__initcall(cris_init_signal); diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c deleted file mode 100644 index d07a3912687e..000000000000 --- a/arch/cris/arch-v32/kernel/time.c +++ /dev/null @@ -1,345 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/arch-v32/kernel/time.c - * - * Copyright (C) 2003-2010 Axis Communications AB - * - */ - -#include <linux/timex.h> -#include <linux/time.h> -#include <linux/clocksource.h> -#include <linux/clockchips.h> -#include <linux/interrupt.h> -#include <linux/swap.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/threads.h> -#include <linux/cpufreq.h> -#include <linux/sched_clock.h> -#include <linux/mm.h> -#include <asm/types.h> -#include <asm/signal.h> -#include <asm/io.h> -#include <asm/delay.h> -#include <asm/irq.h> -#include <asm/irq_regs.h> - -#include <hwregs/reg_map.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/timer_defs.h> -#include <hwregs/intr_vect_defs.h> -#ifdef CONFIG_CRIS_MACH_ARTPEC3 -#include <hwregs/clkgen_defs.h> -#endif - -/* Watchdog defines */ -#define ETRAX_WD_KEY_MASK 0x7F /* key is 7 bit */ -#define ETRAX_WD_HZ 763 /* watchdog counts at 763 Hz */ -/* Number of 763 counts before watchdog bites */ -#define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) - -#define CRISV32_TIMER_FREQ (100000000lu) - -unsigned long timer_regs[NR_CPUS] = -{ - regi_timer0, -}; - -extern int set_rtc_mmss(unsigned long nowtime); - -#ifdef CONFIG_CPU_FREQ -static int cris_time_freq_notifier(struct notifier_block *nb, - unsigned long val, void *data); - -static struct notifier_block cris_time_freq_notifier_block = { - .notifier_call = cris_time_freq_notifier, -}; -#endif - -unsigned long get_ns_in_jiffie(void) -{ - reg_timer_r_tmr0_data data; - unsigned long ns; - - data = REG_RD(timer, regi_timer0, r_tmr0_data); - ns = (TIMER0_DIV - data) * 10; - return ns; -} - -/* From timer MDS describing the hardware watchdog: - * 4.3.1 Watchdog Operation - * The watchdog timer is an 8-bit timer with a configurable start value. - * Once started the watchdog counts downwards with a frequency of 763 Hz - * (100/131072 MHz). When the watchdog counts down to 1, it generates an - * NMI (Non Maskable Interrupt), and when it counts down to 0, it resets the - * chip. - */ -/* This gives us 1.3 ms to do something useful when the NMI comes */ - -/* Right now, starting the watchdog is the same as resetting it */ -#define start_watchdog reset_watchdog - -#if defined(CONFIG_ETRAX_WATCHDOG) -static short int watchdog_key = 42; /* arbitrary 7 bit number */ -#endif - -/* Number of pages to consider "out of memory". It is normal that the memory - * is used though, so set this really low. */ -#define WATCHDOG_MIN_FREE_PAGES 8 - -#if defined(CONFIG_ETRAX_WATCHDOG_NICE_DOGGY) -/* for reliable NICE_DOGGY behaviour */ -static int bite_in_progress; -#endif - -void reset_watchdog(void) -{ -#if defined(CONFIG_ETRAX_WATCHDOG) - reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; - -#if defined(CONFIG_ETRAX_WATCHDOG_NICE_DOGGY) - if (unlikely(bite_in_progress)) - return; -#endif - /* Only keep watchdog happy as long as we have memory left! */ - if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) { - /* Reset the watchdog with the inverse of the old key */ - /* Invert key, which is 7 bits */ - watchdog_key ^= ETRAX_WD_KEY_MASK; - wd_ctrl.cnt = ETRAX_WD_CNT; - wd_ctrl.cmd = regk_timer_start; - wd_ctrl.key = watchdog_key; - REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl); - } -#endif -} - -/* stop the watchdog - we still need the correct key */ - -void stop_watchdog(void) -{ -#if defined(CONFIG_ETRAX_WATCHDOG) - reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; - watchdog_key ^= ETRAX_WD_KEY_MASK; /* invert key, which is 7 bits */ - wd_ctrl.cnt = ETRAX_WD_CNT; - wd_ctrl.cmd = regk_timer_stop; - wd_ctrl.key = watchdog_key; - REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl); -#endif -} - -extern void show_registers(struct pt_regs *regs); - -void handle_watchdog_bite(struct pt_regs *regs) -{ -#if defined(CONFIG_ETRAX_WATCHDOG) - extern int cause_of_death; - - nmi_enter(); - oops_in_progress = 1; -#if defined(CONFIG_ETRAX_WATCHDOG_NICE_DOGGY) - bite_in_progress = 1; -#endif - printk(KERN_WARNING "Watchdog bite\n"); - - /* Check if forced restart or unexpected watchdog */ - if (cause_of_death == 0xbedead) { -#ifdef CONFIG_CRIS_MACH_ARTPEC3 - /* There is a bug in Artpec-3 (voodoo TR 78) that requires - * us to go to lower frequency for the reset to be reliable - */ - reg_clkgen_rw_clk_ctrl ctrl = - REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); - ctrl.pll = 0; - REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, ctrl); -#endif - while(1); - } - - /* Unexpected watchdog, stop the watchdog and dump registers. */ - stop_watchdog(); - printk(KERN_WARNING "Oops: bitten by watchdog\n"); - show_registers(regs); - oops_in_progress = 0; - printk("\n"); /* Flush mtdoops. */ -#ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY - reset_watchdog(); -#endif - while(1) /* nothing */; -#endif -} - -extern void cris_profile_sample(struct pt_regs *regs); -static void __iomem *timer_base; - -static int crisv32_clkevt_switch_state(struct clock_event_device *dev) -{ - reg_timer_rw_tmr0_ctrl ctrl = { - .op = regk_timer_hold, - .freq = regk_timer_f100, - }; - - REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); - return 0; -} - -static int crisv32_clkevt_next_event(unsigned long evt, - struct clock_event_device *dev) -{ - reg_timer_rw_tmr0_ctrl ctrl = { - .op = regk_timer_ld, - .freq = regk_timer_f100, - }; - - REG_WR(timer, timer_base, rw_tmr0_div, evt); - REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); - - ctrl.op = regk_timer_run; - REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); - - return 0; -} - -static irqreturn_t crisv32_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - reg_timer_rw_tmr0_ctrl ctrl = { - .op = regk_timer_hold, - .freq = regk_timer_f100, - }; - reg_timer_rw_ack_intr ack = { .tmr0 = 1 }; - reg_timer_r_masked_intr intr; - - intr = REG_RD(timer, timer_base, r_masked_intr); - if (!intr.tmr0) - return IRQ_NONE; - - REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); - REG_WR(timer, timer_base, rw_ack_intr, ack); - - reset_watchdog(); -#ifdef CONFIG_SYSTEM_PROFILER - cris_profile_sample(get_irq_regs()); -#endif - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct clock_event_device crisv32_clockevent = { - .name = "crisv32-timer", - .rating = 300, - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_state_oneshot = crisv32_clkevt_switch_state, - .set_state_shutdown = crisv32_clkevt_switch_state, - .tick_resume = crisv32_clkevt_switch_state, - .set_next_event = crisv32_clkevt_next_event, -}; - -/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */ -static struct irqaction irq_timer = { - .handler = crisv32_timer_interrupt, - .flags = IRQF_TIMER | IRQF_SHARED, - .name = "crisv32-timer", - .dev_id = &crisv32_clockevent, -}; - -static u64 notrace crisv32_timer_sched_clock(void) -{ - return REG_RD(timer, timer_base, r_time); -} - -static void __init crisv32_timer_init(void) -{ - reg_timer_rw_intr_mask timer_intr_mask; - reg_timer_rw_tmr0_ctrl ctrl = { - .op = regk_timer_hold, - .freq = regk_timer_f100, - }; - - REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); - - timer_intr_mask = REG_RD(timer, timer_base, rw_intr_mask); - timer_intr_mask.tmr0 = 1; - REG_WR(timer, timer_base, rw_intr_mask, timer_intr_mask); -} - -void __init time_init(void) -{ - int irq; - int ret; - - /* Probe for the RTC and read it if it exists. - * Before the RTC can be probed the loops_per_usec variable needs - * to be initialized to make usleep work. A better value for - * loops_per_usec is calculated by the kernel later once the - * clock has started. - */ - loops_per_usec = 50; - - irq = TIMER0_INTR_VECT; - timer_base = (void __iomem *) regi_timer0; - - crisv32_timer_init(); - - sched_clock_register(crisv32_timer_sched_clock, 32, - CRISV32_TIMER_FREQ); - - clocksource_mmio_init(timer_base + REG_RD_ADDR_timer_r_time, - "crisv32-timer", CRISV32_TIMER_FREQ, - 300, 32, clocksource_mmio_readl_up); - - crisv32_clockevent.cpumask = cpu_possible_mask; - crisv32_clockevent.irq = irq; - - ret = setup_irq(irq, &irq_timer); - if (ret) - pr_warn("failed to setup irq %d\n", irq); - - clockevents_config_and_register(&crisv32_clockevent, - CRISV32_TIMER_FREQ, - 2, 0xffffffff); - - /* Enable watchdog if we should use one. */ - -#if defined(CONFIG_ETRAX_WATCHDOG) - printk(KERN_INFO "Enabling watchdog...\n"); - start_watchdog(); - - /* If we use the hardware watchdog, we want to trap it as an NMI - * and dump registers before it resets us. For this to happen, we - * must set the "m" NMI enable flag (which once set, is unset only - * when an NMI is taken). */ - { - unsigned long flags; - local_save_flags(flags); - flags |= (1<<30); /* NMI M flag is at bit 30 */ - local_irq_restore(flags); - } -#endif - -#ifdef CONFIG_CPU_FREQ - cpufreq_register_notifier(&cris_time_freq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); -#endif -} - -#ifdef CONFIG_CPU_FREQ -static int cris_time_freq_notifier(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct cpufreq_freqs *freqs = data; - if (val == CPUFREQ_POSTCHANGE) { - reg_timer_r_tmr0_data data; - reg_timer_rw_tmr0_div div = (freqs->new * 500) / HZ; - do { - data = REG_RD(timer, timer_regs[freqs->cpu], - r_tmr0_data); - } while (data > 20); - REG_WR(timer, timer_regs[freqs->cpu], rw_tmr0_div, div); - } - return 0; -} -#endif diff --git a/arch/cris/arch-v32/kernel/traps.c b/arch/cris/arch-v32/kernel/traps.c deleted file mode 100644 index ba54c7eccbaa..000000000000 --- a/arch/cris/arch-v32/kernel/traps.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2003-2006, Axis Communications AB. - */ - -#include <linux/ptrace.h> -#include <linux/extable.h> -#include <linux/uaccess.h> -#include <linux/sched/debug.h> - -#include <hwregs/supp_reg.h> -#include <hwregs/intr_vect_defs.h> -#include <asm/irq.h> - -void show_registers(struct pt_regs *regs) -{ - /* - * It's possible to use either the USP register or current->thread.usp. - * USP might not correspond to the current process for all cases this - * function is called, and current->thread.usp isn't up to date for the - * current process. Experience shows that using USP is the way to go. - */ - unsigned long usp = rdusp(); - unsigned long d_mmu_cause; - unsigned long i_mmu_cause; - - printk("CPU: %d\n", smp_processor_id()); - - printk("ERP: %08lx SRP: %08lx CCS: %08lx USP: %08lx MOF: %08lx\n", - regs->erp, regs->srp, regs->ccs, usp, regs->mof); - - printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", - regs->r0, regs->r1, regs->r2, regs->r3); - - printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", - regs->r4, regs->r5, regs->r6, regs->r7); - - printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", - regs->r8, regs->r9, regs->r10, regs->r11); - - printk("r12: %08lx r13: %08lx oR10: %08lx acr: %08lx\n", - regs->r12, regs->r13, regs->orig_r10, regs->acr); - - printk(" sp: %08lx\n", (unsigned long)regs); - - SUPP_BANK_SEL(BANK_IM); - SUPP_REG_RD(RW_MM_CAUSE, i_mmu_cause); - - SUPP_BANK_SEL(BANK_DM); - SUPP_REG_RD(RW_MM_CAUSE, d_mmu_cause); - - printk(" Data MMU Cause: %08lx\n", d_mmu_cause); - printk("Instruction MMU Cause: %08lx\n", i_mmu_cause); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, (unsigned long)current); - - /* - * When in-kernel, we also print out the stack and code at the - * time of the fault.. - */ - if (!user_mode(regs)) { - int i; - - show_stack(NULL, (unsigned long *)usp); - - /* - * If the previous stack-dump wasn't a kernel one, dump the - * kernel stack now. - */ - if (usp != 0) - show_stack(NULL, NULL); - - printk("\nCode: "); - - if (regs->erp < PAGE_OFFSET) - goto bad_value; - - /* - * Quite often the value at regs->erp doesn't point to the - * interesting instruction, which often is the previous - * instruction. So dump at an offset large enough that the - * instruction decoding should be in sync at the interesting - * point, but small enough to fit on a row. The regs->erp - * location is pointed out in a ksymoops-friendly way by - * wrapping the byte for that address in parenthesises. - */ - for (i = -12; i < 12; i++) { - unsigned char c; - - if (__get_user(c, &((unsigned char *)regs->erp)[i])) { -bad_value: - printk(" Bad IP value."); - break; - } - - if (i == 0) - printk("(%02x) ", c); - else - printk("%02x ", c); - } - printk("\n"); - } -} - -void arch_enable_nmi(void) -{ - unsigned long flags; - - local_save_flags(flags); - flags |= (1 << 30); /* NMI M flag is at bit 30 */ - local_irq_restore(flags); -} - -extern void (*nmi_handler)(struct pt_regs *); -void handle_nmi(struct pt_regs *regs) -{ -#ifdef CONFIG_ETRAXFS - reg_intr_vect_r_nmi r; -#endif - - if (nmi_handler) - nmi_handler(regs); - -#ifdef CONFIG_ETRAXFS - /* Wait until nmi is no longer active. */ - do { - r = REG_RD(intr_vect, regi_irq, r_nmi); - } while (r.ext == regk_intr_vect_on); -#endif -} - - -#ifdef CONFIG_BUG -extern void die_if_kernel(const char *str, struct pt_regs *regs, long err); - -/* Copy of the regs at BUG() time. */ -struct pt_regs BUG_regs; - -void do_BUG(char *file, unsigned int line) -{ - printk("kernel BUG at %s:%d!\n", file, line); - die_if_kernel("Oops", &BUG_regs, 0); -} -EXPORT_SYMBOL(do_BUG); - -void fixup_BUG(struct pt_regs *regs) -{ - BUG_regs = *regs; - -#ifdef CONFIG_DEBUG_BUGVERBOSE - /* - * Fixup the BUG arguments through exception handlers. - */ - { - const struct exception_table_entry *fixup; - - /* - * ERP points at the "break 14" + 2, compensate for the 2 - * bytes. - */ - fixup = search_exception_tables(instruction_pointer(regs) - 2); - if (fixup) { - /* Adjust the instruction pointer in the stackframe. */ - instruction_pointer(regs) = fixup->fixup; - arch_fixup(regs); - } - } -#else - /* Dont try to lookup the filename + line, just dump regs. */ - do_BUG("unknown", 0); -#endif -} - -/* - * Break 14 handler. Save regs and jump into the fixup_BUG. - */ -__asm__ ( ".text\n\t" - ".global breakh_BUG\n\t" - "breakh_BUG:\n\t" - SAVE_ALL - KGDB_FIXUP - "move.d $sp, $r10\n\t" - "jsr fixup_BUG\n\t" - "nop\n\t" - "jump ret_from_intr\n\t" - "nop\n\t"); - - -#ifdef CONFIG_DEBUG_BUGVERBOSE -void -handle_BUG(struct pt_regs *regs) -{ -} -#endif -#endif |