Merge branches 'tracing/core', 'x86/urgent' and 'x86/ptrace' into tracing/hw-branch...
authorIngo Molnar <mingo@elte.hu>
Tue, 25 Nov 2008 16:30:25 +0000 (17:30 +0100)
committerIngo Molnar <mingo@elte.hu>
Tue, 25 Nov 2008 16:30:30 +0000 (17:30 +0100)
This pulls together all the topic branches that are needed
for the DS/BTS/PEBS tracing work.

1  2  3 
arch/x86/kernel/Makefile
arch/x86/kernel/ds.c

diff --combined arch/x86/kernel/Makefile
@@@@ -14,11 -14,6 -14,6 +14,11 @@@@ CFLAGS_REMOVE_paravirt-spinlocks.o = -p
   CFLAGS_REMOVE_ftrace.o = -pg
   endif
   
 ++ifdef CONFIG_FUNCTION_RET_TRACER
 ++# Don't trace __switch_to() but let it for function tracer
 ++CFLAGS_REMOVE_process_32.o = -pg
 ++endif
 ++
   #
   # vsyscalls (which work on the user stack) should have
   # no stack-protector checks:
@@@@ -46,7 -41,7 -41,7 +46,7 @@@@ obj-$(CONFIG_X86_TRAMPOLINE)  += trampol
   obj-y                                += process.o
   obj-y                                += i387.o xsave.o
   obj-y                                += ptrace.o
- -obj-y                                += ds.o
+ +obj-$(CONFIG_X86_DS)         += ds.o
   obj-$(CONFIG_X86_32)         += tls.o
   obj-$(CONFIG_IA32_EMULATION) += tls.o
   obj-y                                += step.o
@@@@ -70,7 -65,6 -65,6 +70,7 @@@@ obj-$(CONFIG_X86_LOCAL_APIC)  += apic.o 
   obj-$(CONFIG_X86_IO_APIC)    += io_apic.o
   obj-$(CONFIG_X86_REBOOTFIXUPS)       += reboot_fixups_32.o
   obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
 ++obj-$(CONFIG_FUNCTION_RET_TRACER)    += ftrace.o
   obj-$(CONFIG_KEXEC)          += machine_kexec_$(BITS).o
   obj-$(CONFIG_KEXEC)          += relocate_kernel_$(BITS).o crash.o
   obj-$(CONFIG_CRASH_DUMP)     += crash_dump_$(BITS).o
diff --combined arch/x86/kernel/ds.c
    */
   
   
- -#ifdef CONFIG_X86_DS
- -
   #include <asm/ds.h>
   
   #include <linux/errno.h>
@@@@ -211,14 -209,15 -211,14 +209,15 @@@@ static DEFINE_PER_CPU(struct ds_contex
   static inline struct ds_context *ds_get_context(struct task_struct *task)
   {
        struct ds_context *context;
+ +     unsigned long irq;
   
- -     spin_lock(&ds_lock);
+ +     spin_lock_irqsave(&ds_lock, irq);
   
        context = (task ? task->thread.ds_ctx : this_system_context);
        if (context)
                context->count++;
   
- -     spin_unlock(&ds_lock);
+ +     spin_unlock_irqrestore(&ds_lock, irq);
   
        return context;
   }
   /*
    * Same as ds_get_context, but allocates the context and it's DS
    * structure, if necessary; returns NULL; if out of memory.
- - *
- - * pre: requires ds_lock to be held
    */
   static inline struct ds_context *ds_alloc_context(struct task_struct *task)
   {
        struct ds_context **p_context =
                (task ? &task->thread.ds_ctx : &this_system_context);
        struct ds_context *context = *p_context;
+ +     unsigned long irq;
   
        if (!context) {
-               spin_unlock(&ds_lock);
-  
                context = kzalloc(sizeof(*context), GFP_KERNEL);
- -
-               if (!context) {
-                       spin_lock(&ds_lock);
+               if (!context)
                        return NULL;
-               }
   
                context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL);
                if (!context->ds) {
                        kfree(context);
-                       spin_lock(&ds_lock);
                        return NULL;
                }
   
-               spin_lock(&ds_lock);
-               /*
-                * Check for race - another CPU could have allocated
-                * it meanwhile:
-                */
  -             *p_context = context;
+ +             spin_lock_irqsave(&ds_lock, irq);
+  
  -             context->this = p_context;
  -             context->task = task;
  +             if (*p_context) {
  +                     kfree(context->ds);
  +                     kfree(context);
-                       return *p_context;
-               }
  +
-               *p_context = context;
+ +                     context = *p_context;
+ +             } else {
+ +                     *p_context = context;
   
-               context->this = p_context;
-               context->task = task;
  -             if (task)
  -                     set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
+ +                     context->this = p_context;
+ +                     context->task = task;
   
-               if (task)
-                       set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
  -             if (!task || (task == current))
  -                     wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0);
+ +                     if (task)
+ +                             set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
   
-               if (!task || (task == current))
-                       wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0);
-  
- -             get_tracer(task);
+ +                     if (!task || (task == current))
+ +                             wrmsrl(MSR_IA32_DS_AREA,
+ +                                    (unsigned long)context->ds);
+ +             }
+ +             spin_unlock_irqrestore(&ds_lock, irq);
        }
   
        context->count++;
    */
   static inline void ds_put_context(struct ds_context *context)
   {
+ +     unsigned long irq;
+ +
        if (!context)
                return;
   
- -     spin_lock(&ds_lock);
+ +     spin_lock_irqsave(&ds_lock, irq);
   
        if (--context->count)
                goto out;
        kfree(context->ds);
        kfree(context);
    out:
- -     spin_unlock(&ds_lock);
+ +     spin_unlock_irqrestore(&ds_lock, irq);
   }
   
   
