#define PERF_EVENT_MISC_KERNEL                 (1 << 0)
 #define PERF_EVENT_MISC_USER                   (2 << 0)
 #define PERF_EVENT_MISC_HYPERVISOR             (3 << 0)
-#define PERF_EVENT_MISC_OVERFLOW               (1 << 2)
 
 struct perf_event_header {
        __u32   type;
        PERF_EVENT_READ                 = 8,
 
        /*
-        * When header.misc & PERF_EVENT_MISC_OVERFLOW the event_type field
-        * will be PERF_SAMPLE_*
-        *
         * struct {
         *      struct perf_event_header        header;
         *
         *      { u32                   pid, tid; } && PERF_SAMPLE_TID
         *      { u64                   time;     } && PERF_SAMPLE_TIME
         *      { u64                   addr;     } && PERF_SAMPLE_ADDR
-        *      { u64                   config;   } && PERF_SAMPLE_CONFIG
+        *      { u64                   id;       } && PERF_SAMPLE_ID
         *      { u32                   cpu, res; } && PERF_SAMPLE_CPU
+        *      { u64                   period;   } && PERF_SAMPLE_PERIOD
         *
         *      { u64                   nr;
         *        { u64 id, val; }      cnt[nr];  } && PERF_SAMPLE_GROUP
         *        u64                   ips[nr];  } && PERF_SAMPLE_CALLCHAIN
         * };
         */
+       PERF_EVENT_SAMPLE               = 9,
+
+       PERF_EVENT_MAX,                 /* non-ABI */
 };
 
 enum perf_callchain_context {
 
                u32 cpu, reserved;
        } cpu_entry;
 
-       header.type = 0;
+       header.type = PERF_EVENT_SAMPLE;
        header.size = sizeof(header);
 
-       header.misc = PERF_EVENT_MISC_OVERFLOW;
+       header.misc = 0;
        header.misc |= perf_misc_flags(data->regs);
 
        if (sample_type & PERF_SAMPLE_IP) {
                ip = perf_instruction_pointer(data->regs);
-               header.type |= PERF_SAMPLE_IP;
                header.size += sizeof(ip);
        }
 
                tid_entry.pid = perf_counter_pid(counter, current);
                tid_entry.tid = perf_counter_tid(counter, current);
 
-               header.type |= PERF_SAMPLE_TID;
                header.size += sizeof(tid_entry);
        }
 
                 */
                time = sched_clock();
 
-               header.type |= PERF_SAMPLE_TIME;
                header.size += sizeof(u64);
        }
 
-       if (sample_type & PERF_SAMPLE_ADDR) {
-               header.type |= PERF_SAMPLE_ADDR;
+       if (sample_type & PERF_SAMPLE_ADDR)
                header.size += sizeof(u64);
-       }
 
-       if (sample_type & PERF_SAMPLE_ID) {
-               header.type |= PERF_SAMPLE_ID;
+       if (sample_type & PERF_SAMPLE_ID)
                header.size += sizeof(u64);
-       }
 
        if (sample_type & PERF_SAMPLE_CPU) {
-               header.type |= PERF_SAMPLE_CPU;
                header.size += sizeof(cpu_entry);
 
                cpu_entry.cpu = raw_smp_processor_id();
        }
 
-       if (sample_type & PERF_SAMPLE_PERIOD) {
-               header.type |= PERF_SAMPLE_PERIOD;
+       if (sample_type & PERF_SAMPLE_PERIOD)
                header.size += sizeof(u64);
-       }
 
        if (sample_type & PERF_SAMPLE_GROUP) {
-               header.type |= PERF_SAMPLE_GROUP;
                header.size += sizeof(u64) +
                        counter->nr_siblings * sizeof(group_entry);
        }
 
                if (callchain) {
                        callchain_size = (1 + callchain->nr) * sizeof(u64);
-
-                       header.type |= PERF_SAMPLE_CALLCHAIN;
                        header.size += callchain_size;
-               }
+               } else
+                       header.size += sizeof(u64);
        }
 
        ret = perf_output_begin(&handle, counter, header.size, nmi, 1);
                }
        }
 
