diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 09:00:19 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 09:00:19 -0800 |
commit | 17c330f98383629cfd359ee62b3adde1d2a3ff7c (patch) | |
tree | 876bed8fc7de7d404fae579035a948c46a7f05d4 /arch/sparc/kernel | |
parent | 48e902f0a3aea4b6b3a73e9d277b92024a493e6d (diff) | |
parent | 7466bd3caab6bd1d0095de957affbacd02ca58a7 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
sparc64: Fix clock event multiplier printf format.
sparc64: Use clock{source,events}_calc_mult_shift().
sparc64: Use free_bootmem_late() in mdesc_lmb_free().
sparc: Add alignment and emulation fault perf events.
sparc64: Add syscall tracepoint support.
sparc: Stop trying to be so fancy and use __builtin_{memcpy,memset}()
sparc: Use __builtin_object_size() to validate the buffer size for copy_from_user()
sparc64: Add some missing __kprobes annotations to kernel fault paths.
sparc64: Use kprobes_built_in() to avoid ifdefs in fault_64.c
sparc: Validate that kprobe address is 4-byte aligned.
sparc64: Don't specify IRQF_SHARED for LDC interrupts.
sparc64: Fix stack debugging IRQ stack regression.
sparc64: Fix overly strict range type matching for PCI devices.
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r-- | arch/sparc/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/ftrace.c | 11 | ||||
-rw-r--r-- | arch/sparc/kernel/kprobes.c | 3 | ||||
-rw-r--r-- | arch/sparc/kernel/ldc.c | 4 | ||||
-rw-r--r-- | arch/sparc/kernel/mdesc.c | 21 | ||||
-rw-r--r-- | arch/sparc/kernel/of_device_64.c | 14 | ||||
-rw-r--r-- | arch/sparc/kernel/ptrace_64.c | 10 | ||||
-rw-r--r-- | arch/sparc/kernel/syscalls.S | 14 | ||||
-rw-r--r-- | arch/sparc/kernel/time_64.c | 26 | ||||
-rw-r--r-- | arch/sparc/kernel/unaligned_32.c | 15 | ||||
-rw-r--r-- | arch/sparc/kernel/unaligned_64.c | 23 | ||||
-rw-r--r-- | arch/sparc/kernel/visemul.c | 3 |
12 files changed, 70 insertions, 76 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index ec9c7bc67d2..1504df8ddf7 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1294,7 +1294,7 @@ linux_sparc_syscall: sethi %hi(PSR_SYSCALL), %l4 or %l0, %l4, %l0 /* Direct access to user regs, must faster. */ - cmp %g1, NR_SYSCALLS + cmp %g1, NR_syscalls bgeu linux_sparc_ni_syscall sll %g1, 2, %l4 ld [%l7 + %l4], %l7 diff --git a/arch/sparc/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c index d3b1a307656..29973daa993 100644 --- a/arch/sparc/kernel/ftrace.c +++ b/arch/sparc/kernel/ftrace.c @@ -4,6 +4,7 @@ #include <linux/percpu.h> #include <linux/init.h> #include <linux/list.h> +#include <trace/syscall.h> #include <asm/ftrace.h> @@ -91,3 +92,13 @@ int __init ftrace_dyn_arch_init(void *data) } #endif +#ifdef CONFIG_FTRACE_SYSCALLS + +extern unsigned int sys_call_table[]; + +unsigned long __init arch_syscall_addr(int nr) +{ + return (unsigned long)sys_call_table[nr]; +} + +#endif diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c index 3bc6527c95a..6716584e48a 100644 --- a/arch/sparc/kernel/kprobes.c +++ b/arch/sparc/kernel/kprobes.c @@ -46,6 +46,9 @@ struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; int __kprobes arch_prepare_kprobe(struct kprobe *p) { + if ((unsigned long) p->addr & 0x3UL) + return -EILSEQ; + p->ainsn.insn[0] = *p->addr; flushi(&p->ainsn.insn[0]); diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index cb3c72c45aa..e0ba898e30c 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -1242,13 +1242,13 @@ int ldc_bind(struct ldc_channel *lp, const char *name) snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); err = request_irq(lp->cfg.rx_irq, ldc_rx, - IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED, + IRQF_SAMPLE_RANDOM | IRQF_DISABLED, lp->rx_irq_name, lp); if (err) return err; err = request_irq(lp->cfg.tx_irq, ldc_tx, - IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED, + IRQF_SAMPLE_RANDOM | IRQF_DISABLED, lp->tx_irq_name, lp); if (err) { free_irq(lp->cfg.rx_irq, lp); diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 938da19dc06..cdc91d919e9 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -10,6 +10,7 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/miscdevice.h> +#include <linux/bootmem.h> #include <asm/cpudata.h> #include <asm/hypervisor.h> @@ -108,25 +109,15 @@ static struct mdesc_handle * __init mdesc_lmb_alloc(unsigned int mdesc_size) static void mdesc_lmb_free(struct mdesc_handle *hp) { - unsigned int alloc_size, handle_size = hp->handle_size; - unsigned long start, end; + unsigned int alloc_size; + unsigned long start; BUG_ON(atomic_read(&hp->refcnt) != 0); BUG_ON(!list_empty(&hp->list)); - alloc_size = PAGE_ALIGN(handle_size); - - start = (unsigned long) hp; - end = start + alloc_size; - - while (start < end) { - struct page *p; - - p = virt_to_page(start); - ClearPageReserved(p); - __free_page(p); - start += PAGE_SIZE; - } + alloc_size = PAGE_ALIGN(hp->handle_size); + start = __pa(hp); + free_bootmem_late(start, alloc_size); } static struct mdesc_mem_ops lmb_mdesc_ops = { diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 881947e59e9..0a6f2d1798d 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -104,9 +104,19 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, int i; /* Check address type match */ - if ((addr[0] ^ range[0]) & 0x03000000) - return -EINVAL; + if (!((addr[0] ^ range[0]) & 0x03000000)) + goto type_match; + + /* Special exception, we can map a 64-bit address into + * a 32-bit range. + */ + if ((addr[0] & 0x03000000) == 0x03000000 && + (range[0] & 0x03000000) == 0x02000000) + goto type_match; + + return -EINVAL; +type_match: if (of_out_of_range(addr + 1, range + 1, range + na + pna, na - 1, ns)) return -EINVAL; diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 4ae91dc2feb..2f6524d1a81 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -23,6 +23,7 @@ #include <linux/signal.h> #include <linux/regset.h> #include <linux/tracehook.h> +#include <trace/syscall.h> #include <linux/compat.h> #include <linux/elf.h> @@ -37,6 +38,9 @@ #include <asm/cpudata.h> #include <asm/cacheflush.h> +#define CREATE_TRACE_POINTS +#include <trace/events/syscalls.h> + #include "entry.h" /* #define ALLOW_INIT_TRACING */ @@ -1059,6 +1063,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) if (test_thread_flag(TIF_SYSCALL_TRACE)) ret = tracehook_report_syscall_entry(regs); + if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) + trace_sys_enter(regs, regs->u_regs[UREG_G1]); + if (unlikely(current->audit_context) && !ret) audit_syscall_entry((test_thread_flag(TIF_32BIT) ? AUDIT_ARCH_SPARC : @@ -1084,6 +1091,9 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) audit_syscall_exit(result, regs->u_regs[UREG_I0]); } + if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) + trace_sys_exit(regs, regs->u_regs[UREG_G1]); + if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, 0); } diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index d150c2aa98d..dc4a458f74d 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -62,7 +62,7 @@ sys32_rt_sigreturn: #endif .align 32 1: ldx [%g6 + TI_FLAGS], %l5 - andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 + andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 be,pt %icc, rtrap nop call syscall_trace_leave @@ -187,7 +187,7 @@ linux_syscall_trace: .globl linux_sparc_syscall32 linux_sparc_syscall32: /* Direct access to user regs, much faster. */ - cmp %g1, NR_SYSCALLS ! IEU1 Group + cmp %g1, NR_syscalls ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI srl %i0, 0, %o0 ! IEU0 sll %g1, 2, %l4 ! IEU0 Group @@ -198,7 +198,7 @@ linux_sparc_syscall32: srl %i5, 0, %o5 ! IEU1 srl %i2, 0, %o2 ! IEU0 Group - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 + andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 bne,pn %icc, linux_syscall_trace32 ! CTI mov %i0, %l5 ! IEU1 call %l7 ! CTI Group brk forced @@ -210,7 +210,7 @@ linux_sparc_syscall32: .globl linux_sparc_syscall linux_sparc_syscall: /* Direct access to user regs, much faster. */ - cmp %g1, NR_SYSCALLS ! IEU1 Group + cmp %g1, NR_syscalls ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI mov %i0, %o0 ! IEU0 sll %g1, 2, %l4 ! IEU0 Group @@ -221,7 +221,7 @@ linux_sparc_syscall: mov %i3, %o3 ! IEU1 mov %i4, %o4 ! IEU0 Group - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 + andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 bne,pn %icc, linux_syscall_trace ! CTI Group mov %i0, %l5 ! IEU0 2: call %l7 ! CTI Group brk forced @@ -245,7 +245,7 @@ ret_sys_call: cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6 + andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 80: /* System call success, clear Carry condition code. */ andn %g3, %g2, %g3 @@ -260,7 +260,7 @@ ret_sys_call: /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. */ - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6 + andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 sub %g0, %o0, %o0 or %g3, %g2, %g3 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 63f73ae8a89..67e16510288 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -774,26 +774,9 @@ void __devinit setup_sparc64_timer(void) static struct clocksource clocksource_tick = { .rating = 100, .mask = CLOCKSOURCE_MASK(64), - .shift = 16, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static void __init setup_clockevent_multiplier(unsigned long hz) -{ - unsigned long mult, shift = 32; - - while (1) { - mult = div_sc(hz, NSEC_PER_SEC, shift); - if (mult && (mult >> 32UL) == 0UL) - break; - - shift--; - } - - sparc64_clockevent.shift = shift; - sparc64_clockevent.mult = mult; -} - static unsigned long tb_ticks_per_usec __read_mostly; void __delay(unsigned long loops) @@ -828,9 +811,7 @@ void __init time_init(void) clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); clocksource_tick.name = tick_ops->name; - clocksource_tick.mult = - clocksource_hz2mult(freq, - clocksource_tick.shift); + clocksource_calc_mult_shift(&clocksource_tick, freq, 4); clocksource_tick.read = clocksource_tick_read; printk("clocksource: mult[%x] shift[%d]\n", @@ -839,15 +820,14 @@ void __init time_init(void) clocksource_register(&clocksource_tick); sparc64_clockevent.name = tick_ops->name; - - setup_clockevent_multiplier(freq); + clockevents_calc_mult_shift(&sparc64_clockevent, freq, 4); sparc64_clockevent.max_delta_ns = clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); sparc64_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &sparc64_clockevent); - printk("clockevent: mult[%ux] shift[%d]\n", + printk("clockevent: mult[%x] shift[%d]\n", sparc64_clockevent.mult, sparc64_clockevent.shift); setup_sparc64_timer(); diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c index 6b1e6cde6ff..f8514e291e1 100644 --- a/arch/sparc/kernel/unaligned_32.c +++ b/arch/sparc/kernel/unaligned_32.c @@ -17,8 +17,7 @@ #include <asm/uaccess.h> #include <linux/smp.h> #include <linux/smp_lock.h> - -/* #define DEBUG_MNA */ +#include <linux/perf_event.h> enum direction { load, /* ld, ldd, ldh, ldsh */ @@ -29,12 +28,6 @@ enum direction { invalid, }; -#ifdef DEBUG_MNA -static char *dirstrings[] = { - "load", "store", "both", "fpload", "fpstore", "invalid" -}; -#endif - static inline enum direction decode_direction(unsigned int insn) { unsigned long tmp = (insn >> 21) & 1; @@ -255,10 +248,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) unsigned long addr = compute_effective_address(regs, insn); int err; -#ifdef DEBUG_MNA - printk("KMNA: pc=%08lx [dir=%s addr=%08lx size=%d] retpc[%08lx]\n", - regs->pc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); -#endif + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); switch (dir) { case load: err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f), @@ -350,6 +340,7 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn) } addr = compute_effective_address(regs, insn); + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); switch(dir) { case load: err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f), diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index 379209982a0..378ca82b9cc 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -20,10 +20,9 @@ #include <asm/uaccess.h> #include <linux/smp.h> #include <linux/bitops.h> +#include <linux/perf_event.h> #include <asm/fpumacro.h> -/* #define DEBUG_MNA */ - enum direction { load, /* ld, ldd, ldh, ldsh */ store, /* st, std, sth, stsh */ @@ -33,12 +32,6 @@ enum direction { invalid, }; -#ifdef DEBUG_MNA -static char *dirstrings[] = { - "load", "store", "both", "fpload", "fpstore", "invalid" -}; -#endif - static inline enum direction decode_direction(unsigned int insn) { unsigned long tmp = (insn >> 21) & 1; @@ -327,12 +320,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); -#ifdef DEBUG_MNA - printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] " - "retpc[%016lx]\n", - regs->tpc, dirstrings[dir], addr, size, - regs->u_regs[UREG_RETPC]); -#endif + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); switch (asi) { case ASI_NL: case ASI_AIUPL: @@ -399,6 +387,7 @@ int handle_popc(u32 insn, struct pt_regs *regs) int ret, i, rd = ((insn >> 25) & 0x1f); int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; + perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); if (insn & 0x2000) { maybe_flush_windows(0, 0, rd, from_kernel); value = sign_extend_imm13(insn); @@ -445,6 +434,8 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs) int asi = decode_asi(insn, regs); int flag = (freg < 32) ? FPRS_DL : FPRS_DU; + perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); + save_and_clear_fpu(); current_thread_info()->xfsr[0] &= ~0x1c000; if (freg & 3) { @@ -566,6 +557,8 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs) int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; unsigned long *reg; + perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); + maybe_flush_windows(0, 0, rd, from_kernel); reg = fetch_reg_addr(rd, regs); if (from_kernel || rd < 16) { @@ -596,6 +589,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr if (tstate & TSTATE_PRIV) die_if_kernel("lddfmna from kernel", regs); + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar); if (test_thread_flag(TIF_32BIT)) pc = (u32)pc; if (get_user(insn, (u32 __user *) pc) != -EFAULT) { @@ -657,6 +651,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr if (tstate & TSTATE_PRIV) die_if_kernel("stdfmna from kernel", regs); + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar); if (test_thread_flag(TIF_32BIT)) pc = (u32)pc; if (get_user(insn, (u32 __user *) pc) != -EFAULT) { diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c index d231cbd5c52..9dfd2ebcb15 100644 --- a/arch/sparc/kernel/visemul.c +++ b/arch/sparc/kernel/visemul.c @@ -5,6 +5,7 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/thread_info.h> +#include <linux/perf_event.h> #include <asm/ptrace.h> #include <asm/pstate.h> @@ -801,6 +802,8 @@ int vis_emul(struct pt_regs *regs, unsigned int insn) BUG_ON(regs->tstate & TSTATE_PRIV); + perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); + if (test_thread_flag(TIF_32BIT)) pc = (u32)pc; |