Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6 master
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 4 Apr 2010 19:14:44 +0000 (12:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 4 Apr 2010 19:14:44 +0000 (12:14 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  sunxvr500: Ignore secondary output PCI devices.
  sparc64: Implement perf_arch_fetch_caller_regs
  sparc64: Update defconfig.
  sparc64: Fix array size reported by vmemmap_populate()
  sparc: Fix regset register window handling.
  drivers/serial/sunsu.c: Correct use after free

16 files changed:
arch/powerpc/kernel/misc.S
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/dumpstack.h
arch/x86/kernel/kgdb.c
arch/x86/kernel/smpboot.c
fs/proc/task_mmu.c
include/linux/perf_event.h
kernel/perf_event.c
kernel/sched.c
kernel/sched_debug.c
kernel/trace/ring_buffer.c
kernel/trace/trace_clock.c
kernel/trace/trace_event_perf.c
tools/perf/Makefile
tools/perf/util/scripting-engines/trace-event-python.c

index b485a87c94e13b624fb2ab969e753679977ae4f9..22e507c8a5566d1f4dfcfe9db67482e3c0e83e35 100644 (file)
@@ -128,7 +128,6 @@ _GLOBAL(__restore_cpu_power7)
        /* place holder */
        blr
 
-#ifdef CONFIG_EVENT_TRACING
 /*
  * Get a minimal set of registers for our caller's nth caller.
  * r3 = regs pointer, r5 = n.
@@ -154,4 +153,3 @@ _GLOBAL(perf_arch_fetch_caller_regs)
        PPC_STL r4,_NIP-STACK_FRAME_OVERHEAD(r3)
        PPC_STL r7,_LINK-STACK_FRAME_OVERHEAD(r3)
        blr
-#endif /* CONFIG_EVENT_TRACING */
index 60398a0d947c855fbc25687694bb6a2b41100a3d..53ea4cf1a8784f23893ed5cab38c560d34ca634a 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/apic.h>
 #include <asm/stacktrace.h>
 #include <asm/nmi.h>
+#include <asm/compat.h>
 
 static u64 perf_event_mask __read_mostly;
 
@@ -158,7 +159,7 @@ struct x86_pmu {
                                                 struct perf_event *event);
        struct event_constraint *event_constraints;
 
-       void            (*cpu_prepare)(int cpu);
+       int             (*cpu_prepare)(int cpu);
        void            (*cpu_starting)(int cpu);
        void            (*cpu_dying)(int cpu);
        void            (*cpu_dead)(int cpu);
@@ -1333,11 +1334,12 @@ static int __cpuinit
 x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
 {
        unsigned int cpu = (long)hcpu;
+       int ret = NOTIFY_OK;
 
        switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_UP_PREPARE:
                if (x86_pmu.cpu_prepare)
-                       x86_pmu.cpu_prepare(cpu);
+                       ret = x86_pmu.cpu_prepare(cpu);
                break;
 
        case CPU_STARTING:
@@ -1350,6 +1352,7 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
                        x86_pmu.cpu_dying(cpu);
                break;
 
+       case CPU_UP_CANCELED:
        case CPU_DEAD:
                if (x86_pmu.cpu_dead)
                        x86_pmu.cpu_dead(cpu);
@@ -1359,7 +1362,7 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
                break;
        }
 
-       return NOTIFY_OK;
+       return ret;
 }
 
 static void __init pmu_check_apic(void)
@@ -1628,14 +1631,42 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
        return len;
 }
 
