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.
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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();
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user