1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_RING_BUFFER_EXT_H 3 #define _LINUX_RING_BUFFER_EXT_H 4 #include <linux/mm.h> 5 #include <linux/types.h> 6 7 struct rb_ext_stats { 8 u64 entries; 9 unsigned long pages_touched; 10 unsigned long overrun; 11 }; 12 13 #define RB_PAGE_FT_HEAD (1 << 0) 14 #define RB_PAGE_FT_READER (1 << 1) 15 #define RB_PAGE_FT_COMMIT (1 << 2) 16 17 /* 18 * The pages where the events are stored are the only shared elements between 19 * the reader and the external writer. They are convenient to enable 20 * communication from the writer to the reader. The data will be used by the 21 * reader to update its view on the ring buffer. 22 */ 23 struct rb_ext_page_footer { 24 atomic_t writer_status; 25 atomic_t reader_status; 26 struct rb_ext_stats stats; 27 }; 28 rb_ext_page_get_footer(void * page)29static inline struct rb_ext_page_footer *rb_ext_page_get_footer(void *page) 30 { 31 struct rb_ext_page_footer *footer; 32 unsigned long page_va = (unsigned long)page; 33 34 page_va = ALIGN_DOWN(page_va, PAGE_SIZE); 35 36 return (struct rb_ext_page_footer *)(page_va + PAGE_SIZE - 37 sizeof(*footer)); 38 } 39 40 #define BUF_EXT_PAGE_SIZE (BUF_PAGE_SIZE - sizeof(struct rb_ext_page_footer)) 41 42 /* 43 * An external writer can't rely on the internal struct ring_buffer_per_cpu. 44 * Instead, allow to pack the relevant information into struct 45 * ring_buffer_pack which can be sent to the writer. The latter can then create 46 * its own view on the ring buffer. 47 */ 48 struct ring_buffer_pack { 49 int cpu; 50 unsigned long reader_page_va; 51 unsigned long nr_pages; 52 unsigned long page_va[]; 53 }; 54 55 struct trace_buffer_pack { 56 int nr_cpus; 57 unsigned long total_pages; 58 char __data[]; /* contains ring_buffer_pack */ 59 }; 60 61 static inline __next_ring_buffer_pack(struct ring_buffer_pack * rb_pack)62struct ring_buffer_pack *__next_ring_buffer_pack(struct ring_buffer_pack *rb_pack) 63 { 64 size_t len; 65 66 len = offsetof(struct ring_buffer_pack, page_va) + 67 sizeof(unsigned long) * rb_pack->nr_pages; 68 69 return (struct ring_buffer_pack *)((void *)rb_pack + len); 70 } 71 72 /* 73 * Accessor for ring_buffer_pack's within trace_buffer_pack 74 */ 75 #define for_each_ring_buffer_pack(rb_pack, cpu, trace_pack) \ 76 for (rb_pack = (struct ring_buffer_pack *)&trace_pack->__data[0], cpu = 0; \ 77 cpu < trace_pack->nr_cpus; \ 78 cpu++, rb_pack = __next_ring_buffer_pack(rb_pack)) 79 #endif 80