-static int copy_stack_frame(const void __user *fp, struct stack_frame *frame)
+#ifdef CONFIG_COMPAT
+static inline int
+perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
 {
-       unsigned long bytes;
+       /* 32-bit process in 64-bit kernel. */
+       struct stack_frame_ia32 frame;
+       const void __user *fp;
 
-       bytes = copy_from_user_nmi(frame, fp, sizeof(*frame));
+       if (!test_thread_flag(TIF_IA32))
+               return 0;
+
+       fp = compat_ptr(regs->bp);
+       while (entry->nr < PERF_MAX_STACK_DEPTH) {
+               unsigned long bytes;
+               frame.next_frame     = 0;
+               frame.return_address = 0;
+
+               bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
+               if (bytes != sizeof(frame))
+                       break;
+
+               if (fp < compat_ptr(regs->sp))
+                       break;
 
-       return bytes == sizeof(*frame);
+               callchain_store(entry, frame.return_address);
+               fp = compat_ptr(frame.next_frame);
+       }
+       return 1;
+}
+#else
+static inline int
+perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
+{
+    return 0;
 }
+#endif
 
 static void
 perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
@@ -1651,11 +1682,16 @@ perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
        callchain_store(entry, PERF_CONTEXT_USER);
        callchain_store(entry, regs->ip);
 
+       if (perf_callchain_user32(regs, entry))
+               return;
+
        while (entry->nr < PERF_MAX_STACK_DEPTH) {
+               unsigned long bytes;
                frame.next_frame             = NULL;
                frame.return_address = 0;
 
-               if (!copy_stack_frame(fp, &frame))
+               bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
+               if (bytes != sizeof(frame))
                        break;
 
                if ((unsigned long)fp < regs->sp)
@@ -1702,7 +1738,6 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
        return entry;
 }
 
-#ifdef CONFIG_EVENT_TRACING
 void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip)
 {
        regs->ip = ip;
@@ -1714,4 +1749,3 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski
        regs->cs = __KERNEL_CS;
        local_save_flags(regs->flags);
 }
-#endif
index b87e0b6970cbc363d2a6c4b233796416176ba09e..db6f7d4056e110873cbef10b92841152458871a1 100644 (file)
@@ -137,6 +137,13 @@ static inline int amd_is_nb_event(struct hw_perf_event *hwc)
        return (hwc->config & 0xe0) == 0xe0;
 }
 
+static inline int amd_has_nb(struct cpu_hw_events *cpuc)
+{
+       struct amd_nb *nb = cpuc->amd_nb;
+
+       return nb && nb->nb_id != -1;
+}
+
 static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
                                      struct perf_event *event)
 {
@@ -147,7 +154,7 @@ static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
        /*
         * only care about NB events
         */
-       if (!(nb && amd_is_nb_event(hwc)))
+       if (!(amd_has_nb(cpuc) && amd_is_nb_event(hwc)))
                return;
 
        /*
@@ -214,7 +221,7 @@ amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
        /*
         * if not NB event or no NB, then no constraints
         */
-       if (!(nb && amd_is_nb_event(hwc)))
+       if (!(amd_has_nb(cpuc) && amd_is_nb_event(hwc)))
                return &unconstrained;
 
        /*
@@ -293,51 +300,55 @@ static struct amd_nb *amd_alloc_nb(int cpu, int nb_id)
        return nb;
 }
 
-static void amd_pmu_cpu_online(int cpu)
+static int amd_pmu_cpu_prepare(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+
+       WARN_ON_ONCE(cpuc->amd_nb);
+
+       if (boot_cpu_data.x86_max_cores < 2)
+               return NOTIFY_OK;
+
+       cpuc->amd_nb = amd_alloc_nb(cpu, -1);
+       if (!cpuc->amd_nb)
+               return NOTIFY_BAD;
+
+       return NOTIFY_OK;
+}
+
+static void amd_pmu_cpu_starting(int cpu)
 {
-       struct cpu_hw_events *cpu1, *cpu2;
-       struct amd_nb *nb = NULL;
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       struct amd_nb *nb;
        int i, nb_id;
 
        if (boot_cpu_data.x86_max_cores < 2)
                return;
 
-       /*
-        * function may be called too early in the
-        * boot process, in which case nb_id is bogus
-        */
        nb_id = amd_get_nb_id(cpu);
-       if (nb_id == BAD_APICID)
-               return;
-
-       cpu1 = &per_cpu(cpu_hw_events, cpu);
-       cpu1->amd_nb = NULL;
+       WARN_ON_ONCE(nb_id == BAD_APICID);
 
        raw_spin_lock(&amd_nb_lock);
 
        for_each_online_cpu(i) {
-               cpu2 = &per_cpu(cpu_hw_events, i);
-               nb = cpu2->amd_nb;
-               if (!nb)
+               nb = per_cpu(cpu_hw_events, i).amd_nb;
+               if (WARN_ON_ONCE(!nb))
                        continue;
-               if (nb->nb_id == nb_id)
-                       goto found;
-       }
 
-       nb = amd_alloc_nb(cpu, nb_id);
-       if (!nb) {
-               pr_err("perf_events: failed NB allocation for CPU%d\n", cpu);
-               raw_spin_unlock(&amd_nb_lock);
-               return;
+               if (nb->nb_id == nb_id) {
+                       kfree(cpuc->amd_nb);
+                       cpuc->amd_nb = nb;
+                       break;
+               }
        }
-found:
-       nb->refcnt++;
-       cpu1->amd_nb = nb;
+
+       cpuc->amd_nb->nb_id = nb_id;
+       cpuc->amd_nb->refcnt++;
 
        raw_spin_unlock(&amd_nb_lock);
 }
 
