From 91887a362984324e254473e92820758c8e658f78 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 16 Mar 2009 14:19:37 +1030 Subject: cpumask: arch_send_call_function_ipi_mask: parisc We're weaning the core code off handing cpumask's around on-stack. This introduces arch_send_call_function_ipi_mask(), and by defining it, the old arch_send_call_function_ipi is defined by the core code. We also take the chance to change send_IPI_mask() and use the new for_each_cpu() iterator. Signed-off-by: Rusty Russell --- arch/parisc/kernel/smp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 9995d7ed581..ba9b6808e2d 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -214,11 +214,11 @@ ipi_send(int cpu, enum ipi_message_type op) } static void -send_IPI_mask(cpumask_t mask, enum ipi_message_type op) +send_IPI_mask(const struct cpumask *mask, enum ipi_message_type op) { int cpu; - for_each_cpu_mask(cpu, mask) + for_each_cpu(cpu, mask) ipi_send(cpu, op); } @@ -257,7 +257,7 @@ smp_send_all_nop(void) send_IPI_allbutself(IPI_NOP); } -void arch_send_call_function_ipi(cpumask_t mask) +void arch_send_call_function_ipi_mask(const struct cpumask *mask) { send_IPI_mask(mask, IPI_CALL_FUNC); } -- cgit v1.2.3 From bd071e1a371d31db243edc4714ff9e8d1ea1309e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 16 Mar 2009 14:19:37 +1030 Subject: cpumask: prepare for iterators to only go to nr_cpu_ids/nr_cpumask_bits.: parisc Impact: cleanup, futureproof In fact, all cpumask ops will only be valid (in general) for bit numbers < nr_cpu_ids. So use that instead of NR_CPUS in various places. This is always safe: no cpu number can be >= nr_cpu_ids, and nr_cpu_ids is initialized to NR_CPUS at boot. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis Acked-by: Ingo Molnar --- arch/parisc/kernel/irq.c | 4 ++-- arch/parisc/kernel/processor.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 29e70e16ede..103752a8fb9 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -311,12 +311,12 @@ unsigned long txn_alloc_addr(unsigned int virt_irq) next_cpu++; /* assign to "next" CPU we want this bugger on */ /* validate entry */ - while ((next_cpu < NR_CPUS) && + while ((next_cpu < nr_cpu_ids) && (!per_cpu(cpu_data, next_cpu).txn_addr || !cpu_online(next_cpu))) next_cpu++; - if (next_cpu >= NR_CPUS) + if (next_cpu >= nr_cpu_ids) next_cpu = 0; /* nothing else, assign monarch */ return txn_affinity_addr(virt_irq, next_cpu); diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index ecb609342fe..44a1a509d89 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -100,8 +100,8 @@ static int __cpuinit processor_probe(struct parisc_device *dev) struct cpuinfo_parisc *p; #ifdef CONFIG_SMP - if (num_online_cpus() >= NR_CPUS) { - printk(KERN_INFO "num_online_cpus() >= NR_CPUS\n"); + if (num_online_cpus() >= nr_cpu_ids) { + printk(KERN_INFO "num_online_cpus() >= nr_cpu_ids\n"); return 1; } #else -- cgit v1.2.3 From 9bc181d8d7cb6462de0c315e364780ad275f7c57 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 16 Mar 2009 14:19:38 +1030 Subject: cpumask: Use accessors code.: parisc Impact: use new API Use the accessors rather than frobbing bits directly. Most of this is in arch code I haven't even compiled, but it is mostly straightforward. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis --- arch/parisc/kernel/processor.c | 2 +- arch/parisc/kernel/smp.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 44a1a509d89..bdbabfb8734 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -214,7 +214,7 @@ static int __cpuinit processor_probe(struct parisc_device *dev) */ #ifdef CONFIG_SMP if (cpuid) { - cpu_set(cpuid, cpu_present_map); + set_cpu_present(cpuid, true); cpu_up(cpuid); } #endif diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index ba9b6808e2d..869197992f9 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -113,7 +113,7 @@ halt_processor(void) { /* REVISIT : redirect I/O Interrupts to another CPU? */ /* REVISIT : does PM *know* this CPU isn't available? */ - cpu_clear(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), false); local_irq_disable(); for (;;) ; @@ -296,13 +296,14 @@ smp_cpu_init(int cpunum) mb(); /* Well, support 2.4 linux scheme as well. */ - if (cpu_test_and_set(cpunum, cpu_online_map)) + if (cpu_isset(cpunum, cpu_online_map)) { extern void machine_halt(void); /* arch/parisc.../process.c */ printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); machine_halt(); } + set_cpu_online(cpunum, true); /* Initialise the idle task for this CPU */ atomic_inc(&init_mm.mm_count); @@ -424,8 +425,8 @@ void __init smp_prepare_boot_cpu(void) /* Setup BSP mappings */ printk(KERN_INFO "SMP: bootstrap CPU ID is %d\n", bootstrap_processor); - cpu_set(bootstrap_processor, cpu_online_map); - cpu_set(bootstrap_processor, cpu_present_map); + set_cpu_online(bootstrap_processor, true); + set_cpu_present(bootstrap_processor, true); } @@ -436,8 +437,7 @@ void __init smp_prepare_boot_cpu(void) */ void __init smp_prepare_cpus(unsigned int max_cpus) { - cpus_clear(cpu_present_map); - cpu_set(0, cpu_present_map); + init_cpu_present(cpumask_of(0)); parisc_max_cpus = max_cpus; if (!max_cpus) -- cgit v1.2.3 From 1152a68c4226ce48c95241b6ffc543850b4b3a97 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Jan 2009 19:30:18 +0100 Subject: parisc: use constants instead of numbers in assembly A few small fixups: * _PAGE_SIZE_ENCODING_DEFAULT is wrong here, as one might assume that it's possible to define the page size that way. This is wrong. Use 0 instead. * use constants instead of hardcoded numerical values in depi and extru while building the PFN out of the pte entry * use SHRREG instead of extru (iitlba expects the PFN at bits {7..26}) Still wondering why we can use the same register (pte) as extru source and target register, but it seems to work on PA1.1 and PA2.0... Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/entry.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 0db9fdcb770..0f7ff938b06 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -563,8 +563,8 @@ /* Get rid of prot bits and convert to page addr for iitlba */ - depi _PAGE_SIZE_ENCODING_DEFAULT,31,ASM_PFN_PTE_SHIFT,\pte - extru \pte,24,25,\pte + depi 0,31,ASM_PFN_PTE_SHIFT,\pte + SHRREG \pte,(ASM_PFN_PTE_SHIFT-(31-26)),\pte .endm /* This is for ILP32 PA2.0 only. The TLB insertion needs @@ -1337,8 +1337,8 @@ nadtlb_check_flush_11: /* Get rid of prot bits and convert to page addr for idtlba */ - depi 0,31,12,pte - extru pte,24,25,pte + depi 0,31,ASM_PFN_PTE_SHIFT,pte + SHRREG pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 -- cgit v1.2.3 From 445c088f88d63db49598390be3525252d211688f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 30 Jan 2009 01:03:50 +0000 Subject: parisc: expose 32/64-bit capabilities in cpuinfo It'd be rather useful for debian-installer if we could get hold of accurate firmware information on whether only 32-bit kernels are supported, only 64-bit kernels, or both; this would allow us to present an accurate menu of kernel packages if more than one is available, rather than the user having to guess. This patch attempts to expose it in cpuinfo. I adjusted pdc_model_capabilities to cope with a potential PDC_INVALID_ARG return as the firmware manual instructs, by assuming 32-bit only. This may be the wrong place for it. I made up user-visible capability names by total fiat and for the moment ignored the other bits that may appear in the capabilities word. I have no PA-RISC machine myself to test on, and no PA experience either, so I rather hope that somebody will kind-heartedly take this and fix it up if needed. I ran it past Dann Frazier on IRC and he said "looks good to me", but I think without testing. Also, this is against the Ubuntu 2.6.28 kernel tree since that's what I had handy and I was a bit tight on disk space to slurp down another tree. Sorry if it's skewed in any relevant way; I'll be happy to adjust if necessary. Thanks in advance! Signed-off-by: Colin Watson Signed-off-by: Kyle McMartin --- arch/parisc/kernel/firmware.c | 6 +++++- arch/parisc/kernel/processor.c | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index f6d241238a7..4c247e02d9b 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -527,7 +527,11 @@ int pdc_model_capabilities(unsigned long *capabilities) pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); convert_to_wide(pdc_result); - *capabilities = pdc_result[0]; + if (retval == PDC_OK) { + *capabilities = pdc_result[0]; + } else { + *capabilities = PDC_MODEL_OS32; + } spin_unlock_irqrestore(&pdc_lock, flags); return retval; diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index ecb609342fe..df5e28c7a82 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -364,6 +364,13 @@ show_cpuinfo (struct seq_file *m, void *v) boot_cpu_data.cpu_hz / 1000000, boot_cpu_data.cpu_hz % 1000000 ); + seq_printf(m, "capabilities\t:"); + if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32) + seq_printf(m, " os32"); + if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS64) + seq_printf(m, " os64"); + seq_printf(m, "\n"); + seq_printf(m, "model\t\t: %s\n" "model name\t: %s\n", boot_cpu_data.pdc.sys_model_name, -- cgit v1.2.3 From afca2523876301cc6130fc3cc402173eeeb89830 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 5 Feb 2009 00:06:00 +0100 Subject: parisc: allow to build with 16k default kernel page size Introduce new convert_for_tlb_insert20 macro and use it to replace assembler statements with hardcoded constants. This change allows the parisc64 kernel to boot with 16kb default kernel page size, aka CONFIG_PARISC_PAGE_SIZE_16KB=y. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/entry.S | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 0f7ff938b06..4e9dd15e076 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -505,6 +505,18 @@ STREG \pte,0(\ptep) .endm + /* bitshift difference between a PFN (based on kernel's PAGE_SIZE) + * to a CPU TLB 4k PFN (4k => 12 bits to shift) */ + #define PAGE_ADD_SHIFT (PAGE_SHIFT-12) + + /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ + .macro convert_for_tlb_insert20 pte + extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\ + 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte + depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\ + (63-58)+PAGE_ADD_SHIFT,\pte + .endm + /* Convert the pte and prot to tlb insertion values. How * this happens is quite subtle, read below */ .macro make_insert_tlb spc,pte,prot @@ -544,8 +556,7 @@ depi 1,12,1,\prot /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ - extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte - depdi _PAGE_SIZE_ENCODING_DEFAULT,63,63-58,\pte + convert_for_tlb_insert20 \pte .endm /* Identical macro to make_insert_tlb above, except it @@ -1244,10 +1255,9 @@ nadtlb_check_flush_20w: depdi,z 7,7,3,prot depdi 1,10,1,prot - /* Get rid of prot bits and convert to page addr for idtlbt */ + /* Drop prot bits from pte and convert to page addr for idtlbt */ + convert_for_tlb_insert20 pte - depdi 0,63,12,pte - extrd,u pte,56,52,pte idtlbt pte,prot rfir @@ -1403,10 +1413,9 @@ nadtlb_check_flush_20: depdi,z 7,7,3,prot depdi 1,10,1,prot - /* Get rid of prot bits and convert to page addr for idtlbt */ + /* Drop prot bits from pte and convert to page addr for idtlbt */ + convert_for_tlb_insert20 pte - depdi 0,63,12,pte - extrd,u pte,56,32,pte idtlbt pte,prot rfir -- cgit v1.2.3 From 548f1176f0ac637eff895defb715ce6fde7c460a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 6 Feb 2009 21:50:39 +0100 Subject: parisc: add LATENCYTOP_SUPPORT and CONFIG_STACKTRACE_SUPPORT Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/Makefile | 1 + arch/parisc/kernel/stacktrace.c | 63 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 arch/parisc/kernel/stacktrace.c (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 016d3fc4111..a7ba8cd9417 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_PA11) += pci-dma.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o signal32.o +obj-$(CONFIG_STACKTRACE)+= stacktrace.o # only supported for PCX-W/U in 64-bit mode at the moment obj-$(CONFIG_64BIT) += perf.o perf_asm.o diff --git a/arch/parisc/kernel/stacktrace.c b/arch/parisc/kernel/stacktrace.c new file mode 100644 index 00000000000..2fe914c5f53 --- /dev/null +++ b/arch/parisc/kernel/stacktrace.c @@ -0,0 +1,63 @@ +/* + * Stack trace management functions + * + * Copyright (C) 2009 Helge Deller + * based on arch/x86/kernel/stacktrace.c by Ingo Molnar + * and parisc unwind functions by Randolph Chung + * + * TODO: Userspace stacktrace (CONFIG_USER_STACKTRACE_SUPPORT) + */ +#include +#include + +#include + +static void dump_trace(struct task_struct *task, struct stack_trace *trace) +{ + struct unwind_frame_info info; + + /* initialize unwind info */ + if (task == current) { + unsigned long sp; + struct pt_regs r; +HERE: + asm volatile ("copy %%r30, %0" : "=r"(sp)); + memset(&r, 0, sizeof(struct pt_regs)); + r.iaoq[0] = (unsigned long)&&HERE; + r.gr[2] = (unsigned long)__builtin_return_address(0); + r.gr[30] = sp; + unwind_frame_init(&info, task, &r); + } else { + unwind_frame_init_from_blocked_task(&info, task); + } + + /* unwind stack and save entries in stack_trace struct */ + trace->nr_entries = 0; + while (trace->nr_entries < trace->max_entries) { + if (unwind_once(&info) < 0 || info.ip == 0) + break; + + if (__kernel_text_address(info.ip)) + trace->entries[trace->nr_entries++] = info.ip; + } +} + + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +void save_stack_trace(struct stack_trace *trace) +{ + dump_trace(current, trace); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + dump_trace(tsk, trace); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); -- cgit v1.2.3 From 803094f480aa5b7dd5187a17e6e60ff24721c212 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 13 Feb 2009 23:58:29 +0100 Subject: parisc: simplify sys_clone() No need to test clone_flags here and set parent_tidptr and child_tidptr accordingly. The same check will be done in do_fork() and copy_process() anyway. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/process.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index b80e02a4d81..ad585fd7748 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -231,8 +231,8 @@ sys_clone(unsigned long clone_flags, unsigned long usp, However, these last 3 args are only examined if the proper flags are set. */ - int __user *child_tidptr; - int __user *parent_tidptr; + int __user *parent_tidptr = (int __user *)regs->gr[24]; + int __user *child_tidptr = (int __user *)regs->gr[22]; /* usp must be word aligned. This also prevents users from * passing in the value 1 (which is the signal for a special @@ -243,16 +243,6 @@ sys_clone(unsigned long clone_flags, unsigned long usp, if (usp == 0) usp = regs->gr[30]; - if (clone_flags & CLONE_PARENT_SETTID) - parent_tidptr = (int __user *)regs->gr[24]; - else - parent_tidptr = NULL; - - if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) - child_tidptr = (int __user *)regs->gr[22]; - else - child_tidptr = NULL; - return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr); } -- cgit v1.2.3 From d75f054a2cf0614ff63d534ff21ca8eaab41e713 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 9 Feb 2009 00:43:36 +0100 Subject: parisc: add ftrace (function and graph tracer) functionality This patch adds the ftrace debugging functionality to the parisc kernel. It will currently only work with 64bit kernels, because the gcc options -pg and -ffunction-sections can't be enabled at the same time and -ffunction-sections is still needed to be able to link 32bit kernels. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/Makefile | 14 +++ arch/parisc/kernel/entry.S | 27 ++++++ arch/parisc/kernel/ftrace.c | 185 ++++++++++++++++++++++++++++++++++++++ arch/parisc/kernel/parisc_ksyms.c | 5 ++ arch/parisc/kernel/smp.c | 3 +- arch/parisc/kernel/time.c | 3 +- arch/parisc/kernel/traps.c | 2 +- arch/parisc/kernel/vmlinux.lds.S | 2 + 8 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 arch/parisc/kernel/ftrace.c (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index a7ba8cd9417..67db0722e6c 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -11,6 +11,18 @@ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ topology.o +ifdef CONFIG_FUNCTION_TRACER +# Do not profile debug and lowlevel utilities +CFLAGS_REMOVE_ftrace.o = -pg +CFLAGS_REMOVE_cache.o = -pg +CFLAGS_REMOVE_irq.o = -pg +CFLAGS_REMOVE_pacache.o = -pg +CFLAGS_REMOVE_perf.o = -pg +CFLAGS_REMOVE_traps.o = -pg +CFLAGS_REMOVE_unaligned.o = -pg +CFLAGS_REMOVE_unwind.o = -pg +endif + obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PA11) += pci-dma.o obj-$(CONFIG_PCI) += pci.o @@ -19,3 +31,5 @@ obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o signal32.o obj-$(CONFIG_STACKTRACE)+= stacktrace.o # only supported for PCX-W/U in 64-bit mode at the moment obj-$(CONFIG_64BIT) += perf.o perf_asm.o +obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 4e9dd15e076..ae3e70cd1e1 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -2185,6 +2185,33 @@ syscall_do_resched: ENDPROC(syscall_exit) +#ifdef CONFIG_FUNCTION_TRACER + .import ftrace_function_trampoline,code +ENTRY(_mcount) + copy %r3, %arg2 + b ftrace_function_trampoline + nop +ENDPROC(_mcount) + +ENTRY(return_to_handler) + load32 return_trampoline, %rp + copy %ret0, %arg0 + copy %ret1, %arg1 + b ftrace_return_to_handler + nop +return_trampoline: + copy %ret0, %rp + copy %r23, %ret0 + copy %r24, %ret1 + +.globl ftrace_stub +ftrace_stub: + bv %r0(%rp) + nop +ENDPROC(return_to_handler) +#endif /* CONFIG_FUNCTION_TRACER */ + + get_register: /* * get_register is used by the non access tlb miss handlers to diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c new file mode 100644 index 00000000000..9877372ffdb --- /dev/null +++ b/arch/parisc/kernel/ftrace.c @@ -0,0 +1,185 @@ +/* + * Code for tracing calls in Linux kernel. + * Copyright (C) 2009 Helge Deller + * + * based on code for x86 which is: + * Copyright (C) 2007-2008 Steven Rostedt + * + * future possible enhancements: + * - add CONFIG_DYNAMIC_FTRACE + * - add CONFIG_STACK_TRACER + */ + +#include +#include + +#include +#include + + + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + +/* Add a function return address to the trace stack on thread info.*/ +static int push_return_trace(unsigned long ret, unsigned long long time, + unsigned long func, int *depth) +{ + int index; + + if (!current->ret_stack) + return -EBUSY; + + /* The return trace stack is full */ + if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { + atomic_inc(¤t->trace_overrun); + return -EBUSY; + } + + index = ++current->curr_ret_stack; + barrier(); + current->ret_stack[index].ret = ret; + current->ret_stack[index].func = func; + current->ret_stack[index].calltime = time; + *depth = index; + + return 0; +} + +/* Retrieve a function return address to the trace stack on thread info.*/ +static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) +{ + int index; + + index = current->curr_ret_stack; + + if (unlikely(index < 0)) { + ftrace_graph_stop(); + WARN_ON(1); + /* Might as well panic, otherwise we have no where to go */ + *ret = (unsigned long) + dereference_function_descriptor(&panic); + return; + } + + *ret = current->ret_stack[index].ret; + trace->func = current->ret_stack[index].func; + trace->calltime = current->ret_stack[index].calltime; + trace->overrun = atomic_read(¤t->trace_overrun); + trace->depth = index; + barrier(); + current->curr_ret_stack--; + +} + +/* + * Send the trace to the ring-buffer. + * @return the original return address. + */ +unsigned long ftrace_return_to_handler(unsigned long retval0, + unsigned long retval1) +{ + struct ftrace_graph_ret trace; + unsigned long ret; + + pop_return_trace(&trace, &ret); + trace.rettime = cpu_clock(raw_smp_processor_id()); + ftrace_graph_return(&trace); + + if (unlikely(!ret)) { + ftrace_graph_stop(); + WARN_ON(1); + /* Might as well panic. What else to do? */ + ret = (unsigned long) + dereference_function_descriptor(&panic); + } + + /* HACK: we hand over the old functions' return values + in %r23 and %r24. Assembly in entry.S will take care + and move those to their final registers %ret0 and %ret1 */ + asm( "copy %0, %%r23 \n\t" + "copy %1, %%r24 \n" : : "r" (retval0), "r" (retval1) ); + + return ret; +} + +/* + * Hook the return address and push it in the stack of return addrs + * in current thread info. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +{ + unsigned long old; + unsigned long long calltime; + struct ftrace_graph_ent trace; + + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + return; + + old = *parent; + *parent = (unsigned long) + dereference_function_descriptor(&return_to_handler); + + if (unlikely(!__kernel_text_address(old))) { + ftrace_graph_stop(); + *parent = old; + WARN_ON(1); + return; + } + + calltime = cpu_clock(raw_smp_processor_id()); + + if (push_return_trace(old, calltime, + self_addr, &trace.depth) == -EBUSY) { + *parent = old; + return; + } + + trace.func = self_addr; + + /* Only trace if the calling function expects to */ + if (!ftrace_graph_entry(&trace)) { + current->curr_ret_stack--; + *parent = old; + } +} + +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + + +void ftrace_function_trampoline(unsigned long parent, + unsigned long self_addr, + unsigned long org_sp_gr3) +{ + extern ftrace_func_t ftrace_trace_function; + + if (function_trace_stop) + return; + + if (ftrace_trace_function != ftrace_stub) { + ftrace_trace_function(parent, self_addr); + return; + } +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + if (ftrace_graph_entry && ftrace_graph_return) { + unsigned long sp; + unsigned long *parent_rp; + + asm volatile ("copy %%r30, %0" : "=r"(sp)); + /* sanity check: is stack pointer which we got from + assembler function in entry.S in a reasonable + range compared to current stack pointer? */ + if ((sp - org_sp_gr3) > 0x400) + return; + + /* calculate pointer to %rp in stack */ + parent_rp = (unsigned long *) org_sp_gr3 - 0x10; + /* sanity check: parent_rp should hold parent */ + if (*parent_rp != parent) + return; + + prepare_ftrace_return(parent_rp, self_addr); + return; + } +#endif +} + diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 0eecfbbc59c..df653663d3d 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -153,5 +153,10 @@ EXPORT_SYMBOL(node_data); EXPORT_SYMBOL(pfnnid_map); #endif +#ifdef CONFIG_FUNCTION_TRACER +extern void _mcount(void); +EXPORT_SYMBOL(_mcount); +#endif + /* from pacache.S -- needed for copy_page */ EXPORT_SYMBOL(copy_user_page_asm); diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 9995d7ed581..8545f2e7a2c 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -120,7 +121,7 @@ halt_processor(void) } -irqreturn_t +irqreturn_t __irq_entry ipi_interrupt(int irq, void *dev_id) { int this_cpu = smp_processor_id(); diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 9d46c43a415..badaad9ff13 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -53,7 +54,7 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */ * held off for an arbitrarily long period of time by interrupts being * disabled, so we may miss one or more ticks. */ -irqreturn_t timer_interrupt(int irq, void *dev_id) +irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) { unsigned long now; unsigned long next_tick; diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index ba658d2086f..7bf122a5f16 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -494,7 +494,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o panic(msg); } -void handle_interruption(int code, struct pt_regs *regs) +void notrace handle_interruption(int code, struct pt_regs *regs) { unsigned long fault_address = 0; unsigned long fault_space = 0; diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 1a3b6ccd362..fd2cc4fd2b6 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -54,6 +54,8 @@ SECTIONS TEXT_TEXT SCHED_TEXT LOCK_TEXT + KPROBES_TEXT + IRQENTRY_TEXT *(.text.do_softirq) *(.text.sys_exit) *(.text.do_sigaltstack) -- cgit v1.2.3 From c84c3a698f17ae5d55a6ecc76298fb894e106336 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 30 Dec 2008 02:47:38 +0000 Subject: parisc: document light weight syscall ABI Document the LWS ABI including implementation notes for userspace, and comment cleanup. Remove extraneous .align 16 after lws_lock_start. Signed-off-by: Carlos O'Donell Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/syscall.S | 58 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 69b6eebc466..59fc1a43ec3 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -365,17 +365,51 @@ tracesys_sigexit: /********************************************************* - Light-weight-syscall code + 32/64-bit Light-Weight-Syscall ABI - r20 - lws number - r26,r25,r24,r23,r22 - Input registers - r28 - Function return register - r21 - Error code. + * - Indicates a hint for userspace inline asm + implementations. - Scracth: Any of the above that aren't being - currently used, including r1. + Syscall number (caller-saves) + - %r20 + * In asm clobber. - Return pointer: r31 (Not usable) + Argument registers (caller-saves) + - %r26, %r25, %r24, %r23, %r22 + * In asm input. + + Return registers (caller-saves) + - %r28 (return), %r21 (errno) + * In asm output. + + Caller-saves registers + - %r1, %r27, %r29 + - %r2 (return pointer) + - %r31 (ble link register) + * In asm clobber. + + Callee-saves registers + - %r3-%r18 + - %r30 (stack pointer) + * Not in asm clobber. + + If userspace is 32-bit: + Callee-saves registers + - %r19 (32-bit PIC register) + + Differences from 32-bit calling convention: + - Syscall number in %r20 + - Additional argument register %r22 (arg4) + - Callee-saves %r19. + + If userspace is 64-bit: + Callee-saves registers + - %r27 (64-bit PIC register) + + Differences from 64-bit calling convention: + - Syscall number in %r20 + - Additional argument register %r22 (arg4) + - Callee-saves %r27. Error codes returned by entry path: @@ -473,7 +507,8 @@ lws_compare_and_swap64: b,n lws_compare_and_swap #else /* If we are not a 64-bit kernel, then we don't - * implement having 64-bit input registers + * have 64-bit input registers, and calling + * the 64-bit LWS CAS returns ENOSYS. */ b,n lws_exit_nosys #endif @@ -635,12 +670,15 @@ END(sys_call_table64) /* All light-weight-syscall atomic operations will use this set of locks + + NOTE: The lws_lock_start symbol must be + at least 16-byte aligned for safe use + with ldcw. */ .section .data .align PAGE_SIZE ENTRY(lws_lock_start) /* lws locks */ - .align 16 .rept 16 /* Keep locks aligned at 16-bytes */ .word 1 -- cgit v1.2.3 From c48faf86b0d59cc43ff4eede59c4af7afbd7c0ff Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 16 Feb 2009 03:03:11 +0000 Subject: parisc: oops_enter()/oops_exit() in die() As pointed out by Russell in http://marc.info/?l=linux-arch&m=118208089204630&w=2 Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/traps.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 7bf122a5f16..c32f5d6d778 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -247,6 +247,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) oops_in_progress = 1; + oops_enter(); + /* Amuse the user in a SPARC fashion */ if (err) printk( KERN_CRIT " _______________________________ \n" @@ -293,6 +295,7 @@ KERN_CRIT " || ||\n"); panic("Fatal exception"); } + oops_exit(); do_exit(SIGSEGV); } -- cgit v1.2.3 From bf589a349b9a41ea202ddb8115b18f543b944bfd Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 15 Mar 2009 16:44:25 -0400 Subject: parisc: Move kernel Elf_Fdesc define to elf.h probably won't be exported to userspace, but play it safe and cram it in a #ifdef __KERNEL__ guard. Signed-off-by: Kyle McMartin --- arch/parisc/kernel/module.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 9013243cecc..3439cbd896b 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -115,8 +115,6 @@ struct got_entry { Elf32_Addr addr; }; -#define Elf_Fdesc Elf32_Fdesc - struct stub_entry { Elf32_Word insns[2]; /* each stub entry has two insns */ }; @@ -125,8 +123,6 @@ struct got_entry { Elf64_Addr addr; }; -#define Elf_Fdesc Elf64_Fdesc - struct stub_entry { Elf64_Word insns[4]; /* each stub entry has four insns */ }; -- cgit v1.2.3 From b609308e1415efebdf79ebd553f4dd47b0ff2722 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 15 Mar 2009 16:49:55 -0400 Subject: parisc: move dereference_function_descriptor to process.c Commit deac93df26b20cf8438339b5935b5f5643bc30c9 fixed up printing of %pF on parisc, but added the dereference_function_descriptor prototype to module.c... this isn't a particularly wise idea as module.c might not always be compiled. Signed-off-by: Kyle McMartin --- arch/parisc/kernel/module.c | 14 -------------- arch/parisc/kernel/process.c | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 15 deletions(-) (limited to 'arch/parisc/kernel') diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 3439cbd896b..ecd1c502444 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -61,9 +61,7 @@ #include #include #include -#include -#include #include #if 0 @@ -912,15 +910,3 @@ void module_arch_cleanup(struct module *mod) deregister_unwind_table(mod); module_bug_cleanup(mod); } - -#ifdef CONFIG_64BIT -void *dereference_function_descriptor(void *ptr) -{ - Elf64_Fdesc *desc = ptr; - void *p; - - if (!probe_kernel_address(&desc->addr, p)) - ptr = p; - return ptr; -} -#endif diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index ad585fd7748..029831dfce3 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -46,14 +46,15 @@ #include #include #include +#include #include #include #include #include #include -#include #include +#include /* * The idle thread. There's no useful work to be @@ -390,3 +391,15 @@ get_wchan(struct task_struct *p) } while (count++ < 16); return 0; } + +#ifdef CONFIG_64BIT +void *dereference_function_descriptor(void *ptr) +{ + Elf64_Fdesc *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->addr, p)) + ptr = p; + return ptr; +} +#endif -- cgit v1.2.3