-       if (callchain)
-               perf_output_copy(&handle, callchain, callchain_size);
+       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
+               if (callchain)
+                       perf_output_copy(&handle, callchain, callchain_size);
+               else {
+                       u64 nr = 0;
+                       perf_output_put(&handle, nr);
+               }
+       }
 
        perf_output_end(&handle);
 }
 
                     total_unknown = 0;
 
 static int
-process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
+process_sample_event(event_t *event, unsigned long offset, unsigned long head)
 {
        char level;
        int show = 0;
 static int
 process_event(event_t *event, unsigned long offset, unsigned long head)
 {
-       if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
-               return process_overflow_event(event, offset, head);
-
        switch (event->header.type) {
+       case PERF_EVENT_SAMPLE:
+               return process_sample_event(event, offset, head);
+
        case PERF_EVENT_MMAP:
                return process_mmap_event(event, offset, head);
 
 
 
 static int             exclude_other = 1;
 
+static u64             sample_type;
+
 struct ip_event {
        struct perf_event_header header;
        u64 ip;
 }
 
 static int
-process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
+process_sample_event(event_t *event, unsigned long offset, unsigned long head)
 {
        char level;
        int show = 0;
        void *more_data = event->ip.__more_data;
        struct ip_callchain *chain = NULL;
 
-       if (event->header.type & PERF_SAMPLE_PERIOD) {
+       if (sample_type & PERF_SAMPLE_PERIOD) {
                period = *(u64 *)more_data;
                more_data += sizeof(u64);
        }
 
-       dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n",
+       dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d: %p period: %Ld\n",
                (void *)(offset + head),
                (void *)(long)(event->header.size),
                event->header.misc,
                (void *)(long)ip,
                (long long)period);
 
-       if (event->header.type & PERF_SAMPLE_CALLCHAIN) {
+       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
                int i;
 
                chain = (void *)more_data;
 {
        trace_event(event);
 
-       if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
-               return process_overflow_event(event, offset, head);
-
        switch (event->header.type) {
+       case PERF_EVENT_SAMPLE:
+               return process_sample_event(event, offset, head);
+
        case PERF_EVENT_MMAP:
                return process_mmap_event(event, offset, head);
 
 
 static struct perf_header      *header;
 
-static int perf_header__has_sample(u64 sample_mask)
+static u64 perf_header__sample_type(void)
 {
+       u64 sample_type = 0;
        int i;
 
        for (i = 0; i < header->attrs; i++) {
                struct perf_header_attr *attr = header->attr[i];
 
-               if (!(attr->attr.sample_type & sample_mask))
-                       return 0;
+               if (!sample_type)
+                       sample_type = attr->attr.sample_type;
+               else if (sample_type != attr->attr.sample_type)
+                       die("non matching sample_type");
        }
 
-       return 1;
+       return sample_type;
 }
 
 static int __cmd_report(void)
        header = perf_header__read(input);
        head = header->data_offset;
 
-       if (sort__has_parent &&
-           !perf_header__has_sample(PERF_SAMPLE_CALLCHAIN)) {
+       sample_type = perf_header__sample_type();
+
+       if (sort__has_parent && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
                fprintf(stderr, "selected --sort parent, but no callchain data\n");
                exit(-1);
        }
 
        samples--;
 }
 
-static void process_event(u64 ip, int counter)
+static void process_event(u64 ip, int counter, int user)
 {
        samples++;
 
-       if (ip < min_ip || ip > max_ip) {
+       if (user) {
                userspace_samples++;
                return;
        }
 
                old += size;
 
-               if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
-                       if (event->header.type & PERF_SAMPLE_IP)
-                               process_event(event->ip.ip, md->counter);
+               if (event->header.type == PERF_EVENT_SAMPLE) {
+                       int user =
+       (event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK) == PERF_EVENT_MISC_USER;
+                       process_event(event->ip.ip, md->counter, user);
                }
        }