-static void amd_pmu_cpu_offline(int cpu)
+static void amd_pmu_cpu_dead(int cpu)
 {
        struct cpu_hw_events *cpuhw;
 
@@ -349,8 +360,10 @@ static void amd_pmu_cpu_offline(int cpu)
        raw_spin_lock(&amd_nb_lock);
 
        if (cpuhw->amd_nb) {
-               if (--cpuhw->amd_nb->refcnt == 0)
-                       kfree(cpuhw->amd_nb);
+               struct amd_nb *nb = cpuhw->amd_nb;
+
+               if (nb->nb_id == -1 || --nb->refcnt == 0)
+                       kfree(nb);
 
                cpuhw->amd_nb = NULL;
        }
@@ -379,8 +392,9 @@ static __initconst struct x86_pmu amd_pmu = {
        .get_event_constraints  = amd_get_event_constraints,
        .put_event_constraints  = amd_put_event_constraints,
 
-       .cpu_prepare            = amd_pmu_cpu_online,
-       .cpu_dead               = amd_pmu_cpu_offline,
+       .cpu_prepare            = amd_pmu_cpu_prepare,
+       .cpu_starting           = amd_pmu_cpu_starting,
+       .cpu_dead               = amd_pmu_cpu_dead,
 };
 
 static __init int amd_pmu_init(void)
index 29e5f7c845b25e4ef3d92f6bc79a7e79c050e942..e39e77168a3786e4e5f21e09d6523bd47d5be631 100644 (file)
@@ -30,6 +30,11 @@ struct stack_frame {
        unsigned long return_address;
 };
 
+struct stack_frame_ia32 {
+    u32 next_frame;
+    u32 return_address;
+};
+
 static inline unsigned long rewind_frame_pointer(int n)
 {
        struct stack_frame *frame;
index bfba6019d762aa6652e58b3b09681a83b2e74525..b2258ca9100349c2618d00e4aadf8c7cdd62bb26 100644 (file)
@@ -618,8 +618,8 @@ int kgdb_arch_init(void)
         * portion of kgdb because this operation requires mutexs to
         * complete.
         */
+       hw_breakpoint_init(&attr);
        attr.bp_addr = (unsigned long)kgdb_arch_init;
-       attr.type = PERF_TYPE_BREAKPOINT;
        attr.bp_len = HW_BREAKPOINT_LEN_1;
        attr.bp_type = HW_BREAKPOINT_W;
        attr.disabled = 1;
index 06d98ae5a80245ad4351c90bbff28d31ddfd2245..6808b934d6c0a1e6854ceeb1037566212ddb237c 100644 (file)
@@ -242,8 +242,6 @@ static void __cpuinit smp_callin(void)
        end_local_APIC_setup();
        map_cpu_to_logical_apicid();
 
-       notify_cpu_starting(cpuid);
-
        /*
         * Need to setup vector mappings before we enable interrupts.
         */
@@ -264,6 +262,8 @@ static void __cpuinit smp_callin(void)
         */
        smp_store_cpu_info(cpuid);
 
+       notify_cpu_starting(cpuid);
+
        /*
         * Allow the master to continue.
         */
index 183f8ff5f400b90d8b128465551d8157004f20d2..096273984c3be0be3635fef6974f5460efcfa2b8 100644 (file)
@@ -406,6 +406,7 @@ static int show_smap(struct seq_file *m, void *v)
 
        memset(&mss, 0, sizeof mss);
        mss.vma = vma;
+       /* mmap_sem is held in m_start */
        if (vma->vm_mm && !is_vm_hugetlb_page(vma))
                walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
 
@@ -552,7 +553,8 @@ const struct file_operations proc_clear_refs_operations = {
 };
 
 struct pagemapread {
-       u64 __user *out, *end;
+       int pos, len;
+       u64 *buffer;
 };
 
 #define PM_ENTRY_BYTES      sizeof(u64)
@@ -575,10 +577,8 @@ struct pagemapread {
 static int add_to_pagemap(unsigned long addr, u64 pfn,
                          struct pagemapread *pm)
 {
-       if (put_user(pfn, pm->out))
-               return -EFAULT;
-       pm->out++;
-       if (pm->out >= pm->end)
+       pm->buffer[pm->pos++] = pfn;
+       if (pm->pos >= pm->len)
                return PM_END_OF_BUFFER;
        return 0;
 }
@@ -720,21 +720,20 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long addr,
  * determine which areas of memory are actually mapped and llseek to
  * skip over unmapped regions.
  */
+#define PAGEMAP_WALK_SIZE      (PMD_SIZE)
 static ssize_t pagemap_read(struct file *file, char __user *buf,
                            size_t count, loff_t *ppos)
 {
        struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
-       struct page **pages, *page;
-       unsigned long uaddr, uend;
        struct mm_struct *mm;
        struct pagemapread pm;
-       int pagecount;
        int ret = -ESRCH;
        struct mm_walk pagemap_walk = {};
        unsigned long src;
        unsigned long svpfn;
        unsigned long start_vaddr;
        unsigned long end_vaddr;
+       int copied = 0;
 
        if (!task)
                goto out;
@@ -757,35 +756,12 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        if (!mm)
                goto out_task;
 
-
-       uaddr = (unsigned long)buf & PAGE_MASK;
-       uend = (unsigned long)(buf + count);
-       pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE;
-       ret = 0;
-       if (pagecount == 0)
-               goto out_mm;
-       pages = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL);
+       pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
+       pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
        ret = -ENOMEM;
-       if (!pages)
+       if (!pm.buffer)
                goto out_mm;
 
-       down_read(&current->mm->mmap_sem);
-       ret = get_user_pages(current, current->mm, uaddr, pagecount,
-                            1, 0, pages, NULL);
-       up_read(&current->mm->mmap_sem);
-
-       if (ret < 0)
-               goto out_free;
-
-       if (ret != pagecount) {
-               pagecount = ret;
-               ret = -EFAULT;
-               goto out_pages;
-       }
-
-       pm.out = (u64 __user *)buf;
-       pm.end = (u64 __user *)(buf + count);
-
        pagemap_walk.pmd_entry = pagemap_pte_range;
        pagemap_walk.pte_hole = pagemap_pte_hole;
        pagemap_walk.hugetlb_entry = pagemap_hugetlb_range;
@@ -807,23 +783,36 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
         * user buffer is tracked in "pm", and the walk
         * will stop when we hit the end of the buffer.
         */
-       ret = walk_page_range(start_vaddr, end_vaddr, &pagemap_walk);
-       if (ret == PM_END_OF_BUFFER)
-               ret = 0;
-       /* don't need mmap_sem for these, but this looks cleaner */
-       *ppos += (char __user *)pm.out - buf;
-       if (!ret)
-               ret = (char __user *)pm.out - buf;
-
-out_pages:
-       for (; pagecount; pagecount--) {
-               page = pages[pagecount-1];
-               if (!PageReserved(page))
-                       SetPageDirty(page);
-               page_cache_release(page);
+       ret = 0;
+       while (count && (start_vaddr < end_vaddr)) {
+               int len;
+               unsigned long end;
+
+               pm.pos = 0;
+               end = start_vaddr + PAGEMAP_WALK_SIZE;
+               /* overflow ? */
+               if (end < start_vaddr || end > end_vaddr)
+                       end = end_vaddr;
+               down_read(&mm->mmap_sem);
+               ret = walk_page_range(start_vaddr, end, &pagemap_walk);
+               up_read(&mm->mmap_sem);
+               start_vaddr = end;
+
+               len = min(count, PM_ENTRY_BYTES * pm.pos);
+               if (copy_to_user(buf, pm.buffer, len) < 0) {
+                       ret = -EFAULT;
+                       goto out_free;
+               }
+               copied += len;
+               buf += len;
+               count -= len;
        }
+       *ppos += copied;
+       if (!ret || ret == PM_END_OF_BUFFER)
+               ret = copied;
+
 out_free:
-       kfree(pages);
+       kfree(pm.buffer);
 out_mm:
        mmput(mm);
 out_task:
index 95477038a72ad479b2c1b5d19138e9ff675ee62c..c8e375440403de53f6deb7be5e5ad3d0b0bb84e6 100644 (file)
@@ -842,13 +842,6 @@ extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
 
 extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64);
 
-static inline void
-perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
-{
-       if (atomic_read(&perf_swevent_enabled[event_id]))
-               __perf_sw_event(event_id, nr, nmi, regs, addr);
-}
-
 extern void
 perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip);
 
@@ -887,6 +880,20 @@ static inline void perf_fetch_caller_regs(struct pt_regs *regs, int skip)
        return perf_arch_fetch_caller_regs(regs, ip, skip);
 }
 
+static inline void
+perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
+{
+       if (atomic_read(&perf_swevent_enabled[event_id])) {
+               struct pt_regs hot_regs;
+
+               if (!regs) {
+                       perf_fetch_caller_regs(&hot_regs, 1);
+                       regs = &hot_regs;
+               }
+               __perf_sw_event(event_id, nr, nmi, regs, addr);
+       }
+}
+
 extern void __perf_event_mmap(struct vm_area_struct *vma);
 
 static inline void perf_event_mmap(struct vm_area_struct *vma)
index 574ee58a3046a4bff950aa9051e73a2d5dfd7d8b..681af806d76b41b38c3f7de775610327ff288ac5 100644 (file)
@@ -1164,11 +1164,9 @@ void perf_event_task_sched_out(struct task_struct *task,
        struct perf_event_context *ctx = task->perf_event_ctxp;
        struct perf_event_context *next_ctx;
        struct perf_event_context *parent;
-       struct pt_regs *regs;
        int do_switch = 1;
 
-       regs = task_pt_regs(task);
-       perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, regs, 0);
+       perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
 
        if (likely(!ctx || !cpuctx->task_ctx))
                return;
@@ -2786,12 +2784,11 @@ __weak struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
        return NULL;
 }
 