@@@@ -384,6 -376,7 -368,6 +376,7 @@@@ static int ds_request(struct task_struc
        struct ds_context *context;
        unsigned long buffer, adj;
        const unsigned long alignment = (1 << 3);
+ +     unsigned long irq;
        int error = 0;
   
        if (!ds_cfg.sizeof_ds)
                return -EOPNOTSUPP;
   
   
- -     spin_lock(&ds_lock);
  -
  -     if (!check_tracer(task))
  -             return -EPERM;
- -
- -     error = -ENOMEM;
        context = ds_alloc_context(task);
        if (!context)
-               goto out_unlock;
+ +             return -ENOMEM;
+ +
+ +     spin_lock_irqsave(&ds_lock, irq);
  +
  +     error = -EPERM;
  +     if (!check_tracer(task))
                goto out_unlock;
   
+ +     get_tracer(task);
+ +
        error = -EALREADY;
        if (context->owner[qual] == current)
- -             goto out_unlock;
+ +             goto out_put_tracer;
        error = -EPERM;
        if (context->owner[qual] != NULL)
- -             goto out_unlock;
+ +             goto out_put_tracer;
        context->owner[qual] = current;
   
- -     spin_unlock(&ds_lock);
+ +     spin_unlock_irqrestore(&ds_lock, irq);
   
   
        error = -ENOMEM;
    out_release:
        context->owner[qual] = NULL;
        ds_put_context(context);
+ +     put_tracer(task);
+ +     return error;
+ +
+ + out_put_tracer:
+ +     spin_unlock_irqrestore(&ds_lock, irq);
+ +     ds_put_context(context);
+ +     put_tracer(task);
        return error;
   
    out_unlock:
- -     spin_unlock(&ds_lock);
+ +     spin_unlock_irqrestore(&ds_lock, irq);
        ds_put_context(context);
        return error;
   }
@@@@ -818,13 -819,21 -801,13 +819,21 @@@@ static const struct ds_configuration ds
        .sizeof_ds    = sizeof(long) * 12,
        .sizeof_field = sizeof(long),
        .sizeof_rec[ds_bts]   = sizeof(long) * 3,
+ +#ifdef __i386__
        .sizeof_rec[ds_pebs]  = sizeof(long) * 10
+ +#else
+ +     .sizeof_rec[ds_pebs]  = sizeof(long) * 18
+ +#endif
   };
   static const struct ds_configuration ds_cfg_64 = {
        .sizeof_ds    = 8 * 12,
        .sizeof_field = 8,
        .sizeof_rec[ds_bts]   = 8 * 3,
+ +#ifdef __i386__
        .sizeof_rec[ds_pebs]  = 8 * 10
+ +#else
+ +     .sizeof_rec[ds_pebs]  = 8 * 18
+ +#endif
   };
   
   static inline void
@@@@ -838,17 -847,17 -821,16 +847,16 @@@@ void __cpuinit ds_init_intel(struct cpu
        switch (c->x86) {
        case 0x6:
                switch (c->x86_model) {
++              case 0 ... 0xC:
++                      /* sorry, don't know about them */
++                      break;
                case 0xD:
                case 0xE: /* Pentium M */
                        ds_configure(&ds_cfg_var);
                        break;
--              case 0xF: /* Core2 */
--              case 0x1C: /* Atom */
++              default: /* Core2, Atom, ... */
                        ds_configure(&ds_cfg_64);
                        break;
--              default:
--                      /* sorry, don't know about them */
--                      break;
                }
                break;
        case 0xF:
@@@@ -878,4 -887,3 -860,4 +886,3 @@@@ void ds_free(struct ds_context *context
        while (leftovers--)
                ds_put_context(context);
   }
- -#endif /* CONFIG_X86_DS */