diff options
Diffstat (limited to 'arch/frv/kernel')
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(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - - 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 = ¤t->saved_sigmask; - else - oldset = ¤t->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, ¤t->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(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -#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(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->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; |