-#ifdef CONFIG_EVENT_TRACING
 __weak
 void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip)
 {
 }
-#endif
+
 
 /*
  * Output
@@ -3378,15 +3375,23 @@ static void perf_event_task_output(struct perf_event *event,
                                     struct perf_task_event *task_event)
 {
        struct perf_output_handle handle;
-       int size;
        struct task_struct *task = task_event->task;
-       int ret;
+       unsigned long flags;
+       int size, ret;
+
+       /*
+        * If this CPU attempts to acquire an rq lock held by a CPU spinning
+        * in perf_output_lock() from interrupt context, it's game over.
+        */
+       local_irq_save(flags);
 
        size  = task_event->event_id.header.size;
        ret = perf_output_begin(&handle, event, size, 0, 0);
 
-       if (ret)
+       if (ret) {
+               local_irq_restore(flags);
                return;
+       }
 
        task_event->event_id.pid = perf_event_pid(event, task);
        task_event->event_id.ppid = perf_event_pid(event, current);
@@ -3397,6 +3402,7 @@ static void perf_event_task_output(struct perf_event *event,
        perf_output_put(&handle, task_event->event_id);
 
        perf_output_end(&handle);
+       local_irq_restore(flags);
 }
 
 static int perf_event_task_match(struct perf_event *event)
