aboutsummaryrefslogtreecommitdiff
path: root/arch/frv/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/frv/kernel')
-rw-r--r--arch/frv/kernel/Makefile8
-rw-r--r--arch/frv/kernel/asm-offsets.c9
-rw-r--r--arch/frv/kernel/break.S4
-rw-r--r--arch/frv/kernel/cmode.S2
-rw-r--r--arch/frv/kernel/debug-stub.c2
-rw-r--r--arch/frv/kernel/entry-table.S12
-rw-r--r--arch/frv/kernel/entry.S109
-rw-r--r--arch/frv/kernel/frv_ksyms.c6
-rw-r--r--arch/frv/kernel/futex.c14
-rw-r--r--arch/frv/kernel/gdb-io.c5
-rw-r--r--arch/frv/kernel/gdb-stub.c156
-rw-r--r--arch/frv/kernel/head-mmu-fr451.S3
-rw-r--r--arch/frv/kernel/head-uc-fr401.S3
-rw-r--r--arch/frv/kernel/head-uc-fr451.S3
-rw-r--r--arch/frv/kernel/head-uc-fr555.S3
-rw-r--r--arch/frv/kernel/head.S10
-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.c35
-rw-r--r--arch/frv/kernel/irq-mb93093.c33
-rw-r--r--arch/frv/kernel/irq-mb93493.c28
-rw-r--r--arch/frv/kernel/irq.c84
-rw-r--r--arch/frv/kernel/kernel_execve.S33
-rw-r--r--arch/frv/kernel/kernel_thread.S77
-rw-r--r--arch/frv/kernel/local64.h1
-rw-r--r--arch/frv/kernel/module.c59
-rw-r--r--arch/frv/kernel/pm.c154
-rw-r--r--arch/frv/kernel/process.c161
-rw-r--r--arch/frv/kernel/ptrace.c799
-rw-r--r--arch/frv/kernel/semaphore.c155
-rw-r--r--arch/frv/kernel/setup.c38
-rw-r--r--arch/frv/kernel/signal.c207
-rw-r--r--arch/frv/kernel/sleep.S2
-rw-r--r--arch/frv/kernel/switch_to.S7
-rw-r--r--arch/frv/kernel/sys_frv.c176
-rw-r--r--arch/frv/kernel/sysctl.c26
-rw-r--r--arch/frv/kernel/time.c51
-rw-r--r--arch/frv/kernel/traps.c264
-rw-r--r--arch/frv/kernel/uaccess.c6
-rw-r--r--arch/frv/kernel/vmlinux.lds.S82
40 files changed, 911 insertions, 1957 deletions
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index e8f73ed28b5..3cbb3294b9f 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -5,11 +5,11 @@
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 \
- kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
- sys_frv.o time.o semaphore.o setup.o frv_ksyms.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 setup.o frv_ksyms.o \
debug-stub.o irq.o sleep.o uaccess.o
obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o
diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c
index fbb19fc1af4..9de96843a27 100644
--- a/arch/frv/kernel/asm-offsets.c
+++ b/arch/frv/kernel/asm-offsets.c
@@ -7,15 +7,13 @@
#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 DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
#define DEF_PTREG(sym, reg) \
asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \
: : "i" (offsetof(struct pt_regs, reg)))
@@ -32,11 +30,6 @@
asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \
: : "i" (offsetof(struct frv_frame0, reg)))
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
- DEFINE(sym, offsetof(struct str, mem));
-
void foo(void)
{
/* offsets into the thread_info structure */
diff --git a/arch/frv/kernel/break.S b/arch/frv/kernel/break.S
index bd0bdf908d9..cbb6958a314 100644
--- a/arch/frv/kernel/break.S
+++ b/arch/frv/kernel/break.S
@@ -21,7 +21,7 @@
#
# the break handler has its own stack
#
- .section .bss.stack
+ .section .bss..stack
.globl __break_user_context
.balign THREAD_SIZE
__break_stack:
@@ -63,7 +63,7 @@ __break_trace_through_exceptions:
# entry point for Break Exceptions/Interrupts
#
###############################################################################
- .section .text.break
+ .section .text..break
.balign 4
.globl __entry_break
__entry_break:
diff --git a/arch/frv/kernel/cmode.S b/arch/frv/kernel/cmode.S
index 81ba28ad220..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
diff --git a/arch/frv/kernel/debug-stub.c b/arch/frv/kernel/debug-stub.c
index 2f6c60c921e..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>
diff --git a/arch/frv/kernel/entry-table.S b/arch/frv/kernel/entry-table.S
index d3b9253d862..06c5ae191e5 100644
--- a/arch/frv/kernel/entry-table.S
+++ b/arch/frv/kernel/entry-table.S
@@ -86,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
@@ -145,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
@@ -316,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 f36d7f4a7c2..dfcd263c051 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -38,7 +38,7 @@
#define nr_syscalls ((syscall_table_size)/4)
- .section .text.entry
+ .section .text..entry
.balign 4
.macro LEDS val
@@ -656,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
#
###############################################################################
@@ -843,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,
@@ -866,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
@@ -886,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
@@ -905,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
@@ -1049,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
###############################################################################
@@ -1092,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:
@@ -1114,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
@@ -1130,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
@@ -1145,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:
@@ -1341,7 +1346,7 @@ sys_call_table:
.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
@@ -1499,6 +1504,16 @@ sys_call_table:
.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 f772704b3d2..86c516d96dc 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -12,7 +12,6 @@
#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>
@@ -31,7 +30,6 @@ EXPORT_SYMBOL(ip_fast_csum);
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
#endif
-EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
EXPORT_SYMBOL(__page_offset);
@@ -68,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 14f64b054c7..d155ca9e509 100644
--- a/arch/frv/kernel/futex.c
+++ b/arch/frv/kernel/futex.c
@@ -18,7 +18,7 @@
* 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,7 +197,7 @@ 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;
pagefault_disable();
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 48a0393e7ce..bbe78b0bffe 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -126,7 +126,6 @@
#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)
@@ -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
@@ -674,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--;
}
@@ -683,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;
}
@@ -694,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;
}
@@ -709,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;
}
@@ -720,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;
@@ -1356,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
@@ -1471,22 +1496,22 @@ void gdbstub(int sigval)
*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;
@@ -1500,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++ = ';';
@@ -1513,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++ = ';';
@@ -1522,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++ = ';';
@@ -1548,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;
@@ -1767,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];
@@ -1856,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':
@@ -1868,6 +1899,14 @@ void gdbstub(int sigval)
__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];
@@ -1939,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;
}
@@ -2059,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('-');
diff --git a/arch/frv/kernel/head-mmu-fr451.S b/arch/frv/kernel/head-mmu-fr451.S
index c8f210d84ff..98f87d586e5 100644
--- a/arch/frv/kernel/head-mmu-fr451.S
+++ b/arch/frv/kernel/head-mmu-fr451.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -31,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 ee282be20ff..438643cfa38 100644
--- a/arch/frv/kernel/head-uc-fr401.S
+++ b/arch/frv/kernel/head-uc-fr401.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -30,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 b10d9c8295d..b2a76c4a178 100644
--- a/arch/frv/kernel/head-uc-fr451.S
+++ b/arch/frv/kernel/head-uc-fr451.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -30,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 39937c19b46..5497aaf34f7 100644
--- a/arch/frv/kernel/head-uc-fr555.S
+++ b/arch/frv/kernel/head-uc-fr555.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -29,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 fecf751c5ca..a7d0bea9c03 100644
--- a/arch/frv/kernel/head.S
+++ b/arch/frv/kernel/head.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/thread_info.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
@@ -541,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 9e38f99bbab..2cc327a1ca4 100644
--- a/arch/frv/kernel/irq-mb93091.c
+++ b/arch/frv/kernel/irq-mb93091.c
@@ -20,7 +20,6 @@
#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/system.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
@@ -36,45 +35,45 @@
/*
* on-motherboard FPGA PIC operations
*/
-static void frv_fpga_mask(unsigned int irq)
+static void frv_fpga_mask(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- imr |= 1 << (irq - IRQ_BASE_FPGA);
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
__set_IMR(imr);
}
-static void frv_fpga_ack(unsigned int irq)
+static void frv_fpga_ack(struct irq_data *d)
{
- __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
}
-static void frv_fpga_mask_ack(unsigned int irq)
+static void frv_fpga_mask_ack(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- imr |= 1 << (irq - IRQ_BASE_FPGA);
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
__set_IMR(imr);
- __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
}
-static void frv_fpga_unmask(unsigned int irq)
+static void frv_fpga_unmask(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- imr &= ~(1 << (irq - IRQ_BASE_FPGA));
+ imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
__set_IMR(imr);
}
static struct irq_chip frv_fpga_pic = {
.name = "mb93091",
- .ack = frv_fpga_ack,
- .mask = frv_fpga_mask,
- .mask_ack = frv_fpga_mask_ack,
- .unmask = frv_fpga_unmask,
+ .irq_ack = frv_fpga_ack,
+ .irq_mask = frv_fpga_mask,
+ .irq_mask_ack = frv_fpga_mask_ack,
+ .irq_unmask = frv_fpga_unmask,
};
/*
@@ -109,28 +108,24 @@ static struct irqaction fpga_irq[4] = {
[0] = {
.handler = fpga_interrupt,
.flags = IRQF_DISABLED | IRQF_SHARED,
- .mask = CPU_MASK_NONE,
.name = "fpga.0",
.dev_id = (void *) 0x0028UL,
},
[1] = {
.handler = fpga_interrupt,
.flags = IRQF_DISABLED | IRQF_SHARED,
- .mask = CPU_MASK_NONE,
.name = "fpga.1",
.dev_id = (void *) 0x0050UL,
},
[2] = {
.handler = fpga_interrupt,
.flags = IRQF_DISABLED | IRQF_SHARED,
- .mask = CPU_MASK_NONE,
.name = "fpga.2",
.dev_id = (void *) 0x1c00UL,
},
[3] = {
.handler = fpga_interrupt,
.flags = IRQF_DISABLED | IRQF_SHARED,
- .mask = CPU_MASK_NONE,
.name = "fpga.3",
.dev_id = (void *) 0x6386UL,
}
@@ -150,9 +145,9 @@ void __init fpga_init(void)
__clr_IFR(0x0000);
for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
- set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
+ irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
- set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_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]);
diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c
index 3c2752ca977..95e4eb4f1f3 100644
--- a/arch/frv/kernel/irq-mb93093.c
+++ b/arch/frv/kernel/irq-mb93093.c
@@ -20,7 +20,6 @@
#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/system.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
@@ -35,45 +34,44 @@
/*
* off-CPU FPGA PIC operations
*/
-static void frv_fpga_mask(unsigned int irq)
+static void frv_fpga_mask(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- imr |= 1 << (irq - IRQ_BASE_FPGA);
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
__set_IMR(imr);
}
-static void frv_fpga_ack(unsigned int irq)
+static void frv_fpga_ack(struct irq_data *d)
{
- __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
}
-static void frv_fpga_mask_ack(unsigned int irq)
+static void frv_fpga_mask_ack(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- imr |= 1 << (irq - IRQ_BASE_FPGA);
+ imr |= 1 << (d->irq - IRQ_BASE_FPGA);
__set_IMR(imr);
- __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+ __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
}
-static void frv_fpga_unmask(unsigned int irq)
+static void frv_fpga_unmask(struct irq_data *d)
{
uint16_t imr = __get_IMR();
- imr &= ~(1 << (irq - IRQ_BASE_FPGA));
+ imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
__set_IMR(imr);
}
static struct irq_chip frv_fpga_pic = {
.name = "mb93093",
- .ack = frv_fpga_ack,
- .mask = frv_fpga_mask,
- .mask_ack = frv_fpga_mask_ack,
- .unmask = frv_fpga_unmask,
- .end = frv_fpga_end,
+ .irq_ack = frv_fpga_ack,
+ .irq_mask = frv_fpga_mask,
+ .irq_mask_ack = frv_fpga_mask_ack,
+ .irq_unmask = frv_fpga_unmask,
};
/*
@@ -94,7 +92,7 @@ static irqreturn_t fpga_interrupt(int irq, void *_mask)
irq = 31 - irq;
mask &= ~(1 << irq);
- generic_irq_handle(IRQ_BASE_FPGA + irq);
+ generic_handle_irq(IRQ_BASE_FPGA + irq);
}
return IRQ_HANDLED;
@@ -108,7 +106,6 @@ static struct irqaction fpga_irq[1] = {
[0] = {
.handler = fpga_interrupt,
.flags = IRQF_DISABLED,
- .mask = CPU_MASK_NONE,
.name = "fpga.0",
.dev_id = (void *) 0x0700UL,
}
@@ -126,7 +123,7 @@ void __init fpga_init(void)
__clr_IFR(0x0000);
for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
- set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_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 7754c7338e4..ba648da0932 100644
--- a/arch/frv/kernel/irq-mb93493.c
+++ b/arch/frv/kernel/irq-mb93493.c
@@ -20,7 +20,6 @@
#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/system.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
@@ -45,46 +44,46 @@
* daughter board PIC operations
* - there is no way to ACK interrupts in the MB93493 chip
*/
-static void frv_mb93493_mask(unsigned int irq)
+static void frv_mb93493_mask(struct irq_data *d)
{
uint32_t iqsr;
volatile void *piqsr;
- if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+ if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
piqsr = __addr_MB93493_IQSR(1);
else
piqsr = __addr_MB93493_IQSR(0);
iqsr = readl(piqsr);
- iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16));
+ iqsr &= ~(1 << (d->irq - IRQ_BASE_MB93493 + 16));
writel(iqsr, piqsr);
}
-static void frv_mb93493_ack(unsigned int irq)
+static void frv_mb93493_ack(struct irq_data *d)
{
}
-static void frv_mb93493_unmask(unsigned int irq)
+static void frv_mb93493_unmask(struct irq_data *d)
{
uint32_t iqsr;
volatile void *piqsr;
- if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+ if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
piqsr = __addr_MB93493_IQSR(1);
else
piqsr = __addr_MB93493_IQSR(0);
iqsr = readl(piqsr);
- iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16);
+ iqsr |= 1 << (d->irq - IRQ_BASE_MB93493 + 16);
writel(iqsr, piqsr);
}
static struct irq_chip frv_mb93493_pic = {
.name = "mb93093",
- .ack = frv_mb93493_ack,
- .mask = frv_mb93493_mask,
- .mask_ack = frv_mb93493_mask,
- .unmask = frv_mb93493_unmask,
+ .irq_ack = frv_mb93493_ack,
+ .irq_mask = frv_mb93493_mask,
+ .irq_mask_ack = frv_mb93493_mask,
+ .irq_unmask = frv_mb93493_unmask,
};
/*
@@ -120,14 +119,12 @@ static struct irqaction mb93493_irq[2] = {
[0] = {
.handler = mb93493_interrupt,
.flags = IRQF_DISABLED | IRQF_SHARED,
- .mask = CPU_MASK_NONE,
.name = "mb93493.0",
.dev_id = (void *) __addr_MB93493_IQSR(0),
},
[1] = {
.handler = mb93493_interrupt,
.flags = IRQF_DISABLED | IRQF_SHARED,
- .mask = CPU_MASK_NONE,
.name = "mb93493.1",
.dev_id = (void *) __addr_MB93493_IQSR(1),
}
@@ -141,7 +138,8 @@ void __init mb93493_init(void)
int irq;
for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
- set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_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]);
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 73abae767fd..2239346fa3d 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -16,7 +16,6 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
-#include <linux/slab.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
@@ -26,10 +25,9 @@
#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/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/delay.h>
@@ -48,89 +46,45 @@ extern void __init mb93493_init(void);
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)
{
- int i = *(loff_t *) v, cpu;
- struct irqaction * action;
- unsigned long flags;
-
- if (i == 0) {
- char cpuname[12];
-
- seq_printf(p, " ");
- for_each_present_cpu(cpu) {
- sprintf(cpuname, "CPU%d", cpu);
- seq_printf(p, " %10s", cpuname);
- }
- seq_putc(p, '\n');
- }
-
- if (i < NR_IRQS) {
- spin_lock_irqsave(&irq_desc[i].lock, flags);
- action = irq_desc[i].action;
- if (action) {
- seq_printf(p, "%3d: ", i);
- for_each_present_cpu(cpu)
- seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
- seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
- seq_printf(p, " %s", action->name);
- for (action = action->next;
- action;
- action = action->next)
- seq_printf(p, ", %s", action->name);
-
- seq_putc(p, '\n');
- }
-
- spin_unlock_irqrestore(&irq_desc[i].lock, flags);
- } else if (i == NR_IRQS) {
- seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
- }
-
+ seq_printf(p, "%*s: ", prec, "ERR");
+ seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
return 0;
}
/*
* on-CPU PIC operations
*/
-static void frv_cpupic_ack(unsigned int irqlevel)
+static void frv_cpupic_ack(struct irq_data *d)
{
- __clr_RC(irqlevel);
+ __clr_RC(d->irq);
__clr_IRL();
}
-static void frv_cpupic_mask(unsigned int irqlevel)
+static void frv_cpupic_mask(struct irq_data *d)
{
- __set_MASK(irqlevel);
+ __set_MASK(d->irq);
}
-static void frv_cpupic_mask_ack(unsigned int irqlevel)
+static void frv_cpupic_mask_ack(struct irq_data *d)
{
- __set_MASK(irqlevel);
- __clr_RC(irqlevel);
+ __set_MASK(d->irq);
+ __clr_RC(d->irq);
__clr_IRL();
}
-static void frv_cpupic_unmask(unsigned int irqlevel)
-{
- __clr_MASK(irqlevel);
-}
-
-static void frv_cpupic_end(unsigned int irqlevel)
+static void frv_cpupic_unmask(struct irq_data *d)
{
- __clr_MASK(irqlevel);
+ __clr_MASK(d->irq);
}
static struct irq_chip frv_cpu_pic = {
.name = "cpu",
- .ack = frv_cpupic_ack,
- .mask = frv_cpupic_mask,
- .mask_ack = frv_cpupic_mask_ack,
- .unmask = frv_cpupic_unmask,
- .end = frv_cpupic_end,
+ .irq_ack = frv_cpupic_ack,
+ .irq_mask = frv_cpupic_mask,
+ .irq_mask_ack = frv_cpupic_mask_ack,
+ .irq_unmask = frv_cpupic_unmask,
};
/*
@@ -162,10 +116,10 @@ void __init init_IRQ(void)
int level;
for (level = 1; level <= 14; level++)
- set_irq_chip_and_handler(level, &frv_cpu_pic,
+ irq_set_chip_and_handler(level, &frv_cpu_pic,
handle_level_irq);
- set_irq_handler(IRQ_CPU_TIMER0, handle_edge_irq);
+ irq_set_handler(IRQ_CPU_TIMER0, handle_edge_irq);
/* set the trigger levels for internal interrupt sources
* - timers all falling-edge
diff --git a/arch/frv/kernel/kernel_execve.S b/arch/frv/kernel/kernel_execve.S
deleted file mode 100644
index 9b074a16a05..00000000000
--- a/arch/frv/kernel/kernel_execve.S
+++ /dev/null
@@ -1,33 +0,0 @@
-/* in-kernel program execution
- *
- * 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
- * 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>
-
-###############################################################################
-#
-# Do a system call from kernel instead of calling sys_execve so we end up with
-# proper pt_regs.
-#
-# int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-#
-# On entry: GR8/GR9/GR10: arguments to function
-# On return: GR8: syscall return.
-#
-###############################################################################
- .globl kernel_execve
- .type kernel_execve,@function
-kernel_execve:
- setlos __NR_execve,gr7
- tira gr0,#0
- bralr
-
- .size kernel_execve,.-kernel_execve
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/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.c b/arch/frv/kernel/pm.c
index c57ce3f1f2e..ac767d94a88 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -14,7 +14,6 @@
#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>
@@ -151,29 +150,25 @@ static int user_atoi(char __user *ubuf, size_t len)
/*
* Send us to sleep.
*/
-static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
+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)
@@ -183,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();
@@ -201,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,
+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 __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen)
-{
- 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 __user *)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 __user *)newval))
- return -EFAULT;
-
- return try_set_cmode(new_cmode)?:1;
- }
- return 1;
-}
-
static int try_set_p0(int new_p0)
{
unsigned long flags, clkc;
@@ -310,144 +269,73 @@ static int try_set_cm(int new_cm)
return 0;
}
-static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
+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 __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen)
-{
- 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 __user *)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 __user *)newval))
- return -EFAULT;
-
- return try_set_p0(new_p0)?:1;
- }
- return 1;
-}
-
-static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
+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 __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen)
-{
- 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 __user *)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 __user *)newval))
- return -EFAULT;
-
- return try_set_cm(new_cm)?:1;
- }
- return 1;
-}
-
-
static struct ctl_table pm_table[] =
{
{
- .ctl_name = CTL_PM_SUSPEND,
.procname = "suspend",
.data = NULL,
.maxlen = 0,
.mode = 0200,
- .proc_handler = &sysctl_pm_do_suspend,
+ .proc_handler = sysctl_pm_do_suspend,
},
{
- .ctl_name = CTL_PM_CMODE,
.procname = "cmode",
.data = &clock_cmode_current,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &cmode_procctl,
- .strategy = &cmode_sysctl,
+ .proc_handler = cmode_procctl,
},
{
- .ctl_name = CTL_PM_P0,
.procname = "p0",
.data = &clock_p0_current,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &p0_procctl,
- .strategy = &p0_sysctl,
+ .proc_handler = p0_procctl,
},
{
- .ctl_name = CTL_PM_CM,
.procname = "cm",
.data = &clock_cm_current,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &cm_procctl,
- .strategy = &cm_sysctl,
+ .proc_handler = cm_procctl,
},
- { .ctl_name = 0}
+ { }
};
static struct ctl_table pm_dir_table[] =
{
{
- .ctl_name = CTL_PM,
.procname = "pm",
.mode = 0555,
.child = pm_table,
},
- { .ctl_name = 0}
+ { }
};
/*
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 9583a338e9d..5d40aeb7712 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -16,7 +16,6 @@
#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>
@@ -26,10 +25,10 @@
#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>
@@ -39,26 +38,13 @@
#include "local.h"
asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
#include <asm/pgalloc.h>
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
-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);
-}
-
static void core_sleep_idle(void)
{
#ifdef LED_DEBUG_SLEEP
@@ -73,33 +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;
-
- check_pgt_cache();
-
- 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)
@@ -147,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)
@@ -160,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 *)
+ childregs = (struct pt_regs *)
(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
- childregs = childregs0;
/* 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)
@@ -251,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 __user *name, char __user * __user *argv, char __user * __user *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;
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index 709e9bdc612..3987ff88dab 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -19,11 +19,13 @@
#include <linux/user.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>
@@ -33,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)
@@ -69,67 +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:
- ret = -EIO;
- if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
- break;
- ret = generic_ptrace_peekdata(child, addr, 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:
@@ -158,555 +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;
- ret = generic_ptrace_pokedata(child, addr, data);
- 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 7ee3a147b47..00000000000
--- a/arch/frv/kernel/semaphore.c
+++ /dev/null
@@ -1,155 +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/sched.h>
-#include <linux/module.h>
-#include <asm/semaphore.h>
-
-struct sem_waiter {
- struct list_head list;
- struct task_struct *task;
-};
-
-#ifdef CONFIG_DEBUG_SEMAPHORE
-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 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 0669e138238..9f3a7a62d78 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
@@ -46,7 +46,6 @@
#include <asm/io.h>
#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
#include <asm/pgtable.h>
#endif
@@ -113,9 +112,11 @@ 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 {
@@ -185,7 +186,7 @@ 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 __pminitdata __frv_uart0 = {
@@ -708,7 +709,7 @@ static void __init reserve_dma_coherent(void)
/*
* calibrate the delay loop
*/
-void __cpuinit calibrate_delay(void)
+void calibrate_delay(void)
{
loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ);
@@ -734,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);
@@ -803,9 +804,9 @@ void __init setup_arch(char **cmdline_p)
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
@@ -813,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
@@ -853,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
@@ -877,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;
@@ -894,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;
@@ -980,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;
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index d64bcaff54c..d822700d4f1 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -20,78 +20,19 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/personality.h>
-#include <linux/freezer.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.
*/
@@ -120,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)))
@@ -153,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;
@@ -179,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;
@@ -249,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)))
@@ -292,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 __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;
#if DEBUG_SIG
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
@@ -322,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() */
@@ -337,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,9 +296,7 @@ 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(NULL, &frame->uc.uc_link) ||
- __put_user((void __user *)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))
+ __save_altstack(&frame->uc.uc_stack, __frame->sp))
goto give_sigsegv;
if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
@@ -391,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) {
+ 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",
@@ -421,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() */
@@ -430,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:
@@ -455,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 */
@@ -463,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() */
/*****************************************************************************/
@@ -487,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:
@@ -534,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() */
/*****************************************************************************/
@@ -561,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 c9b2d51ab9a..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
diff --git a/arch/frv/kernel/switch_to.S b/arch/frv/kernel/switch_to.S
index b5275fa9cd0..b06668670fc 100644
--- a/arch/frv/kernel/switch_to.S
+++ b/arch/frv/kernel/switch_to.S
@@ -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 04c6b1677cc..9c4980825bb 100644
--- a/arch/frv/kernel/sys_frv.c
+++ b/arch/frv/kernel/sys_frv.c
@@ -21,194 +21,24 @@
#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>
-/*
- * 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 __user * 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 3e9d7e03fb9..f4dfae2c75a 100644
--- a/arch/frv/kernel/sysctl.c
+++ b/arch/frv/kernel/sysctl.c
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
@@ -47,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 __user *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];
@@ -85,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;
}
@@ -111,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() */
@@ -121,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 __user *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;
@@ -151,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;
}
@@ -164,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,21 +177,19 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
static struct ctl_table frv_table[] =
{
{
- .ctl_name = 1,
.procname = "cache-mode",
.data = NULL,
.maxlen = 0,
.mode = 0644,
- .proc_handler = &procctl_frv_cachemode,
+ .proc_handler = procctl_frv_cachemode,
},
#ifdef CONFIG_MMU
{
- .ctl_name = 2,
.procname = "pin-cxnr",
.data = NULL,
.maxlen = 0,
.mode = 0644,
- .proc_handler = &procctl_frv_pin_cxnr
+ .proc_handler = procctl_frv_pin_cxnr
},
#endif
{}
@@ -203,7 +202,6 @@ static struct ctl_table frv_table[] =
static struct ctl_table frv_dir_table[] =
{
{
- .ctl_name = CTL_FRV,
.procname = "frv",
.mode = 0555,
.child = frv_table
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 69f6a4ef5d6..b457de496b7 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -45,51 +45,18 @@ static irqreturn_t timer_interrupt(int irq, void *dummy);
static struct irqaction timer_irq = {
.handler = timer_interrupt,
.flags = IRQF_DISABLED,
- .mask = CPU_MASK_NONE,
.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)
{
- /* last time the cmos clock got updated */
- static long last_rtc_update = 0;
-
profile_tick(CPU_PROFILING);
- /*
- * 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(1);
-
- /*
- * 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 */
- }
+
+ xtime_update(1);
#ifdef CONFIG_HEARTBEAT
static unsigned short n;
@@ -97,8 +64,6 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
__set_LEDS(n);
#endif /* CONFIG_HEARTBEAT */
- write_sequnlock(&xtime_lock);
-
update_process_times(user_mode(get_irq_regs()));
return IRQ_HANDLED;
@@ -120,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;
@@ -136,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);
diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c
index 2e6098c8557..a6d105d61b2 100644
--- a/arch/frv/kernel/traps.c
+++ b/arch/frv/kernel/traps.c
@@ -23,7 +23,6 @@
#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)
{
}
@@ -284,6 +497,7 @@ void show_regs(struct pt_regs *regs)
int loop;
printk("\n");
+ show_regs_print_info(KERN_DEFAULT);
printk("Frame: @%08lx [%s]\n",
(unsigned long) regs,
@@ -298,8 +512,6 @@ void show_regs(struct pt_regs *regs)
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();
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c
index 9fb771a20df..374f88d6cc0 100644
--- a/arch/frv/kernel/uaccess.c
+++ b/arch/frv/kernel/uaccess.c
@@ -23,8 +23,7 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
char *p, ch;
long err = -EFAULT;
- if (count < 0)
- BUG();
+ BUG_ON(count < 0);
p = dst;
@@ -76,8 +75,7 @@ long strnlen_user(const char __user *src, long count)
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 b95c4eace62..7e958d829ec 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -26,7 +26,7 @@ SECTIONS
_sinittext = .;
.init.text : {
- *(.text.head)
+ HEAD_TEXT
#ifndef CONFIG_DEBUG_INFO
INIT_TEXT
EXIT_TEXT
@@ -35,50 +35,13 @@ SECTIONS
#endif
}
_einittext = .;
- .init.data : { INIT_DATA }
- . = ALIGN(8);
- __setup_start = .;
- .setup.init : { KEEP(*(.init.setup)) }
- __setup_end = .;
+ INIT_DATA_SECTION(8)
+ PERCPU_SECTION(L1_CACHE_BYTES)
- __initcall_start = .;
- .initcall.init : {
- INITCALLS
- }
- __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) }
-
- PERCPU(4096)
-
-#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(4096);
- __initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
- __initramfs_end = .;
-#endif
-
- . = 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)
- }
-
- . = ALIGN(L1_CACHE_BYTES);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
.trap : {
/* trap table management - read entry-table.S before modifying */
. = ALIGN(8192);
@@ -94,10 +57,10 @@ SECTIONS
_text = .;
_stext = .;
.text : {
- *(.text.start)
- *(.text.entry)
- *(.text.break)
- *(.text.tlbmiss)
+ *(.text..start)
+ *(.text..entry)
+ *(.text..break)
+ *(.text..tlbmiss)
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
@@ -124,13 +87,12 @@ SECTIONS
}
- . = ALIGN(8); /* Exception table */
- __start___ex_table = .;
- __ex_table : { KEEP(*(__ex_table)) }
- __stop___ex_table = .;
+ EXCEPTION_TABLE(8)
_sdata = .;
.data : { /* Data */
+ INIT_TASK_DATA(THREAD_SIZE)
+ CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
DATA_DATA
*(.data.*)
EXIT_DATA
@@ -152,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;