aboutsummaryrefslogtreecommitdiff
path: root/arch/frv/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/frv/kernel')
-rw-r--r--arch/frv/kernel/Makefile11
-rw-r--r--arch/frv/kernel/asm-offsets.c109
-rw-r--r--arch/frv/kernel/break.S116
-rw-r--r--arch/frv/kernel/cmode.S3
-rw-r--r--arch/frv/kernel/debug-stub.c15
-rw-r--r--arch/frv/kernel/dma.c5
-rw-r--r--arch/frv/kernel/entry-table.S52
-rw-r--r--arch/frv/kernel/entry.S249
-rw-r--r--arch/frv/kernel/frv_ksyms.c27
-rw-r--r--arch/frv/kernel/futex.c20
-rw-r--r--arch/frv/kernel/gdb-io.c5
-rw-r--r--arch/frv/kernel/gdb-stub.c343
-rw-r--r--arch/frv/kernel/head-mmu-fr451.S4
-rw-r--r--arch/frv/kernel/head-uc-fr401.S4
-rw-r--r--arch/frv/kernel/head-uc-fr451.S4
-rw-r--r--arch/frv/kernel/head-uc-fr555.S4
-rw-r--r--arch/frv/kernel/head.S15
-rw-r--r--arch/frv/kernel/head.inc2
-rw-r--r--arch/frv/kernel/init_task.c39
-rw-r--r--arch/frv/kernel/irq-mb93091.c157
-rw-r--r--arch/frv/kernel/irq-mb93093.c117
-rw-r--r--arch/frv/kernel/irq-mb93493.c163
-rw-r--r--arch/frv/kernel/irq-routing.c291
-rw-r--r--arch/frv/kernel/irq.c770
-rw-r--r--arch/frv/kernel/kernel_thread.S77
-rw-r--r--arch/frv/kernel/local.h3
-rw-r--r--arch/frv/kernel/local64.h1
-rw-r--r--arch/frv/kernel/module.c59
-rw-r--r--arch/frv/kernel/pm-mb93093.c1
-rw-r--r--arch/frv/kernel/pm.c195
-rw-r--r--arch/frv/kernel/process.c175
-rw-r--r--arch/frv/kernel/ptrace.c811
-rw-r--r--arch/frv/kernel/semaphore.c156
-rw-r--r--arch/frv/kernel/setup.c90
-rw-r--r--arch/frv/kernel/signal.c228
-rw-r--r--arch/frv/kernel/sleep.S3
-rw-r--r--arch/frv/kernel/switch_to.S11
-rw-r--r--arch/frv/kernel/sys_frv.c180
-rw-r--r--arch/frv/kernel/sysctl.c49
-rw-r--r--arch/frv/kernel/time.c147
-rw-r--r--arch/frv/kernel/traps.c290
-rw-r--r--arch/frv/kernel/uaccess.c12
-rw-r--r--arch/frv/kernel/vmlinux.lds.S114
43 files changed, 1799 insertions, 3328 deletions
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index 5a827b349b5..3cbb3294b9f 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -5,20 +5,19 @@
heads-y := head-uc-fr401.o head-uc-fr451.o head-uc-fr555.o
heads-$(CONFIG_MMU) := head-mmu-fr451.o
-extra-y:= head.o init_task.o vmlinux.lds
+extra-y:= head.o vmlinux.lds
-obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
+obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o \
process.o traps.o ptrace.o signal.o dma.o \
- sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
- debug-stub.o irq.o irq-routing.o sleep.o uaccess.o
+ sys_frv.o time.o setup.o frv_ksyms.o \
+ debug-stub.o irq.o sleep.o uaccess.o
obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o
obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o
-obj-$(CONFIG_MB93093_PDK) += irq-mb93093.o
-obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
obj-$(CONFIG_PM) += pm.o cmode.o
obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o
+obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
obj-$(CONFIG_SYSCTL) += sysctl.o
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c
index 9e263112a6e..9de96843a27 100644
--- a/arch/frv/kernel/asm-offsets.c
+++ b/arch/frv/kernel/asm-offsets.c
@@ -1 +1,108 @@
-/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <linux/kbuild.h>
+#include <asm/registers.h>
+#include <asm/ucontext.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/gdb-stub.h>
+
+#define DEF_PTREG(sym, reg) \
+ asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \
+ : : "i" (offsetof(struct pt_regs, reg)))
+
+#define DEF_IREG(sym, reg) \
+ asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \
+ : : "i" (offsetof(struct user_context, reg)))
+
+#define DEF_FREG(sym, reg) \
+ asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \
+ : : "i" (offsetof(struct user_context, reg)))
+
+#define DEF_0REG(sym, reg) \
+ asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \
+ : : "i" (offsetof(struct frv_frame0, reg)))
+
+void foo(void)
+{
+ /* offsets into the thread_info structure */
+ OFFSET(TI_TASK, thread_info, task);
+ OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain);
+ OFFSET(TI_FLAGS, thread_info, flags);
+ OFFSET(TI_STATUS, thread_info, status);
+ OFFSET(TI_CPU, thread_info, cpu);
+ OFFSET(TI_PREEMPT_COUNT, thread_info, preempt_count);
+ OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
+ OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
+ BLANK();
+
+ /* offsets into register file storage */
+ DEF_PTREG(REG_PSR, psr);
+ DEF_PTREG(REG_ISR, isr);
+ DEF_PTREG(REG_CCR, ccr);
+ DEF_PTREG(REG_CCCR, cccr);
+ DEF_PTREG(REG_LR, lr);
+ DEF_PTREG(REG_LCR, lcr);
+ DEF_PTREG(REG_PC, pc);
+ DEF_PTREG(REG__STATUS, __status);
+ DEF_PTREG(REG_SYSCALLNO, syscallno);
+ DEF_PTREG(REG_ORIG_GR8, orig_gr8);
+ DEF_PTREG(REG_GNER0, gner0);
+ DEF_PTREG(REG_GNER1, gner1);
+ DEF_PTREG(REG_IACC0, iacc0);
+ DEF_PTREG(REG_TBR, tbr);
+ DEF_PTREG(REG_GR0, tbr);
+ DEFINE(REG__END, sizeof(struct pt_regs));
+ BLANK();
+
+ DEF_0REG(REG_DCR, debug.dcr);
+ DEF_0REG(REG_IBAR0, debug.ibar[0]);
+ DEF_0REG(REG_DBAR0, debug.dbar[0]);
+ DEF_0REG(REG_DBDR00, debug.dbdr[0][0]);
+ DEF_0REG(REG_DBMR00, debug.dbmr[0][0]);
+ BLANK();
+
+ DEF_IREG(__INT_GR0, i.gr[0]);
+ DEF_FREG(__USER_FPMEDIA, f);
+ DEF_FREG(__FPMEDIA_FR0, f.fr[0]);
+ DEF_FREG(__FPMEDIA_FNER0, f.fner[0]);
+ DEF_FREG(__FPMEDIA_MSR0, f.msr[0]);
+ DEF_FREG(__FPMEDIA_ACC0, f.acc[0]);
+ DEF_FREG(__FPMEDIA_ACCG0, f.accg[0]);
+ DEF_FREG(__FPMEDIA_FSR0, f.fsr[0]);
+ BLANK();
+
+ DEFINE(NR_PT_REGS, sizeof(struct pt_regs) / 4);
+ DEFINE(NR_USER_INT_REGS, sizeof(struct user_int_regs) / 4);
+ DEFINE(NR_USER_FPMEDIA_REGS, sizeof(struct user_fpmedia_regs) / 4);
+ DEFINE(NR_USER_CONTEXT, sizeof(struct user_context) / 4);
+ DEFINE(FRV_FRAME0_SIZE, sizeof(struct frv_frame0));
+ BLANK();
+
+ /* offsets into thread_struct */
+ OFFSET(__THREAD_FRAME, thread_struct, frame);
+ OFFSET(__THREAD_CURR, thread_struct, curr);
+ OFFSET(__THREAD_SP, thread_struct, sp);
+ OFFSET(__THREAD_FP, thread_struct, fp);
+ OFFSET(__THREAD_LR, thread_struct, lr);
+ OFFSET(__THREAD_PC, thread_struct, pc);
+ OFFSET(__THREAD_GR16, thread_struct, gr[0]);
+ OFFSET(__THREAD_SCHED_LR, thread_struct, sched_lr);
+ OFFSET(__THREAD_FRAME0, thread_struct, frame0);
+ OFFSET(__THREAD_USER, thread_struct, user);
+ BLANK();
+
+ /* offsets into frv_debug_status */
+ OFFSET(DEBUG_BPSR, frv_debug_status, bpsr);
+ OFFSET(DEBUG_DCR, frv_debug_status, dcr);
+ OFFSET(DEBUG_BRR, frv_debug_status, brr);
+ OFFSET(DEBUG_NMAR, frv_debug_status, nmar);
+ BLANK();
+}
diff --git a/arch/frv/kernel/break.S b/arch/frv/kernel/break.S
index 33233dc23e2..cbb6958a314 100644
--- a/arch/frv/kernel/break.S
+++ b/arch/frv/kernel/break.S
@@ -9,12 +9,11 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/sys.h>
-#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/ptrace.h>
+#include <asm/thread_info.h>
#include <asm/spr-regs.h>
#include <asm/errno.h>
@@ -22,15 +21,13 @@
#
# the break handler has its own stack
#
- .section .bss.stack
+ .section .bss..stack
.globl __break_user_context
- .balign 8192
+ .balign THREAD_SIZE
__break_stack:
- .space (8192 - (USER_CONTEXT_SIZE + REG__DEBUG_XTRA)) & ~7
-__break_stack_tos:
- .space REG__DEBUG_XTRA
-__break_user_context:
- .space USER_CONTEXT_SIZE
+ .space THREAD_SIZE - FRV_FRAME0_SIZE
+__break_frame_0:
+ .space FRV_FRAME0_SIZE
#
# miscellaneous variables
@@ -66,7 +63,7 @@ __break_trace_through_exceptions:
# entry point for Break Exceptions/Interrupts
#
###############################################################################
- .text
+ .section .text..break
.balign 4
.globl __entry_break
__entry_break:
@@ -75,8 +72,8 @@ __entry_break:
#endif
LEDS 0x1001,gr31
- sethi.p %hi(__break_user_context),gr31
- setlo %lo(__break_user_context),gr31
+ sethi.p %hi(__break_frame_0),gr31
+ setlo %lo(__break_frame_0),gr31
stdi gr2,@(gr31,#REG_GR(2))
movsg ccr,gr3
@@ -200,12 +197,20 @@ __break_step:
movsg bpcsr,gr2
sethi.p %hi(__entry_kernel_external_interrupt),gr3
setlo %lo(__entry_kernel_external_interrupt),gr3
- subcc gr2,gr3,gr0,icc0
+ subcc.p gr2,gr3,gr0,icc0
+ sethi %hi(__entry_uspace_external_interrupt),gr3
+ setlo.p %lo(__entry_uspace_external_interrupt),gr3
beq icc0,#2,__break_step_kernel_external_interrupt
- sethi.p %hi(__entry_uspace_external_interrupt),gr3
- setlo %lo(__entry_uspace_external_interrupt),gr3
- subcc gr2,gr3,gr0,icc0
+ subcc.p gr2,gr3,gr0,icc0
+ sethi %hi(__entry_kernel_external_interrupt_virtually_disabled),gr3
+ setlo.p %lo(__entry_kernel_external_interrupt_virtually_disabled),gr3
beq icc0,#2,__break_step_uspace_external_interrupt
+ subcc.p gr2,gr3,gr0,icc0
+ sethi %hi(__entry_kernel_external_interrupt_virtual_reenable),gr3
+ setlo.p %lo(__entry_kernel_external_interrupt_virtual_reenable),gr3
+ beq icc0,#2,__break_step_kernel_external_interrupt_virtually_disabled
+ subcc gr2,gr3,gr0,icc0
+ beq icc0,#2,__break_step_kernel_external_interrupt_virtual_reenable
LEDS 0x2007,gr2
@@ -254,6 +259,9 @@ __break_step_kernel_softprog_interrupt:
# step through an external interrupt from kernel mode
.globl __break_step_kernel_external_interrupt
__break_step_kernel_external_interrupt:
+ # deal with virtual interrupt disablement
+ beq icc2,#0,__break_step_kernel_external_interrupt_virtually_disabled
+
sethi.p %hi(__entry_kernel_external_interrupt_reentry),gr3
setlo %lo(__entry_kernel_external_interrupt_reentry),gr3
@@ -294,6 +302,64 @@ __break_return_as_kernel_prologue:
#endif
rett #1
+# we single-stepped into an interrupt handler whilst interrupts were merely virtually disabled
+# need to really disable interrupts, set flag, fix up and return
+__break_step_kernel_external_interrupt_virtually_disabled:
+ movsg psr,gr2
+ andi gr2,#~PSR_PIL,gr2
+ ori gr2,#PSR_PIL_14,gr2 /* debugging interrupts only */
+ movgs gr2,psr
+
+ ldi @(gr31,#REG_CCR),gr3
+ movgs gr3,ccr
+ subcc.p gr0,gr0,gr0,icc2 /* leave Z set, clear C */
+
+ # exceptions must've been enabled and we must've been in supervisor mode
+ setlos BPSR_BET|BPSR_BS,gr3
+ movgs gr3,bpsr
+
+ # return to where the interrupt happened
+ movsg pcsr,gr2
+ movgs gr2,bpcsr
+
+ lddi.p @(gr31,#REG_GR(2)),gr2
+
+ xor gr31,gr31,gr31
+ movgs gr0,brr
+#ifdef CONFIG_MMU
+ movsg scr3,gr31
+#endif
+ rett #1
+
+# we stepped through into the virtual interrupt reenablement trap
+#
+# we also want to single step anyway, but after fixing up so that we get an event on the
+# instruction after the broken-into exception returns
+ .globl __break_step_kernel_external_interrupt_virtual_reenable
+__break_step_kernel_external_interrupt_virtual_reenable:
+ movsg psr,gr2
+ andi gr2,#~PSR_PIL,gr2
+ movgs gr2,psr
+
+ ldi @(gr31,#REG_CCR),gr3
+ movgs gr3,ccr
+ subicc gr0,#1,gr0,icc2 /* clear Z, set C */
+
+ # save the adjusted ICC2
+ movsg ccr,gr3
+ sti gr3,@(gr31,#REG_CCR)
+
+ # exceptions must've been enabled and we must've been in supervisor mode
+ setlos BPSR_BET|BPSR_BS,gr3
+ movgs gr3,bpsr
+
+ # return to where the trap happened
+ movsg pcsr,gr2
+ movgs gr2,bpcsr
+
+ # and then process the single step
+ bra __break_continue
+
# step through an internal exception from uspace mode
.globl __break_step_uspace_softprog_interrupt
__break_step_uspace_softprog_interrupt:
@@ -517,8 +583,8 @@ __break_continue:
# set up the kernel stack pointer
sti sp,@(gr31,#REG_SP)
- sethi.p %hi(__break_stack_tos),sp
- setlo %lo(__break_stack_tos),sp
+ sethi.p %hi(__break_frame_0),sp
+ setlo %lo(__break_frame_0),sp
# finish building the exception frame
stdi gr4 ,@(gr31,#REG_GR(4))
@@ -583,9 +649,12 @@ __break_continue:
movsg nmar,gr5
movsg dcr,gr6
- stdi gr4 ,@(gr31,#REG_BRR)
- sti gr19,@(gr31,#REG_BPSR)
- sti.p gr6 ,@(gr31,#REG_DCR)
+ sethi.p %hi(__debug_status),gr7
+ setlo %lo(__debug_status),gr7
+
+ stdi gr4 ,@(gr7,#DEBUG_BRR)
+ sti gr19,@(gr7,#DEBUG_BPSR)
+ sti.p gr6 ,@(gr7,#DEBUG_DCR)
# trap exceptions during break handling and disable h/w breakpoints/watchpoints
sethi %hi(DCR_EBE),gr5
@@ -630,7 +699,10 @@ __break_continue:
lddi @(gr31,#REG_PSR) ,gr22
ldi @(gr31,#REG_PC) ,gr21
ldi @(gr31,#REG_TBR) ,gr20
- ldi.p @(gr31,#REG_DCR) ,gr6
+
+ sethi.p %hi(__debug_status),gr6
+ setlo %lo(__debug_status),gr6
+ ldi.p @(gr6,#DEBUG_DCR) ,gr6
andi gr22,#PSR_S,gr19 /* rebuild BPSR */
andi.p gr22,#PSR_ET,gr5
diff --git a/arch/frv/kernel/cmode.S b/arch/frv/kernel/cmode.S
index 6591e6a37ae..53deeb5d7e8 100644
--- a/arch/frv/kernel/cmode.S
+++ b/arch/frv/kernel/cmode.S
@@ -1,7 +1,7 @@
/* cmode.S: clock mode management
*
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Woodhouse (dwmw2@redhat.com)
+ * Written by David Woodhouse (dwmw2@infradead.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -11,7 +11,6 @@
*/
#include <linux/sys.h>
-#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/setup.h>
#include <asm/segment.h>
diff --git a/arch/frv/kernel/debug-stub.c b/arch/frv/kernel/debug-stub.c
index 4761cc4b4a9..a0228f717ef 100644
--- a/arch/frv/kernel/debug-stub.c
+++ b/arch/frv/kernel/debug-stub.c
@@ -15,8 +15,8 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/serial_reg.h>
+#include <linux/start_kernel.h>
-#include <asm/system.h>
#include <asm/serial-regs.h>
#include <asm/timer-regs.h>
#include <asm/irc-regs.h>
@@ -39,10 +39,9 @@ do { \
gdbstub_do_rx(); \
} while(!FLOWCTL_QUERY(LINE))
-static void __init debug_stub_init(void);
+struct frv_debug_status __debug_status;
-extern asmlinkage void __break_hijack_kernel_event(void);
-extern asmlinkage void __break_hijack_kernel_event_breaks_here(void);
+static void __init debug_stub_init(void);
/*****************************************************************************/
/*
@@ -67,7 +66,7 @@ asmlinkage void debug_stub(void)
__set_HSR(0, hsr0 & ~HSR0_ETMD);
/* disable single stepping */
- __debug_regs->dcr &= ~DCR_SE;
+ __debug_status.dcr &= ~DCR_SE;
/* kernel mode can propose an exception be handled in debug mode by jumping to a special
* location */
@@ -76,8 +75,8 @@ asmlinkage void debug_stub(void)
* the top kernel context */
*__debug_frame = *__frame;
__frame = __debug_frame->next_frame;
- __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
- __debug_regs->brr |= BRR_EB;
+ __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12;
+ __debug_status.brr |= BRR_EB;
}
if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) {
@@ -124,7 +123,7 @@ static void __init debug_stub_init(void)
__debug_frame->pc = (unsigned long) start_kernel;
/* enable the debug events we want to trap */
- __debug_regs->dcr = DCR_EBE;
+ __debug_status.dcr = DCR_EBE;
#ifdef CONFIG_GDBSTUB
gdbstub_init();
diff --git a/arch/frv/kernel/dma.c b/arch/frv/kernel/dma.c
index f5de6cf7df4..156184e17e5 100644
--- a/arch/frv/kernel/dma.c
+++ b/arch/frv/kernel/dma.c
@@ -121,15 +121,14 @@ unsigned long frv_dma_inprogress;
/*
* DMA irq handler - determine channel involved, grab status and call real handler
*/
-static irqreturn_t dma_irq_handler(int irq, void *_channel, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *_channel)
{
struct frv_dma_channel *channel = _channel;
frv_clear_dma_inprogress(channel - frv_dma_channels);
return channel->handler(channel - frv_dma_channels,
__get_DMAC(channel->ioaddr, CSTR),
- channel->data,
- regs);
+ channel->data);
} /* end dma_irq_handler() */
diff --git a/arch/frv/kernel/entry-table.S b/arch/frv/kernel/entry-table.S
index 9b9243e2103..06c5ae191e5 100644
--- a/arch/frv/kernel/entry-table.S
+++ b/arch/frv/kernel/entry-table.S
@@ -11,7 +11,6 @@
*/
#include <linux/sys.h>
-#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/spr-regs.h>
@@ -87,7 +86,7 @@ __break_usertrap_fixup_table:
.globl __break_kerneltrap_fixup_table
__break_kerneltrap_fixup_table:
- # handler declaration for a sofware or program interrupt
+ # handler declaration for a software or program interrupt
.macro VECTOR_SOFTPROG tbr_tt, vec
.section .trap.user
.org \tbr_tt
@@ -116,6 +115,8 @@ __break_kerneltrap_fixup_table:
.long __break_step_uspace_external_interrupt
.section .trap.kernel
.org \tbr_tt
+ # deal with virtual interrupt disablement
+ beq icc2,#0,__entry_kernel_external_interrupt_virtually_disabled
bra __entry_kernel_external_interrupt
.section .trap.fixup.kernel
.org \tbr_tt >> 2
@@ -144,7 +145,7 @@ __break_kerneltrap_fixup_table:
.long \vec
.endm
- # handler declaration for an MMU only sofware or program interrupt
+ # handler declaration for an MMU only software or program interrupt
.macro VECTOR_SP_MMU tbr_tt, vec
#ifdef CONFIG_MMU
VECTOR_SOFTPROG \tbr_tt, \vec
@@ -259,25 +260,52 @@ __trap_fixup_kernel_data_tlb_miss:
.org TBR_TT_TRAP0
.rept 127
bra __entry_uspace_softprog_interrupt
- bra __break_step_uspace_softprog_interrupt
- .long 0,0
+ .long 0,0,0
.endr
.org TBR_TT_BREAK
bra __entry_break
.long 0,0,0
+ .section .trap.fixup.user
+ .org TBR_TT_TRAP0 >> 2
+ .rept 127
+ .long __break_step_uspace_softprog_interrupt
+ .endr
+ .org TBR_TT_BREAK >> 2
+ .long 0
+
# miscellaneous kernel mode entry points
.section .trap.kernel
.org TBR_TT_TRAP0
- .rept 127
bra __entry_kernel_softprog_interrupt
- bra __break_step_kernel_softprog_interrupt
- .long 0,0
+ .org TBR_TT_TRAP1
+ bra __entry_kernel_softprog_interrupt
+
+ # trap #2 in kernel - reenable interrupts
+ .org TBR_TT_TRAP2
+ bra __entry_kernel_external_interrupt_virtual_reenable
+
+ # miscellaneous kernel traps
+ .org TBR_TT_TRAP3
+ .rept 124
+ bra __entry_kernel_softprog_interrupt
+ .long 0,0,0
.endr
.org TBR_TT_BREAK
bra __entry_break
.long 0,0,0
+ .section .trap.fixup.kernel
+ .org TBR_TT_TRAP0 >> 2
+ .long __break_step_kernel_softprog_interrupt
+ .long __break_step_kernel_softprog_interrupt
+ .long __break_step_kernel_external_interrupt_virtual_reenable
+ .rept 124
+ .long __break_step_kernel_softprog_interrupt
+ .endr
+ .org TBR_TT_BREAK >> 2
+ .long 0
+
# miscellaneous debug mode entry points
.section .trap.break
.org TBR_TT_BREAK
@@ -288,8 +316,14 @@ __trap_fixup_kernel_data_tlb_miss:
.section .trap.vector
.org TBR_TT_TRAP0 >> 2
.long system_call
- .rept 126
+ .rept 119
.long __entry_unsupported_trap
.endr
+
+ # userspace atomic op emulation, traps 120-126
+ .rept 7
+ .long __entry_atomic_op
+ .endr
+
.org TBR_TT_BREAK >> 2
.long __entry_debug_exception
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 5f6548388b7..dfcd263c051 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -27,8 +27,6 @@
*
*/
-#include <linux/sys.h>
-#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/setup.h>
@@ -40,7 +38,7 @@
#define nr_syscalls ((syscall_table_size)/4)
- .text
+ .section .text..entry
.balign 4
.macro LEDS val
@@ -141,7 +139,10 @@ __entry_uspace_external_interrupt_reentry:
movsg gner0,gr4
movsg gner1,gr5
- stdi gr4,@(gr28,#REG_GNER0)
+ stdi.p gr4,@(gr28,#REG_GNER0)
+
+ # interrupts start off fully disabled in the interrupt handler
+ subcc gr0,gr0,gr0,icc2 /* set Z and clear C */
# set up kernel global registers
sethi.p %hi(__kernel_current_task),gr5
@@ -193,9 +194,8 @@ __entry_uspace_external_interrupt_reentry:
.type __entry_kernel_external_interrupt,@function
__entry_kernel_external_interrupt:
LEDS 0x6210
-
- sub sp,gr15,gr31
- LEDS32
+// sub sp,gr15,gr31
+// LEDS32
# set up the stack pointer
or.p sp,gr0,gr30
@@ -231,7 +231,10 @@ __entry_kernel_external_interrupt_reentry:
stdi gr24,@(gr28,#REG_GR(24))
stdi gr26,@(gr28,#REG_GR(26))
sti gr29,@(gr28,#REG_GR(29))
- stdi gr30,@(gr28,#REG_GR(30))
+ stdi.p gr30,@(gr28,#REG_GR(30))
+
+ # note virtual interrupts will be fully enabled upon return
+ subicc gr0,#1,gr0,icc2 /* clear Z, set C */
movsg tbr ,gr20
movsg psr ,gr22
@@ -250,7 +253,7 @@ __entry_kernel_external_interrupt_reentry:
andi.p gr5,#~PSR_ET,gr5
# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
- # - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
+ # - for an explanation of how it works, see: Documentation/frv/atomic-ops.txt
andi gr25,#~0xc0,gr25
sti gr20,@(gr28,#REG_TBR)
@@ -267,7 +270,10 @@ __entry_kernel_external_interrupt_reentry:
movsg gner0,gr4
movsg gner1,gr5
- stdi gr4,@(gr28,#REG_GNER0)
+ stdi.p gr4,@(gr28,#REG_GNER0)
+
+ # interrupts start off fully disabled in the interrupt handler
+ subcc gr0,gr0,gr0,icc2 /* set Z and clear C */
# set the return address
sethi.p %hi(__entry_return_from_kernel_interrupt),gr4
@@ -291,6 +297,45 @@ __entry_kernel_external_interrupt_reentry:
.size __entry_kernel_external_interrupt,.-__entry_kernel_external_interrupt
+###############################################################################
+#
+# deal with interrupts that were actually virtually disabled
+# - we need to really disable them, flag the fact and return immediately
+# - if you change this, you must alter break.S also
+#
+###############################################################################
+ .balign L1_CACHE_BYTES
+ .globl __entry_kernel_external_interrupt_virtually_disabled
+ .type __entry_kernel_external_interrupt_virtually_disabled,@function
+__entry_kernel_external_interrupt_virtually_disabled:
+ movsg psr,gr30
+ andi gr30,#~PSR_PIL,gr30
+ ori gr30,#PSR_PIL_14,gr30 ; debugging interrupts only
+ movgs gr30,psr
+ subcc gr0,gr0,gr0,icc2 ; leave Z set, clear C
+ rett #0
+
+ .size __entry_kernel_external_interrupt_virtually_disabled,.-__entry_kernel_external_interrupt_virtually_disabled
+
+###############################################################################
+#
+# deal with re-enablement of interrupts that were pending when virtually re-enabled
+# - set ICC2.C, re-enable the real interrupts and return
+# - we can clear ICC2.Z because we shouldn't be here if it's not 0 [due to TIHI]
+# - if you change this, you must alter break.S also
+#
+###############################################################################
+ .balign L1_CACHE_BYTES
+ .globl __entry_kernel_external_interrupt_virtual_reenable
+ .type __entry_kernel_external_interrupt_virtual_reenable,@function
+__entry_kernel_external_interrupt_virtual_reenable:
+ movsg psr,gr30
+ andi gr30,#~PSR_PIL,gr30 ; re-enable interrupts
+ movgs gr30,psr
+ subicc gr0,#1,gr0,icc2 ; clear Z, set C
+ rett #0
+
+ .size __entry_kernel_external_interrupt_virtual_reenable,.-__entry_kernel_external_interrupt_virtual_reenable
###############################################################################
#
@@ -335,6 +380,7 @@ __entry_uspace_softprog_interrupt_reentry:
sethi.p %hi(__entry_return_from_user_exception),gr23
setlo %lo(__entry_return_from_user_exception),gr23
+
bra __entry_common
.size __entry_uspace_softprog_interrupt,.-__entry_uspace_softprog_interrupt
@@ -399,7 +445,7 @@ __entry_kernel_softprog_interrupt_reentry:
sti gr22,@(sp,#REG_SP)
# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
- # - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
+ # - for an explanation of how it works, see: Documentation/frv/atomic-ops.txt
movsg cccr,gr20
andi gr20,#~0xc0,gr20
movgs gr20,cccr
@@ -495,7 +541,10 @@ __entry_common:
movsg gner0,gr4
movsg gner1,gr5
- stdi gr4,@(gr28,#REG_GNER0)
+ stdi.p gr4,@(gr28,#REG_GNER0)
+
+ # set up virtual interrupt disablement
+ subicc gr0,#1,gr0,icc2 /* clear Z flag, set C flag */
# set up kernel global registers
sethi.p %hi(__kernel_current_task),gr5
@@ -607,6 +656,26 @@ __entry_debug_exception:
###############################################################################
#
+# handle atomic operation emulation for userspace
+#
+###############################################################################
+ .globl __entry_atomic_op
+__entry_atomic_op:
+ LEDS 0x6012
+ sethi.p %hi(atomic_operation),gr5
+ setlo %lo(atomic_operation),gr5
+ movsg esfr1,gr8
+ movsg epcr0,gr9
+ movsg esr0,gr10
+
+ # now that we've accessed the exception regs, we can enable exceptions
+ movsg psr,gr4
+ ori gr4,#PSR_ET,gr4
+ movgs gr4,psr
+ jmpl @(gr5,gr0) ; call atomic_operation(esfr1,epcr0,esr0)
+
+###############################################################################
+#
# handle media exception
#
###############################################################################
@@ -794,6 +863,14 @@ ret_from_fork:
setlos.p #0,gr8
bra __syscall_exit
+ .globl ret_from_kernel_thread
+ret_from_kernel_thread:
+ lddi.p @(gr28,#REG_GR(8)),gr20
+ call schedule_tail
+ calll.p @(gr21,gr0)
+ or gr20,gr20,gr8
+ bra __syscall_exit
+
###################################################################################################
#
# Return to user mode is not as complex as all this looks,
@@ -817,7 +894,6 @@ system_call:
bnc icc0,#0,__syscall_badsys
ldi @(gr15,#TI_FLAGS),gr4
- ori gr4,#_TIF_SYSCALL_TRACE,gr4
andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
bne icc0,#0,__syscall_trace_entry
@@ -837,18 +913,19 @@ __syscall_call:
__syscall_exit:
LEDS 0x6300
- sti gr8,@(gr28,#REG_GR(8)) ; save return value
+ # keep current PSR in GR23
+ movsg psr,gr23
- # rebuild saved psr - execve will change it for init/main.c
ldi @(gr28,#REG_PSR),gr22
+
+ sti.p gr8,@(gr28,#REG_GR(8)) ; save return value
+
+ # rebuild saved psr - execve will change it for init/main.c
srli gr22,#1,gr5
andi.p gr22,#~PSR_PS,gr22
andi gr5,#PSR_PS,gr5
or gr5,gr22,gr22
- ori gr22,#PSR_S,gr22
-
- # keep current PSR in GR23
- movsg psr,gr23
+ ori.p gr22,#PSR_S,gr22
# make sure we don't miss an interrupt setting need_resched or sigpending between
# sampling and the RETT
@@ -856,9 +933,7 @@ __syscall_exit:
movgs gr23,psr
ldi @(gr15,#TI_FLAGS),gr4
- sethi.p %hi(_TIF_ALLWORK_MASK),gr5
- setlo %lo(_TIF_ALLWORK_MASK),gr5
- andcc gr4,gr5,gr0,icc0
+ andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0
bne icc0,#0,__syscall_exit_work
# restore all registers and return
@@ -1000,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
subicc gr5,#0,gr0,icc0
beq icc0,#0,__entry_return_direct
-__entry_preempt_need_resched:
- ldi @(gr15,#TI_FLAGS),gr4
- andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0
- beq icc0,#1,__entry_return_direct
-
- setlos #PREEMPT_ACTIVE,gr5
- sti gr5,@(gr15,#TI_FLAGS)
-
- andi gr23,#~PSR_PIL,gr23
- movgs gr23,psr
-
- call schedule
- sti gr0,@(gr15,#TI_PRE_COUNT)
-
- movsg psr,gr23
- ori gr23,#PSR_PIL_14,gr23
- movgs gr23,psr
- bra __entry_preempt_need_resched
-#else
- bra __entry_return_direct
+ subcc gr0,gr0,gr0,icc2 /* set Z and clear C */
+ call preempt_schedule_irq
#endif
+ bra __entry_return_direct
###############################################################################
@@ -1043,9 +1101,7 @@ __entry_resume_userspace:
__entry_return_from_user_interrupt:
LEDS 0x6402
ldi @(gr15,#TI_FLAGS),gr4
- sethi.p %hi(_TIF_WORK_MASK),gr5
- setlo %lo(_TIF_WORK_MASK),gr5
- andcc gr4,gr5,gr0,icc0
+ andicc gr4,#_TIF_WORK_MASK,gr0,icc0
beq icc0,#1,__entry_return_direct
__entry_work_pending:
@@ -1065,9 +1121,7 @@ __entry_work_resched:
LEDS 0x6401
ldi @(gr15,#TI_FLAGS),gr4
- sethi.p %hi(_TIF_WORK_MASK),gr5
- setlo %lo(_TIF_WORK_MASK),gr5
- andcc gr4,gr5,gr0,icc0
+ andicc gr4,#_TIF_WORK_MASK,gr0,icc0
beq icc0,#1,__entry_return_direct
andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0
bne icc0,#1,__entry_work_resched
@@ -1081,11 +1135,10 @@ __entry_work_notifysig:
# perform syscall entry tracing
__syscall_trace_entry:
LEDS 0x6320
- setlos.p #0,gr8
- call do_syscall_trace
+ call syscall_trace_entry
- ldi @(gr28,#REG_SYSCALLNO),gr7
- lddi @(gr28,#REG_GR(8)) ,gr8
+ lddi.p @(gr28,#REG_GR(8)) ,gr8
+ ori gr8,#0,gr7 ; syscall_trace_entry() returned new syscallno
lddi @(gr28,#REG_GR(10)),gr10
lddi.p @(gr28,#REG_GR(12)),gr12
@@ -1096,15 +1149,16 @@ __syscall_trace_entry:
# perform syscall exit tracing
__syscall_exit_work:
LEDS 0x6340
- andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
+ andicc gr22,#PSR_PS,gr0,icc1 ; don't handle on return to kernel mode
+ andicc.p gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
+ bne icc1,#0,__entry_return_direct
beq icc0,#1,__entry_work_pending
movsg psr,gr23
- andi gr23,#~PSR_PIL,gr23 ; could let do_syscall_trace() call schedule()
+ andi gr23,#~PSR_PIL,gr23 ; could let syscall_trace_exit() call schedule()
movgs gr23,psr
- setlos.p #1,gr8
- call do_syscall_trace
+ call syscall_trace_exit
bra __entry_resume_userspace
__syscall_badsys:
@@ -1119,12 +1173,6 @@ __syscall_badsys:
# syscall vector table
#
###############################################################################
-#ifdef CONFIG_MMU
-#define __MMU(X) X
-#else
-#define __MMU(X) sys_ni_syscall
-#endif
-
.section .rodata
ALIGN
.globl sys_call_table
@@ -1254,7 +1302,7 @@ sys_call_table:
.long sys_newuname
.long sys_ni_syscall /* old "cacheflush" */
.long sys_adjtimex
- .long __MMU(sys_mprotect) /* 125 */
+ .long sys_mprotect /* 125 */
.long sys_sigprocmask
.long sys_ni_syscall /* old "create_module" */
.long sys_init_module
@@ -1273,16 +1321,16 @@ sys_call_table:
.long sys_getdents
.long sys_select
.long sys_flock
- .long __MMU(sys_msync)
+ .long sys_msync
.long sys_readv /* 145 */
.long sys_writev
.long sys_getsid
.long sys_fdatasync
.long sys_sysctl
- .long __MMU(sys_mlock) /* 150 */
- .long __MMU(sys_munlock)
- .long __MMU(sys_mlockall)
- .long __MMU(sys_munlockall)
+ .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
@@ -1292,13 +1340,13 @@ sys_call_table:
.long sys_sched_get_priority_min /* 160 */
.long sys_sched_rr_get_interval
.long sys_nanosleep
- .long __MMU(sys_mremap)
+ .long sys_mremap
.long sys_setresuid16
.long sys_getresuid16 /* 165 */
.long sys_ni_syscall /* for vm86 */
.long sys_ni_syscall /* Old sys_query_module */
.long sys_poll
- .long sys_nfsservctl
+ .long sys_ni_syscall /* Old nfsservctl */
.long sys_setresgid16 /* 170 */
.long sys_getresgid16
.long sys_prctl
@@ -1347,8 +1395,8 @@ sys_call_table:
.long sys_setfsuid /* 215 */
.long sys_setfsgid
.long sys_pivot_root
- .long __MMU(sys_mincore)
- .long __MMU(sys_madvise)
+ .long sys_mincore
+ .long sys_madvise
.long sys_getdents64 /* 220 */
.long sys_fcntl64
.long sys_ni_syscall /* reserved for TUX */
@@ -1386,7 +1434,7 @@ sys_call_table:
.long sys_epoll_create
.long sys_epoll_ctl /* 255 */
.long sys_epoll_wait
- .long __MMU(sys_remap_file_pages)
+ .long sys_remap_file_pages
.long sys_set_tid_address
.long sys_timer_create
.long sys_timer_settime /* 260 */
@@ -1418,11 +1466,54 @@ sys_call_table:
.long sys_add_key
.long sys_request_key
.long sys_keyctl
- .long sys_ni_syscall // sys_vperfctr_open
- .long sys_ni_syscall // sys_vperfctr_control /* 290 */
- .long sys_ni_syscall // sys_vperfctr_unlink
- .long sys_ni_syscall // sys_vperfctr_iresume
- .long sys_ni_syscall // sys_vperfctr_read
-
+ .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_rt_tgsigqueueinfo /* 335 */
+ .long sys_perf_event_open
+ .long sys_setns
syscall_table_size = (. - sys_call_table)
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 0f1c6cbc4f5..86c516d96dc 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -7,13 +7,11 @@
#include <linux/elfcore.h>
#include <linux/in6.h>
#include <linux/interrupt.h>
-#include <linux/config.h>
#include <asm/setup.h>
#include <asm/pgalloc.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/semaphore.h>
#include <asm/checksum.h>
#include <asm/hardirq.h>
#include <asm/cacheflush.h>
@@ -26,26 +24,13 @@ extern long __memset_user(void *dst, const void *src, size_t count);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-
EXPORT_SYMBOL(ip_fast_csum);
#if 0
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
#endif
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
EXPORT_SYMBOL(__page_offset);
EXPORT_SYMBOL(__memcpy_user);
@@ -62,24 +47,16 @@ EXPORT_SYMBOL(memory_end);
EXPORT_SYMBOL(__debug_bug_trap);
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
-
/* The following are special because they're not called
explicitly (the C compiler generates them). Fortunately,
their interface isn't gonna change any time soon now, so
it's OK to leave it out of version control. */
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__outsl_ns);
EXPORT_SYMBOL(__insl_ns);
-EXPORT_SYMBOL(get_wchan);
-
#ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
EXPORT_SYMBOL(atomic_test_and_ANDNOT_mask);
EXPORT_SYMBOL(atomic_test_and_OR_mask);
@@ -89,6 +66,10 @@ EXPORT_SYMBOL(atomic_sub_return);
EXPORT_SYMBOL(__xchg_32);
EXPORT_SYMBOL(__cmpxchg_32);
#endif
+EXPORT_SYMBOL(atomic64_add_return);
+EXPORT_SYMBOL(atomic64_sub_return);
+EXPORT_SYMBOL(__xchg_64);
+EXPORT_SYMBOL(__cmpxchg_64);
EXPORT_SYMBOL(__debug_bug_printk);
EXPORT_SYMBOL(__delay_loops_MHz);
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
index eae874a970c..d155ca9e509 100644
--- a/arch/frv/kernel/futex.c
+++ b/arch/frv/kernel/futex.c
@@ -10,15 +10,15 @@
*/
#include <linux/futex.h>
+#include <linux/uaccess.h>
#include <asm/futex.h>
#include <asm/errno.h>
-#include <asm/uaccess.h>
/*
* the various futex operations; MMU fault checking is ignored under no-MMU
* conditions
*/
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
{
int oldval, ret;
@@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o
return ret;
}
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
{
int oldval, ret;
@@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o
return ret;
}
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
{
int oldval, ret;
@@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol
return ret;
}
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
{
int oldval, ret;
@@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o
return ret;
}
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
{
int oldval, ret;
@@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o
/*
* do the futex operations
*/
-int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
{
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
@@ -197,10 +197,10 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
- inc_preempt_count();
+ pagefault_disable();
switch (op) {
case FUTEX_OP_SET:
@@ -223,7 +223,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
break;
}
- dec_preempt_count();
+ pagefault_enable();
if (!ret) {
switch (cmp) {
diff --git a/arch/frv/kernel/gdb-io.c b/arch/frv/kernel/gdb-io.c
index c997bccb922..0707d35079b 100644
--- a/arch/frv/kernel/gdb-io.c
+++ b/arch/frv/kernel/gdb-io.c
@@ -19,7 +19,6 @@
#include <linux/serial_reg.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/irc-regs.h>
#include <asm/timer-regs.h>
#include <asm/gdb-stub.h>
@@ -171,11 +170,11 @@ int gdbstub_rx_char(unsigned char *_ch, int nonblock)
return -EINTR;
}
else if (st & (UART_LSR_FE|UART_LSR_OE|UART_LSR_PE)) {
- gdbstub_proto("### GDB Rx Error (st=%02x) ###\n",st);
+ gdbstub_io("### GDB Rx Error (st=%02x) ###\n",st);
return -EIO;
}
else {
- gdbstub_proto("### GDB Rx %02x (st=%02x) ###\n",ch,st);
+ gdbstub_io("### GDB Rx %02x (st=%02x) ###\n",ch,st);
*_ch = ch & 0x7f;
return 0;
}
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index 8f860d9c494..bbe78b0bffe 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -87,7 +87,7 @@
* Example:
* $ cd ~/linux
* $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
- * $ make dep; make vmlinux
+ * $ make vmlinux
*
* Step 3:
* Download the kernel to the remote target and start
@@ -124,8 +124,8 @@
#include <linux/slab.h>
#include <linux/nmi.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/gdb-stub.h>
#define LEDS(x) do { /* *(u32*)0xe1200004 = ~(x); mb(); */ } while(0)
@@ -136,7 +136,6 @@ extern void debug_to_serial(const char *p, int n);
extern void gdbstub_console_write(struct console *co, const char *p, unsigned n);
extern volatile uint32_t __break_error_detect[3]; /* ESFR1, ESR15, EAR15 */
-extern struct user_context __break_user_context;
struct __debug_amr {
unsigned long L, P;
@@ -182,8 +181,6 @@ extern volatile u32 __attribute__((section(".bss"))) gdbstub_trace_through_excep
static char input_buffer[BUFMAX];
static char output_buffer[BUFMAX];
-static const char hexchars[] = "0123456789abcdef";
-
static const char *regnames[] = {
"PSR ", "ISR ", "CCR ", "CCCR",
"LR ", "LCR ", "PC ", "_stt",
@@ -383,8 +380,8 @@ static int gdbstub_send_packet(char *buffer)
}
gdbstub_tx_char('#');
- gdbstub_tx_char(hexchars[checksum >> 4]);
- gdbstub_tx_char(hexchars[checksum & 0xf]);
+ gdbstub_tx_char(hex_asc_hi(checksum));
+ gdbstub_tx_char(hex_asc_lo(checksum));
} while (gdbstub_rx_char(&ch,0),
#ifdef GDBSTUB_DEBUG_PROTOCOL
@@ -647,17 +644,11 @@ void debug_to_serial(const char *p, int n)
}
#endif
-#ifdef CONFIG_GDBSTUB_CONSOLE
-
-static kdev_t gdbstub_console_dev(struct console *con)
-{
- return MKDEV(1,3); /* /dev/null */
-}
+#ifdef CONFIG_GDB_CONSOLE
static struct console gdbstub_console = {
.name = "gdb",
.write = gdbstub_console_write, /* in break.S */
- .device = gdbstub_console_dev,
.flags = CON_PRINTBUFFER,
.index = -1,
};
@@ -680,8 +671,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if ((uint32_t)mem&1 && count>=1) {
if (!gdbstub_read_byte(mem,ch))
return NULL;
- *buf++ = hexchars[ch[0] >> 4];
- *buf++ = hexchars[ch[0] & 0xf];
+ buf = hex_byte_pack(buf, ch[0]);
mem++;
count--;
}
@@ -689,10 +679,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if ((uint32_t)mem&3 && count>=2) {
if (!gdbstub_read_word(mem,(uint16_t *)ch))
return NULL;
- *buf++ = hexchars[ch[0] >> 4];
- *buf++ = hexchars[ch[0] & 0xf];
- *buf++ = hexchars[ch[1] >> 4];
- *buf++ = hexchars[ch[1] & 0xf];
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -700,14 +688,10 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
while (count>=4) {
if (!gdbstub_read_dword(mem,(uint32_t *)ch))
return NULL;
- *buf++ = hexchars[ch[0] >> 4];
- *buf++ = hexchars[ch[0] & 0xf];
- *buf++ = hexchars[ch[1] >> 4];
- *buf++ = hexchars[ch[1] & 0xf];
- *buf++ = hexchars[ch[2] >> 4];
- *buf++ = hexchars[ch[2] & 0xf];
- *buf++ = hexchars[ch[3] >> 4];
- *buf++ = hexchars[ch[3] & 0xf];
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[2]);
+ buf = hex_byte_pack(buf, ch[3]);
mem += 4;
count -= 4;
}
@@ -715,10 +699,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if (count>=2) {
if (!gdbstub_read_word(mem,(uint16_t *)ch))
return NULL;
- *buf++ = hexchars[ch[0] >> 4];
- *buf++ = hexchars[ch[0] & 0xf];
- *buf++ = hexchars[ch[1] >> 4];
- *buf++ = hexchars[ch[1] & 0xf];
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -726,8 +708,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if (count>=1) {
if (!gdbstub_read_byte(mem,ch))
return NULL;
- *buf++ = hexchars[ch[0] >> 4];
- *buf++ = hexchars[ch[0] & 0xf];
+ buf = hex_byte_pack(buf, ch[0]);
}
*buf = 0;
@@ -926,6 +907,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign
if (!(__debug_regs->dcr & DCR_IBE0)) {
//gdbstub_printk("set h/w break 0: %08lx\n", addr);
__debug_regs->dcr |= DCR_IBE0;
+ __debug_regs->ibar[0] = addr;
asm volatile("movgs %0,ibar0" : : "r"(addr));
return 0;
}
@@ -933,6 +915,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign
if (!(__debug_regs->dcr & DCR_IBE1)) {
//gdbstub_printk("set h/w break 1: %08lx\n", addr);
__debug_regs->dcr |= DCR_IBE1;
+ __debug_regs->ibar[1] = addr;
asm volatile("movgs %0,ibar1" : : "r"(addr));
return 0;
}
@@ -940,6 +923,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign
if (!(__debug_regs->dcr & DCR_IBE2)) {
//gdbstub_printk("set h/w break 2: %08lx\n", addr);
__debug_regs->dcr |= DCR_IBE2;
+ __debug_regs->ibar[2] = addr;
asm volatile("movgs %0,ibar2" : : "r"(addr));
return 0;
}
@@ -947,6 +931,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign
if (!(__debug_regs->dcr & DCR_IBE3)) {
//gdbstub_printk("set h/w break 3: %08lx\n", addr);
__debug_regs->dcr |= DCR_IBE3;
+ __debug_regs->ibar[3] = addr;
asm volatile("movgs %0,ibar3" : : "r"(addr));
return 0;
}
@@ -971,7 +956,14 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign
if (!(__debug_regs->dcr & (DCR_DRBE0|DCR_DWBE0))) {
//gdbstub_printk("set h/w watchpoint 0 type %ld: %08lx\n", type, addr);
tmp = type==2 ? DCR_DWBE0 : type==3 ? DCR_DRBE0 : DCR_DRBE0|DCR_DWBE0;
+
__debug_regs->dcr |= tmp;
+ __debug_regs->dbar[0] = addr;
+ __debug_regs->dbmr[0][0] = dbmr.mask0;
+ __debug_regs->dbmr[0][1] = dbmr.mask1;
+ __debug_regs->dbdr[0][0] = 0;
+ __debug_regs->dbdr[0][1] = 0;
+
asm volatile(" movgs %0,dbar0 \n"
" movgs %1,dbmr00 \n"
" movgs %2,dbmr01 \n"
@@ -984,7 +976,14 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign
if (!(__debug_regs->dcr & (DCR_DRBE1|DCR_DWBE1))) {
//gdbstub_printk("set h/w watchpoint 1 type %ld: %08lx\n", type, addr);
tmp = type==2 ? DCR_DWBE1 : type==3 ? DCR_DRBE1 : DCR_DRBE1|DCR_DWBE1;
+
__debug_regs->dcr |= tmp;
+ __debug_regs->dbar[1] = addr;
+ __debug_regs->dbmr[1][0] = dbmr.mask0;
+ __debug_regs->dbmr[1][1] = dbmr.mask1;
+ __debug_regs->dbdr[1][0] = 0;
+ __debug_regs->dbdr[1][1] = 0;
+
asm volatile(" movgs %0,dbar1 \n"
" movgs %1,dbmr10 \n"
" movgs %2,dbmr11 \n"
@@ -1047,6 +1046,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo
if (__debug_regs->dcr & DCR_IBE0 && __get_ibar(0) == addr) {
//gdbstub_printk("clear h/w break 0: %08lx\n", addr);
__debug_regs->dcr &= ~DCR_IBE0;
+ __debug_regs->ibar[0] = 0;
asm volatile("movgs gr0,ibar0");
return 0;
}
@@ -1054,6 +1054,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo
if (__debug_regs->dcr & DCR_IBE1 && __get_ibar(1) == addr) {
//gdbstub_printk("clear h/w break 1: %08lx\n", addr);
__debug_regs->dcr &= ~DCR_IBE1;
+ __debug_regs->ibar[1] = 0;
asm volatile("movgs gr0,ibar1");
return 0;
}
@@ -1061,6 +1062,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo
if (__debug_regs->dcr & DCR_IBE2 && __get_ibar(2) == addr) {
//gdbstub_printk("clear h/w break 2: %08lx\n", addr);
__debug_regs->dcr &= ~DCR_IBE2;
+ __debug_regs->ibar[2] = 0;
asm volatile("movgs gr0,ibar2");
return 0;
}
@@ -1068,6 +1070,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo
if (__debug_regs->dcr & DCR_IBE3 && __get_ibar(3) == addr) {
//gdbstub_printk("clear h/w break 3: %08lx\n", addr);
__debug_regs->dcr &= ~DCR_IBE3;
+ __debug_regs->ibar[3] = 0;
asm volatile("movgs gr0,ibar3");
return 0;
}
@@ -1104,6 +1107,12 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo
//gdbstub_printk("clear h/w watchpoint 0 type %ld: %08lx\n", type, addr);
__debug_regs->dcr &= ~(DCR_DRBE0|DCR_DWBE0);
+ __debug_regs->dbar[0] = 0;
+ __debug_regs->dbmr[0][0] = 0;
+ __debug_regs->dbmr[0][1] = 0;
+ __debug_regs->dbdr[0][0] = 0;
+ __debug_regs->dbdr[0][1] = 0;
+
asm volatile(" movgs gr0,dbar0 \n"
" movgs gr0,dbmr00 \n"
" movgs gr0,dbmr01 \n"
@@ -1123,6 +1132,12 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo
//gdbstub_printk("clear h/w watchpoint 1 type %ld: %08lx\n", type, addr);
__debug_regs->dcr &= ~(DCR_DRBE1|DCR_DWBE1);
+ __debug_regs->dbar[1] = 0;
+ __debug_regs->dbmr[1][0] = 0;
+ __debug_regs->dbmr[1][1] = 0;
+ __debug_regs->dbdr[1][0] = 0;
+ __debug_regs->dbdr[1][1] = 0;
+
asm volatile(" movgs gr0,dbar1 \n"
" movgs gr0,dbmr10 \n"
" movgs gr0,dbmr11 \n"
@@ -1161,9 +1176,9 @@ static void gdbstub_check_breakpoint(void)
/*
*
*/
-static void __attribute__((unused)) gdbstub_show_regs(void)
+static void __maybe_unused gdbstub_show_regs(void)
{
- uint32_t *reg;
+ unsigned long *reg;
int loop;
gdbstub_printk("\n");
@@ -1172,11 +1187,11 @@ static void __attribute__((unused)) gdbstub_show_regs(void)
__debug_frame,
__debug_frame->psr & PSR_S ? "kernel" : "user");
- reg = (uint32_t *) __debug_frame;
- for (loop = 0; loop < REG__END; loop++) {
- printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+ reg = (unsigned long *) __debug_frame;
+ for (loop = 0; loop < NR_PT_REGS; loop++) {
+ printk("%s %08lx", regnames[loop + 0], reg[loop + 0]);
- if (loop == REG__END - 1 || loop % 5 == 4)
+ if (loop == NR_PT_REGS - 1 || loop % 5 == 4)
printk("\n");
else
printk(" | ");
@@ -1189,15 +1204,10 @@ static void __attribute__((unused)) gdbstub_show_regs(void)
/*
* dump debugging regs
*/
-static void __attribute__((unused)) gdbstub_dump_debugregs(void)
+static void __maybe_unused gdbstub_dump_debugregs(void)
{
- unsigned long x;
-
- x = __debug_regs->dcr;
- gdbstub_printk("DCR %08lx ", x);
-
- x = __debug_regs->brr;
- gdbstub_printk("BRR %08lx\n", x);
+ gdbstub_printk("DCR %08lx ", __debug_status.dcr);
+ gdbstub_printk("BRR %08lx\n", __debug_status.brr);
gdbstub_printk("IBAR0 %08lx ", __get_ibar(0));
gdbstub_printk("IBAR1 %08lx ", __get_ibar(1));
@@ -1333,6 +1343,44 @@ void gdbstub_get_mmu_state(void)
} /* end gdbstub_get_mmu_state() */
+/*
+ * handle general query commands of the form 'qXXXXX'
+ */
+static void gdbstub_handle_query(void)
+{
+ if (strcmp(input_buffer, "qAttached") == 0) {
+ /* return current thread ID */
+ sprintf(output_buffer, "1");
+ return;
+ }
+
+ if (strcmp(input_buffer, "qC") == 0) {
+ /* return current thread ID */
+ sprintf(output_buffer, "QC 0");
+ return;
+ }
+
+ if (strcmp(input_buffer, "qOffsets") == 0) {
+ /* return relocation offset of text and data segments */
+ sprintf(output_buffer, "Text=0;Data=0;Bss=0");
+ return;
+ }
+
+ if (strcmp(input_buffer, "qSymbol::") == 0) {
+ sprintf(output_buffer, "OK");
+ return;
+ }
+
+ if (strcmp(input_buffer, "qSupported") == 0) {
+ /* query of supported features */
+ sprintf(output_buffer, "PacketSize=%u;ReverseContinue-;ReverseStep-",
+ sizeof(input_buffer));
+ return;
+ }
+
+ gdbstub_strcpy(output_buffer,"E01");
+}
+
/*****************************************************************************/
/*
* handle event interception and GDB remote protocol processing
@@ -1360,7 +1408,7 @@ void gdbstub(int sigval)
#endif
}
- save_user_regs(&__break_user_context);
+ save_user_regs(&__debug_frame0->uc);
#if 0
gdbstub_printk("--> gdbstub() %08x %p %08x %08x\n",
@@ -1389,8 +1437,8 @@ void gdbstub(int sigval)
__debug_frame->psr &= ~PSR_S;
if (__debug_frame->psr & PSR_PS)
__debug_frame->psr |= PSR_S;
- __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
- __debug_regs->brr |= BRR_EB;
+ __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12;
+ __debug_status.brr |= BRR_EB;
sigval = SIGINT;
}
@@ -1404,15 +1452,15 @@ void gdbstub(int sigval)
__debug_frame->psr &= ~PSR_S;
if (__debug_frame->psr & PSR_PS)
__debug_frame->psr |= PSR_S;
- __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
- __debug_regs->brr |= BRR_EB;
- sigval = SIGXCPU;;
+ __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12;
+ __debug_status.brr |= BRR_EB;
+ sigval = SIGXCPU;
}
LEDS(0x5002);
/* after a BREAK insn, the PC lands on the far side of it */
- if (__debug_regs->brr & BRR_SB)
+ if (__debug_status.brr & BRR_SB)
gdbstub_check_breakpoint();
LEDS(0x5003);
@@ -1431,7 +1479,7 @@ void gdbstub(int sigval)
}
if (!sigval)
- sigval = gdbstub_compute_signal(__debug_regs->brr);
+ sigval = gdbstub_compute_signal(__debug_status.brr);
LEDS(0x5004);
@@ -1441,29 +1489,29 @@ void gdbstub(int sigval)
if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) {
static const char title[] = "Break ";
static const char crlf[] = "\r\n";
- unsigned long brr = __debug_regs->brr;
+ unsigned long brr = __debug_status.brr;
char hx;
ptr = output_buffer;
*ptr++ = 'O';
ptr = mem2hex(title, ptr, sizeof(title) - 1,0);
- hx = hexchars[(brr & 0xf0000000) >> 28];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
- hx = hexchars[(brr & 0x0f000000) >> 24];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
- hx = hexchars[(brr & 0x00f00000) >> 20];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
- hx = hexchars[(brr & 0x000f0000) >> 16];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
- hx = hexchars[(brr & 0x0000f000) >> 12];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
- hx = hexchars[(brr & 0x00000f00) >> 8];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
- hx = hexchars[(brr & 0x000000f0) >> 4];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
- hx = hexchars[(brr & 0x0000000f)];
- *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hex_asc_hi(brr >> 24);
+ ptr = hex_byte_pack(ptr, hx);
+ hx = hex_asc_lo(brr >> 24);
+ ptr = hex_byte_pack(ptr, hx);
+ hx = hex_asc_hi(brr >> 16);
+ ptr = hex_byte_pack(ptr, hx);
+ hx = hex_asc_lo(brr >> 16);
+ ptr = hex_byte_pack(ptr, hx);
+ hx = hex_asc_hi(brr >> 8);
+ ptr = hex_byte_pack(ptr, hx);
+ hx = hex_asc_lo(brr >> 8);
+ ptr = hex_byte_pack(ptr, hx);
+ hx = hex_asc_hi(brr);
+ ptr = hex_byte_pack(ptr, hx);
+ hx = hex_asc_lo(brr);
+ ptr = hex_byte_pack(ptr, hx);
ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
*ptr = 0;
@@ -1477,12 +1525,10 @@ void gdbstub(int sigval)
/* Send trap type (converted to signal) */
*ptr++ = 'T';
- *ptr++ = hexchars[sigval >> 4];
- *ptr++ = hexchars[sigval & 0xf];
+ ptr = hex_byte_pack(ptr, sigval);
/* Send Error PC */
- *ptr++ = hexchars[GDB_REG_PC >> 4];
- *ptr++ = hexchars[GDB_REG_PC & 0xf];
+ ptr = hex_byte_pack(ptr, GDB_REG_PC);
*ptr++ = ':';
ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0);
*ptr++ = ';';
@@ -1490,8 +1536,7 @@ void gdbstub(int sigval)
/*
* Send frame pointer
*/
- *ptr++ = hexchars[GDB_REG_FP >> 4];
- *ptr++ = hexchars[GDB_REG_FP & 0xf];
+ ptr = hex_byte_pack(ptr, GDB_REG_FP);
*ptr++ = ':';
ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0);
*ptr++ = ';';
@@ -1499,8 +1544,7 @@ void gdbstub(int sigval)
/*
* Send stack pointer
*/
- *ptr++ = hexchars[GDB_REG_SP >> 4];
- *ptr++ = hexchars[GDB_REG_SP & 0xf];
+ ptr = hex_byte_pack(ptr, GDB_REG_SP);
*ptr++ = ':';
ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0);
*ptr++ = ';';
@@ -1525,8 +1569,8 @@ void gdbstub(int sigval)
/* request repeat of last signal number */
case '?':
output_buffer[0] = 'S';
- output_buffer[1] = hexchars[sigval >> 4];
- output_buffer[2] = hexchars[sigval & 0xf];
+ output_buffer[1] = hex_asc_hi(sigval);
+ output_buffer[2] = hex_asc_lo(sigval);
output_buffer[3] = 0;
break;
@@ -1565,28 +1609,24 @@ void gdbstub(int sigval)
ptr = mem2hex(&zero, ptr, 4, 0);
for (loop = 1; loop <= 27; loop++)
- ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop),
- ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->i.gr[loop], ptr, 4, 0);
temp = (unsigned long) __frame;
ptr = mem2hex(&temp, ptr, 4, 0);
- ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(29), ptr, 4, 0);
- ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(30), ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->i.gr[29], ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->i.gr[30], ptr, 4, 0);
#ifdef CONFIG_MMU
- ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(31), ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->i.gr[31], ptr, 4, 0);
#else
temp = (unsigned long) __debug_frame;
ptr = mem2hex(&temp, ptr, 4, 0);
#endif
for (loop = 32; loop <= 63; loop++)
- ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop),
- ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->i.gr[loop], ptr, 4, 0);
/* deal with FR0-FR63 */
for (loop = 0; loop <= 63; loop++)
- ptr = mem2hex((unsigned long *)&__break_user_context +
- __FPMEDIA_FR(loop),
- ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->f.fr[loop], ptr, 4, 0);
/* deal with special registers */
ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0);
@@ -1597,7 +1637,7 @@ void gdbstub(int sigval)
ptr = mem2hex(&zero, ptr, 4, 0);
ptr = mem2hex(&zero, ptr, 4, 0);
ptr = mem2hex(&__debug_frame->tbr, ptr, 4, 0);
- ptr = mem2hex(&__debug_regs->brr , ptr, 4, 0);
+ ptr = mem2hex(&__debug_status.brr , ptr, 4, 0);
asm volatile("movsg dbar0,%0" : "=r"(dbar));
ptr = mem2hex(&dbar, ptr, 4, 0);
@@ -1622,21 +1662,21 @@ void gdbstub(int sigval)
ptr = mem2hex(&__debug_frame->iacc0, ptr, 8, 0);
- ptr = mem2hex(&__break_user_context.f.fsr[0], ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->f.fsr[0], ptr, 4, 0);
for (loop = 0; loop <= 7; loop++)
- ptr = mem2hex(&__break_user_context.f.acc[loop], ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->f.acc[loop], ptr, 4, 0);
- ptr = mem2hex(&__break_user_context.f.accg, ptr, 8, 0);
+ ptr = mem2hex(&__debug_user_context->f.accg, ptr, 8, 0);
for (loop = 0; loop <= 1; loop++)
- ptr = mem2hex(&__break_user_context.f.msr[loop], ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->f.msr[loop], ptr, 4, 0);
ptr = mem2hex(&__debug_frame->gner0, ptr, 4, 0);
ptr = mem2hex(&__debug_frame->gner1, ptr, 4, 0);
- ptr = mem2hex(&__break_user_context.f.fner[0], ptr, 4, 0);
- ptr = mem2hex(&__break_user_context.f.fner[1], ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->f.fner[0], ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->f.fner[1], ptr, 4, 0);
break;
@@ -1648,8 +1688,7 @@ void gdbstub(int sigval)
ptr = hex2mem(ptr, &temp, 4);
for (loop = 1; loop <= 27; loop++)
- ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop),
- 4);
+ ptr = hex2mem(ptr, &__debug_user_context->i.gr[loop], 4);
ptr = hex2mem(ptr, &temp, 4);
__frame = (struct pt_regs *) temp;
@@ -1662,14 +1701,11 @@ void gdbstub(int sigval)
#endif
for (loop = 32; loop <= 63; loop++)
- ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop),
- 4);
+ ptr = hex2mem(ptr, &__debug_user_context->i.gr[loop], 4);
/* deal with FR0-FR63 */
for (loop = 0; loop <= 63; loop++)
- ptr = mem2hex((unsigned long *)&__break_user_context +
- __FPMEDIA_FR(loop),
- ptr, 4, 0);
+ ptr = mem2hex(&__debug_user_context->f.fr[loop], ptr, 4, 0);
/* deal with special registers */
ptr = hex2mem(ptr, &__debug_frame->pc, 4);
@@ -1694,21 +1730,21 @@ void gdbstub(int sigval)
ptr = hex2mem(ptr, &__debug_frame->iacc0, 8);
- ptr = hex2mem(ptr, &__break_user_context.f.fsr[0], 4);
+ ptr = hex2mem(ptr, &__debug_user_context->f.fsr[0], 4);
for (loop = 0; loop <= 7; loop++)
- ptr = hex2mem(ptr, &__break_user_context.f.acc[loop], 4);
+ ptr = hex2mem(ptr, &__debug_user_context->f.acc[loop], 4);
- ptr = hex2mem(ptr, &__break_user_context.f.accg, 8);
+ ptr = hex2mem(ptr, &__debug_user_context->f.accg, 8);
for (loop = 0; loop <= 1; loop++)
- ptr = hex2mem(ptr, &__break_user_context.f.msr[loop], 4);
+ ptr = hex2mem(ptr, &__debug_user_context->f.msr[loop], 4);
ptr = hex2mem(ptr, &__debug_frame->gner0, 4);
ptr = hex2mem(ptr, &__debug_frame->gner1, 4);
- ptr = hex2mem(ptr, &__break_user_context.f.fner[0], 4);
- ptr = hex2mem(ptr, &__break_user_context.f.fner[1], 4);
+ ptr = hex2mem(ptr, &__debug_user_context->f.fner[0], 4);
+ ptr = hex2mem(ptr, &__debug_user_context->f.fner[1], 4);
gdbstub_strcpy(output_buffer,"OK");
break;
@@ -1752,6 +1788,12 @@ void gdbstub(int sigval)
flush_cache = 1;
break;
+ /* pNN: Read value of reg N and return it */
+ case 'p':
+ /* return no value, indicating that we don't support
+ * this command and that gdb should use 'g' instead */
+ break;
+
/* PNN,=RRRRRRRR: Write value R to reg N return OK */
case 'P':
ptr = &input_buffer[1];
@@ -1769,52 +1811,52 @@ void gdbstub(int sigval)
case GDB_REG_GR(0):
break;
case GDB_REG_GR(1) ... GDB_REG_GR(63):
- __break_user_context.i.gr[addr - GDB_REG_GR(0)] = temp;
+ __debug_user_context->i.gr[addr - GDB_REG_GR(0)] = temp;
break;
case GDB_REG_FR(0) ... GDB_REG_FR(63):
- __break_user_context.f.fr[addr - GDB_REG_FR(0)] = temp;
+ __debug_user_context->f.fr[addr - GDB_REG_FR(0)] = temp;
break;
case GDB_REG_PC:
- __break_user_context.i.pc = temp;
+ __debug_user_context->i.pc = temp;
break;
case GDB_REG_PSR:
- __break_user_context.i.psr = temp;
+ __debug_user_context->i.psr = temp;
break;
case GDB_REG_CCR:
- __break_user_context.i.ccr = temp;
+ __debug_user_context->i.ccr = temp;
break;
case GDB_REG_CCCR:
- __break_user_context.i.cccr = temp;
+ __debug_user_context->i.cccr = temp;
break;
case GDB_REG_BRR:
- __debug_regs->brr = temp;
+ __debug_status.brr = temp;
break;
case GDB_REG_LR:
- __break_user_context.i.lr = temp;
+ __debug_user_context->i.lr = temp;
break;
case GDB_REG_LCR:
- __break_user_context.i.lcr = temp;
+ __debug_user_context->i.lcr = temp;
break;
case GDB_REG_FSR0:
- __break_user_context.f.fsr[0] = temp;
+ __debug_user_context->f.fsr[0] = temp;
break;
case GDB_REG_ACC(0) ... GDB_REG_ACC(7):
- __break_user_context.f.acc[addr - GDB_REG_ACC(0)] = temp;
+ __debug_user_context->f.acc[addr - GDB_REG_ACC(0)] = temp;
break;
case GDB_REG_ACCG(0):
- *(uint32_t *) &__break_user_context.f.accg[0] = temp;
+ *(uint32_t *) &__debug_user_context->f.accg[0] = temp;
break;
case GDB_REG_ACCG(4):
- *(uint32_t *) &__break_user_context.f.accg[4] = temp;
+ *(uint32_t *) &__debug_user_context->f.accg[4] = temp;
break;
case GDB_REG_MSR(0) ... GDB_REG_MSR(1):
- __break_user_context.f.msr[addr - GDB_REG_MSR(0)] = temp;
+ __debug_user_context->f.msr[addr - GDB_REG_MSR(0)] = temp;
break;
case GDB_REG_GNER(0) ... GDB_REG_GNER(1):
- __break_user_context.i.gner[addr - GDB_REG_GNER(0)] = temp;
+ __debug_user_context->i.gner[addr - GDB_REG_GNER(0)] = temp;
break;
case GDB_REG_FNER(0) ... GDB_REG_FNER(1):
- __break_user_context.f.fner[addr - GDB_REG_FNER(0)] = temp;
+ __debug_user_context->f.fner[addr - GDB_REG_FNER(0)] = temp;
break;
default:
temp2 = 0;
@@ -1841,6 +1883,10 @@ void gdbstub(int sigval)
case 'k' :
goto done; /* just continue */
+ /* detach */
+ case 'D':
+ gdbstub_strcpy(output_buffer, "OK");
+ break;
/* reset the whole machine (FIXME: system dependent) */
case 'r':
@@ -1850,8 +1896,17 @@ void gdbstub(int sigval)
/* step to next instruction */
case 's':
__debug_regs->dcr |= DCR_SE;
+ __debug_status.dcr |= DCR_SE;
goto done;
+ /* extended command */
+ case 'v':
+ if (strcmp(input_buffer, "vCont?") == 0) {
+ output_buffer[0] = 0;
+ break;
+ }
+ goto unsupported_cmd;
+
/* set baud rate (bBB) */
case 'b':
ptr = &input_buffer[1];
@@ -1923,8 +1978,19 @@ void gdbstub(int sigval)
gdbstub_strcpy(output_buffer,"OK");
break;
+ /* Thread-setting packet */
+ case 'H':
+ gdbstub_strcpy(output_buffer, "OK");
+ break;
+
+ case 'q':
+ gdbstub_handle_query();
+ break;
+
default:
+ unsupported_cmd:
gdbstub_proto("### GDB Unsupported Cmd '%s'\n",input_buffer);
+ gdbstub_strcpy(output_buffer,"E01");
break;
}
@@ -1934,7 +2000,7 @@ void gdbstub(int sigval)
}
done:
- restore_user_regs(&__break_user_context);
+ restore_user_regs(&__debug_frame0->uc);
//gdbstub_dump_debugregs();
//gdbstub_printk("<-- gdbstub() %08x\n", __debug_frame->pc);
@@ -1966,7 +2032,6 @@ void __init gdbstub_init(void)
#endif
gdbstub_printk("%s", gdbstub_banner);
- gdbstub_printk("DCR: %x\n", __debug_regs->dcr);
gdbstub_io_init();
@@ -2000,7 +2065,7 @@ void __init gdbstub_init(void)
ptr = mem2hex(gdbstub_banner, ptr, sizeof(gdbstub_banner) - 1, 0);
gdbstub_send_packet(output_buffer);
#endif
-#if defined(CONFIG_GDBSTUB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined(CONFIG_GDB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
register_console(&gdbstub_console);
#endif
@@ -2010,7 +2075,7 @@ void __init gdbstub_init(void)
/*
* register the console at a more appropriate time
*/
-#if defined (CONFIG_GDBSTUB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined (CONFIG_GDB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
static int __init gdbstub_postinit(void)
{
printk("registering console\n");
@@ -2044,8 +2109,8 @@ void gdbstub_exit(int status)
}
gdbstub_tx_char('#');
- gdbstub_tx_char(hexchars[checksum >> 4]);
- gdbstub_tx_char(hexchars[checksum & 0xf]);
+ gdbstub_tx_char(hex_asc_hi(checksum));
+ gdbstub_tx_char(hex_asc_lo(checksum));
/* make sure the output is flushed, or else RedBoot might clobber it */
gdbstub_tx_char('-');
@@ -2058,25 +2123,25 @@ void gdbstub_exit(int status)
* GDB wants to call malloc() and free() to allocate memory for calling kernel
* functions directly from its command line
*/
-static void *malloc(size_t size) __attribute__((unused));
+static void *malloc(size_t size) __maybe_unused;
static void *malloc(size_t size)
{
return kmalloc(size, GFP_ATOMIC);
}
-static void free(void *p) __attribute__((unused));
+static void free(void *p) __maybe_unused;
static void free(void *p)
{
kfree(p);
}
-static uint32_t ___get_HSR0(void) __attribute__((unused));
+static uint32_t ___get_HSR0(void) __maybe_unused;
static uint32_t ___get_HSR0(void)
{
return __get_HSR(0);
}
-static uint32_t ___set_HSR0(uint32_t x) __attribute__((unused));
+static uint32_t ___set_HSR0(uint32_t x) __maybe_unused;
static uint32_t ___set_HSR0(uint32_t x)
{
__set_HSR(0, x);
diff --git a/arch/frv/kernel/head-mmu-fr451.S b/arch/frv/kernel/head-mmu-fr451.S
index a143c2f66ee..98f87d586e5 100644
--- a/arch/frv/kernel/head-mmu-fr451.S
+++ b/arch/frv/kernel/head-mmu-fr451.S
@@ -9,7 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -32,7 +32,7 @@
#define __400_LCR 0xfe000100
#define __400_LSBR 0xfe000c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head-uc-fr401.S b/arch/frv/kernel/head-uc-fr401.S
index 4ccf8414ae4..438643cfa38 100644
--- a/arch/frv/kernel/head-uc-fr401.S
+++ b/arch/frv/kernel/head-uc-fr401.S
@@ -9,7 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -31,7 +31,7 @@
#define __400_LCR 0xfe000100
#define __400_LSBR 0xfe000c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head-uc-fr451.S b/arch/frv/kernel/head-uc-fr451.S
index 31cb54a6f08..b2a76c4a178 100644
--- a/arch/frv/kernel/head-uc-fr451.S
+++ b/arch/frv/kernel/head-uc-fr451.S
@@ -9,7 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -31,7 +31,7 @@
#define __400_LCR 0xfe000100
#define __400_LSBR 0xfe000c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head-uc-fr555.S b/arch/frv/kernel/head-uc-fr555.S
index d088db2699b..5497aaf34f7 100644
--- a/arch/frv/kernel/head-uc-fr555.S
+++ b/arch/frv/kernel/head-uc-fr555.S
@@ -9,7 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -30,7 +30,7 @@
#define __551_LCR 0xfeff1100
#define __551_LSBR 0xfeff1c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head.S b/arch/frv/kernel/head.S
index c73b4fe9f6c..a7d0bea9c03 100644
--- a/arch/frv/kernel/head.S
+++ b/arch/frv/kernel/head.S
@@ -9,9 +9,10 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
+#include <asm/thread_info.h>
#include <asm/ptrace.h>
#include <asm/page.h>
#include <asm/spr-regs.h>
@@ -27,7 +28,7 @@
# command line string
#
###############################################################################
- .section .text.head,"ax"
+ __HEAD
.balign 4
.globl _boot, __head_reference
@@ -478,11 +479,6 @@ __head_mmu_enabled:
LEDS 0x000c
- # initialise the processor and the peripherals
- #call SYMBOL_NAME(processor_init)
- #call SYMBOL_NAME(unit_init)
- #LEDS 0x0aff
-
sethi.p #0xe5e5,gr3
setlo #0xe5e5,gr3
or.p gr3,gr0,gr4
@@ -513,6 +509,9 @@ __head_mmu_enabled:
movgs gr0,ccr
movgs gr0,cccr
+ # initialise the virtual interrupt handling
+ subcc gr0,gr0,gr0,icc2 /* set Z, clear C */
+
#ifdef CONFIG_MMU
movgs gr3,scr2
movgs gr3,scr3
@@ -538,7 +537,7 @@ __head_end:
.size _boot, .-_boot
# provide a point for GDB to place a break
- .section .text.start,"ax"
+ .section .text..start,"ax"
.globl _start
.balign 4
_start:
diff --git a/arch/frv/kernel/head.inc b/arch/frv/kernel/head.inc
index d424cd2eb21..bff66628b99 100644
--- a/arch/frv/kernel/head.inc
+++ b/arch/frv/kernel/head.inc
@@ -46,5 +46,5 @@
#ifdef CONFIG_MMU
__sdram_base = 0x00000000 /* base address to which SDRAM relocated */
#else
-__sdram_base = 0xc0000000 /* base address to which SDRAM relocated */
+__sdram_base = __page_offset /* base address to which SDRAM relocated */
#endif
diff --git a/arch/frv/kernel/init_task.c b/arch/frv/kernel/init_task.c
deleted file mode 100644
index 22993932b3f..00000000000
--- a/arch/frv/kernel/init_task.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-
-static struct fs_struct init_fs = INIT_FS;
-static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union
- __attribute__((__section__(".data.init_task"))) =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c
index 9778e0ff7c1..2cc327a1ca4 100644
--- a/arch/frv/kernel/irq-mb93091.c
+++ b/arch/frv/kernel/irq-mb93091.c
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -18,14 +17,12 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
@@ -34,83 +31,127 @@
#define __get_IFR() ({ __reg16(0xffc0000c); })
#define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0)
-static void frv_fpga_doirq(struct irq_source *source);
-static void frv_fpga_control(struct irq_group *group, int irq, int on);
-/*****************************************************************************/
/*
- * FPGA IRQ multiplexor
+ * on-motherboard FPGA PIC operations
*/
-static struct irq_source frv_fpga[4] = {
-#define __FPGA(X, M) \
- [X] = { \
- .muxname = "fpga."#X, \
- .irqmask = M, \
- .doirq = frv_fpga_doirq, \
- }
+static void frv_fpga_mask(struct irq_data *d)
+{
+ uint16_t imr = __get_IMR();
- __FPGA(0, 0x0028),
- __FPGA(1, 0x0050),
- __FPGA(2, 0x1c00),
- __FPGA(3, 0x6386),
-};
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
-static struct irq_group frv_fpga_irqs = {
- .first_irq = IRQ_BASE_FPGA,
- .control = frv_fpga_control,
- .sources = {
- [ 1] = &frv_fpga[3],
- [ 2] = &frv_fpga[3],
- [ 3] = &frv_fpga[0],
- [ 4] = &frv_fpga[1],
- [ 5] = &frv_fpga[0],
- [ 6] = &frv_fpga[1],
- [ 7] = &frv_fpga[3],
- [ 8] = &frv_fpga[3],
- [ 9] = &frv_fpga[3],
- [10] = &frv_fpga[2],
- [11] = &frv_fpga[2],
- [12] = &frv_fpga[2],
- [13] = &frv_fpga[3],
- [14] = &frv_fpga[3],
- },
-};
+ __set_IMR(imr);
+}
+static void frv_fpga_ack(struct irq_data *d)
+{
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
+}
-static void frv_fpga_control(struct irq_group *group, int index, int on)
+static void frv_fpga_mask_ack(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- if (on)
- imr &= ~(1 << index);
- else
- imr |= 1 << index;
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
+ __set_IMR(imr);
+
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
+}
+
+static void frv_fpga_unmask(struct irq_data *d)
+{
+ uint16_t imr = __get_IMR();
+
+ imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
__set_IMR(imr);
}
-static void frv_fpga_doirq(struct irq_source *source)
+static struct irq_chip frv_fpga_pic = {
+ .name = "mb93091",
+ .irq_ack = frv_fpga_ack,
+ .irq_mask = frv_fpga_mask,
+ .irq_mask_ack = frv_fpga_mask_ack,
+ .irq_unmask = frv_fpga_unmask,
+};
+
+/*
+ * FPGA PIC interrupt handler
+ */
+static irqreturn_t fpga_interrupt(int irq, void *_mask)
{
- uint16_t mask, imr;
+ uint16_t imr, mask = (unsigned long) _mask;
imr = __get_IMR();
- mask = source->irqmask & ~imr & __get_IFR();
- if (mask) {
- __set_IMR(imr | mask);
- __clr_IFR(mask);
- distribute_irqs(&frv_fpga_irqs, mask);
- __set_IMR(imr);
+ mask = mask & ~imr & __get_IFR();
+
+ /* poll all the triggered IRQs */
+ while (mask) {
+ int irq;
+
+ asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
+ irq = 31 - irq;
+ mask &= ~(1 << irq);
+
+ generic_handle_irq(IRQ_BASE_FPGA + irq);
}
+
+ return IRQ_HANDLED;
}
+/*
+ * define an interrupt action for each FPGA PIC output
+ * - use dev_id to indicate the FPGA PIC input to output mappings
+ */
+static struct irqaction fpga_irq[4] = {
+ [0] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .name = "fpga.0",
+ .dev_id = (void *) 0x0028UL,
+ },
+ [1] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .name = "fpga.1",
+ .dev_id = (void *) 0x0050UL,
+ },
+ [2] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .name = "fpga.2",
+ .dev_id = (void *) 0x1c00UL,
+ },
+ [3] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .name = "fpga.3",
+ .dev_id = (void *) 0x6386UL,
+ }
+};
+
+/*
+ * initialise the motherboard FPGA's PIC
+ */
void __init fpga_init(void)
{
+ int irq;
+
+ /* all PIC inputs are all set to be low-level driven, apart from the
+ * NMI button (15) which is fixed at falling-edge
+ */
__set_IMR(0x7ffe);
__clr_IFR(0x0000);
- frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0);
- frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1);
- frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2);
- frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3);
- frv_irq_set_group(&frv_fpga_irqs);
+ for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
+ irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
+
+ irq_set_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
+
+ /* the FPGA drives the first four external IRQ inputs on the CPU PIC */
+ setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
+ setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]);
+ setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]);
+ setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]);
}
diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c
index 21ca2b29824..95e4eb4f1f3 100644
--- a/arch/frv/kernel/irq-mb93093.c
+++ b/arch/frv/kernel/irq-mb93093.c
@@ -1,6 +1,6 @@
/* irq-mb93093.c: MB93093 FPGA interrupt handling
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -18,14 +17,12 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))
@@ -34,66 +31,100 @@
#define __get_IFR() ({ __reg16(0x02); })
#define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0)
-static void frv_fpga_doirq(struct irq_source *source);
-static void frv_fpga_control(struct irq_group *group, int irq, int on);
-
-/*****************************************************************************/
/*
- * FPGA IRQ multiplexor
+ * off-CPU FPGA PIC operations
*/
-static struct irq_source frv_fpga[4] = {
-#define __FPGA(X, M) \
- [X] = { \
- .muxname = "fpga."#X, \
- .irqmask = M, \
- .doirq = frv_fpga_doirq, \
- }
+static void frv_fpga_mask(struct irq_data *d)
+{
+ uint16_t imr = __get_IMR();
- __FPGA(0, 0x0700),
-};
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
+ __set_IMR(imr);
+}
-static struct irq_group frv_fpga_irqs = {
- .first_irq = IRQ_BASE_FPGA,
- .control = frv_fpga_control,
- .sources = {
- [ 8] = &frv_fpga[0],
- [ 9] = &frv_fpga[0],
- [10] = &frv_fpga[0],
- },
-};
+static void frv_fpga_ack(struct irq_data *d)
+{
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
+}
+
+static void frv_fpga_mask_ack(struct irq_data *d)
+{
+ uint16_t imr = __get_IMR();
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
+ __set_IMR(imr);
+
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
+}
-static void frv_fpga_control(struct irq_group *group, int index, int on)
+static void frv_fpga_unmask(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- if (on)
- imr &= ~(1 << index);
- else
- imr |= 1 << index;
+ imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
__set_IMR(imr);
}
-static void frv_fpga_doirq(struct irq_source *source)
+static struct irq_chip frv_fpga_pic = {
+ .name = "mb93093",
+ .irq_ack = frv_fpga_ack,
+ .irq_mask = frv_fpga_mask,
+ .irq_mask_ack = frv_fpga_mask_ack,
+ .irq_unmask = frv_fpga_unmask,
+};
+
+/*
+ * FPGA PIC interrupt handler
+ */
+static irqreturn_t fpga_interrupt(int irq, void *_mask)
{
- uint16_t mask, imr;
+ uint16_t imr, mask = (unsigned long) _mask;
imr = __get_IMR();
- mask = source->irqmask & ~imr & __get_IFR();
- if (mask) {
- __set_IMR(imr | mask);
- __clr_IFR(mask);
- distribute_irqs(&frv_fpga_irqs, mask);
- __set_IMR(imr);
+ mask = mask & ~imr & __get_IFR();
+
+ /* poll all the triggered IRQs */
+ while (mask) {
+ int irq;
+
+ asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
+ irq = 31 - irq;
+ mask &= ~(1 << irq);
+
+ generic_handle_irq(IRQ_BASE_FPGA + irq);
}
+
+ return IRQ_HANDLED;
}
+/*
+ * define an interrupt action for each FPGA PIC output
+ * - use dev_id to indicate the FPGA PIC input to output mappings
+ */
+static struct irqaction fpga_irq[1] = {
+ [0] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED,
+ .name = "fpga.0",
+ .dev_id = (void *) 0x0700UL,
+ }
+};
+
+/*
+ * initialise the motherboard FPGA's PIC
+ */
void __init fpga_init(void)
{
+ int irq;
+
+ /* all PIC inputs are all set to be edge triggered */
__set_IMR(0x0700);
__clr_IFR(0x0000);
- frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2);
- frv_irq_set_group(&frv_fpga_irqs);
+ for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
+ irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
+
+ /* the FPGA drives external IRQ input #2 on the CPU PIC */
+ setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
}
diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c
index c003ae5e2b3..ba648da0932 100644
--- a/arch/frv/kernel/irq-mb93493.c
+++ b/arch/frv/kernel/irq-mb93493.c
@@ -1,6 +1,6 @@
/* irq-mb93493.c: MB93493 companion chip interrupt handler
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -18,91 +17,131 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#include <asm/mb93493-irqs.h>
+#include <asm/mb93493-regs.h>
-static void frv_mb93493_doirq(struct irq_source *source);
+#define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493))
+
+#define IRQ_ROUTING \
+ (IRQ_ROUTE_ONE(IRQ_MB93493_VDC) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_VCC) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_USB) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_GPIO) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN))
-/*****************************************************************************/
/*
- * MB93493 companion chip IRQ multiplexor
+ * daughter board PIC operations
+ * - there is no way to ACK interrupts in the MB93493 chip
*/
-static struct irq_source frv_mb93493[2] = {
- [0] = {
- .muxname = "mb93493.0",
- .muxdata = __region_CS3 + 0x3d0,
- .doirq = frv_mb93493_doirq,
- .irqmask = 0x0000,
- },
- [1] = {
- .muxname = "mb93493.1",
- .muxdata = __region_CS3 + 0x3d4,
- .doirq = frv_mb93493_doirq,
- .irqmask = 0x0000,
- },
-};
-
-static void frv_mb93493_control(struct irq_group *group, int index, int on)
+static void frv_mb93493_mask(struct irq_data *d)
{
- struct irq_source *source;
uint32_t iqsr;
+ volatile void *piqsr;
- if ((frv_mb93493[0].irqmask & (1 << index)))
- source = &frv_mb93493[0];
+ if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
+ piqsr = __addr_MB93493_IQSR(1);
else
- source = &frv_mb93493[1];
+ piqsr = __addr_MB93493_IQSR(0);
+
+ iqsr = readl(piqsr);
+ iqsr &= ~(1 << (d->irq - IRQ_BASE_MB93493 + 16));
+ writel(iqsr, piqsr);
+}
- iqsr = readl(source->muxdata);
- if (on)
- iqsr |= 1 << (index + 16);
+static void frv_mb93493_ack(struct irq_data *d)
+{
+}
+
+static void frv_mb93493_unmask(struct irq_data *d)
+{
+ uint32_t iqsr;
+ volatile void *piqsr;
+
+ if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
+ piqsr = __addr_MB93493_IQSR(1);
else
- iqsr &= ~(1 << (index + 16));
+ piqsr = __addr_MB93493_IQSR(0);
- writel(iqsr, source->muxdata);
+ iqsr = readl(piqsr);
+ iqsr |= 1 << (d->irq - IRQ_BASE_MB93493 + 16);
+ writel(iqsr, piqsr);
}
-static struct irq_group frv_mb93493_irqs = {
- .first_irq = IRQ_BASE_MB93493,
- .control = frv_mb93493_control,
+static struct irq_chip frv_mb93493_pic = {
+ .name = "mb93093",
+ .irq_ack = frv_mb93493_ack,
+ .irq_mask = frv_mb93493_mask,
+ .irq_mask_ack = frv_mb93493_mask,
+ .irq_unmask = frv_mb93493_unmask,
};
-static void frv_mb93493_doirq(struct irq_source *source)
+/*
+ * MB93493 PIC interrupt handler
+ */
+static irqreturn_t mb93493_interrupt(int irq, void *_piqsr)
{
- uint32_t mask = readl(source->muxdata);
- mask = mask & (mask >> 16) & 0xffff;
+ volatile void *piqsr = _piqsr;
+ uint32_t iqsr;
- if (mask)
- distribute_irqs(&frv_mb93493_irqs, mask);
-}
+ iqsr = readl(piqsr);
+ iqsr = iqsr & (iqsr >> 16) & 0xffff;
-static void __init mb93493_irq_route(int irq, int source)
-{
- frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493);
- frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source];
+ /* poll all the triggered IRQs */
+ while (iqsr) {
+ int irq;
+
+ asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr));
+ irq = 31 - irq;
+ iqsr &= ~(1 << irq);
+
+ generic_handle_irq(IRQ_BASE_MB93493 + irq);
+ }
+
+ return IRQ_HANDLED;
}
-void __init route_mb93493_irqs(void)
+/*
+ * define an interrupt action for each MB93493 PIC output
+ * - use dev_id to indicate the MB93493 PIC input to output mappings
+ */
+static struct irqaction mb93493_irq[2] = {
+ [0] = {
+ .handler = mb93493_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .name = "mb93493.0",
+ .dev_id = (void *) __addr_MB93493_IQSR(0),
+ },
+ [1] = {
+ .handler = mb93493_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .name = "mb93493.1",
+ .dev_id = (void *) __addr_MB93493_IQSR(1),
+ }
+};
+
+/*
+ * initialise the motherboard MB93493's PIC
+ */
+void __init mb93493_init(void)
{
- frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0);
- frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1);
-
- frv_irq_set_group(&frv_mb93493_irqs);
-
- mb93493_irq_route(IRQ_MB93493_VDC, IRQ_MB93493_VDC_ROUTE);
- mb93493_irq_route(IRQ_MB93493_VCC, IRQ_MB93493_VCC_ROUTE);
- mb93493_irq_route(IRQ_MB93493_AUDIO_IN, IRQ_MB93493_AUDIO_IN_ROUTE);
- mb93493_irq_route(IRQ_MB93493_I2C_0, IRQ_MB93493_I2C_0_ROUTE);
- mb93493_irq_route(IRQ_MB93493_I2C_1, IRQ_MB93493_I2C_1_ROUTE);
- mb93493_irq_route(IRQ_MB93493_USB, IRQ_MB93493_USB_ROUTE);
- mb93493_irq_route(IRQ_MB93493_LOCAL_BUS, IRQ_MB93493_LOCAL_BUS_ROUTE);
- mb93493_irq_route(IRQ_MB93493_PCMCIA, IRQ_MB93493_PCMCIA_ROUTE);
- mb93493_irq_route(IRQ_MB93493_GPIO, IRQ_MB93493_GPIO_ROUTE);
- mb93493_irq_route(IRQ_MB93493_AUDIO_OUT, IRQ_MB93493_AUDIO_OUT_ROUTE);
+ int irq;
+
+ for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
+ irq_set_chip_and_handler(irq, &frv_mb93493_pic,
+ handle_edge_irq);
+
+ /* the MB93493 drives external IRQ inputs on the CPU PIC */
+ setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
+ setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]);
}
diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c
deleted file mode 100644
index d4776d1f4e8..00000000000
--- a/arch/frv/kernel/irq-routing.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/* irq-routing.c: IRQ routing
- *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/sched.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/serial_reg.h>
-#include <asm/io.h>
-#include <asm/irq-routing.h>
-#include <asm/irc-regs.h>
-#include <asm/serial-regs.h>
-#include <asm/dma.h>
-
-struct irq_level frv_irq_levels[16] = {
- [0 ... 15] = {
- .lock = SPIN_LOCK_UNLOCKED,
- }
-};
-
-struct irq_group *irq_groups[NR_IRQ_GROUPS];
-
-extern struct irq_group frv_cpu_irqs;
-
-void __init frv_irq_route(struct irq_source *source, int irqlevel)
-{
- source->level = &frv_irq_levels[irqlevel];
- source->next = frv_irq_levels[irqlevel].sources;
- frv_irq_levels[irqlevel].sources = source;
-}
-
-void __init frv_irq_route_external(struct irq_source *source, int irq)
-{
- int irqlevel = 0;
-
- switch (irq) {
- case IRQ_CPU_EXTERNAL0: irqlevel = IRQ_XIRQ0_LEVEL; break;
- case IRQ_CPU_EXTERNAL1: irqlevel = IRQ_XIRQ1_LEVEL; break;
- case IRQ_CPU_EXTERNAL2: irqlevel = IRQ_XIRQ2_LEVEL; break;
- case IRQ_CPU_EXTERNAL3: irqlevel = IRQ_XIRQ3_LEVEL; break;
- case IRQ_CPU_EXTERNAL4: irqlevel = IRQ_XIRQ4_LEVEL; break;
- case IRQ_CPU_EXTERNAL5: irqlevel = IRQ_XIRQ5_LEVEL; break;
- case IRQ_CPU_EXTERNAL6: irqlevel = IRQ_XIRQ6_LEVEL; break;
- case IRQ_CPU_EXTERNAL7: irqlevel = IRQ_XIRQ7_LEVEL; break;
- default: BUG();
- }
-
- source->level = &frv_irq_levels[irqlevel];
- source->next = frv_irq_levels[irqlevel].sources;
- frv_irq_levels[irqlevel].sources = source;
-}
-
-void __init frv_irq_set_group(struct irq_group *group)
-{
- irq_groups[group->first_irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP] = group;
-}
-
-void distribute_irqs(struct irq_group *group, unsigned long irqmask)
-{
- struct irqaction *action;
- int irq;
-
- while (irqmask) {
- asm("scan %1,gr0,%0" : "=r"(irq) : "r"(irqmask));
- if (irq < 0 || irq > 31)
- asm volatile("break");
- irq = 31 - irq;
-
- irqmask &= ~(1 << irq);
- action = group->actions[irq];
-
- irq += group->first_irq;
-
- if (action) {
- int status = 0;
-
-// if (!(action->flags & SA_INTERRUPT))
-// local_irq_enable();
-
- do {
- status |= action->flags;
- action->handler(irq, action->dev_id, __frame);
- action = action->next;
- } while (action);
-
- if (status & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- local_irq_disable();
- }
- }
-}
-
-/*****************************************************************************/
-/*
- * CPU UART interrupts
- */
-static void frv_cpuuart_doirq(struct irq_source *source)
-{
-// uint8_t iir = readb(source->muxdata + UART_IIR * 8);
-// if ((iir & 0x0f) != UART_IIR_NO_INT)
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cpuuart[2] = {
-#define __CPUUART(X, A) \
- [X] = { \
- .muxname = "uart", \
- .muxdata = (volatile void __iomem *) A, \
- .irqmask = 1 << IRQ_CPU_UART##X, \
- .doirq = frv_cpuuart_doirq, \
- }
-
- __CPUUART(0, UART0_BASE),
- __CPUUART(1, UART1_BASE),
-};
-
-/*****************************************************************************/
-/*
- * CPU DMA interrupts
- */
-static void frv_cpudma_doirq(struct irq_source *source)
-{
- uint32_t cstr = readl(source->muxdata + DMAC_CSTRx);
- if (cstr & DMAC_CSTRx_INT)
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cpudma[8] = {
-#define __CPUDMA(X, A) \
- [X] = { \
- .muxname = "dma", \
- .muxdata = (volatile void __iomem *) A, \
- .irqmask = 1 << IRQ_CPU_DMA##X, \
- .doirq = frv_cpudma_doirq, \
- }
-
- __CPUDMA(0, 0xfe000900),
- __CPUDMA(1, 0xfe000980),
- __CPUDMA(2, 0xfe000a00),
- __CPUDMA(3, 0xfe000a80),
- __CPUDMA(4, 0xfe001000),
- __CPUDMA(5, 0xfe001080),
- __CPUDMA(6, 0xfe001100),
- __CPUDMA(7, 0xfe001180),
-};
-
-/*****************************************************************************/
-/*
- * CPU timer interrupts - can't tell whether they've generated an interrupt or not
- */
-static void frv_cputimer_doirq(struct irq_source *source)
-{
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cputimer[3] = {
-#define __CPUTIMER(X) \
- [X] = { \
- .muxname = "timer", \
- .muxdata = 0, \
- .irqmask = 1 << IRQ_CPU_TIMER##X, \
- .doirq = frv_cputimer_doirq, \
- }
-
- __CPUTIMER(0),
- __CPUTIMER(1),
- __CPUTIMER(2),
-};
-
-/*****************************************************************************/
-/*
- * external CPU interrupts - can't tell directly whether they've generated an interrupt or not
- */
-static void frv_cpuexternal_doirq(struct irq_source *source)
-{
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cpuexternal[8] = {
-#define __CPUEXTERNAL(X) \
- [X] = { \
- .muxname = "ext", \
- .muxdata = 0, \
- .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \
- .doirq = frv_cpuexternal_doirq, \
- }
-
- __CPUEXTERNAL(0),
- __CPUEXTERNAL(1),
- __CPUEXTERNAL(2),
- __CPUEXTERNAL(3),
- __CPUEXTERNAL(4),
- __CPUEXTERNAL(5),
- __CPUEXTERNAL(6),
- __CPUEXTERNAL(7),
-};
-
-#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
-
-struct irq_group frv_cpu_irqs = {
- .sources = {
- [IRQ_CPU_UART0] = &frv_cpuuart[0],
- [IRQ_CPU_UART1] = &frv_cpuuart[1],
- [IRQ_CPU_TIMER0] = &frv_cputimer[0],
- [IRQ_CPU_TIMER1] = &frv_cputimer[1],
- [IRQ_CPU_TIMER2] = &frv_cputimer[2],
- [IRQ_CPU_DMA0] = &frv_cpudma[0],
- [IRQ_CPU_DMA1] = &frv_cpudma[1],
- [IRQ_CPU_DMA2] = &frv_cpudma[2],
- [IRQ_CPU_DMA3] = &frv_cpudma[3],
- [IRQ_CPU_DMA4] = &frv_cpudma[4],
- [IRQ_CPU_DMA5] = &frv_cpudma[5],
- [IRQ_CPU_DMA6] = &frv_cpudma[6],
- [IRQ_CPU_DMA7] = &frv_cpudma[7],
- [IRQ_CPU_EXTERNAL0] = &frv_cpuexternal[0],
- [IRQ_CPU_EXTERNAL1] = &frv_cpuexternal[1],
- [IRQ_CPU_EXTERNAL2] = &frv_cpuexternal[2],
- [IRQ_CPU_EXTERNAL3] = &frv_cpuexternal[3],
- [IRQ_CPU_EXTERNAL4] = &frv_cpuexternal[4],
- [IRQ_CPU_EXTERNAL5] = &frv_cpuexternal[5],
- [IRQ_CPU_EXTERNAL6] = &frv_cpuexternal[6],
- [IRQ_CPU_EXTERNAL7] = &frv_cpuexternal[7],
- },
-};
-
-/*****************************************************************************/
-/*
- * route the CPU's interrupt sources
- */
-void __init route_cpu_irqs(void)
-{
- frv_irq_set_group(&frv_cpu_irqs);
-
- __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 IRQ detect levels */
- __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 IRQ detect levels */
-
- /* route UART and error interrupts */
- frv_irq_route(&frv_cpuuart[0], IRQ_UART0_LEVEL);
- frv_irq_route(&frv_cpuuart[1], IRQ_UART1_LEVEL);
-
- set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
-
- /* route DMA channel interrupts */
- frv_irq_route(&frv_cpudma[0], IRQ_DMA0_LEVEL);
- frv_irq_route(&frv_cpudma[1], IRQ_DMA1_LEVEL);
- frv_irq_route(&frv_cpudma[2], IRQ_DMA2_LEVEL);
- frv_irq_route(&frv_cpudma[3], IRQ_DMA3_LEVEL);
- frv_irq_route(&frv_cpudma[4], IRQ_DMA4_LEVEL);
- frv_irq_route(&frv_cpudma[5], IRQ_DMA5_LEVEL);
- frv_irq_route(&frv_cpudma[6], IRQ_DMA6_LEVEL);
- frv_irq_route(&frv_cpudma[7], IRQ_DMA7_LEVEL);
-
- set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, IRQ_DMA0_LEVEL);
- set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, IRQ_DMA4_LEVEL);
-
- /* route timer interrupts */
- frv_irq_route(&frv_cputimer[0], IRQ_TIMER0_LEVEL);
- frv_irq_route(&frv_cputimer[1], IRQ_TIMER1_LEVEL);
- frv_irq_route(&frv_cputimer[2], IRQ_TIMER2_LEVEL);
-
- set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
-
- /* route external interrupts */
- frv_irq_route(&frv_cpuexternal[0], IRQ_XIRQ0_LEVEL);
- frv_irq_route(&frv_cpuexternal[1], IRQ_XIRQ1_LEVEL);
- frv_irq_route(&frv_cpuexternal[2], IRQ_XIRQ2_LEVEL);
- frv_irq_route(&frv_cpuexternal[3], IRQ_XIRQ3_LEVEL);
- frv_irq_route(&frv_cpuexternal[4], IRQ_XIRQ4_LEVEL);
- frv_irq_route(&frv_cpuexternal[5], IRQ_XIRQ5_LEVEL);
- frv_irq_route(&frv_cpuexternal[6], IRQ_XIRQ6_LEVEL);
- frv_irq_route(&frv_cpuexternal[7], IRQ_XIRQ7_LEVEL);
-
- set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, IRQ_XIRQ4_LEVEL);
- set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, IRQ_XIRQ0_LEVEL);
-
-#if defined(CONFIG_MB93091_VDK)
- __set_TM1(0x55550000); /* XIRQ7-0 all active low */
-#elif defined(CONFIG_MB93093_PDK)
- __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
-#else
-#error dont know external IRQ trigger levels for this setup
-#endif
-
-} /* end route_cpu_irqs() */
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 59580c59c62..2239346fa3d 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -1,6 +1,6 @@
/* irq.c: FRV IRQ handling
*
- * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -9,14 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-/*
- * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
- *
- * IRQs are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
- */
-
-#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -24,758 +16,144 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
-#include <linux/slab.h>
#include <linux/random.h>
-#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/irq.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/module.h>
+#include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/smp.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#include <asm/gdb-stub.h>
-extern void __init fpga_init(void);
-extern void __init route_mb93493_irqs(void);
-
-static void register_irq_proc (unsigned int irq);
+#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
-/*
- * Special irq handlers.
- */
+extern void __init fpga_init(void);
+#ifdef CONFIG_FUJITSU_MB93493
+extern void __init mb93493_init(void);
+#endif
-irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_HANDLED; }
+#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
atomic_t irq_err_count;
-/*
- * Generic, controller-independent functions:
- */
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
{
- struct irqaction *action;
- struct irq_group *group;
- unsigned long flags;
- int level, grp, ix, i, j;
-
- i = *(loff_t *) v;
-
- switch (i) {
- case 0:
- seq_printf(p, " ");
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "CPU%d ",j);
-
- seq_putc(p, '\n');
- break;
-
- case 1 ... NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP:
- local_irq_save(flags);
-
- grp = (i - 1) / NR_IRQ_ACTIONS_PER_GROUP;
- group = irq_groups[grp];
- if (!group)
- goto skip;
-
- ix = (i - 1) % NR_IRQ_ACTIONS_PER_GROUP;
- action = group->actions[ix];
- if (!action)
- goto skip;
-
- seq_printf(p, "%3d: ", i - 1);
-
-#ifndef CONFIG_SMP
- seq_printf(p, "%10u ", kstat_irqs(i));
-#else
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]);
-#endif
-
- level = group->sources[ix]->level - frv_irq_levels;
-
- seq_printf(p, " %12s@%x", group->sources[ix]->muxname, level);
- seq_printf(p, " %s", action->name);
-
- for (action = action->next; action; action = action->next)
- seq_printf(p, ", %s", action->name);
-
- seq_putc(p, '\n');
-skip:
- local_irq_restore(flags);
- break;
-
- case NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP + 1:
- seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
- break;
-
- default:
- break;
- }
-
+ seq_printf(p, "%*s: ", prec, "ERR");
+ seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
return 0;
}
-
/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock.
- */
-
-/**
- * disable_irq_nosync - disable an irq without waiting
- * @irq: Interrupt to disable
- *
- * Disable the selected interrupt line. Disables and Enables are
- * nested.
- * Unlike disable_irq(), this function does not ensure existing
- * instances of the IRQ handler have completed before returning.
- *
- * This function may be called from IRQ context.
+ * on-CPU PIC operations
*/
-
-void disable_irq_nosync(unsigned int irq)
+static void frv_cpupic_ack(struct irq_data *d)
{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- unsigned long flags;
- int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[idx];
- if (!source)
- BUG();
-
- level = source->level;
-
- spin_lock_irqsave(&level->lock, flags);
-
- if (group->control) {
- if (!group->disable_cnt[idx]++)
- group->control(group, idx, 0);
- } else if (!level->disable_count++) {
- __set_MASK(level - frv_irq_levels);
- }
-
- spin_unlock_irqrestore(&level->lock, flags);
+ __clr_RC(d->irq);
+ __clr_IRL();
}
-EXPORT_SYMBOL(disable_irq_nosync);
-
-/**
- * disable_irq - disable an irq and wait for completion
- * @irq: Interrupt to disable
- *
- * Disable the selected interrupt line. Enables and Disables are
- * nested.
- * This function waits for any pending IRQ handlers for this interrupt
- * to complete before returning. If you use this function while
- * holding a resource the IRQ handler may need you will deadlock.
- *
- * This function may be called - with care - from IRQ context.
- */
-
-void disable_irq(unsigned int irq)
+static void frv_cpupic_mask(struct irq_data *d)
{
- disable_irq_nosync(irq);
-
-#ifdef CONFIG_SMP
- if (!local_irq_count(smp_processor_id())) {
- do {
- barrier();
- } while (irq_desc[irq].status & IRQ_INPROGRESS);
- }
-#endif
+ __set_MASK(d->irq);
}
-EXPORT_SYMBOL(disable_irq);
-
-/**
- * enable_irq - enable handling of an irq
- * @irq: Interrupt to enable
- *
- * Undoes the effect of one call to disable_irq(). If this
- * matches the last disable, processing of interrupts on this
- * IRQ line is re-enabled.
- *
- * This function may be called from IRQ context.
- */
-
-void enable_irq(unsigned int irq)
+static void frv_cpupic_mask_ack(struct irq_data *d)
{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- unsigned long flags;
- int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
- int count;
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[idx];
- if (!source)
- BUG();
-
- level = source->level;
-
- spin_lock_irqsave(&level->lock, flags);
-
- if (group->control)
- count = group->disable_cnt[idx];
- else
- count = level->disable_count;
-
- switch (count) {
- case 1:
- if (group->control) {
- if (group->actions[idx])
- group->control(group, idx, 1);
- } else {
- if (level->usage)
- __clr_MASK(level - frv_irq_levels);
- }
- /* fall-through */
-
- default:
- count--;
- break;
-
- case 0:
- printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0));
- }
-
- if (group->control)
- group->disable_cnt[idx] = count;
- else
- level->disable_count = count;
+ __set_MASK(d->irq);
+ __clr_RC(d->irq);
+ __clr_IRL();
+}
- spin_unlock_irqrestore(&level->lock, flags);
+static void frv_cpupic_unmask(struct irq_data *d)
+{
+ __clr_MASK(d->irq);
}
-EXPORT_SYMBOL(enable_irq);
+static struct irq_chip frv_cpu_pic = {
+ .name = "cpu",
+ .irq_ack = frv_cpupic_ack,
+ .irq_mask = frv_cpupic_mask,
+ .irq_mask_ack = frv_cpupic_mask_ack,
+ .irq_unmask = frv_cpupic_unmask,
+};
-/*****************************************************************************/
/*
- * handles all normal device IRQ's
+ * handles all normal device IRQs
* - registers are referred to by the __frame variable (GR28)
* - IRQ distribution is complicated in this arch because of the many PICs, the
* way they work and the way they cascade
*/
asmlinkage void do_IRQ(void)
{
- struct irq_source *source;
- int level, cpu;
-
- level = (__frame->tbr >> 4) & 0xf;
- cpu = smp_processor_id();
-
-#if 0
- {
- static u32 irqcount;
- *(volatile u32 *) 0xe1200004 = ~((irqcount++ << 8) | level);
- *(volatile u16 *) 0xffc00100 = (u16) ~0x9999;
- mb();
- }
-#endif
-
- if ((unsigned long) __frame - (unsigned long) (current + 1) < 512)
- BUG();
-
- __set_MASK(level);
- __clr_RC(level);
- __clr_IRL();
-
- kstat_this_cpu.irqs[level]++;
-
irq_enter();
-
- for (source = frv_irq_levels[level].sources; source; source = source->next)
- source->doirq(source);
-
+ generic_handle_irq(__get_IRL());
irq_exit();
+}
- __clr_MASK(level);
-
- /* only process softirqs if we didn't interrupt another interrupt handler */
- if ((__frame->psr & PSR_PIL) == PSR_PIL_0)
- if (local_softirq_pending())
- do_softirq();
-
-#ifdef CONFIG_PREEMPT
- local_irq_disable();
- while (--current->preempt_count == 0) {
- if (!(__frame->psr & PSR_S) ||
- current->need_resched == 0 ||
- in_interrupt())
- break;
- current->preempt_count++;
- local_irq_enable();
- preempt_schedule();
- local_irq_disable();
- }
-#endif
-
-#if 0
- {
- *(volatile u16 *) 0xffc00100 = (u16) ~0x6666;
- mb();
- }
-#endif
-
-} /* end do_IRQ() */
-
-/*****************************************************************************/
/*
* handles all NMIs when not co-opted by the debugger
* - registers are referred to by the __frame variable (GR28)
*/
asmlinkage void do_NMI(void)
{
-} /* end do_NMI() */
-
-/*****************************************************************************/
-/**
- * request_irq - allocate an interrupt line
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs
- * @irqflags: Interrupt type flags
- * @devname: An ascii name for the claiming device
- * @dev_id: A cookie passed back to the handler function
- *
- * This call allocates interrupt resources and enables the
- * interrupt line and IRQ handling. From the point this
- * call is made your handler function may be invoked. Since
- * your handler function must clear any interrupt the board
- * raises, you must take care both to initialise your hardware
- * and to set up the interrupt handler in the right order.
- *
- * Dev_id must be globally unique. Normally the address of the
- * device data structure is used as the cookie. Since the handler
- * receives this value it makes sense to use it.
- *
- * If your interrupt is shared you must pass a non NULL dev_id
- * as this is required when freeing the interrupt.
- *
- * Flags:
- *
- * SA_SHIRQ Interrupt is shared
- *
- * SA_INTERRUPT Disable local interrupts while processing
- *
- * SA_SAMPLE_RANDOM The interrupt can be used for entropy
- *
- */
-
-int request_irq(unsigned int irq,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char * devname,
- void *dev_id)
-{
- int retval;
- struct irqaction *action;
-
-#if 1
- /*
- * Sanity-check: shared interrupts should REALLY pass in
- * a real dev-ID, otherwise we'll have trouble later trying
- * to figure out which interrupt is which (messes up the
- * interrupt freeing logic etc).
- */
- if (irqflags & SA_SHIRQ) {
- if (!dev_id)
- printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n",
- devname, (&irq)[-1]);
- }
-#endif
-
- if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
- return -EINVAL;
- if (!handler)
- return -EINVAL;
-
- action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
-
- action->handler = handler;
- action->flags = irqflags;
- action->mask = CPU_MASK_NONE;
- action->name = devname;
- action->next = NULL;
- action->dev_id = dev_id;
-
- retval = setup_irq(irq, action);
- if (retval)
- kfree(action);
- return retval;
}
-EXPORT_SYMBOL(request_irq);
-
-/**
- * free_irq - free an interrupt
- * @irq: Interrupt line to free
- * @dev_id: Device identity to free
- *
- * Remove an interrupt handler. The handler is removed and if the
- * interrupt line is no longer in use by any driver it is disabled.
- * On a shared IRQ the caller must ensure the interrupt is disabled
- * on the card it drives before calling this function. The function
- * does not return until any executing interrupts for this IRQ
- * have completed.
- *
- * This function may be called from interrupt context.
- *
- * Bugs: Attempting to free an irq in a handler for the same irq hangs
- * the machine.
- */
-
-void free_irq(unsigned int irq, void *dev_id)
-{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- struct irqaction **p, **pp;
- unsigned long flags;
-
- if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
- return;
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
- if (!source)
- BUG();
-
- level = source->level;
- p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
-
- spin_lock_irqsave(&level->lock, flags);
-
- for (pp = p; *pp; pp = &(*pp)->next) {
- struct irqaction *action = *pp;
-
- if (action->dev_id != dev_id)
- continue;
-
- /* found it - remove from the list of entries */
- *pp = action->next;
-
- level->usage--;
-
- if (p == pp && group->control)
- group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 0);
-
- if (level->usage == 0)
- __set_MASK(level - frv_irq_levels);
-
- spin_unlock_irqrestore(&level->lock,flags);
-
-#ifdef CONFIG_SMP
- /* Wait to make sure it's not being used on another CPU */
- while (desc->status & IRQ_INPROGRESS)
- barrier();
-#endif
- kfree(action);
- return;
- }
-}
-
-EXPORT_SYMBOL(free_irq);
-
/*
- * IRQ autodetection code..
- *
- * This depends on the fact that any interrupt that comes in on to an
- * unassigned IRQ will cause GxICR_DETECT to be set
- */
-
-static DECLARE_MUTEX(probe_sem);
-
-/**
- * probe_irq_on - begin an interrupt autodetect
- *
- * Commence probing for an interrupt. The interrupts are scanned
- * and a mask of potential interrupt lines is returned.
- *
- */
-
-unsigned long probe_irq_on(void)
-{
- down(&probe_sem);
- return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-/*
- * Return a mask of triggered interrupts (this
- * can handle only legacy ISA interrupts).
- */
-
-/**
- * probe_irq_mask - scan a bitmap of interrupt lines
- * @val: mask of interrupts to consider
- *
- * Scan the ISA bus interrupt lines and return a bitmap of
- * active interrupts. The interrupt probe logic state is then
- * returned to its previous value.
- *
- * Note: we need to scan all the irq's even though we will
- * only return ISA irq numbers - just so that we reset them
- * all to a known state.
- */
-unsigned int probe_irq_mask(unsigned long xmask)
-{
- up(&probe_sem);
- return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_mask);
-
-/*
- * Return the one interrupt that triggered (this can
- * handle any interrupt source).
- */
-
-/**
- * probe_irq_off - end an interrupt autodetect
- * @xmask: mask of potential interrupts (unused)
- *
- * Scans the unused interrupt lines and returns the line which
- * appears to have triggered the interrupt. If no interrupt was
- * found then zero is returned. If more than one interrupt is
- * found then minus the first candidate is returned to indicate
- * their is doubt.
- *
- * The interrupt probe logic state is returned to its previous
- * value.
- *
- * BUGS: When used in a module (which arguably shouldnt happen)
- * nothing prevents two IRQ probe callers from overlapping. The
- * results of this are non-optimal.
+ * initialise the interrupt system
*/
-
-int probe_irq_off(unsigned long xmask)
-{
- up(&probe_sem);
- return -1;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-/* this was setup_x86_irq but it seems pretty generic */
-int setup_irq(unsigned int irq, struct irqaction *new)
-{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- struct irqaction **p, **pp;
- unsigned long flags;
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
- if (!source)
- BUG();
-
- level = source->level;
-
- p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
-
- /*
- * Some drivers like serial.c use request_irq() heavily,
- * so we have to be careful not to interfere with a
- * running system.
- */
- if (new->flags & SA_SAMPLE_RANDOM) {
- /*
- * This function might sleep, we want to call it first,
- * outside of the atomic block.
- * Yes, this might clear the entropy pool if the wrong
- * driver is attempted to be loaded, without actually
- * installing a new handler, but is this really a problem,
- * only the sysadmin is able to do this.
- */
- rand_initialize_irq(irq);
- }
-
- /* must juggle the interrupt processing stuff with interrupts disabled */
- spin_lock_irqsave(&level->lock, flags);
-
- /* can't share interrupts unless all parties agree to */
- if (level->usage != 0 && !(level->flags & new->flags & SA_SHIRQ)) {
- spin_unlock_irqrestore(&level->lock,flags);
- return -EBUSY;
- }
-
- /* add new interrupt at end of irq queue */
- pp = p;
- while (*pp)
- pp = &(*pp)->next;
-
- *pp = new;
-
- level->usage++;
- level->flags = new->flags;
-
- /* turn the interrupts on */
- if (level->usage == 1)
- __clr_MASK(level - frv_irq_levels);
-
- if (p == pp && group->control)
- group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 1);
-
- spin_unlock_irqrestore(&level->lock, flags);
- register_irq_proc(irq);
- return 0;
-}
-
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NR_IRQS];
-
-#define HEX_DIGITS 8
-
-static unsigned int parse_hex_value (const char *buffer,
- unsigned long count, unsigned long *ret)
-{
- unsigned char hexnum [HEX_DIGITS];
- unsigned long value;
- int i;
-
- if (!count)
- return -EINVAL;
- if (count > HEX_DIGITS)
- count = HEX_DIGITS;
- if (copy_from_user(hexnum, buffer, count))
- return -EFAULT;
-
- /*
- * Parse the first 8 characters as a hex string, any non-hex char
- * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
- */
- value = 0;
-
- for (i = 0; i < count; i++) {
- unsigned int c = hexnum[i];
-
- switch (c) {
- case '0' ... '9': c -= '0'; break;
- case 'a' ... 'f': c -= 'a'-10; break;
- case 'A' ... 'F': c -= 'A'-10; break;
- default:
- goto out;
- }
- value = (value << 4) | c;
- }
-out:
- *ret = value;
- return 0;
-}
-
-
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- unsigned long *mask = (unsigned long *) data;
- if (count < HEX_DIGITS+1)
- return -EINVAL;
- return sprintf (page, "%08lx\n", *mask);
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- unsigned long *mask = (unsigned long *) data, full_count = count, err;
- unsigned long new_value;
-
- show_state();
- err = parse_hex_value(buffer, count, &new_value);
- if (err)
- return err;
-
- *mask = new_value;
- return full_count;
-}
-
-#define MAX_NAMELEN 10
-
-static void register_irq_proc (unsigned int irq)
-{
- char name [MAX_NAMELEN];
-
- if (!root_irq_dir || irq_dir[irq])
- return;
-
- memset(name, 0, MAX_NAMELEN);
- sprintf(name, "%d", irq);
-
- /* create /proc/irq/1234 */
- irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-}
-
-unsigned long prof_cpu_mask = -1;
-
-void init_irq_proc (void)
+void __init init_IRQ(void)
{
- struct proc_dir_entry *entry;
- int i;
-
- /* create /proc/irq */
- root_irq_dir = proc_mkdir("irq", 0);
+ int level;
- /* create /proc/irq/prof_cpu_mask */
- entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
- if (!entry)
- return;
+ for (level = 1; level <= 14; level++)
+ irq_set_chip_and_handler(level, &frv_cpu_pic,
+ handle_level_irq);
- entry->nlink = 1;
- entry->data = (void *)&prof_cpu_mask;
- entry->read_proc = prof_cpu_mask_read_proc;
- entry->write_proc = prof_cpu_mask_write_proc;
+ irq_set_handler(IRQ_CPU_TIMER0, handle_edge_irq);
- /*
- * Create entries for all existing IRQs.
+ /* set the trigger levels for internal interrupt sources
+ * - timers all falling-edge
+ * - ERR0 is rising-edge
+ * - all others are high-level
*/
- for (i = 0; i < NR_IRQS; i++)
- register_irq_proc(i);
-}
+ __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 */
+ __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 */
+
+ /* route internal interrupts */
+ set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL,
+ IRQ_DMA0_LEVEL);
+ set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
+ set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL,
+ IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
+ set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL,
+ IRQ_DMA4_LEVEL);
+
+ /* route external interrupts */
+ set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL,
+ IRQ_XIRQ4_LEVEL);
+ set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL,
+ IRQ_XIRQ0_LEVEL);
+
+#if defined(CONFIG_MB93091_VDK)
+ __set_TM1(0x55550000); /* XIRQ7-0 all active low */
+#elif defined(CONFIG_MB93093_PDK)
+ __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
+#else
+#error dont know external IRQ trigger levels for this setup
+#endif
-/*****************************************************************************/
-/*
- * initialise the interrupt system
- */
-void __init init_IRQ(void)
-{
- route_cpu_irqs();
fpga_init();
#ifdef CONFIG_FUJITSU_MB93493
- route_mb93493_irqs();
+ mb93493_init();
#endif
-} /* end init_IRQ() */
+}
diff --git a/arch/frv/kernel/kernel_thread.S b/arch/frv/kernel/kernel_thread.S
deleted file mode 100644
index 4531c830d20..00000000000
--- a/arch/frv/kernel/kernel_thread.S
+++ /dev/null
@@ -1,77 +0,0 @@
-/* kernel_thread.S: kernel thread creation
- *
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/linkage.h>
-#include <asm/unistd.h>
-
-#define CLONE_VM 0x00000100 /* set if VM shared between processes */
-#define KERN_ERR "<3>"
-
- .section .rodata
-kernel_thread_emsg:
- .asciz KERN_ERR "failed to create kernel thread: error=%d\n"
-
- .text
- .balign 4
-
-###############################################################################
-#
-# Create a kernel thread
-#
-# int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-#
-###############################################################################
- .globl kernel_thread
- .type kernel_thread,@function
-kernel_thread:
- or.p gr8,gr0,gr4
- or gr9,gr0,gr5
-
- # start by forking the current process, but with shared VM
- setlos.p #__NR_clone,gr7 ; syscall number
- ori gr10,#CLONE_VM,gr8 ; first syscall arg [clone_flags]
- sethi.p #0xe4e4,gr9 ; second syscall arg [newsp]
- setlo #0xe4e4,gr9
- setlos.p #0,gr10 ; third syscall arg [parent_tidptr]
- setlos #0,gr11 ; fourth syscall arg [child_tidptr]
- tira gr0,#0
- setlos.p #4095,gr7
- andcc gr8,gr8,gr0,icc0
- addcc.p gr8,gr7,gr0,icc1
- bnelr icc0,#2
- bc icc1,#0,kernel_thread_error
-
- # now invoke the work function
- or gr5,gr0,gr8
- calll @(gr4,gr0)
-
- # and finally exit the thread
- setlos #__NR_exit,gr7 ; syscall number
- tira gr0,#0
-
-kernel_thread_error:
- subi sp,#8,sp
- movsg lr,gr4
- sti gr8,@(sp,#0)
- sti.p gr4,@(sp,#4)
-
- or gr8,gr0,gr9
- sethi.p %hi(kernel_thread_emsg),gr8
- setlo %lo(kernel_thread_emsg),gr8
-
- call printk
-
- ldi @(sp,#4),gr4
- ldi @(sp,#0),gr8
- subi sp,#8,sp
- jmpl @(gr4,gr0)
-
- .size kernel_thread,.-kernel_thread
diff --git a/arch/frv/kernel/local.h b/arch/frv/kernel/local.h
index e9471761d78..76606d13b1a 100644
--- a/arch/frv/kernel/local.h
+++ b/arch/frv/kernel/local.h
@@ -51,6 +51,9 @@ extern void (*__power_switch_wake_cleanup)(void);
/* time.c */
extern void time_divisor_init(void);
+/* cmode.S */
+extern asmlinkage void frv_change_cmode(int);
+
#endif /* __ASSEMBLY__ */
#endif /* _FRV_LOCAL_H */
diff --git a/arch/frv/kernel/local64.h b/arch/frv/kernel/local64.h
new file mode 100644
index 00000000000..36c93b5cc23
--- /dev/null
+++ b/arch/frv/kernel/local64.h
@@ -0,0 +1 @@
+#include <asm-generic/local64.h>
diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c
index 850d168f69f..9d9835f1fe2 100644
--- a/arch/frv/kernel/module.c
+++ b/arch/frv/kernel/module.c
@@ -22,59 +22,6 @@
#define DEBUGP(fmt...)
#endif
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
-
- return vmalloc_exec(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
- /* FIXME: If module_region == mod->init_region, trim exception
- table entries. */
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
- return -ENOEXEC;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
- return -ENOEXEC;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
+/* TODO: At least one of apply_relocate or apply_relocate_add must be
+ * implemented in order to get working module support.
+ */
diff --git a/arch/frv/kernel/pm-mb93093.c b/arch/frv/kernel/pm-mb93093.c
index 34d01d7dcc3..eaa7b582ef5 100644
--- a/arch/frv/kernel/pm-mb93093.c
+++ b/arch/frv/kernel/pm-mb93093.c
@@ -10,7 +10,6 @@
*
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/sched.h>
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index f0b8fff3e73..ac767d94a88 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -11,11 +11,9 @@
*
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
@@ -27,11 +25,6 @@
#include "local.h"
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
-extern void frv_change_cmode(int);
-
/*
* Debug macros
*/
@@ -131,13 +124,12 @@ unsigned long sleep_phys_sp(void *sp)
* Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
* when all the PM interfaces exist nicely.
*/
-#define CTL_PM 9899
#define CTL_PM_SUSPEND 1
#define CTL_PM_CMODE 2
#define CTL_PM_P0 4
#define CTL_PM_CM 5
-static int user_atoi(char *ubuf, size_t len)
+static int user_atoi(char __user *ubuf, size_t len)
{
char buf[16];
unsigned long ret;
@@ -158,29 +150,25 @@ static int user_atoi(char *ubuf, size_t len)
/*
* Send us to sleep.
*/
-static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *fpos)
+static int sysctl_pm_do_suspend(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos)
{
- int retval, mode;
+ int mode;
if (*lenp <= 0)
return -EIO;
mode = user_atoi(buffer, *lenp);
- if ((mode != 1) && (mode != 5))
- return -EINVAL;
+ switch (mode) {
+ case 1:
+ return pm_do_suspend();
- retval = pm_send_all(PM_SUSPEND, (void *)3);
+ case 5:
+ return pm_do_bus_sleep();
- if (retval == 0) {
- if (mode == 5)
- retval = pm_do_bus_sleep();
- else
- retval = pm_do_suspend();
- pm_send_all(PM_RESUME, (void *)0);
+ default:
+ return -EINVAL;
}
-
- return retval;
}
static int try_set_cmode(int new_cmode)
@@ -190,9 +178,6 @@ static int try_set_cmode(int new_cmode)
if (!(clock_cmodes_permitted & (1<<new_cmode)))
return -EINVAL;
- /* tell all the drivers we're suspending */
- pm_send_all(PM_SUSPEND, (void *)3);
-
/* now change cmode */
local_irq_disable();
frv_dma_pause_all();
@@ -208,56 +193,23 @@ static int try_set_cmode(int new_cmode)
frv_dma_resume_all();
local_irq_enable();
- /* tell all the drivers we're resuming */
- pm_send_all(PM_RESUME, (void *)0);
return 0;
}
-static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *fpos)
+static int cmode_procctl(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos)
{
int new_cmode;
if (!write)
- return proc_dointvec(ctl, write, filp, buffer, lenp, fpos);
+ return proc_dointvec(ctl, write, buffer, lenp, fpos);
new_cmode = user_atoi(buffer, *lenp);
return try_set_cmode(new_cmode)?:*lenp;
}
-static int cmode_sysctl(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen, void **context)
-{
- if (oldval && oldlenp) {
- size_t oldlen;
-
- if (get_user(oldlen, oldlenp))
- return -EFAULT;
-
- if (oldlen != sizeof(int))
- return -EINVAL;
-
- if (put_user(clock_cmode_current, (unsigned int *)oldval) ||
- put_user(sizeof(int), oldlenp))
- return -EFAULT;
- }
- if (newval && newlen) {
- int new_cmode;
-
- if (newlen != sizeof(int))
- return -EINVAL;
-
- if (get_user(new_cmode, (int *)newval))
- return -EFAULT;
-
- return try_set_cmode(new_cmode)?:1;
- }
- return 1;
-}
-
static int try_set_p0(int new_p0)
{
unsigned long flags, clkc;
@@ -317,108 +269,73 @@ static int try_set_cm(int new_cm)
return 0;
}
-static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *fpos)
+static int p0_procctl(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos)
{
int new_p0;
if (!write)
- return proc_dointvec(ctl, write, filp, buffer, lenp, fpos);
+ return proc_dointvec(ctl, write, buffer, lenp, fpos);
new_p0 = user_atoi(buffer, *lenp);
return try_set_p0(new_p0)?:*lenp;
}
-static int p0_sysctl(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen, void **context)
-{
- if (oldval && oldlenp) {
- size_t oldlen;
-
- if (get_user(oldlen, oldlenp))
- return -EFAULT;
-
- if (oldlen != sizeof(int))
- return -EINVAL;
-
- if (put_user(clock_p0_current, (unsigned int *)oldval) ||
- put_user(sizeof(int), oldlenp))
- return -EFAULT;
- }
- if (newval && newlen) {
- int new_p0;
-
- if (newlen != sizeof(int))
- return -EINVAL;
-
- if (get_user(new_p0, (int *)newval))
- return -EFAULT;
-
- return try_set_p0(new_p0)?:1;
- }
- return 1;
-}
-
-static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *fpos)
+static int cm_procctl(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos)
{
int new_cm;
if (!write)
- return proc_dointvec(ctl, write, filp, buffer, lenp, fpos);
+ return proc_dointvec(ctl, write, buffer, lenp, fpos);
new_cm = user_atoi(buffer, *lenp);
return try_set_cm(new_cm)?:*lenp;
}
-static int cm_sysctl(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen, void **context)
-{
- if (oldval && oldlenp) {
- size_t oldlen;
-
- if (get_user(oldlen, oldlenp))
- return -EFAULT;
-
- if (oldlen != sizeof(int))
- return -EINVAL;
-
- if (put_user(clock_cm_current, (unsigned int *)oldval) ||
- put_user(sizeof(int), oldlenp))
- return -EFAULT;
- }
- if (newval && newlen) {
- int new_cm;
-
- if (newlen != sizeof(int))
- return -EINVAL;
-
- if (get_user(new_cm, (int *)newval))
- return -EFAULT;
-
- return try_set_cm(new_cm)?:1;
- }
- return 1;
-}
-
-
static struct ctl_table pm_table[] =
{
- {CTL_PM_SUSPEND, "suspend", NULL, 0, 0200, NULL, &sysctl_pm_do_suspend},
- {CTL_PM_CMODE, "cmode", &clock_cmode_current, sizeof(int), 0644, NULL, &cmode_procctl, &cmode_sysctl, NULL},
- {CTL_PM_P0, "p0", &clock_p0_current, sizeof(int), 0644, NULL, &p0_procctl, &p0_sysctl, NULL},
- {CTL_PM_CM, "cm", &clock_cm_current, sizeof(int), 0644, NULL, &cm_procctl, &cm_sysctl, NULL},
- {0}
+ {
+ .procname = "suspend",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0200,
+ .proc_handler = sysctl_pm_do_suspend,
+ },
+ {
+ .procname = "cmode",
+ .data = &clock_cmode_current,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = cmode_procctl,
+ },
+ {
+ .procname = "p0",
+ .data = &clock_p0_current,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = p0_procctl,
+ },
+ {
+ .procname = "cm",
+ .data = &clock_cm_current,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = cm_procctl,
+ },
+ { }
};
static struct ctl_table pm_dir_table[] =
{
- {CTL_PM, "pm", NULL, 0, 0555, pm_table},
- {0}
+ {
+ .procname = "pm",
+ .mode = 0555,
+ .child = pm_table,
+ },
+ { }
};
/*
@@ -426,7 +343,7 @@ static struct ctl_table pm_dir_table[] =
*/
static int __init pm_init(void)
{
- register_sysctl_table(pm_dir_table, 1);
+ register_sysctl_table(pm_dir_table);
return 0;
}
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 0fff8a61ef2..5d40aeb7712 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -10,13 +10,12 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
@@ -25,33 +24,26 @@
#include <linux/elf.h>
#include <linux/reboot.h>
#include <linux/interrupt.h>
+#include <linux/pagemap.h>
+#include <linux/rcupdate.h>
+#include <asm/asm-offsets.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
+#include <asm/tlb.h>
#include <asm/gdb-stub.h>
#include <asm/mb-regs.h>
#include "local.h"
asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
#include <asm/pgalloc.h>
-struct task_struct *alloc_task_struct(void)
-{
- struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL);
- if (p)
- atomic_set((atomic_t *)(p+1), 1);
- return p;
-}
-
-void free_task_struct(struct task_struct *p)
-{
- if (atomic_dec_and_test((atomic_t *)(p+1)))
- kfree(p);
-}
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
static void core_sleep_idle(void)
{
@@ -67,31 +59,12 @@ static void core_sleep_idle(void)
mb();
}
-void (*idle)(void) = core_sleep_idle;
-
-/*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
- */
-void cpu_idle(void)
+void arch_cpu_idle(void)
{
- int cpu = smp_processor_id();
-
- /* endless idle loop with no priority at all */
- while (1) {
- while (!need_resched()) {
- irq_stat[cpu].idle_timestamp = jiffies;
-
- if (!frv_dma_inprogress && idle)
- idle();
- }
-
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
+ if (!frv_dma_inprogress)
+ core_sleep_idle();
+ else
+ local_irq_enable();
}
void machine_restart(char * __unused)
@@ -139,10 +112,7 @@ void machine_power_off(void)
void flush_thread(void)
{
-#if 0 //ndef NO_FPU
- unsigned long zero = 0;
-#endif
- set_fs(USER_DS);
+ /* nothing */
}
inline unsigned long user_stack(const struct pt_regs *regs)
@@ -152,87 +122,40 @@ inline unsigned long user_stack(const struct pt_regs *regs)
return user_mode(regs) ? regs->sp : 0;
}
-asmlinkage int sys_fork(void)
-{
-#ifndef CONFIG_MMU
- /* fork almost works, enough to trick you into looking elsewhere:-( */
- return -EINVAL;
-#else
- return do_fork(SIGCHLD, user_stack(__frame), __frame, 0, NULL, NULL);
-#endif
-}
-
-asmlinkage int sys_vfork(void)
-{
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, user_stack(__frame), __frame, 0,
- NULL, NULL);
-}
-
-/*****************************************************************************/
-/*
- * clone a process
- * - tlsptr is retrieved by copy_thread()
- */
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
- int __user *parent_tidptr, int __user *child_tidptr,
- int __user *tlsptr)
-{
- if (!newsp)
- newsp = user_stack(__frame);
- return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr);
-} /* end sys_clone() */
-
-/*****************************************************************************/
-/*
- * This gets called before we allocate a new thread and copy
- * the current task into it.
- */
-void prepare_to_copy(struct task_struct *tsk)
-{
- //unlazy_fpu(tsk);
-} /* end prepare_to_copy() */
-
-/*****************************************************************************/
/*
* set up the kernel stack and exception frames for a new process
*/
-int copy_thread(int nr, unsigned long clone_flags,
- unsigned long usp, unsigned long topstk,
- struct task_struct *p, struct pt_regs *regs)
+int copy_thread(unsigned long clone_flags,
+ unsigned long usp, unsigned long arg,
+ struct task_struct *p)
{
- struct pt_regs *childregs0, *childregs, *regs0;
+ struct pt_regs *childregs;
- regs0 = __kernel_frame0_ptr;
- childregs0 = (struct pt_regs *)
- (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE);
- childregs = childregs0;
+ childregs = (struct pt_regs *)
+ (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
/* set up the userspace frame (the only place that the USP is stored) */
- *childregs0 = *regs0;
-
- childregs0->gr8 = 0;
- childregs0->sp = usp;
- childregs0->next_frame = NULL;
-
- /* set up the return kernel frame if called from kernel_thread() */
- if (regs != regs0) {
- childregs--;
- *childregs = *regs;
- childregs->sp = (unsigned long) childregs0;
- childregs->next_frame = childregs0;
- childregs->gr15 = (unsigned long) task_thread_info(p);
- childregs->gr29 = (unsigned long) p;
- }
-
- p->set_child_tid = p->clear_child_tid = NULL;
+ *childregs = *current_pt_regs();
p->thread.frame = childregs;
p->thread.curr = p;
p->thread.sp = (unsigned long) childregs;
p->thread.fp = 0;
p->thread.lr = 0;
- p->thread.pc = (unsigned long) ret_from_fork;
- p->thread.frame0 = childregs0;
+ p->thread.frame0 = childregs;
+
+ if (unlikely(p->flags & PF_KTHREAD)) {
+ childregs->gr9 = usp; /* function */
+ childregs->gr8 = arg;
+ p->thread.pc = (unsigned long) ret_from_kernel_thread;
+ save_user_regs(p->thread.user);
+ return 0;
+ }
+ if (usp)
+ childregs->sp = usp;
+ childregs->next_frame = NULL;
+
+ p->thread.pc = (unsigned long) ret_from_fork;
/* the new TLS pointer is passed in as arg #5 to sys_clone() */
if (clone_flags & CLONE_SETTLS)
@@ -243,26 +166,6 @@ int copy_thread(int nr, unsigned long clone_flags,
return 0;
} /* end copy_thread() */
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(char *name, char **argv, char **envp)
-{
- int error;
- char * filename;
-
- lock_kernel();
- filename = getname(name);
- error = PTR_ERR(filename);
- if (IS_ERR(filename))
- goto out;
- error = do_execve(filename, argv, envp, __frame);
- putname(filename);
- out:
- unlock_kernel();
- return error;
-}
-
unsigned long get_wchan(struct task_struct *p)
{
struct pt_regs *regs0;
@@ -368,3 +271,11 @@ int elf_check_arch(const struct elf32_hdr *hdr)
return 1;
}
+
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+{
+ memcpy(fpregs,
+ &current->thread.user->f,
+ sizeof(current->thread.user->f));
+ return 1;
+}
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index f953484e7d5..3987ff88dab 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -14,18 +14,18 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
-#include <linux/config.h>
#include <linux/security.h>
#include <linux/signal.h>
+#include <linux/regset.h>
+#include <linux/elf.h>
+#include <linux/tracehook.h>
#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/processor.h>
#include <asm/unistd.h>
@@ -35,6 +35,169 @@
*/
/*
+ * retrieve the contents of FRV userspace general registers
+ */
+static int genregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ const struct user_int_regs *iregs = &target->thread.user->i;
+ int ret;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ iregs, 0, sizeof(*iregs));
+ if (ret < 0)
+ return ret;
+
+ return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ sizeof(*iregs), -1);
+}
+
+/*
+ * update the contents of the FRV userspace general registers
+ */
+static int genregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct user_int_regs *iregs = &target->thread.user->i;
+ unsigned int offs_gr0, offs_gr1;
+ int ret;
+
+ /* not allowed to set PSR or __status */
+ if (pos < offsetof(struct user_int_regs, psr) + sizeof(long) &&
+ pos + count > offsetof(struct user_int_regs, psr))
+ return -EIO;
+
+ if (pos < offsetof(struct user_int_regs, __status) + sizeof(long) &&
+ pos + count > offsetof(struct user_int_regs, __status))
+ return -EIO;
+
+ /* set the control regs */
+ offs_gr0 = offsetof(struct user_int_regs, gr[0]);
+ offs_gr1 = offsetof(struct user_int_regs, gr[1]);
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ iregs, 0, offs_gr0);
+ if (ret < 0)
+ return ret;
+
+ /* skip GR0/TBR */
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ offs_gr0, offs_gr1);
+ if (ret < 0)
+ return ret;
+
+ /* set the general regs */
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &iregs->gr[1], offs_gr1, sizeof(*iregs));
+ if (ret < 0)
+ return ret;
+
+ return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ sizeof(*iregs), -1);
+}
+
+/*
+ * retrieve the contents of FRV userspace FP/Media registers
+ */
+static int fpmregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ const struct user_fpmedia_regs *fpregs = &target->thread.user->f;
+ int ret;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ fpregs, 0, sizeof(*fpregs));
+ if (ret < 0)
+ return ret;
+
+ return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ sizeof(*fpregs), -1);
+}
+
+/*
+ * update the contents of the FRV userspace FP/Media registers
+ */
+static int fpmregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct user_fpmedia_regs *fpregs = &target->thread.user->f;
+ int ret;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ fpregs, 0, sizeof(*fpregs));
+ if (ret < 0)
+ return ret;
+
+ return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ sizeof(*fpregs), -1);
+}
+
+/*
+ * determine if the FP/Media registers have actually been used
+ */
+static int fpmregs_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ return tsk_used_math(target) ? regset->n : 0;
+}
+
+/*
+ * Define the register sets available on the FRV under Linux
+ */
+enum frv_regset {
+ REGSET_GENERAL,
+ REGSET_FPMEDIA,
+};
+
+static const struct user_regset frv_regsets[] = {
+ /*
+ * General register format is:
+ * PSR, ISR, CCR, CCCR, LR, LCR, PC, (STATUS), SYSCALLNO, ORIG_G8
+ * GNER0-1, IACC0, TBR, GR1-63
+ */
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .get = genregs_get,
+ .set = genregs_set,
+ },
+ /*
+ * FPU/Media register format is:
+ * FR0-63, FNER0-1, MSR0-1, ACC0-7, ACCG0-8, FSR
+ */
+ [REGSET_FPMEDIA] = {
+ .core_note_type = NT_PRFPREG,
+ .n = sizeof(struct user_fpmedia_regs) / sizeof(long),
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .get = fpmregs_get,
+ .set = fpmregs_set,
+ .active = fpmregs_active,
+ },
+};
+
+static const struct user_regset_view user_frv_native_view = {
+ .name = "frv",
+ .e_machine = EM_FRV,
+ .regsets = frv_regsets,
+ .n = ARRAY_SIZE(frv_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ return &user_frv_native_view;
+}
+
+/*
* Get contents of register REGNO in task TASK.
*/
static inline long get_reg(struct task_struct *task, int regno)
@@ -71,75 +234,45 @@ static inline int put_reg(struct task_struct *task, int regno,
}
/*
- * check that an address falls within the bounds of the target process's memory mappings
- */
-static inline int is_user_addr_valid(struct task_struct *child,
- unsigned long start, unsigned long len)
-{
-#ifdef CONFIG_MMU
- if (start >= PAGE_OFFSET || len > PAGE_OFFSET - start)
- return -EIO;
- return 0;
-#else
- struct vm_list_struct *vml;
-
- for (vml = child->mm->context.vmlist; vml; vml = vml->next)
- if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end)
- return 0;
-
- return -EIO;
-#endif
-}
-
-/*
* Called by kernel/ptrace.c when detaching..
*
* Control h/w single stepping
*/
-void ptrace_disable(struct task_struct *child)
+void user_enable_single_step(struct task_struct *child)
+{
+ child->thread.frame0->__status |= REG__STATUS_STEP;
+}
+
+void user_disable_single_step(struct task_struct *child)
{
child->thread.frame0->__status &= ~REG__STATUS_STEP;
}
-void ptrace_enable(struct task_struct *child)
+void ptrace_disable(struct task_struct *child)
{
- child->thread.frame0->__status |= REG__STATUS_STEP;
+ user_disable_single_step(child);
}
-long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request,
+ unsigned long addr, unsigned long data)
{
unsigned long tmp;
int ret;
+ int regno = addr >> 2;
+ unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- int copied;
-
- ret = -EIO;
- if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
- break;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- if (copied != sizeof(tmp))
- break;
-
- ret = put_user(tmp,(unsigned long *) data);
- break;
- }
-
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
tmp = 0;
ret = -EIO;
- if ((addr & 3) || addr < 0)
+ if (addr & 3)
break;
ret = 0;
- switch (addr >> 2) {
+ switch (regno) {
case 0 ... PT__END - 1:
- tmp = get_reg(child, addr >> 2);
+ tmp = get_reg(child, regno);
break;
case PT__END + 0:
@@ -168,557 +301,77 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
if (ret == 0)
- ret = put_user(tmp, (unsigned long *) data);
+ ret = put_user(tmp, datap);
break;
}
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- ret = -EIO;
- if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
- break;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
- break;
- ret = 0;
- break;
-
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
- if ((addr & 3) || addr < 0)
- break;
-
- ret = 0;
- switch (addr >> 2) {
- case 0 ... PT__END-1:
- ret = put_reg(child, addr >> 2, data);
- break;
-
- default:
- ret = -EIO;
- break;
- }
- break;
-
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: /* restart after signal. */
- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- child->exit_code = data;
- ptrace_disable(child);
- wake_up_process(child);
- ret = 0;
- break;
-
- /* make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL:
- ret = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ if (addr & 3)
break;
- child->exit_code = SIGKILL;
- clear_tsk_thread_flag(child, TIF_SINGLESTEP);
- ptrace_disable(child);
- wake_up_process(child);
- break;
- case PTRACE_SINGLESTEP: /* set the trap flag. */
- ret = -EIO;
- if (!valid_signal(data))
+ switch (regno) {
+ case 0 ... PT__END - 1:
+ ret = put_reg(child, regno, data);
break;
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- ptrace_enable(child);
- child->exit_code = data;
- wake_up_process(child);
- ret = 0;
- break;
-
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
- case PTRACE_GETREGS: { /* Get all integer regs from the child. */
- int i;
- for (i = 0; i < PT__GPEND; i++) {
- tmp = get_reg(child, i);
- if (put_user(tmp, (unsigned long *) data)) {
- ret = -EFAULT;
- break;
- }
- data += sizeof(long);
- }
- ret = 0;
- break;
- }
-
- case PTRACE_SETREGS: { /* Set all integer regs in the child. */
- int i;
- for (i = 0; i < PT__GPEND; i++) {
- if (get_user(tmp, (unsigned long *) data)) {
- ret = -EFAULT;
- break;
- }
- put_reg(child, i, tmp);
- data += sizeof(long);
}
- ret = 0;
- break;
- }
-
- case PTRACE_GETFPREGS: { /* Get the child FP/Media state. */
- ret = 0;
- if (copy_to_user((void *) data,
- &child->thread.user->f,
- sizeof(child->thread.user->f)))
- ret = -EFAULT;
- break;
- }
-
- case PTRACE_SETFPREGS: { /* Set the child FP/Media state. */
- ret = 0;
- if (copy_from_user(&child->thread.user->f,
- (void *) data,
- sizeof(child->thread.user->f)))
- ret = -EFAULT;
break;
- }
-
- case PTRACE_GETFDPIC:
- tmp = 0;
- switch (addr) {
- case PTRACE_GETFDPIC_EXEC:
- tmp = child->mm->context.exec_fdpic_loadmap;
- break;
- case PTRACE_GETFDPIC_INTERP:
- tmp = child->mm->context.interp_fdpic_loadmap;
- break;
- default:
- break;
- }
- ret = 0;
- if (put_user(tmp, (unsigned long *) data)) {
- ret = -EFAULT;
- break;
- }
- break;
+ case PTRACE_GETREGS: /* Get all integer regs from the child. */
+ return copy_regset_to_user(child, &user_frv_native_view,
+ REGSET_GENERAL,
+ 0, sizeof(child->thread.user->i),
+ datap);
+
+ case PTRACE_SETREGS: /* Set all integer regs in the child. */
+ return copy_regset_from_user(child, &user_frv_native_view,
+ REGSET_GENERAL,
+ 0, sizeof(child->thread.user->i),
+ datap);
+
+ case PTRACE_GETFPREGS: /* Get the child FP/Media state. */
+ return copy_regset_to_user(child, &user_frv_native_view,
+ REGSET_FPMEDIA,
+ 0, sizeof(child->thread.user->f),
+ datap);
+
+ case PTRACE_SETFPREGS: /* Set the child FP/Media state. */
+ return copy_regset_from_user(child, &user_frv_native_view,
+ REGSET_FPMEDIA,
+ 0, sizeof(child->thread.user->f),
+ datap);
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
return ret;
}
-int __nongprelbss kstrace;
-
-static const struct {
- const char *name;
- unsigned argmask;
-} __syscall_name_table[NR_syscalls] = {
- [0] = { "restart_syscall" },
- [1] = { "exit", 0x000001 },
- [2] = { "fork", 0xffffff },
- [3] = { "read", 0x000141 },
- [4] = { "write", 0x000141 },
- [5] = { "open", 0x000235 },
- [6] = { "close", 0x000001 },
- [7] = { "waitpid", 0x000141 },
- [8] = { "creat", 0x000025 },
- [9] = { "link", 0x000055 },
- [10] = { "unlink", 0x000005 },
- [11] = { "execve", 0x000445 },
- [12] = { "chdir", 0x000005 },
- [13] = { "time", 0x000004 },
- [14] = { "mknod", 0x000325 },
- [15] = { "chmod", 0x000025 },
- [16] = { "lchown", 0x000025 },
- [17] = { "break" },
- [18] = { "oldstat", 0x000045 },
- [19] = { "lseek", 0x000131 },
- [20] = { "getpid", 0xffffff },
- [21] = { "mount", 0x043555 },
- [22] = { "umount", 0x000005 },
- [23] = { "setuid", 0x000001 },
- [24] = { "getuid", 0xffffff },
- [25] = { "stime", 0x000004 },
- [26] = { "ptrace", 0x004413 },
- [27] = { "alarm", 0x000001 },
- [28] = { "oldfstat", 0x000041 },
- [29] = { "pause", 0xffffff },
- [30] = { "utime", 0x000045 },
- [31] = { "stty" },
- [32] = { "gtty" },
- [33] = { "access", 0x000025 },
- [34] = { "nice", 0x000001 },
- [35] = { "ftime" },
- [36] = { "sync", 0xffffff },
- [37] = { "kill", 0x000011 },
- [38] = { "rename", 0x000055 },
- [39] = { "mkdir", 0x000025 },
- [40] = { "rmdir", 0x000005 },
- [41] = { "dup", 0x000001 },
- [42] = { "pipe", 0x000004 },
- [43] = { "times", 0x000004 },
- [44] = { "prof" },
- [45] = { "brk", 0x000004 },
- [46] = { "setgid", 0x000001 },
- [47] = { "getgid", 0xffffff },
- [48] = { "signal", 0x000041 },
- [49] = { "geteuid", 0xffffff },
- [50] = { "getegid", 0xffffff },
- [51] = { "acct", 0x000005 },
- [52] = { "umount2", 0x000035 },
- [53] = { "lock" },
- [54] = { "ioctl", 0x000331 },
- [55] = { "fcntl", 0x000331 },
- [56] = { "mpx" },
- [57] = { "setpgid", 0x000011 },
- [58] = { "ulimit" },
- [60] = { "umask", 0x000002 },
- [61] = { "chroot", 0x000005 },
- [62] = { "ustat", 0x000043 },
- [63] = { "dup2", 0x000011 },
- [64] = { "getppid", 0xffffff },
- [65] = { "getpgrp", 0xffffff },
- [66] = { "setsid", 0xffffff },
- [67] = { "sigaction" },
- [68] = { "sgetmask" },
- [69] = { "ssetmask" },
- [70] = { "setreuid" },
- [71] = { "setregid" },
- [72] = { "sigsuspend" },
- [73] = { "sigpending" },
- [74] = { "sethostname" },
- [75] = { "setrlimit" },
- [76] = { "getrlimit" },
- [77] = { "getrusage" },
- [78] = { "gettimeofday" },
- [79] = { "settimeofday" },
- [80] = { "getgroups" },
- [81] = { "setgroups" },
- [82] = { "select" },
- [83] = { "symlink" },
- [84] = { "oldlstat" },
- [85] = { "readlink" },
- [86] = { "uselib" },
- [87] = { "swapon" },
- [88] = { "reboot" },
- [89] = { "readdir" },
- [91] = { "munmap", 0x000034 },
- [92] = { "truncate" },
- [93] = { "ftruncate" },
- [94] = { "fchmod" },
- [95] = { "fchown" },
- [96] = { "getpriority" },
- [97] = { "setpriority" },
- [99] = { "statfs" },
- [100] = { "fstatfs" },
- [102] = { "socketcall" },
- [103] = { "syslog" },
- [104] = { "setitimer" },
- [105] = { "getitimer" },
- [106] = { "stat" },
- [107] = { "lstat" },
- [108] = { "fstat" },
- [111] = { "vhangup" },
- [114] = { "wait4" },
- [115] = { "swapoff" },
- [116] = { "sysinfo" },
- [117] = { "ipc" },
- [118] = { "fsync" },
- [119] = { "sigreturn" },
- [120] = { "clone" },
- [121] = { "setdomainname" },
- [122] = { "uname" },
- [123] = { "modify_ldt" },
- [123] = { "cacheflush" },
- [124] = { "adjtimex" },
- [125] = { "mprotect" },
- [126] = { "sigprocmask" },
- [127] = { "create_module" },
- [128] = { "init_module" },
- [129] = { "delete_module" },
- [130] = { "get_kernel_syms" },
- [131] = { "quotactl" },
- [132] = { "getpgid" },
- [133] = { "fchdir" },
- [134] = { "bdflush" },
- [135] = { "sysfs" },
- [136] = { "personality" },
- [137] = { "afs_syscall" },
- [138] = { "setfsuid" },
- [139] = { "setfsgid" },
- [140] = { "_llseek", 0x014331 },
- [141] = { "getdents" },
- [142] = { "_newselect", 0x000141 },
- [143] = { "flock" },
- [144] = { "msync" },
- [145] = { "readv" },
- [146] = { "writev" },
- [147] = { "getsid", 0x000001 },
- [148] = { "fdatasync", 0x000001 },
- [149] = { "_sysctl", 0x000004 },
- [150] = { "mlock" },
- [151] = { "munlock" },
- [152] = { "mlockall" },
- [153] = { "munlockall" },
- [154] = { "sched_setparam" },
- [155] = { "sched_getparam" },
- [156] = { "sched_setscheduler" },
- [157] = { "sched_getscheduler" },
- [158] = { "sched_yield" },
- [159] = { "sched_get_priority_max" },
- [160] = { "sched_get_priority_min" },
- [161] = { "sched_rr_get_interval" },
- [162] = { "nanosleep", 0x000044 },
- [163] = { "mremap" },
- [164] = { "setresuid" },
- [165] = { "getresuid" },
- [166] = { "vm86" },
- [167] = { "query_module" },
- [168] = { "poll" },
- [169] = { "nfsservctl" },
- [170] = { "setresgid" },
- [171] = { "getresgid" },
- [172] = { "prctl", 0x333331 },
- [173] = { "rt_sigreturn", 0xffffff },
- [174] = { "rt_sigaction", 0x001441 },
- [175] = { "rt_sigprocmask", 0x001441 },
- [176] = { "rt_sigpending", 0x000014 },
- [177] = { "rt_sigtimedwait", 0x001444 },
- [178] = { "rt_sigqueueinfo", 0x000411 },
- [179] = { "rt_sigsuspend", 0x000014 },
- [180] = { "pread", 0x003341 },
- [181] = { "pwrite", 0x003341 },
- [182] = { "chown", 0x000115 },
- [183] = { "getcwd" },
- [184] = { "capget" },
- [185] = { "capset" },
- [186] = { "sigaltstack" },
- [187] = { "sendfile" },
- [188] = { "getpmsg" },
- [189] = { "putpmsg" },
- [190] = { "vfork", 0xffffff },
- [191] = { "ugetrlimit" },
- [192] = { "mmap2", 0x313314 },
- [193] = { "truncate64" },
- [194] = { "ftruncate64" },
- [195] = { "stat64", 0x000045 },
- [196] = { "lstat64", 0x000045 },
- [197] = { "fstat64", 0x000041 },
- [198] = { "lchown32" },
- [199] = { "getuid32", 0xffffff },
- [200] = { "getgid32", 0xffffff },
- [201] = { "geteuid32", 0xffffff },
- [202] = { "getegid32", 0xffffff },
- [203] = { "setreuid32" },
- [204] = { "setregid32" },
- [205] = { "getgroups32" },
- [206] = { "setgroups32" },
- [207] = { "fchown32" },
- [208] = { "setresuid32" },
- [209] = { "getresuid32" },
- [210] = { "setresgid32" },
- [211] = { "getresgid32" },
- [212] = { "chown32" },
- [213] = { "setuid32" },
- [214] = { "setgid32" },
- [215] = { "setfsuid32" },
- [216] = { "setfsgid32" },
- [217] = { "pivot_root" },
- [218] = { "mincore" },
- [219] = { "madvise" },
- [220] = { "getdents64" },
- [221] = { "fcntl64" },
- [223] = { "security" },
- [224] = { "gettid" },
- [225] = { "readahead" },
- [226] = { "setxattr" },
- [227] = { "lsetxattr" },
- [228] = { "fsetxattr" },
- [229] = { "getxattr" },
- [230] = { "lgetxattr" },
- [231] = { "fgetxattr" },
- [232] = { "listxattr" },
- [233] = { "llistxattr" },
- [234] = { "flistxattr" },
- [235] = { "removexattr" },
- [236] = { "lremovexattr" },
- [237] = { "fremovexattr" },
- [238] = { "tkill" },
- [239] = { "sendfile64" },
- [240] = { "futex" },
- [241] = { "sched_setaffinity" },
- [242] = { "sched_getaffinity" },
- [243] = { "set_thread_area" },
- [244] = { "get_thread_area" },
- [245] = { "io_setup" },
- [246] = { "io_destroy" },
- [247] = { "io_getevents" },
- [248] = { "io_submit" },
- [249] = { "io_cancel" },
- [250] = { "fadvise64" },
- [252] = { "exit_group", 0x000001 },
- [253] = { "lookup_dcookie" },
- [254] = { "epoll_create" },
- [255] = { "epoll_ctl" },
- [256] = { "epoll_wait" },
- [257] = { "remap_file_pages" },
- [258] = { "set_tid_address" },
- [259] = { "timer_create" },
- [260] = { "timer_settime" },
- [261] = { "timer_gettime" },
- [262] = { "timer_getoverrun" },
- [263] = { "timer_delete" },
- [264] = { "clock_settime" },
- [265] = { "clock_gettime" },
- [266] = { "clock_getres" },
- [267] = { "clock_nanosleep" },
- [268] = { "statfs64" },
- [269] = { "fstatfs64" },
- [270] = { "tgkill" },
- [271] = { "utimes" },
- [272] = { "fadvise64_64" },
- [273] = { "vserver" },
- [274] = { "mbind" },
- [275] = { "get_mempolicy" },
- [276] = { "set_mempolicy" },
- [277] = { "mq_open" },
- [278] = { "mq_unlink" },
- [279] = { "mq_timedsend" },
- [280] = { "mq_timedreceive" },
- [281] = { "mq_notify" },
- [282] = { "mq_getsetattr" },
- [283] = { "sys_kexec_load" },
-};
-
-asmlinkage void do_syscall_trace(int leaving)
+/*
+ * handle tracing of system call entry
+ * - return the revised system call number or ULONG_MAX to cause ENOSYS
+ */
+asmlinkage unsigned long syscall_trace_entry(void)
{
-#if 0
- unsigned long *argp;
- const char *name;
- unsigned argmask;
- char buffer[16];
-
- if (!kstrace)
- return;
-
- if (!current->mm)
- return;
-
- if (__frame->gr7 == __NR_close)
- return;
-
-#if 0
- if (__frame->gr7 != __NR_mmap2 &&
- __frame->gr7 != __NR_vfork &&
- __frame->gr7 != __NR_execve &&
- __frame->gr7 != __NR_exit)
- return;
-#endif
-
- argmask = 0;
- name = NULL;
- if (__frame->gr7 < NR_syscalls) {
- name = __syscall_name_table[__frame->gr7].name;
- argmask = __syscall_name_table[__frame->gr7].argmask;
- }
- if (!name) {
- sprintf(buffer, "sys_%lx", __frame->gr7);
- name = buffer;
- }
-
- if (!leaving) {
- if (!argmask) {
- printk(KERN_CRIT "[%d] %s(%lx,%lx,%lx,%lx,%lx,%lx)\n",
- current->pid,
- name,
- __frame->gr8,
- __frame->gr9,
- __frame->gr10,
- __frame->gr11,
- __frame->gr12,
- __frame->gr13);
- }
- else if (argmask == 0xffffff) {
- printk(KERN_CRIT "[%d] %s()\n",
- current->pid,
- name);
- }
- else {
- printk(KERN_CRIT "[%d] %s(",
- current->pid,
- name);
-
- argp = &__frame->gr8;
-
- do {
- switch (argmask & 0xf) {
- case 1:
- printk("%ld", (long) *argp);
- break;
- case 2:
- printk("%lo", *argp);
- break;
- case 3:
- printk("%lx", *argp);
- break;
- case 4:
- printk("%p", (void *) *argp);
- break;
- case 5:
- printk("\"%s\"", (char *) *argp);
- break;
- }
-
- argp++;
- argmask >>= 4;
- if (argmask)
- printk(",");
-
- } while (argmask);
-
- printk(")\n");
- }
- }
- else {
- if ((int)__frame->gr8 > -4096 && (int)__frame->gr8 < 4096)
- printk(KERN_CRIT "[%d] %s() = %ld\n", current->pid, name, __frame->gr8);
- else
- printk(KERN_CRIT "[%d] %s() = %lx\n", current->pid, name, __frame->gr8);
+ __frame->__status |= REG__STATUS_SYSC_ENTRY;
+ if (tracehook_report_syscall_entry(__frame)) {
+ /* tracing decided this syscall should not happen, so
+ * We'll return a bogus call number to get an ENOSYS
+ * error, but leave the original number in
+ * __frame->syscallno
+ */
+ return ULONG_MAX;
}
- return;
-#endif
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
-
- if (!(current->ptrace & PT_PTRACED))
- return;
-
- /* we need to indicate entry or exit to strace */
- if (leaving)
- __frame->__status |= REG__STATUS_SYSC_EXIT;
- else
- __frame->__status |= REG__STATUS_SYSC_ENTRY;
-
- ptrace_notify(SIGTRAP);
+ return __frame->syscallno;
+}
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
+/*
+ * handle tracing of system call exit
+ */
+asmlinkage void syscall_trace_exit(void)
+{
+ __frame->__status |= REG__STATUS_SYSC_EXIT;
+ tracehook_report_syscall_exit(__frame, 0);
}
diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c
deleted file mode 100644
index 7971d680ae2..00000000000
--- a/arch/frv/kernel/semaphore.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* semaphore.c: FR-V semaphores
- *
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- * - Derived from lib/rwsem-spinlock.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <asm/semaphore.h>
-
-struct sem_waiter {
- struct list_head list;
- struct task_struct *task;
-};
-
-#if SEMAPHORE_DEBUG
-void semtrace(struct semaphore *sem, const char *str)
-{
- if (sem->debug)
- printk("[%d] %s({%d,%d})\n",
- current->pid,
- str,
- sem->counter,
- list_empty(&sem->wait_list) ? 0 : 1);
-}
-#else
-#define semtrace(SEM,STR) do { } while(0)
-#endif
-
-/*
- * wait for a token to be granted from a semaphore
- * - entered with lock held and interrupts disabled
- */
-void __down(struct semaphore *sem, unsigned long flags)
-{
- struct task_struct *tsk = current;
- struct sem_waiter waiter;
-
- semtrace(sem, "Entering __down");
-
- /* set up my own style of waitqueue */
- waiter.task = tsk;
- get_task_struct(tsk);
-
- list_add_tail(&waiter.list, &sem->wait_list);
-
- /* we don't need to touch the semaphore struct anymore */
- spin_unlock_irqrestore(&sem->wait_lock, flags);
-
- /* wait to be given the semaphore */
- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-
- for (;;) {
- if (list_empty(&waiter.list))
- break;
- schedule();
- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
- }
-
- tsk->state = TASK_RUNNING;
- semtrace(sem, "Leaving __down");
-}
-
-EXPORT_SYMBOL(__down);
-
-/*
- * interruptibly wait for a token to be granted from a semaphore
- * - entered with lock held and interrupts disabled
- */
-int __down_interruptible(struct semaphore *sem, unsigned long flags)
-{
- struct task_struct *tsk = current;
- struct sem_waiter waiter;
- int ret;
-
- semtrace(sem,"Entering __down_interruptible");
-
- /* set up my own style of waitqueue */
- waiter.task = tsk;
- get_task_struct(tsk);
-
- list_add_tail(&waiter.list, &sem->wait_list);
-
- /* we don't need to touch the semaphore struct anymore */
- set_task_state(tsk, TASK_INTERRUPTIBLE);
-
- spin_unlock_irqrestore(&sem->wait_lock, flags);
-
- /* wait to be given the semaphore */
- ret = 0;
- for (;;) {
- if (list_empty(&waiter.list))
- break;
- if (unlikely(signal_pending(current)))
- goto interrupted;
- schedule();
- set_task_state(tsk, TASK_INTERRUPTIBLE);
- }
-
- out:
- tsk->state = TASK_RUNNING;
- semtrace(sem, "Leaving __down_interruptible");
- return ret;
-
- interrupted:
- spin_lock_irqsave(&sem->wait_lock, flags);
-
- if (!list_empty(&waiter.list)) {
- list_del(&waiter.list);
- ret = -EINTR;
- }
-
- spin_unlock_irqrestore(&sem->wait_lock, flags);
- if (ret == -EINTR)
- put_task_struct(current);
- goto out;
-}
-
-EXPORT_SYMBOL(__down_interruptible);
-
-/*
- * release a single token back to a semaphore
- * - entered with lock held and interrupts disabled
- */
-void __up(struct semaphore *sem)
-{
- struct task_struct *tsk;
- struct sem_waiter *waiter;
-
- semtrace(sem,"Entering __up");
-
- /* grant the token to the process at the front of the queue */
- waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
-
- /* We must be careful not to touch 'waiter' after we set ->task = NULL.
- * It is an allocated on the waiter's stack and may become invalid at
- * any time after that point (due to a wakeup from another source).
- */
- list_del_init(&waiter->list);
- tsk = waiter->task;
- mb();
- waiter->task = NULL;
- wake_up_process(tsk);
- put_task_struct(tsk);
-
- semtrace(sem,"Leaving __up");
-}
-
-EXPORT_SYMBOL(__up);
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 5908deae960..9f3a7a62d78 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -10,8 +10,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
-#include <linux/version.h>
+#include <generated/utsrelease.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
@@ -30,9 +29,9 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
#include <asm/setup.h>
-#include <asm/serial.h>
#include <asm/irq.h>
#include <asm/sections.h>
#include <asm/pgalloc.h>
@@ -44,11 +43,9 @@
#include <asm/mb-regs.h>
#include <asm/mb93493-regs.h>
#include <asm/gdb-stub.h>
-#include <asm/irq-routing.h>
#include <asm/io.h>
#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
#include <asm/pgtable.h>
#endif
@@ -63,10 +60,6 @@ static void __init setup_linux_memory(void);
static void __init setup_uclinux_memory(void);
#endif
-#ifdef CONFIG_CONSOLE
-extern struct consw *conswitchp;
-#endif
-
#ifdef CONFIG_MB93090_MB00
static char __initdata mb93090_banner[] = "FJ/RH FR-V Linux";
static char __initdata mb93090_version[] = UTS_RELEASE;
@@ -113,15 +106,17 @@ unsigned long __initdata num_mappedpages;
struct cpuinfo_frv __nongprelbss boot_cpu_data;
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
char __initdata redboot_command_line[COMMAND_LINE_SIZE];
#ifdef CONFIG_PM
#define __pminit
#define __pminitdata
+#define __pminitconst
#else
#define __pminit __init
#define __pminitdata __initdata
+#define __pminitconst __initconst
#endif
struct clock_cmode {
@@ -191,10 +186,10 @@ static struct clock_cmode __pminitdata clock_cmodes_fr555[16] = {
[6] = { _x1, _x1_5, _x1_5, _x4_5, _x0_375 },
};
-static const struct clock_cmode __pminitdata *clock_cmodes;
+static const struct clock_cmode __pminitconst *clock_cmodes;
static int __pminitdata clock_doubled;
-static struct uart_port __initdata __frv_uart0 = {
+static struct uart_port __pminitdata __frv_uart0 = {
.uartclk = 0,
.membase = (char *) UART0_BASE,
.irq = IRQ_CPU_UART0,
@@ -203,7 +198,7 @@ static struct uart_port __initdata __frv_uart0 = {
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
};
-static struct uart_port __initdata __frv_uart1 = {
+static struct uart_port __pminitdata __frv_uart1 = {
.uartclk = 0,
.membase = (char *) UART1_BASE,
.irq = IRQ_CPU_UART1,
@@ -714,7 +709,7 @@ static void __init reserve_dma_coherent(void)
/*
* calibrate the delay loop
*/
-void __init calibrate_delay(void)
+void calibrate_delay(void)
{
loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ);
@@ -740,7 +735,7 @@ static void __init parse_cmdline_early(char *cmdline)
/* "mem=XXX[kKmM]" sets SDRAM size to <mem>, overriding the value we worked
* out from the SDRAM controller mask register
*/
- if (!memcmp(cmdline, "mem=", 4)) {
+ if (!strncmp(cmdline, "mem=", 4)) {
unsigned long long mem_size;
mem_size = memparse(cmdline + 4, &cmdline);
@@ -765,7 +760,7 @@ void __init setup_arch(char **cmdline_p)
printk("uClinux FR-V port done by Red Hat Inc <dhowells@redhat.com>\n");
#endif
- memcpy(saved_command_line, redboot_command_line, COMMAND_LINE_SIZE);
+ memcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE);
determine_cpu();
determine_clocks(1);
@@ -798,15 +793,8 @@ void __init setup_arch(char **cmdline_p)
#endif
#endif
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
- /* we need to initialize the Flashrom device here since we might
- * do things with flash early on in the boot
- */
- flash_probe();
-#endif
-
/* deal with the command line - RedBoot may have passed one to the kernel */
- memcpy(command_line, saved_command_line, sizeof(command_line));
+ memcpy(command_line, boot_command_line, sizeof(command_line));
*cmdline_p = &command_line[0];
parse_cmdline_early(command_line);
@@ -814,11 +802,11 @@ void __init setup_arch(char **cmdline_p)
* - by now the stack is part of the init task */
printk("Memory %08lx-%08lx\n", memory_start, memory_end);
- if (memory_start == memory_end) BUG();
+ BUG_ON(memory_start == memory_end);
- init_mm.start_code = (unsigned long) &_stext;
- init_mm.end_code = (unsigned long) &_etext;
- init_mm.end_data = (unsigned long) &_edata;
+ init_mm.start_code = (unsigned long) _stext;
+ init_mm.end_code = (unsigned long) _etext;
+ init_mm.end_data = (unsigned long) _edata;
#if 0 /* DAVIDM - don't set brk just incase someone decides to use it */
init_mm.brk = (unsigned long) &_end;
#else
@@ -826,10 +814,8 @@ void __init setup_arch(char **cmdline_p)
#endif
#ifdef DEBUG
- printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x BSS=0x%06x-0x%06x\n",
- (int) &_stext, (int) &_etext,
- (int) &_sdata, (int) &_edata,
- (int) &_sbss, (int) &_ebss);
+ printk("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n",
+ _stext, _etext, _sdata, _edata, __bss_start, __bss_stop);
#endif
#ifdef CONFIG_VT
@@ -840,11 +826,6 @@ void __init setup_arch(char **cmdline_p)
#endif
#endif
-#ifdef CONFIG_BLK_DEV_BLKMEM
- ROOT_DEV = MKDEV(BLKMEM_MAJOR,0);
-#endif
- /*rom_length = (unsigned long)&_flashend - (unsigned long)&_romvec;*/
-
#ifdef CONFIG_MMU
setup_linux_memory();
#else
@@ -871,7 +852,7 @@ void __init setup_arch(char **cmdline_p)
/*
*
*/
-static int __devinit setup_arch_serial(void)
+static int setup_arch_serial(void)
{
/* register those serial ports that are available */
#ifndef CONFIG_GDBSTUB_UART0
@@ -895,6 +876,7 @@ late_initcall(setup_arch_serial);
static void __init setup_linux_memory(void)
{
unsigned long bootmap_size, low_top_pfn, kstart, kend, high_mem;
+ unsigned long physpages;
kstart = (unsigned long) &__kernel_image_start - PAGE_OFFSET;
kend = (unsigned long) &__kernel_image_end - PAGE_OFFSET;
@@ -912,19 +894,19 @@ static void __init setup_linux_memory(void)
);
/* pass the memory that the kernel can immediately use over to the bootmem allocator */
- max_mapnr = num_physpages = (memory_end - memory_start) >> PAGE_SHIFT;
+ max_mapnr = physpages = (memory_end - memory_start) >> PAGE_SHIFT;
low_top_pfn = (KERNEL_LOWMEM_END - KERNEL_LOWMEM_START) >> PAGE_SHIFT;
high_mem = 0;
- if (num_physpages > low_top_pfn) {
+ if (physpages > low_top_pfn) {
#ifdef CONFIG_HIGHMEM
- high_mem = num_physpages - low_top_pfn;
+ high_mem = physpages - low_top_pfn;
#else
- max_mapnr = num_physpages = low_top_pfn;
+ max_mapnr = physpages = low_top_pfn;
#endif
}
else {
- low_top_pfn = num_physpages;
+ low_top_pfn = physpages;
}
min_low_pfn = memory_start >> PAGE_SHIFT;
@@ -943,14 +925,16 @@ static void __init setup_linux_memory(void)
#endif
/* take back the memory occupied by the kernel image and the bootmem alloc map */
- reserve_bootmem(kstart, kend - kstart + bootmap_size);
+ reserve_bootmem(kstart, kend - kstart + bootmap_size,
+ BOOTMEM_DEFAULT);
/* reserve the memory occupied by the initial ramdisk */
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (low_top_pfn << PAGE_SHIFT)) {
- reserve_bootmem(INITRD_START, INITRD_SIZE);
- initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+ reserve_bootmem(INITRD_START, INITRD_SIZE,
+ BOOTMEM_DEFAULT);
+ initrd_start = INITRD_START + PAGE_OFFSET;
initrd_end = initrd_start + INITRD_SIZE;
}
else {
@@ -996,7 +980,7 @@ static void __init setup_uclinux_memory(void)
free_bootmem(memory_start, memory_end - memory_start);
high_memory = (void *) (memory_end & PAGE_MASK);
- max_mapnr = num_physpages = ((unsigned long) high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+ max_mapnr = ((unsigned long) high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
min_low_pfn = memory_start >> PAGE_SHIFT;
max_low_pfn = memory_end >> PAGE_SHIFT;
@@ -1004,9 +988,10 @@ static void __init setup_uclinux_memory(void)
/* now take back the bits the core kernel is occupying */
#ifndef CONFIG_PROTECT_KERNEL
- reserve_bootmem(kend, bootmap_size);
+ reserve_bootmem(kend, bootmap_size, BOOTMEM_DEFAULT);
reserve_bootmem((unsigned long) &__kernel_image_start,
- kend - (unsigned long) &__kernel_image_start);
+ kend - (unsigned long) &__kernel_image_start,
+ BOOTMEM_DEFAULT);
#else
dampr = __get_DAMPR(0);
@@ -1014,14 +999,15 @@ static void __init setup_uclinux_memory(void)
dampr = (dampr >> 4) + 17;
dampr = 1 << dampr;
- reserve_bootmem(__get_DAMPR(0) & xAMPRx_PPFN, dampr);
+ reserve_bootmem(__get_DAMPR(0) & xAMPRx_PPFN, dampr, BOOTMEM_DEFAULT);
#endif
/* reserve some memory to do uncached DMA through if requested */
#ifdef CONFIG_RESERVE_DMA_COHERENT
if (dma_coherent_mem_start)
reserve_bootmem(dma_coherent_mem_start,
- dma_coherent_mem_end - dma_coherent_mem_start);
+ dma_coherent_mem_end - dma_coherent_mem_start,
+ BOOTMEM_DEFAULT);
#endif
} /* end setup_uclinux_memory() */
@@ -1127,7 +1113,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 679c1d5cc95..d822700d4f1 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -13,7 +13,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
@@ -21,84 +20,25 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/personality.h>
-#include <linux/suspend.h>
+#include <linux/tracehook.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
#define DEBUG_SIG 0
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
struct fdpic_func_descriptor {
unsigned long text;
unsigned long GOT;
};
/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
-{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- set_thread_flag(TIF_RESTORE_SIGMASK);
- return -ERESTARTNOHAND;
-}
-
-asmlinkage int sys_sigaction(int sig,
- const struct old_sigaction __user *act,
- struct old_sigaction __user *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
- return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
- return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- }
-
- return ret;
-}
-
-asmlinkage
-int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
- return do_sigaltstack(uss, uoss, __frame->sp);
-}
-
-
-/*
* Do a signal return; undo the signal stack.
*/
struct sigframe
{
- void (*pretcode)(void);
+ __sigrestore_t pretcode;
int sig;
struct sigcontext sc;
unsigned long extramask[_NSIG_WORDS-1];
@@ -107,10 +47,10 @@ struct sigframe
struct rt_sigframe
{
- void (*pretcode)(void);
+ __sigrestore_t pretcode;
int sig;
- struct siginfo *pinfo;
- void *puc;
+ struct siginfo __user *pinfo;
+ void __user *puc;
struct siginfo info;
struct ucontext uc;
uint32_t retcode[2];
@@ -121,6 +61,9 @@ static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8)
struct user_context *user = current->thread.user;
unsigned long tbr, psr;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
tbr = user->i.tbr;
psr = user->i.psr;
if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context)))
@@ -154,11 +97,7 @@ asmlinkage int sys_sigreturn(void)
__copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
goto badframe;
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(&frame->sc, &gr8))
goto badframe;
@@ -180,16 +119,12 @@ asmlinkage int sys_rt_sigreturn(void)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
goto badframe;
- if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
+ if (restore_altstack(&frame->uc.uc_stack))
goto badframe;
return gr8;
@@ -233,7 +168,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! on_sig_stack(sp))
+ if (! sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
@@ -250,6 +185,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
struct sigframe __user *frame;
int rsig;
+ set_fs(USER_DS);
+
frame = get_sigframe(ka, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -284,7 +221,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
* setlos #__NR_sigreturn,gr7
* tira gr0,0
*/
- if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+ if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
__put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
__put_user(0xc0700000, &frame->retcode[1]))
goto give_sigsegv;
@@ -293,26 +230,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
(unsigned long) (frame->retcode + 2));
}
- /* set up registers for signal handler */
- __frame->sp = (unsigned long) frame;
- __frame->lr = (unsigned long) &frame->retcode;
- __frame->gr8 = sig;
-
- if (get_personality & FDPIC_FUNCPTRS) {
+ /* Set up registers for the signal handler */
+ if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr =
- (struct fdpic_func_descriptor *) ka->sa.sa_handler;
- __get_user(__frame->pc, &funcptr->text);
- __get_user(__frame->gr15, &funcptr->GOT);
+ (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+ struct fdpic_func_descriptor desc;
+ if (copy_from_user(&desc, funcptr, sizeof(desc)))
+ goto give_sigsegv;
+ __frame->pc = desc.text;
+ __frame->gr15 = desc.GOT;
} else {
__frame->pc = (unsigned long) ka->sa.sa_handler;
__frame->gr15 = 0;
}
- set_fs(USER_DS);
-
- /* the tracer may want to single-step inside the handler */
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
+ __frame->sp = (unsigned long) frame;
+ __frame->lr = (unsigned long) &frame->retcode;
+ __frame->gr8 = sig;
#if DEBUG_SIG
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
@@ -323,7 +257,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
return 0;
give_sigsegv:
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
return -EFAULT;
} /* end setup_frame() */
@@ -338,6 +272,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
struct rt_sigframe __user *frame;
int rsig;
+ set_fs(USER_DS);
+
frame = get_sigframe(ka, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -359,10 +295,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Create the ucontext. */
if (__put_user(0, &frame->uc.uc_flags) ||
- __put_user(0, &frame->uc.uc_link) ||
- __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
- __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
- __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
+ __put_user(NULL, &frame->uc.uc_link) ||
+ __save_altstack(&frame->uc.uc_stack, __frame->sp))
goto give_sigsegv;
if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
@@ -382,7 +316,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* setlos #__NR_sigreturn,gr7
* tira gr0,0
*/
- if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+ if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
__put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
__put_user(0xc0700000, &frame->retcode[1]))
goto give_sigsegv;
@@ -392,26 +326,23 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
/* Set up registers for signal handler */
- __frame->sp = (unsigned long) frame;
- __frame->lr = (unsigned long) &frame->retcode;
- __frame->gr8 = sig;
- __frame->gr9 = (unsigned long) &frame->info;
-
- if (get_personality & FDPIC_FUNCPTRS) {
- struct fdpic_func_descriptor *funcptr =
+ if (current->personality & FDPIC_FUNCPTRS) {
+ struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
- __get_user(__frame->pc, &funcptr->text);
- __get_user(__frame->gr15, &funcptr->GOT);
+ struct fdpic_func_descriptor desc;
+ if (copy_from_user(&desc, funcptr, sizeof(desc)))
+ goto give_sigsegv;
+ __frame->pc = desc.text;
+ __frame->gr15 = desc.GOT;
} else {
__frame->pc = (unsigned long) ka->sa.sa_handler;
__frame->gr15 = 0;
}
- set_fs(USER_DS);
-
- /* the tracer may want to single-step inside the handler */
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
+ __frame->sp = (unsigned long) frame;
+ __frame->lr = (unsigned long) &frame->retcode;
+ __frame->gr8 = sig;
+ __frame->gr9 = (unsigned long) &frame->info;
#if DEBUG_SIG
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
@@ -422,7 +353,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return 0;
give_sigsegv:
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
return -EFAULT;
} /* end setup_rt_frame() */
@@ -431,13 +362,14 @@ give_sigsegv:
/*
* OK, we're invoking a handler
*/
-static int handle_signal(unsigned long sig, siginfo_t *info,
- struct k_sigaction *ka, sigset_t *oldset)
+static void handle_signal(unsigned long sig, siginfo_t *info,
+ struct k_sigaction *ka)
{
+ sigset_t *oldset = sigmask_to_save();
int ret;
/* Are we from a system call? */
- if (in_syscall(__frame)) {
+ if (__frame->syscallno != -1) {
/* If so, check system call restarting.. */
switch (__frame->gr8) {
case -ERESTART_RESTARTBLOCK:
@@ -456,6 +388,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
__frame->gr8 = __frame->orig_gr8;
__frame->pc -= 4;
}
+ __frame->syscallno = -1;
}
/* Set up the stack frame */
@@ -464,18 +397,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
else
ret = setup_frame(sig, ka, oldset);
- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
-
- return ret;
+ if (ret)
+ return;
+ signal_delivered(sig, info, ka, __frame,
+ test_thread_flag(TIF_SINGLESTEP));
} /* end handle_signal() */
/*****************************************************************************/
@@ -488,43 +414,16 @@ static void do_signal(void)
{
struct k_sigaction ka;
siginfo_t info;
- sigset_t *oldset;
int signr;
- /*
- * We want the common case to go fast, which
- * is why we may in certain cases get here from
- * kernel mode. Just return without doing anything
- * if so.
- */
- if (!user_mode(__frame))
- return;
-
- if (try_to_freeze())
- goto no_signal;
-
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- oldset = &current->saved_sigmask;
- else
- oldset = &current->blocked;
-
signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
if (signr > 0) {
- if (handle_signal(signr, &info, &ka, oldset) == 0) {
- /* a signal was successfully delivered; the saved
- * sigmask will have been stored in the signal frame,
- * and will be restored by sigreturn, so we can simply
- * clear the TIF_RESTORE_SIGMASK flag */
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- }
-
+ handle_signal(signr, &info, &ka);
return;
}
-no_signal:
/* Did we come from a system call? */
- if (__frame->syscallno >= 0) {
+ if (__frame->syscallno != -1) {
/* Restart the system call - no handlers present */
switch (__frame->gr8) {
case -ERESTARTNOHAND:
@@ -535,19 +434,16 @@ no_signal:
break;
case -ERESTART_RESTARTBLOCK:
- __frame->gr8 = __NR_restart_syscall;
+ __frame->gr7 = __NR_restart_syscall;
__frame->pc -= 4;
break;
}
+ __frame->syscallno = -1;
}
/* if there's no signal to deliver, we just put the saved sigmask
* back */
- if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
- }
-
+ restore_saved_sigmask();
} /* end do_signal() */
/*****************************************************************************/
@@ -562,7 +458,13 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
clear_thread_flag(TIF_SINGLESTEP);
/* deal with pending signal delivery */
- if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ if (thread_info_flags & _TIF_SIGPENDING)
do_signal();
+ /* deal with notification on about to resume userspace execution */
+ if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+ clear_thread_flag(TIF_NOTIFY_RESUME);
+ tracehook_notify_resume(__frame);
+ }
+
} /* end do_notify_resume() */
diff --git a/arch/frv/kernel/sleep.S b/arch/frv/kernel/sleep.S
index e6079b8cac6..f67bf73cd2c 100644
--- a/arch/frv/kernel/sleep.S
+++ b/arch/frv/kernel/sleep.S
@@ -1,7 +1,7 @@
/* sleep.S: power saving mode entry
*
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Woodhouse (dwmw2@redhat.com)
+ * Written by David Woodhouse (dwmw2@infradead.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -11,7 +11,6 @@
*/
#include <linux/sys.h>
-#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/setup.h>
#include <asm/segment.h>
diff --git a/arch/frv/kernel/switch_to.S b/arch/frv/kernel/switch_to.S
index 1703dc20174..b06668670fc 100644
--- a/arch/frv/kernel/switch_to.S
+++ b/arch/frv/kernel/switch_to.S
@@ -11,7 +11,7 @@
# 2 of the License, or (at your option) any later version.
#
###############################################################################
-#include <linux/config.h>
+
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/processor.h>
@@ -31,7 +31,7 @@
# address of frame 0 (userspace) on current kernel stack
.globl __kernel_frame0_ptr
__kernel_frame0_ptr:
- .long init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE
+ .long init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE
# address of current task
.globl __kernel_current_task
@@ -102,13 +102,6 @@ __switch_to:
movgs gr14,lr
bar
- srli gr15,#28,gr5
- subicc gr5,#0xc,gr0,icc0
- beq icc0,#0,111f
- break
- nop
-111:
-
# jump to __switch_back or ret_from_fork as appropriate
# - move prev to GR8
movgs gr4,psr
diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c
index 931aa6d895e..9c4980825bb 100644
--- a/arch/frv/kernel/sys_frv.c
+++ b/arch/frv/kernel/sys_frv.c
@@ -13,202 +13,32 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/fs.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/file.h>
-#include <linux/utsname.h>
#include <linux/syscalls.h>
+#include <linux/ipc.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
-
-/*
- * sys_pipe() is the normal C calling standard for creating
- * a pipe. It's not the way unix traditionally does this, though.
- */
-asmlinkage long sys_pipe(unsigned long * fildes)
-{
- int fd[2];
- int error;
-
- error = do_pipe(fd);
- if (!error) {
- if (copy_to_user(fildes, fd, 2*sizeof(int)))
- error = -EFAULT;
- }
- return error;
-}
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
- int error = -EBADF;
- struct file * file = NULL;
-
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (!(flags & MAP_ANONYMOUS)) {
- file = fget(fd);
- if (!file)
- goto out;
- }
-
/* As with sparc32, make sure the shift for mmap2 is constant
(12), no matter what PAGE_SIZE we have.... */
/* But unlike sparc32, don't just silently break if we're
trying to map something we can't */
- if (pgoff & ((1<<(PAGE_SHIFT-12))-1))
+ if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
return -EINVAL;
- pgoff >>= (PAGE_SHIFT - 12);
-
- down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- up_write(&current->mm->mmap_sem);
-
- if (file)
- fput(file);
-out:
- return error;
-}
-
-#if 0 /* DAVIDM - do we want this */
-struct mmap_arg_struct64 {
- __u32 addr;
- __u32 len;
- __u32 prot;
- __u32 flags;
- __u64 offset; /* 64 bits */
- __u32 fd;
-};
-
-asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
-{
- int error = -EFAULT;
- struct file * file = NULL;
- struct mmap_arg_struct64 a;
- unsigned long pgoff;
-
- if (copy_from_user(&a, arg, sizeof(a)))
- return -EFAULT;
-
- if ((long)a.offset & ~PAGE_MASK)
- return -EINVAL;
-
- pgoff = a.offset >> PAGE_SHIFT;
- if ((a.offset >> PAGE_SHIFT) != pgoff)
- return -EINVAL;
-
- if (!(a.flags & MAP_ANONYMOUS)) {
- error = -EBADF;
- file = fget(a.fd);
- if (!file)
- goto out;
- }
- a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
- down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
- up_write(&current->mm->mmap_sem);
- if (file)
- fput(file);
-out:
- return error;
-}
-#endif
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage long sys_ipc(unsigned long call,
- unsigned long first,
- unsigned long second,
- unsigned long third,
- void __user *ptr,
- unsigned long fifth)
-{
- int version, ret;
-
- version = call >> 16; /* hack for backward compatibility */
- call &= 0xffff;
-
- switch (call) {
- case SEMOP:
- return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL);
- case SEMTIMEDOP:
- return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
- (const struct timespec __user *)fifth);
-
- case SEMGET:
- return sys_semget (first, second, third);
- case SEMCTL: {
- union semun fourth;
- if (!ptr)
- return -EINVAL;
- if (get_user(fourth.__pad, (void * __user *) ptr))
- return -EFAULT;
- return sys_semctl (first, second, third, fourth);
- }
-
- case MSGSND:
- return sys_msgsnd (first, (struct msgbuf __user *) ptr,
- second, third);
- case MSGRCV:
- switch (version) {
- case 0: {
- struct ipc_kludge tmp;
- if (!ptr)
- return -EINVAL;
-
- if (copy_from_user(&tmp,
- (struct ipc_kludge __user *) ptr,
- sizeof (tmp)))
- return -EFAULT;
- return sys_msgrcv (first, tmp.msgp, second,
- tmp.msgtyp, third);
- }
- default:
- return sys_msgrcv (first,
- (struct msgbuf __user *) ptr,
- second, fifth, third);
- }
- case MSGGET:
- return sys_msgget ((key_t) first, second);
- case MSGCTL:
- return sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
-
- case SHMAT:
- switch (version) {
- default: {
- ulong raddr;
- ret = do_shmat (first, (char __user *) ptr, second, &raddr);
- if (ret)
- return ret;
- return put_user (raddr, (ulong __user *) third);
- }
- case 1: /* iBCS2 emulator entry point */
- if (!segment_eq(get_fs(), get_ds()))
- return -EINVAL;
- /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */
- return do_shmat (first, (char __user *) ptr, second, (ulong *) third);
- }
- case SHMDT:
- return sys_shmdt ((char __user *)ptr);
- case SHMGET:
- return sys_shmget (first, second, third);
- case SHMCTL:
- return sys_shmctl (first, second,
- (struct shmid_ds __user *) ptr);
- default:
- return -ENOSYS;
- }
+ return sys_mmap_pgoff(addr, len, prot, flags, fd,
+ pgoff >> (PAGE_SHIFT - 12));
}
diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c
index 408b0f382b4..f4dfae2c75a 100644
--- a/arch/frv/kernel/sysctl.c
+++ b/arch/frv/kernel/sysctl.c
@@ -9,8 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
-#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
@@ -48,8 +46,9 @@ static void frv_change_dcache_mode(unsigned long newmode)
/*
* handle requests to dynamically switch the write caching mode delivered by /proc
*/
-static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int procctl_frv_cachemode(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
{
unsigned long hsr0;
char buff[8];
@@ -86,7 +85,7 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
}
/* read the state */
- if (filp->f_pos > 0) {
+ if (*ppos > 0) {
*lenp = 0;
return 0;
}
@@ -112,7 +111,7 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
return -EFAULT;
*lenp = len;
- filp->f_pos = len;
+ *ppos = len;
return 0;
} /* end procctl_frv_cachemode() */
@@ -122,8 +121,9 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
* permit the mm_struct the nominated process is using have its MMU context ID pinned
*/
#ifdef CONFIG_MMU
-static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int procctl_frv_pin_cxnr(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
{
pid_t pid;
char buff[16], *p;
@@ -152,7 +152,7 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
}
/* read the currently pinned CXN */
- if (filp->f_pos > 0) {
+ if (*ppos > 0) {
*lenp = 0;
return 0;
}
@@ -165,7 +165,7 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
return -EFAULT;
*lenp = len;
- filp->f_pos = len;
+ *ppos = len;
return 0;
} /* end procctl_frv_pin_cxnr() */
@@ -176,22 +176,37 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
*/
static struct ctl_table frv_table[] =
{
- { 1, "cache-mode", NULL, 0, 0644, NULL, &procctl_frv_cachemode },
+ {
+ .procname = "cache-mode",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0644,
+ .proc_handler = procctl_frv_cachemode,
+ },
#ifdef CONFIG_MMU
- { 2, "pin-cxnr", NULL, 0, 0644, NULL, &procctl_frv_pin_cxnr },
+ {
+ .procname = "pin-cxnr",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0644,
+ .proc_handler = procctl_frv_pin_cxnr
+ },
#endif
- { 0 }
+ {}
};
/*
* Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
* when all the PM interfaces exist nicely.
*/
-#define CTL_FRV 9898
static struct ctl_table frv_dir_table[] =
{
- {CTL_FRV, "frv", NULL, 0, 0555, frv_table},
- {0}
+ {
+ .procname = "frv",
+ .mode = 0555,
+ .child = frv_table
+ },
+ {}
};
/*
@@ -199,7 +214,7 @@ static struct ctl_table frv_dir_table[] =
*/
static int __init frv_sysctl_init(void)
{
- register_sysctl_table(frv_dir_table, 1);
+ register_sysctl_table(frv_dir_table);
return 0;
}
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 24cf85f89e4..b457de496b7 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -10,7 +10,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h> /* CONFIG_HEARTBEAT */
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
@@ -26,14 +25,11 @@
#include <asm/timer-regs.h>
#include <asm/mb-regs.h>
#include <asm/mb86943a.h>
-#include <asm/irq-routing.h>
#include <linux/timex.h>
#define TICK_SIZE (tick_nsec / 1000)
-extern unsigned long wall_jiffies;
-
unsigned long __nongprelbss __clkin_clock_speed_HZ;
unsigned long __nongprelbss __ext_bus_clock_speed_HZ;
unsigned long __nongprelbss __res_bus_clock_speed_HZ;
@@ -44,54 +40,23 @@ unsigned long __nongprelbss __dsu_clock_speed_HZ;
unsigned long __nongprelbss __serial_clock_speed_HZ;
unsigned long __delay_loops_MHz;
-static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs *regs);
+static irqreturn_t timer_interrupt(int irq, void *dummy);
static struct irqaction timer_irq = {
- timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED,
+ .name = "timer",
};
-static inline int set_rtc_mmss(unsigned long nowtime)
-{
- return -1;
-}
-
/*
* timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
*/
-static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
+static irqreturn_t timer_interrupt(int irq, void *dummy)
{
- /* last time the cmos clock got updated */
- static long last_rtc_update = 0;
-
- /*
- * Here we are in the timer irq handler. We just have irqs locally
- * disabled but we don't know if the timer_bh is running on the other
- * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
- * the irq version of write_lock because as just said we have irq
- * locally disabled. -arca
- */
- write_seqlock(&xtime_lock);
-
- do_timer(regs);
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
-
- /*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (ntp_synced() &&
- xtime.tv_sec > last_rtc_update + 660 &&
- (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
- (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2
- ) {
- if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
- }
+ profile_tick(CPU_PROFILING);
+
+ xtime_update(1);
#ifdef CONFIG_HEARTBEAT
static unsigned short n;
@@ -99,7 +64,8 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
__set_LEDS(n);
#endif /* CONFIG_HEARTBEAT */
- write_sequnlock(&xtime_lock);
+ update_process_times(user_mode(get_irq_regs()));
+
return IRQ_HANDLED;
}
@@ -119,7 +85,8 @@ void time_divisor_init(void)
__set_TCSR_DATA(0, base >> 8);
}
-void time_init(void)
+
+void read_persistent_clock(struct timespec *ts)
{
unsigned int year, mon, day, hour, min, sec;
@@ -127,7 +94,7 @@ void time_init(void)
/* FIX by dqg : Set to zero for platforms that don't have tod */
/* without this time is undefined and can overflow time_t, causing */
- /* very stange errors */
+ /* very strange errors */
year = 1980;
mon = day = 1;
hour = min = sec = 0;
@@ -135,9 +102,12 @@ void time_init(void)
if ((year += 1900) < 1970)
year += 100;
- xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
- xtime.tv_nsec = 0;
+ ts->tv_sec = mktime(year, mon, day, hour, min, sec);
+ ts->tv_nsec = 0;
+}
+void time_init(void)
+{
/* install scheduling interrupt handler */
setup_irq(IRQ_CPU_TIMER0, &timer_irq);
@@ -145,85 +115,6 @@ void time_init(void)
}
/*
- * This version of gettimeofday has near microsecond resolution.
- */
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long seq;
- unsigned long usec, sec;
- unsigned long max_ntp_tick;
-
- do {
- unsigned long lost;
-
- seq = read_seqbegin(&xtime_lock);
-
- usec = 0;
- lost = jiffies - wall_jiffies;
-
- /*
- * If time_adjust is negative then NTP is slowing the clock
- * so make sure not to go into next possible interval.
- * Better to lose some accuracy than have time go backwards..
- */
- if (unlikely(time_adjust < 0)) {
- max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
- usec = min(usec, max_ntp_tick);
-
- if (lost)
- usec += lost * max_ntp_tick;
- }
- else if (unlikely(lost))
- usec += lost * (USEC_PER_SEC / HZ);
-
- sec = xtime.tv_sec;
- usec += (xtime.tv_nsec / 1000);
- } while (read_seqretry(&xtime_lock, seq));
-
- while (usec >= 1000000) {
- usec -= 1000000;
- sec++;
- }
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
- time_t wtm_sec, sec = tv->tv_sec;
- long wtm_nsec, nsec = tv->tv_nsec;
-
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
- return -EINVAL;
-
- write_seqlock_irq(&xtime_lock);
- /*
- * This is revolting. We need to set "xtime" correctly. However, the
- * value in this location is the value at the most recent update of
- * wall time. Discover what correction gettimeofday() would have
- * made, and then undo it!
- */
- nsec -= 0 * NSEC_PER_USEC;
- nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
-
- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
- set_normalized_timespec(&xtime, sec, nsec);
- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
- ntp_clear();
- write_sequnlock_irq(&xtime_lock);
- clock_was_set();
- return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/*
* Scheduler clock - returns current time in nanosec units.
*/
unsigned long long sched_clock(void)
diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c
index 9eb84b2e6ab..a6d105d61b2 100644
--- a/arch/frv/kernel/traps.c
+++ b/arch/frv/kernel/traps.c
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/kernel.h>
@@ -21,9 +20,9 @@
#include <linux/init.h>
#include <linux/module.h>
+#include <asm/asm-offsets.h>
#include <asm/setup.h>
#include <asm/fpu.h>
-#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/siginfo.h>
@@ -49,7 +48,7 @@ asmlinkage void insn_access_error(unsigned long esfr1, unsigned long epcr0, unsi
info.si_signo = SIGSEGV;
info.si_code = SEGV_ACCERR;
info.si_errno = 0;
- info.si_addr = (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
+ info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
force_sig_info(info.si_signo, &info, current);
} /* end insn_access_error() */
@@ -73,7 +72,7 @@ asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, un
epcr0, esr0, esfr1);
info.si_errno = 0;
- info.si_addr = (void *) ((epcr0 & EPCR0_PC) ? (epcr0 & EPCR0_PC) : __frame->pc);
+ info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
switch (__frame->tbr & TBR_TT) {
case TBR_TT_ILLEGAL_INSTR:
@@ -102,6 +101,234 @@ asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, un
/*****************************************************************************/
/*
+ * handle atomic operations with errors
+ * - arguments in gr8, gr9, gr10
+ * - original memory value placed in gr5
+ * - replacement memory value placed in gr9
+ */
+asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0,
+ unsigned long esr0)
+{
+ static DEFINE_SPINLOCK(atomic_op_lock);
+ unsigned long x, y, z;
+ unsigned long __user *p;
+ mm_segment_t oldfs;
+ siginfo_t info;
+ int ret;
+
+ y = 0;
+ z = 0;
+
+ oldfs = get_fs();
+ if (!user_mode(__frame))
+ set_fs(KERNEL_DS);
+
+ switch (__frame->tbr & TBR_TT) {
+ /* TIRA gr0,#120
+ * u32 __atomic_user_cmpxchg32(u32 *ptr, u32 test, u32 new)
+ */
+ case TBR_TT_ATOMIC_CMPXCHG32:
+ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+ y = __frame->gr10;
+
+ for (;;) {
+ ret = get_user(z, p);
+ if (ret < 0)
+ goto error;
+
+ if (z != x)
+ goto done;
+
+ spin_lock_irq(&atomic_op_lock);
+
+ if (__get_user(z, p) == 0) {
+ if (z != x)
+ goto done2;
+
+ if (__put_user(y, p) == 0)
+ goto done2;
+ goto error2;
+ }
+
+ spin_unlock_irq(&atomic_op_lock);
+ }
+
+ /* TIRA gr0,#121
+ * u32 __atomic_kernel_xchg32(void *v, u32 new)
+ */
+ case TBR_TT_ATOMIC_XCHG32:
+ p = (unsigned long __user *) __frame->gr8;
+ y = __frame->gr9;
+
+ for (;;) {
+ ret = get_user(z, p);
+ if (ret < 0)
+ goto error;
+
+ spin_lock_irq(&atomic_op_lock);
+
+ if (__get_user(z, p) == 0) {
+ if (__put_user(y, p) == 0)
+ goto done2;
+ goto error2;
+ }
+
+ spin_unlock_irq(&atomic_op_lock);
+ }
+
+ /* TIRA gr0,#122
+ * ulong __atomic_kernel_XOR_return(ulong i, ulong *v)
+ */
+ case TBR_TT_ATOMIC_XOR:
+ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+ ret = get_user(z, p);
+ if (ret < 0)
+ goto error;
+
+ spin_lock_irq(&atomic_op_lock);
+
+ if (__get_user(z, p) == 0) {
+ y = x ^ z;
+ if (__put_user(y, p) == 0)
+ goto done2;
+ goto error2;
+ }
+
+ spin_unlock_irq(&atomic_op_lock);
+ }
+
+ /* TIRA gr0,#123
+ * ulong __atomic_kernel_OR_return(ulong i, ulong *v)
+ */
+ case TBR_TT_ATOMIC_OR:
+ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+ ret = get_user(z, p);
+ if (ret < 0)
+ goto error;
+
+ spin_lock_irq(&atomic_op_lock);
+
+ if (__get_user(z, p) == 0) {
+ y = x ^ z;
+ if (__put_user(y, p) == 0)
+ goto done2;
+ goto error2;
+ }
+
+ spin_unlock_irq(&atomic_op_lock);
+ }
+
+ /* TIRA gr0,#124
+ * ulong __atomic_kernel_AND_return(ulong i, ulong *v)
+ */
+ case TBR_TT_ATOMIC_AND:
+ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+ ret = get_user(z, p);
+ if (ret < 0)
+ goto error;
+
+ spin_lock_irq(&atomic_op_lock);
+
+ if (__get_user(z, p) == 0) {
+ y = x & z;
+ if (__put_user(y, p) == 0)
+ goto done2;
+ goto error2;
+ }
+
+ spin_unlock_irq(&atomic_op_lock);
+ }
+
+ /* TIRA gr0,#125
+ * int __atomic_user_sub_return(atomic_t *v, int i)
+ */
+ case TBR_TT_ATOMIC_SUB:
+ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+ ret = get_user(z, p);
+ if (ret < 0)
+ goto error;
+
+ spin_lock_irq(&atomic_op_lock);
+
+ if (__get_user(z, p) == 0) {
+ y = z - x;
+ if (__put_user(y, p) == 0)
+ goto done2;
+ goto error2;
+ }
+
+ spin_unlock_irq(&atomic_op_lock);
+ }
+
+ /* TIRA gr0,#126
+ * int __atomic_user_add_return(atomic_t *v, int i)
+ */
+ case TBR_TT_ATOMIC_ADD:
+ p = (unsigned long __user *) __frame->gr8;
+ x = __frame->gr9;
+
+ for (;;) {
+ ret = get_user(z, p);
+ if (ret < 0)
+ goto error;
+
+ spin_lock_irq(&atomic_op_lock);
+
+ if (__get_user(z, p) == 0) {
+ y = z + x;
+ if (__put_user(y, p) == 0)
+ goto done2;
+ goto error2;
+ }
+
+ spin_unlock_irq(&atomic_op_lock);
+ }
+
+ default:
+ BUG();
+ }
+
+done2:
+ spin_unlock_irq(&atomic_op_lock);
+done:
+ if (!user_mode(__frame))
+ set_fs(oldfs);
+ __frame->gr5 = z;
+ __frame->gr9 = y;
+ return;
+
+error2:
+ spin_unlock_irq(&atomic_op_lock);
+error:
+ if (!user_mode(__frame))
+ set_fs(oldfs);
+ __frame->pc -= 4;
+
+ die_if_kernel("-- Atomic Op Error --\n");
+
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_ACCERR;
+ info.si_errno = 0;
+ info.si_addr = (void __user *) __frame->pc;
+
+ force_sig_info(info.si_signo, &info, current);
+}
+
+/*****************************************************************************/
+/*
*
*/
asmlinkage void media_exception(unsigned long msr0, unsigned long msr1)
@@ -116,7 +343,7 @@ asmlinkage void media_exception(unsigned long msr0, unsigned long msr1)
info.si_signo = SIGFPE;
info.si_code = FPE_MDAOVF;
info.si_errno = 0;
- info.si_addr = (void *) __frame->pc;
+ info.si_addr = (void __user *) __frame->pc;
force_sig_info(info.si_signo, &info, current);
} /* end media_exception() */
@@ -134,11 +361,8 @@ asmlinkage void memory_access_exception(unsigned long esr0,
#ifdef CONFIG_MMU
unsigned long fixup;
- if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS)
- if (handle_misalignment(esr0, ear0, epcr0) == 0)
- return;
-
- if ((fixup = search_exception_table(__frame->pc)) != 0) {
+ fixup = search_exception_table(__frame->pc);
+ if (fixup) {
__frame->pc = fixup;
return;
}
@@ -156,7 +380,7 @@ asmlinkage void memory_access_exception(unsigned long esr0,
info.si_addr = NULL;
if ((esr0 & (ESRx_VALID | ESR0_EAV)) == (ESRx_VALID | ESR0_EAV))
- info.si_addr = (void *) ear0;
+ info.si_addr = (void __user *) ear0;
force_sig_info(info.si_signo, &info, current);
@@ -185,7 +409,7 @@ asmlinkage void data_access_error(unsigned long esfr1, unsigned long esr15, unsi
info.si_signo = SIGSEGV;
info.si_code = SEGV_ACCERR;
info.si_errno = 0;
- info.si_addr = (void *)
+ info.si_addr = (void __user *)
(((esr15 & (ESRx_VALID|ESR15_EAV)) == (ESRx_VALID|ESR15_EAV)) ? ear15 : 0);
force_sig_info(info.si_signo, &info, current);
@@ -219,7 +443,7 @@ asmlinkage void division_exception(unsigned long esfr1, unsigned long esr0, unsi
info.si_signo = SIGFPE;
info.si_code = FPE_INTDIV;
info.si_errno = 0;
- info.si_addr = (void *) __frame->pc;
+ info.si_addr = (void __user *) __frame->pc;
force_sig_info(info.si_signo, &info, current);
} /* end division_exception() */
@@ -242,17 +466,6 @@ asmlinkage void compound_exception(unsigned long esfr1,
BUG();
} /* end compound_exception() */
-/*****************************************************************************/
-/*
- * The architecture-independent backtrace generator
- */
-void dump_stack(void)
-{
- show_stack(NULL, NULL);
-}
-
-EXPORT_SYMBOL(dump_stack);
-
void show_stack(struct task_struct *task, unsigned long *sp)
{
}
@@ -280,26 +493,25 @@ static const char *regnames[] = {
void show_regs(struct pt_regs *regs)
{
- uint32_t *reg;
+ unsigned long *reg;
int loop;
printk("\n");
+ show_regs_print_info(KERN_DEFAULT);
- printk("Frame: @%08x [%s]\n",
- (uint32_t) regs,
+ printk("Frame: @%08lx [%s]\n",
+ (unsigned long) regs,
regs->psr & PSR_S ? "kernel" : "user");
- reg = (uint32_t *) regs;
- for (loop = 0; loop < REG__END; loop++) {
- printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+ reg = (unsigned long *) regs;
+ for (loop = 0; loop < NR_PT_REGS; loop++) {
+ printk("%s %08lx", regnames[loop + 0], reg[loop + 0]);
- if (loop == REG__END - 1 || loop % 5 == 4)
+ if (loop == NR_PT_REGS - 1 || loop % 5 == 4)
printk("\n");
else
printk(" | ");
}
-
- printk("Process %s (pid: %d)\n", current->comm, current->pid);
}
void die_if_kernel(const char *str, ...)
@@ -311,7 +523,7 @@ void die_if_kernel(const char *str, ...)
return;
va_start(va, str);
- vsprintf(buffer, str, va);
+ vsnprintf(buffer, sizeof(buffer), str, va);
va_end(va);
console_verbose();
@@ -329,7 +541,7 @@ void die_if_kernel(const char *str, ...)
*/
static void show_backtrace_regs(struct pt_regs *frame)
{
- uint32_t *reg;
+ unsigned long *reg;
int loop;
/* print the registers for this frame */
@@ -337,11 +549,11 @@ static void show_backtrace_regs(struct pt_regs *frame)
frame->psr & PSR_S ? "Kernel Mode" : "User Mode",
frame);
- reg = (uint32_t *) frame;
- for (loop = 0; loop < REG__END; loop++) {
- printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+ reg = (unsigned long *) frame;
+ for (loop = 0; loop < NR_PT_REGS; loop++) {
+ printk("%s %08lx", regnames[loop + 0], reg[loop + 0]);
- if (loop == REG__END - 1 || loop % 5 == 4)
+ if (loop == NR_PT_REGS - 1 || loop % 5 == 4)
printk("\n");
else
printk(" | ");
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c
index 9b751c0f0e8..374f88d6cc0 100644
--- a/arch/frv/kernel/uaccess.c
+++ b/arch/frv/kernel/uaccess.c
@@ -17,14 +17,13 @@
/*
* copy a null terminated string from userspace
*/
-long strncpy_from_user(char *dst, const char *src, long count)
+long strncpy_from_user(char *dst, const char __user *src, long count)
{
unsigned long max;
char *p, ch;
long err = -EFAULT;
- if (count < 0)
- BUG();
+ BUG_ON(count < 0);
p = dst;
@@ -70,14 +69,13 @@ EXPORT_SYMBOL(strncpy_from_user);
*
* Return 0 on exception, a value greater than N if too long
*/
-long strnlen_user(const char *src, long count)
+long strnlen_user(const char __user *src, long count)
{
- const char *p;
+ const char __user *p;
long err = 0;
char ch;
- if (count < 0)
- BUG();
+ BUG_ON(count < 0);
#ifndef CONFIG_MMU
if ((unsigned long) src < memory_start)
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index f474534ba78..7e958d829ec 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -13,7 +13,7 @@ ENTRY(_start)
jiffies = jiffies_64 + 4;
-__page_offset = 0xc0000000; /* start of area covered by struct pages */
+__page_offset = CONFIG_PAGE_OFFSET; /* start of area covered by struct pages */
__kernel_image_start = __page_offset; /* address at which kernel image resides */
SECTIONS
@@ -26,62 +26,22 @@ SECTIONS
_sinittext = .;
.init.text : {
- *(.text.head)
+ HEAD_TEXT
#ifndef CONFIG_DEBUG_INFO
- *(.init.text)
- *(.exit.text)
- *(.exit.data)
+ INIT_TEXT
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
#endif
}
_einittext = .;
- .init.data : { *(.init.data) }
-
- . = ALIGN(8);
- __setup_start = .;
- .setup.init : { KEEP(*(.init.setup)) }
- __setup_end = .;
-
- __initcall_start = .;
- .initcall.init : {
- *(.initcall1.init)
- *(.initcall2.init)
- *(.initcall3.init)
- *(.initcall4.init)
- *(.initcall5.init)
- *(.initcall6.init)
- *(.initcall7.init)
- }
- __initcall_end = .;
- __con_initcall_start = .;
- .con_initcall.init : { *(.con_initcall.init) }
- __con_initcall_end = .;
- SECURITY_INIT
- . = ALIGN(4);
- __alt_instructions = .;
- .altinstructions : { *(.altinstructions) }
- __alt_instructions_end = .;
- .altinstr_replacement : { *(.altinstr_replacement) }
- __per_cpu_start = .;
- .data.percpu : { *(.data.percpu) }
- __per_cpu_end = .;
+ INIT_DATA_SECTION(8)
+ PERCPU_SECTION(L1_CACHE_BYTES)
- . = ALIGN(4096);
- __initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
- __initramfs_end = .;
-
- . = ALIGN(THREAD_SIZE);
+ . = ALIGN(PAGE_SIZE);
__init_end = .;
- /* put sections together that have massive alignment issues */
- . = ALIGN(THREAD_SIZE);
- .data.init_task : {
- /* init task record & stack */
- *(.data.init_task)
- }
-
.trap : {
/* trap table management - read entry-table.S before modifying */
. = ALIGN(8192);
@@ -92,27 +52,23 @@ SECTIONS
*(.trap.break)
}
- . = ALIGN(4096);
- .data.page_aligned : { *(.data.idt) }
-
- . = ALIGN(L1_CACHE_BYTES);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
/* Text and read-only data */
. = ALIGN(4);
_text = .;
_stext = .;
.text : {
- *(
- .text.start .text .text.*
-#ifdef CONFIG_DEBUG_INFO
- .init.text
- .exit.text
- .exitcall.exit
-#endif
- )
+ *(.text..start)
+ *(.text..entry)
+ *(.text..break)
+ *(.text..tlbmiss)
+ TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
+#ifdef CONFIG_DEBUG_INFO
+ INIT_TEXT
+ EXIT_TEXT
+ *(.exitcall.exit)
+#endif
*(.fixup)
*(.gnu.warning)
*(.exitcall.exit)
@@ -131,15 +87,15 @@ SECTIONS
}
- . = ALIGN(8); /* Exception table */
- __start___ex_table = .;
- __ex_table : { KEEP(*(__ex_table)) }
- __stop___ex_table = .;
+ EXCEPTION_TABLE(8)
_sdata = .;
.data : { /* Data */
- *(.data .data.*)
- *(.exit.data)
+ INIT_TASK_DATA(THREAD_SIZE)
+ CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
+ DATA_DATA
+ *(.data.*)
+ EXIT_DATA
CONSTRUCTORS
}
@@ -158,31 +114,19 @@ SECTIONS
.sbss : { *(.sbss .sbss.*) }
.bss : { *(.bss .bss.*) }
- .bss.stack : { *(.bss) }
+ .bss..stack : { *(.bss) }
__bss_stop = .;
_end = . ;
. = ALIGN(PAGE_SIZE);
__kernel_image_end = .;
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
-
- .debug_line 0 : { *(.debug_line) }
- .debug_info 0 : { *(.debug_info) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- .debug_str 0 : { *(.debug_str) }
- .debug_ranges 0 : { *(.debug_ranges) }
+ STABS_DEBUG
+ DWARF_DEBUG
.comment 0 : { *(.comment) }
+
+ DISCARDS
}
__kernel_image_size_no_bss = __bss_start - __kernel_image_start;