index 49d2fa7b687a6cd9956e5d7179ab26822bcff6f1..528a10592c16782e813238e050fb1abba79e05e7 100644 (file)
@@ -5387,7 +5387,7 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
 
                get_task_struct(mt);
                task_rq_unlock(rq, &flags);
-               wake_up_process(rq->migration_thread);
+               wake_up_process(mt);
                put_task_struct(mt);
                wait_for_completion(&req.done);
                tlb_migrate_finish(p->mm);
index 67f95aada4b95637b75432278b9d7391401a62d6..9b49db1440372bd6227e7e4258a0a6d78903e230 100644 (file)
@@ -518,8 +518,4 @@ void proc_sched_set_task(struct task_struct *p)
        p->se.nr_wakeups_idle                   = 0;
        p->sched_info.bkl_count                 = 0;
 #endif
-       p->se.sum_exec_runtime                  = 0;
-       p->se.prev_sum_exec_runtime             = 0;
-       p->nvcsw                                = 0;
-       p->nivcsw                               = 0;
 }
index d1187ef20caf914048fb897dc5c63f1b302edbf6..9a0f9bf6a37b37295a5e4bf6a52d03b3472905fa 100644 (file)
@@ -1209,18 +1209,19 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned nr_pages)
 
        for (i = 0; i < nr_pages; i++) {
                if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages)))
