Merge branch 'perf/urgent' into perf/core
Ingo Molnar [Fri, 2 Apr 2010 17:37:50 +0000 (19:37 +0200)]
Conflicts:
arch/x86/kernel/cpu/perf_event.c

Merge reason: Resolve the conflict, pick up fixes

Signed-off-by: Ingo Molnar <mingo@elte.hu>

1  2 
MAINTAINERS
arch/x86/include/asm/msr-index.h
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/process.c
include/linux/perf_event.h
kernel/perf_event.c
kernel/sched.c

diff --cc MAINTAINERS
Simple merge
Simple merge
  #include <asm/apic.h>
  #include <asm/stacktrace.h>
  #include <asm/nmi.h>
+ #include <asm/compat.h>
  
 -static u64 perf_event_mask __read_mostly;
 +#if 0
 +#undef wrmsrl
 +#define wrmsrl(msr, val)                                      \
 +do {                                                          \
 +      trace_printk("wrmsrl(%lx, %lx)\n", (unsigned long)(msr),\
 +                      (unsigned long)(val));                  \
 +      native_write_msr((msr), (u32)((u64)(val)),              \
 +                      (u32)((u64)(val) >> 32));               \
 +} while (0)
 +#endif
  
 -/* The maximal number of PEBS events: */
 -#define MAX_PEBS_EVENTS       4
 +/*
 + * best effort, GUP based copy_from_user() that assumes IRQ or NMI context
 + */
 +static unsigned long
 +copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
 +{
 +      unsigned long offset, addr = (unsigned long)from;
 +      int type = in_nmi() ? KM_NMI : KM_IRQ0;
 +      unsigned long size, len = 0;
 +      struct page *page;
 +      void *map;
 +      int ret;
  
 -/* The size of a BTS record in bytes: */
 -#define BTS_RECORD_SIZE               24
 +      do {
 +              ret = __get_user_pages_fast(addr, 1, 0, &page);
 +              if (!ret)
 +                      break;
  
 -/* The size of a per-cpu BTS buffer in bytes: */
 -#define BTS_BUFFER_SIZE               (BTS_RECORD_SIZE * 2048)
 +              offset = addr & (PAGE_SIZE - 1);
 +              size = min(PAGE_SIZE - offset, n - len);
  
 -/* The BTS overflow threshold in bytes from the end of the buffer: */
 -#define BTS_OVFL_TH           (BTS_RECORD_SIZE * 128)
 +              map = kmap_atomic(page, type);
 +              memcpy(to, map+offset, size);
 +              kunmap_atomic(map, type);
 +              put_page(page);
  
 +              len  += size;
 +              to   += size;
 +              addr += size;
  
 -/*
 - * Bits in the debugctlmsr controlling branch tracing.
 - */
 -#define X86_DEBUGCTL_TR                       (1 << 6)
 -#define X86_DEBUGCTL_BTS              (1 << 7)
 -#define X86_DEBUGCTL_BTINT            (1 << 8)
 -#define X86_DEBUGCTL_BTS_OFF_OS               (1 << 9)
 -#define X86_DEBUGCTL_BTS_OFF_USR      (1 << 10)
 +      } while (len < n);
  
 -/*
 - * A debug store configuration.
 - *
 - * We only support architectures that use 64bit fields.
 - */
 -struct debug_store {
 -      u64     bts_buffer_base;
 -      u64     bts_index;
 -      u64     bts_absolute_maximum;
 -      u64     bts_interrupt_threshold;
 -      u64     pebs_buffer_base;
 -      u64     pebs_index;
 -      u64     pebs_absolute_maximum;
 -      u64     pebs_interrupt_threshold;
 -      u64     pebs_event_reset[MAX_PEBS_EVENTS];
 -};
 +      return len;
 +}
  
  struct event_constraint {
        union {
@@@ -207,9 -158,8 +208,9 @@@ struct x86_pmu 
        void            (*put_event_constraints)(struct cpu_hw_events *cpuc,
                                                 struct perf_event *event);
        struct event_constraint *event_constraints;
 +      void            (*quirks)(void);
  
-       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);
@@@ -1620,14 -1596,77 +1623,42 @@@ perf_callchain_kernel(struct pt_regs *r
        dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry);
  }
  
- static int copy_stack_frame(const void __user *fp, struct stack_frame *frame)
 -/*
 - * best effort, GUP based copy_from_user() that assumes IRQ or NMI context
 - */
 -static unsigned long
 -copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
 -{
 -      unsigned long offset, addr = (unsigned long)from;
 -      int type = in_nmi() ? KM_NMI : KM_IRQ0;
 -      unsigned long size, len = 0;
 -      struct page *page;
 -      void *map;
 -      int ret;
 -
 -      do {
 -              ret = __get_user_pages_fast(addr, 1, 0, &page);
 -              if (!ret)
 -                      break;
 -
 -              offset = addr & (PAGE_SIZE - 1);
 -              size = min(PAGE_SIZE - offset, n - len);
 -
 -              map = kmap_atomic(page, type);
 -              memcpy(to, map+offset, size);
 -              kunmap_atomic(map, type);
 -              put_page(page);
 -
 -              len  += size;
 -              to   += size;
 -              addr += size;
 -
 -      } while (len < n);
 -
 -      return len;
 -}
 -
+ #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)
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc kernel/sched.c
Simple merge