cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kbuffer-parse.c (18654B)


      1// SPDX-License-Identifier: LGPL-2.1
      2/*
      3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
      4 *
      5 */
      6#include <stdio.h>
      7#include <stdlib.h>
      8#include <string.h>
      9
     10#include "kbuffer.h"
     11
     12#define MISSING_EVENTS (1UL << 31)
     13#define MISSING_STORED (1UL << 30)
     14
     15#define COMMIT_MASK ((1 << 27) - 1)
     16
     17enum {
     18	KBUFFER_FL_HOST_BIG_ENDIAN	= (1<<0),
     19	KBUFFER_FL_BIG_ENDIAN		= (1<<1),
     20	KBUFFER_FL_LONG_8		= (1<<2),
     21	KBUFFER_FL_OLD_FORMAT		= (1<<3),
     22};
     23
     24#define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN)
     25
     26/** kbuffer
     27 * @timestamp		- timestamp of current event
     28 * @lost_events		- # of lost events between this subbuffer and previous
     29 * @flags		- special flags of the kbuffer
     30 * @subbuffer		- pointer to the sub-buffer page
     31 * @data		- pointer to the start of data on the sub-buffer page
     32 * @index		- index from @data to the @curr event data
     33 * @curr		- offset from @data to the start of current event
     34 *			   (includes metadata)
     35 * @next		- offset from @data to the start of next event
     36 * @size		- The size of data on @data
     37 * @start		- The offset from @subbuffer where @data lives
     38 *
     39 * @read_4		- Function to read 4 raw bytes (may swap)
     40 * @read_8		- Function to read 8 raw bytes (may swap)
     41 * @read_long		- Function to read a long word (4 or 8 bytes with needed swap)
     42 */
     43struct kbuffer {
     44	unsigned long long 	timestamp;
     45	long long		lost_events;
     46	unsigned long		flags;
     47	void			*subbuffer;
     48	void			*data;
     49	unsigned int		index;
     50	unsigned int		curr;
     51	unsigned int		next;
     52	unsigned int		size;
     53	unsigned int		start;
     54
     55	unsigned int (*read_4)(void *ptr);
     56	unsigned long long (*read_8)(void *ptr);
     57	unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr);
     58	int (*next_event)(struct kbuffer *kbuf);
     59};
     60
     61static void *zmalloc(size_t size)
     62{
     63	return calloc(1, size);
     64}
     65
     66static int host_is_bigendian(void)
     67{
     68	unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
     69	unsigned int *ptr;
     70
     71	ptr = (unsigned int *)str;
     72	return *ptr == 0x01020304;
     73}
     74
     75static int do_swap(struct kbuffer *kbuf)
     76{
     77	return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) &
     78		ENDIAN_MASK;
     79}
     80
     81static unsigned long long __read_8(void *ptr)
     82{
     83	unsigned long long data = *(unsigned long long *)ptr;
     84
     85	return data;
     86}
     87
     88static unsigned long long __read_8_sw(void *ptr)
     89{
     90	unsigned long long data = *(unsigned long long *)ptr;
     91	unsigned long long swap;
     92
     93	swap = ((data & 0xffULL) << 56) |
     94		((data & (0xffULL << 8)) << 40) |
     95		((data & (0xffULL << 16)) << 24) |
     96		((data & (0xffULL << 24)) << 8) |
     97		((data & (0xffULL << 32)) >> 8) |
     98		((data & (0xffULL << 40)) >> 24) |
     99		((data & (0xffULL << 48)) >> 40) |
    100		((data & (0xffULL << 56)) >> 56);
    101
    102	return swap;
    103}
    104
    105static unsigned int __read_4(void *ptr)
    106{
    107	unsigned int data = *(unsigned int *)ptr;
    108
    109	return data;
    110}
    111
    112static unsigned int __read_4_sw(void *ptr)
    113{
    114	unsigned int data = *(unsigned int *)ptr;
    115	unsigned int swap;
    116
    117	swap = ((data & 0xffULL) << 24) |
    118		((data & (0xffULL << 8)) << 8) |
    119		((data & (0xffULL << 16)) >> 8) |
    120		((data & (0xffULL << 24)) >> 24);
    121
    122	return swap;
    123}
    124
    125static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
    126{
    127	return kbuf->read_8(ptr);
    128}
    129
    130static unsigned int read_4(struct kbuffer *kbuf, void *ptr)
    131{
    132	return kbuf->read_4(ptr);
    133}
    134
    135static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr)
    136{
    137	return kbuf->read_8(ptr);
    138}
    139
    140static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr)
    141{
    142	return kbuf->read_4(ptr);
    143}
    144
    145static unsigned long long read_long(struct kbuffer *kbuf, void *ptr)
    146{
    147	return kbuf->read_long(kbuf, ptr);
    148}
    149
    150static int calc_index(struct kbuffer *kbuf, void *ptr)
    151{
    152	return (unsigned long)ptr - (unsigned long)kbuf->data;
    153}
    154
    155static int __next_event(struct kbuffer *kbuf);
    156
    157/**
    158 * kbuffer_alloc - allocat a new kbuffer
    159 * @size;	enum to denote size of word
    160 * @endian:	enum to denote endianness
    161 *
    162 * Allocates and returns a new kbuffer.
    163 */
    164struct kbuffer *
    165kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
    166{
    167	struct kbuffer *kbuf;
    168	int flags = 0;
    169
    170	switch (size) {
    171	case KBUFFER_LSIZE_4:
    172		break;
    173	case KBUFFER_LSIZE_8:
    174		flags |= KBUFFER_FL_LONG_8;
    175		break;
    176	default:
    177		return NULL;
    178	}
    179
    180	switch (endian) {
    181	case KBUFFER_ENDIAN_LITTLE:
    182		break;
    183	case KBUFFER_ENDIAN_BIG:
    184		flags |= KBUFFER_FL_BIG_ENDIAN;
    185		break;
    186	default:
    187		return NULL;
    188	}
    189
    190	kbuf = zmalloc(sizeof(*kbuf));
    191	if (!kbuf)
    192		return NULL;
    193
    194	kbuf->flags = flags;
    195
    196	if (host_is_bigendian())
    197		kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN;
    198
    199	if (do_swap(kbuf)) {
    200		kbuf->read_8 = __read_8_sw;
    201		kbuf->read_4 = __read_4_sw;
    202	} else {
    203		kbuf->read_8 = __read_8;
    204		kbuf->read_4 = __read_4;
    205	}
    206
    207	if (kbuf->flags & KBUFFER_FL_LONG_8)
    208		kbuf->read_long = __read_long_8;
    209	else
    210		kbuf->read_long = __read_long_4;
    211
    212	/* May be changed by kbuffer_set_old_format() */
    213	kbuf->next_event = __next_event;
    214
    215	return kbuf;
    216}
    217
    218/** kbuffer_free - free an allocated kbuffer
    219 * @kbuf:	The kbuffer to free
    220 *
    221 * Can take NULL as a parameter.
    222 */
    223void kbuffer_free(struct kbuffer *kbuf)
    224{
    225	free(kbuf);
    226}
    227
    228static unsigned int type4host(struct kbuffer *kbuf,
    229			      unsigned int type_len_ts)
    230{
    231	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
    232		return (type_len_ts >> 29) & 3;
    233	else
    234		return type_len_ts & 3;
    235}
    236
    237static unsigned int len4host(struct kbuffer *kbuf,
    238			     unsigned int type_len_ts)
    239{
    240	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
    241		return (type_len_ts >> 27) & 7;
    242	else
    243		return (type_len_ts >> 2) & 7;
    244}
    245
    246static unsigned int type_len4host(struct kbuffer *kbuf,
    247				  unsigned int type_len_ts)
    248{
    249	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
    250		return (type_len_ts >> 27) & ((1 << 5) - 1);
    251	else
    252		return type_len_ts & ((1 << 5) - 1);
    253}
    254
    255static unsigned int ts4host(struct kbuffer *kbuf,
    256			    unsigned int type_len_ts)
    257{
    258	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
    259		return type_len_ts & ((1 << 27) - 1);
    260	else
    261		return type_len_ts >> 5;
    262}
    263
    264/*
    265 * Linux 2.6.30 and earlier (not much ealier) had a different
    266 * ring buffer format. It should be obsolete, but we handle it anyway.
    267 */
    268enum old_ring_buffer_type {
    269	OLD_RINGBUF_TYPE_PADDING,
    270	OLD_RINGBUF_TYPE_TIME_EXTEND,
    271	OLD_RINGBUF_TYPE_TIME_STAMP,
    272	OLD_RINGBUF_TYPE_DATA,
    273};
    274
    275static unsigned int old_update_pointers(struct kbuffer *kbuf)
    276{
    277	unsigned long long extend;
    278	unsigned int type_len_ts;
    279	unsigned int type;
    280	unsigned int len;
    281	unsigned int delta;
    282	unsigned int length;
    283	void *ptr = kbuf->data + kbuf->curr;
    284
    285	type_len_ts = read_4(kbuf, ptr);
    286	ptr += 4;
    287
    288	type = type4host(kbuf, type_len_ts);
    289	len = len4host(kbuf, type_len_ts);
    290	delta = ts4host(kbuf, type_len_ts);
    291
    292	switch (type) {
    293	case OLD_RINGBUF_TYPE_PADDING:
    294		kbuf->next = kbuf->size;
    295		return 0;
    296
    297	case OLD_RINGBUF_TYPE_TIME_EXTEND:
    298		extend = read_4(kbuf, ptr);
    299		extend <<= TS_SHIFT;
    300		extend += delta;
    301		delta = extend;
    302		ptr += 4;
    303		length = 0;
    304		break;
    305
    306	case OLD_RINGBUF_TYPE_TIME_STAMP:
    307		/* should never happen! */
    308		kbuf->curr = kbuf->size;
    309		kbuf->next = kbuf->size;
    310		kbuf->index = kbuf->size;
    311		return -1;
    312	default:
    313		if (len)
    314			length = len * 4;
    315		else {
    316			length = read_4(kbuf, ptr);
    317			length -= 4;
    318			ptr += 4;
    319		}
    320		break;
    321	}
    322
    323	kbuf->timestamp += delta;
    324	kbuf->index = calc_index(kbuf, ptr);
    325	kbuf->next = kbuf->index + length;
    326
    327	return type;
    328}
    329
    330static int __old_next_event(struct kbuffer *kbuf)
    331{
    332	int type;
    333
    334	do {
    335		kbuf->curr = kbuf->next;
    336		if (kbuf->next >= kbuf->size)
    337			return -1;
    338		type = old_update_pointers(kbuf);
    339	} while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING);
    340
    341	return 0;
    342}
    343
    344static unsigned int
    345translate_data(struct kbuffer *kbuf, void *data, void **rptr,
    346	       unsigned long long *delta, int *length)
    347{
    348	unsigned long long extend;
    349	unsigned int type_len_ts;
    350	unsigned int type_len;
    351
    352	type_len_ts = read_4(kbuf, data);
    353	data += 4;
    354
    355	type_len = type_len4host(kbuf, type_len_ts);
    356	*delta = ts4host(kbuf, type_len_ts);
    357
    358	switch (type_len) {
    359	case KBUFFER_TYPE_PADDING:
    360		*length = read_4(kbuf, data);
    361		break;
    362
    363	case KBUFFER_TYPE_TIME_EXTEND:
    364	case KBUFFER_TYPE_TIME_STAMP:
    365		extend = read_4(kbuf, data);
    366		data += 4;
    367		extend <<= TS_SHIFT;
    368		extend += *delta;
    369		*delta = extend;
    370		*length = 0;
    371		break;
    372
    373	case 0:
    374		*length = read_4(kbuf, data) - 4;
    375		*length = (*length + 3) & ~3;
    376		data += 4;
    377		break;
    378	default:
    379		*length = type_len * 4;
    380		break;
    381	}
    382
    383	*rptr = data;
    384
    385	return type_len;
    386}
    387
    388static unsigned int update_pointers(struct kbuffer *kbuf)
    389{
    390	unsigned long long delta;
    391	unsigned int type_len;
    392	int length;
    393	void *ptr = kbuf->data + kbuf->curr;
    394
    395	type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
    396
    397	if (type_len == KBUFFER_TYPE_TIME_STAMP)
    398		kbuf->timestamp = delta;
    399	else
    400		kbuf->timestamp += delta;
    401
    402	kbuf->index = calc_index(kbuf, ptr);
    403	kbuf->next = kbuf->index + length;
    404
    405	return type_len;
    406}
    407
    408/**
    409 * kbuffer_translate_data - read raw data to get a record
    410 * @swap:	Set to 1 if bytes in words need to be swapped when read
    411 * @data:	The raw data to read
    412 * @size:	Address to store the size of the event data.
    413 *
    414 * Returns a pointer to the event data. To determine the entire
    415 * record size (record metadata + data) just add the difference between
    416 * @data and the returned value to @size.
    417 */
    418void *kbuffer_translate_data(int swap, void *data, unsigned int *size)
    419{
    420	unsigned long long delta;
    421	struct kbuffer kbuf;
    422	int type_len;
    423	int length;
    424	void *ptr;
    425
    426	if (swap) {
    427		kbuf.read_8 = __read_8_sw;
    428		kbuf.read_4 = __read_4_sw;
    429		kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN;
    430	} else {
    431		kbuf.read_8 = __read_8;
    432		kbuf.read_4 = __read_4;
    433		kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0;
    434	}
    435
    436	type_len = translate_data(&kbuf, data, &ptr, &delta, &length);
    437	switch (type_len) {
    438	case KBUFFER_TYPE_PADDING:
    439	case KBUFFER_TYPE_TIME_EXTEND:
    440	case KBUFFER_TYPE_TIME_STAMP:
    441		return NULL;
    442	}
    443
    444	*size = length;
    445
    446	return ptr;
    447}
    448
    449static int __next_event(struct kbuffer *kbuf)
    450{
    451	int type;
    452
    453	do {
    454		kbuf->curr = kbuf->next;
    455		if (kbuf->next >= kbuf->size)
    456			return -1;
    457		type = update_pointers(kbuf);
    458	} while (type == KBUFFER_TYPE_TIME_EXTEND ||
    459		 type == KBUFFER_TYPE_TIME_STAMP ||
    460		 type == KBUFFER_TYPE_PADDING);
    461
    462	return 0;
    463}
    464
    465static int next_event(struct kbuffer *kbuf)
    466{
    467	return kbuf->next_event(kbuf);
    468}
    469
    470/**
    471 * kbuffer_next_event - increment the current pointer
    472 * @kbuf:	The kbuffer to read
    473 * @ts:		Address to store the next record's timestamp (may be NULL to ignore)
    474 *
    475 * Increments the pointers into the subbuffer of the kbuffer to point to the
    476 * next event so that the next kbuffer_read_event() will return a
    477 * new event.
    478 *
    479 * Returns the data of the next event if a new event exists on the subbuffer,
    480 * NULL otherwise.
    481 */
    482void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts)
    483{
    484	int ret;
    485
    486	if (!kbuf || !kbuf->subbuffer)
    487		return NULL;
    488
    489	ret = next_event(kbuf);
    490	if (ret < 0)
    491		return NULL;
    492
    493	if (ts)
    494		*ts = kbuf->timestamp;
    495
    496	return kbuf->data + kbuf->index;
    497}
    498
    499/**
    500 * kbuffer_load_subbuffer - load a new subbuffer into the kbuffer
    501 * @kbuf:	The kbuffer to load
    502 * @subbuffer:	The subbuffer to load into @kbuf.
    503 *
    504 * Load a new subbuffer (page) into @kbuf. This will reset all
    505 * the pointers and update the @kbuf timestamp. The next read will
    506 * return the first event on @subbuffer.
    507 *
    508 * Returns 0 on succes, -1 otherwise.
    509 */
    510int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
    511{
    512	unsigned long long flags;
    513	void *ptr = subbuffer;
    514
    515	if (!kbuf || !subbuffer)
    516		return -1;
    517
    518	kbuf->subbuffer = subbuffer;
    519
    520	kbuf->timestamp = read_8(kbuf, ptr);
    521	ptr += 8;
    522
    523	kbuf->curr = 0;
    524
    525	if (kbuf->flags & KBUFFER_FL_LONG_8)
    526		kbuf->start = 16;
    527	else
    528		kbuf->start = 12;
    529
    530	kbuf->data = subbuffer + kbuf->start;
    531
    532	flags = read_long(kbuf, ptr);
    533	kbuf->size = (unsigned int)flags & COMMIT_MASK;
    534
    535	if (flags & MISSING_EVENTS) {
    536		if (flags & MISSING_STORED) {
    537			ptr = kbuf->data + kbuf->size;
    538			kbuf->lost_events = read_long(kbuf, ptr);
    539		} else
    540			kbuf->lost_events = -1;
    541	} else
    542		kbuf->lost_events = 0;
    543
    544	kbuf->index = 0;
    545	kbuf->next = 0;
    546
    547	next_event(kbuf);
    548
    549	return 0;
    550}
    551
    552/**
    553 * kbuffer_subbuf_timestamp - read the timestamp from a sub buffer
    554 * @kbuf:      The kbuffer to load
    555 * @subbuf:    The subbuffer to read from.
    556 *
    557 * Return the timestamp from a subbuffer.
    558 */
    559unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf)
    560{
    561	return kbuf->read_8(subbuf);
    562}
    563
    564/**
    565 * kbuffer_ptr_delta - read the delta field from a record
    566 * @kbuf:      The kbuffer to load
    567 * @ptr:       The record in the buffe.
    568 *
    569 * Return the timestamp delta from a record
    570 */
    571unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr)
    572{
    573	unsigned int type_len_ts;
    574
    575	type_len_ts = read_4(kbuf, ptr);
    576	return ts4host(kbuf, type_len_ts);
    577}
    578
    579
    580/**
    581 * kbuffer_read_event - read the next event in the kbuffer subbuffer
    582 * @kbuf:	The kbuffer to read from
    583 * @ts:		The address to store the timestamp of the event (may be NULL to ignore)
    584 *
    585 * Returns a pointer to the data part of the current event.
    586 * NULL if no event is left on the subbuffer.
    587 */
    588void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts)
    589{
    590	if (!kbuf || !kbuf->subbuffer)
    591		return NULL;
    592
    593	if (kbuf->curr >= kbuf->size)
    594		return NULL;
    595
    596	if (ts)
    597		*ts = kbuf->timestamp;
    598	return kbuf->data + kbuf->index;
    599}
    600
    601/**
    602 * kbuffer_timestamp - Return the timestamp of the current event
    603 * @kbuf:	The kbuffer to read from
    604 *
    605 * Returns the timestamp of the current (next) event.
    606 */
    607unsigned long long kbuffer_timestamp(struct kbuffer *kbuf)
    608{
    609	return kbuf->timestamp;
    610}
    611
    612/**
    613 * kbuffer_read_at_offset - read the event that is at offset
    614 * @kbuf:	The kbuffer to read from
    615 * @offset:	The offset into the subbuffer
    616 * @ts:		The address to store the timestamp of the event (may be NULL to ignore)
    617 *
    618 * The @offset must be an index from the @kbuf subbuffer beginning.
    619 * If @offset is bigger than the stored subbuffer, NULL will be returned.
    620 *
    621 * Returns the data of the record that is at @offset. Note, @offset does
    622 * not need to be the start of the record, the offset just needs to be
    623 * in the record (or beginning of it).
    624 *
    625 * Note, the kbuf timestamp and pointers are updated to the
    626 * returned record. That is, kbuffer_read_event() will return the same
    627 * data and timestamp, and kbuffer_next_event() will increment from
    628 * this record.
    629 */
    630void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
    631			     unsigned long long *ts)
    632{
    633	void *data;
    634
    635	if (offset < kbuf->start)
    636		offset = 0;
    637	else
    638		offset -= kbuf->start;
    639
    640	/* Reset the buffer */
    641	kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
    642	data = kbuffer_read_event(kbuf, ts);
    643
    644	while (kbuf->curr < offset) {
    645		data = kbuffer_next_event(kbuf, ts);
    646		if (!data)
    647			break;
    648	}
    649
    650	return data;
    651}
    652
    653/**
    654 * kbuffer_subbuffer_size - the size of the loaded subbuffer
    655 * @kbuf:	The kbuffer to read from
    656 *
    657 * Returns the size of the subbuffer. Note, this size is
    658 * where the last event resides. The stored subbuffer may actually be
    659 * bigger due to padding and such.
    660 */
    661int kbuffer_subbuffer_size(struct kbuffer *kbuf)
    662{
    663	return kbuf->size;
    664}
    665
    666/**
    667 * kbuffer_curr_index - Return the index of the record
    668 * @kbuf:	The kbuffer to read from
    669 *
    670 * Returns the index from the start of the data part of
    671 * the subbuffer to the current location. Note this is not
    672 * from the start of the subbuffer. An index of zero will
    673 * point to the first record. Use kbuffer_curr_offset() for
    674 * the actually offset (that can be used by kbuffer_read_at_offset())
    675 */
    676int kbuffer_curr_index(struct kbuffer *kbuf)
    677{
    678	return kbuf->curr;
    679}
    680
    681/**
    682 * kbuffer_curr_offset - Return the offset of the record
    683 * @kbuf:	The kbuffer to read from
    684 *
    685 * Returns the offset from the start of the subbuffer to the
    686 * current location.
    687 */
    688int kbuffer_curr_offset(struct kbuffer *kbuf)
    689{
    690	return kbuf->curr + kbuf->start;
    691}
    692
    693/**
    694 * kbuffer_event_size - return the size of the event data
    695 * @kbuf:	The kbuffer to read
    696 *
    697 * Returns the size of the event data (the payload not counting
    698 * the meta data of the record) of the current event.
    699 */
    700int kbuffer_event_size(struct kbuffer *kbuf)
    701{
    702	return kbuf->next - kbuf->index;
    703}
    704
    705/**
    706 * kbuffer_curr_size - return the size of the entire record
    707 * @kbuf:	The kbuffer to read
    708 *
    709 * Returns the size of the entire record (meta data and payload)
    710 * of the current event.
    711 */
    712int kbuffer_curr_size(struct kbuffer *kbuf)
    713{
    714	return kbuf->next - kbuf->curr;
    715}
    716
    717/**
    718 * kbuffer_missed_events - return the # of missed events from last event.
    719 * @kbuf: 	The kbuffer to read from
    720 *
    721 * Returns the # of missed events (if recorded) before the current
    722 * event. Note, only events on the beginning of a subbuffer can
    723 * have missed events, all other events within the buffer will be
    724 * zero.
    725 */
    726int kbuffer_missed_events(struct kbuffer *kbuf)
    727{
    728	/* Only the first event can have missed events */
    729	if (kbuf->curr)
    730		return 0;
    731
    732	return kbuf->lost_events;
    733}
    734
    735/**
    736 * kbuffer_set_old_forma - set the kbuffer to use the old format parsing
    737 * @kbuf:	The kbuffer to set
    738 *
    739 * This is obsolete (or should be). The first kernels to use the
    740 * new ring buffer had a slightly different ring buffer format
    741 * (2.6.30 and earlier). It is still somewhat supported by kbuffer,
    742 * but should not be counted on in the future.
    743 */
    744void kbuffer_set_old_format(struct kbuffer *kbuf)
    745{
    746	kbuf->flags |= KBUFFER_FL_OLD_FORMAT;
    747
    748	kbuf->next_event = __old_next_event;
    749}
    750
    751/**
    752 * kbuffer_start_of_data - return offset of where data starts on subbuffer
    753 * @kbuf:	The kbuffer
    754 *
    755 * Returns the location on the subbuffer where the data starts.
    756 */
    757int kbuffer_start_of_data(struct kbuffer *kbuf)
    758{
    759	return kbuf->start;
    760}
    761
    762/**
    763 * kbuffer_raw_get - get raw buffer info
    764 * @kbuf:	The kbuffer
    765 * @subbuf:	Start of mapped subbuffer
    766 * @info:	Info descriptor to fill in
    767 *
    768 * For debugging. This can return internals of the ring buffer.
    769 * Expects to have info->next set to what it will read.
    770 * The type, length and timestamp delta will be filled in, and
    771 * @info->next will be updated to the next element.
    772 * The @subbuf is used to know if the info is passed the end of
    773 * data and NULL will be returned if it is.
    774 */
    775struct kbuffer_raw_info *
    776kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, struct kbuffer_raw_info *info)
    777{
    778	unsigned long long flags;
    779	unsigned long long delta;
    780	unsigned int type_len;
    781	unsigned int size;
    782	int start;
    783	int length;
    784	void *ptr = info->next;
    785
    786	if (!kbuf || !subbuf)
    787		return NULL;
    788
    789	if (kbuf->flags & KBUFFER_FL_LONG_8)
    790		start = 16;
    791	else
    792		start = 12;
    793
    794	flags = read_long(kbuf, subbuf + 8);
    795	size = (unsigned int)flags & COMMIT_MASK;
    796
    797	if (ptr < subbuf || ptr >= subbuf + start + size)
    798		return NULL;
    799
    800	type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
    801
    802	info->next = ptr + length;
    803
    804	info->type = type_len;
    805	info->delta = delta;
    806	info->length = length;
    807
    808	return info;
    809}