-                       return;
+                       goto out;
                p = cpu_buffer->pages->next;
                bpage = list_entry(p, struct buffer_page, list);
                list_del_init(&bpage->list);
                free_buffer_page(bpage);
        }
        if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages)))
-               return;
+               goto out;
 
        rb_reset_cpu(cpu_buffer);
        rb_check_pages(cpu_buffer);
 
+out:
        spin_unlock_irq(&cpu_buffer->reader_lock);
 }
 
@@ -1237,7 +1238,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer,
 
        for (i = 0; i < nr_pages; i++) {
                if (RB_WARN_ON(cpu_buffer, list_empty(pages)))
-                       return;
+                       goto out;
                p = pages->next;
                bpage = list_entry(p, struct buffer_page, list);
                list_del_init(&bpage->list);
@@ -1246,6 +1247,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer,
        rb_reset_cpu(cpu_buffer);
        rb_check_pages(cpu_buffer);
 
+out:
        spin_unlock_irq(&cpu_buffer->reader_lock);
 }
 
index 6fbfb8f417b9cd9d60d72ff6b6a0c9c54c520ce1..9d589d8dcd1aa7e9470b6868980a20c4aeaf6160 100644 (file)
@@ -84,7 +84,7 @@ u64 notrace trace_clock_global(void)
        int this_cpu;
        u64 now;
 
-       raw_local_irq_save(flags);
+       local_irq_save(flags);
 
        this_cpu = raw_smp_processor_id();
        now = cpu_clock(this_cpu);
@@ -110,7 +110,7 @@ u64 notrace trace_clock_global(void)
        arch_spin_unlock(&trace_clock_struct.lock);
 
  out:
-       raw_local_irq_restore(flags);
+       local_irq_restore(flags);
 
        return now;
 }
index 81f691eb3a30a508706afa874415a6343042adfb..0565bb42566f6982d6d197857e0b7e07511ab8a7 100644 (file)
@@ -17,7 +17,12 @@ EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs);
 static char *perf_trace_buf;
 static char *perf_trace_buf_nmi;
 
-typedef typeof(char [PERF_MAX_TRACE_SIZE]) perf_trace_t ;
+/*
+ * Force it to be aligned to unsigned long to avoid misaligned accesses
+ * suprises
+ */
+typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)])
+       perf_trace_t;
 
 /* Count the events in use (per event id, not per instance) */
 static int     total_ref_count;
@@ -130,6 +135,8 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
        char *trace_buf, *raw_data;
        int pc, cpu;
 
+       BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(unsigned long));
+
        pc = preempt_count();
 
        /* Protect the per cpu buffer, begin the rcu read side */
@@ -152,7 +159,7 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
        raw_data = per_cpu_ptr(trace_buf, cpu);
 
        /* zero the dead bytes from align to not leak stack to user */
-       *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
+       memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64));
 
        entry = (struct trace_entry *)raw_data;
        tracing_generic_entry_update(entry, *irq_flags, pc);
index 8a8f52db7e385c28b2092f255ea07fb532fa5607..bc0f670a8338ac971d7836aaaae27a122a486b6e 100644 (file)
@@ -200,7 +200,7 @@ endif
 
 CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
 EXTLIBS = -lpthread -lrt -lelf -lm
-ALL_CFLAGS = $(CFLAGS)
+ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
 ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
 
@@ -492,19 +492,19 @@ ifeq ($(uname_S),Darwin)
        PTHREAD_LIBS =
 endif
 
-ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
-ifneq ($(shell sh -c "(echo '\#include <gnu/libc-version.h>'; echo 'int main(void) { const char * version = gnu_get_libc_version(); return (long)version; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+ifneq ($(shell sh -c "(echo '\#include <gnu/libc-version.h>'; echo 'int main(void) { const char * version = gnu_get_libc_version(); return (long)version; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
        msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
 endif
 
-       ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+       ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
                BASIC_CFLAGS += -DLIBELF_NO_MMAP
        endif
 else
        msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
 endif
 
-ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
        msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
        BASIC_CFLAGS += -DNO_DWARF_SUPPORT
 else
index 33a414bbba3e1e1bbf410d9f984e401dc555e2b9..6a72f14c5986806dc3bcd4fad1cf0b92ba19b7b0 100644 (file)
@@ -208,7 +208,7 @@ static void python_process_event(int cpu, void *data,
                                 int size __unused,
                                 unsigned long long nsecs, char *comm)
 {
-       PyObject *handler, *retval, *context, *t;
+       PyObject *handler, *retval, *context, *t, *obj;
        static char handler_name[256];
        struct format_field *field;
        unsigned long long val;
@@ -256,16 +256,23 @@ static void python_process_event(int cpu, void *data,
                                offset &= 0xffff;
                        } else
                                offset = field->offset;
-                       PyTuple_SetItem(t, n++,
-                               PyString_FromString((char *)data + offset));
+                       obj = PyString_FromString((char *)data + offset);
                } else { /* FIELD_IS_NUMERIC */
                        val = read_size(data + field->offset, field->size);
                        if (field->flags & FIELD_IS_SIGNED) {
-                               PyTuple_SetItem(t, n++, PyInt_FromLong(val));
+                               if ((long long)val >= LONG_MIN &&
+                                   (long long)val <= LONG_MAX)
+                                       obj = PyInt_FromLong(val);
+                               else
+                                       obj = PyLong_FromLongLong(val);
                        } else {
-                               PyTuple_SetItem(t, n++, PyInt_FromLong(val));
+                               if (val <= LONG_MAX)
+                                       obj = PyInt_FromLong(val);
+                               else
+                                       obj = PyLong_FromUnsignedLongLong(val);
                        }
                }
+               PyTuple_SetItem(t, n++, obj);
        }
 
        if (_PyTuple_Resize(&t, n) == -1)