From patchwork Sat Feb 15 03:43:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975933 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 120CB155308; Sat, 15 Feb 2025 03:43:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=cHAK/FLvF6Ha5oayuinixWQQpbWER0jldkeaT1/PrtsMp5JnNootWdCDM3fG93jx/bpcjt9qvGzEDVr70n8rysawtqk9hfyRq5v9canU+dI4Yr1pucbUtHqmZdA40CntFdg/Mb+mZiFIjmA14uumb6jmxdMnUxLv/ZgL3sAAPYM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=Tn2lOle0ag6owIdPD8+uGiFuZDKAEyNygQQ3TGSMXg4=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=T5Jd+pzpsl4CWsmyxs/DLsPYu/yFoXUUCP2vkTjjWIKCHNUjrfa6Ze0QVT8/YkpwEffiTmfW/gAAG4VDxtaqoqYRnIPLt8fBC4lc7ZpispYTa+7gfgy84n/s1QXhcOtAlsdVzk/2knUdbK/IbfLwdFlZ9MEL1tILvdjl8HZtX7U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 83623C4CEE5; Sat, 15 Feb 2025 03:43:50 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj964-00000002guM-1YFY; Fri, 14 Feb 2025 22:44:04 -0500 Message-ID: <20250215034404.219446232@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:02 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH v2 1/8] ring-buffer: Use kaslr address instead of text delta References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Instead of saving off the text and data pointers and using them to compare with the current boot's text and data pointers, just save off the KASLR offset. Then that can be used to figure out how to read the previous boots buffer. The last_boot_info will now show this offset, but only if it is for a previous boot: ~# cat instances/boot_mapped/last_boot_info 39000000 [kernel] ~# echo function > instances/boot_mapped/current_tracer ~# cat instances/boot_mapped/last_boot_info # Current If the KASLR offset saved is for the current boot, the last_boot_info will show the value of "current". Signed-off-by: Steven Rostedt (Google) --- include/linux/ring_buffer.h | 3 +-- kernel/trace/ring_buffer.c | 31 ++++++++++++------------------- kernel/trace/trace.c | 30 +++++++++++++++++++++--------- kernel/trace/trace.h | 9 +++++---- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 17fbb7855295..8de035f4f0d9 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -94,8 +94,7 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag unsigned long range_size, struct lock_class_key *key); -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text, - long *data); +bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr); /* * Because the ring buffer is generic, if other users of the ring buffer get diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 87caf9d48edb..1bf1228caf0e 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -31,6 +31,7 @@ #include #include +#include #include "trace.h" @@ -49,8 +50,7 @@ static void update_pages_handler(struct work_struct *work); struct ring_buffer_meta { int magic; int struct_size; - unsigned long text_addr; - unsigned long data_addr; + unsigned long kaslr_addr; unsigned long first_buffer; unsigned long head_buffer; unsigned long commit_buffer; @@ -550,8 +550,7 @@ struct trace_buffer { unsigned long range_addr_start; unsigned long range_addr_end; - long last_text_delta; - long last_data_delta; + unsigned long kaslr_addr; unsigned int subbuf_size; unsigned int subbuf_order; @@ -1891,16 +1890,13 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) } } -/* Used to calculate data delta */ -static char rb_data_ptr[] = ""; - -#define THIS_TEXT_PTR ((unsigned long)rb_meta_init_text_addr) -#define THIS_DATA_PTR ((unsigned long)rb_data_ptr) - static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) { - meta->text_addr = THIS_TEXT_PTR; - meta->data_addr = THIS_DATA_PTR; +#ifdef CONFIG_RANDOMIZE_BASE + meta->kaslr_addr = kaslr_offset(); +#else + meta->kaslr_addr = 0; +#endif } static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) @@ -1928,8 +1924,7 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) meta->first_buffer += delta; meta->head_buffer += delta; meta->commit_buffer += delta; - buffer->last_text_delta = THIS_TEXT_PTR - meta->text_addr; - buffer->last_data_delta = THIS_DATA_PTR - meta->data_addr; + buffer->kaslr_addr = meta->kaslr_addr; continue; } @@ -2482,17 +2477,15 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag * * Returns: The true if the delta is non zero */ -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text, - long *data) +bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr) { if (!buffer) return false; - if (!buffer->last_text_delta) + if (!buffer->kaslr_addr) return false; - *text = buffer->last_text_delta; - *data = buffer->last_data_delta; + *kaslr_addr = buffer->kaslr_addr; return true; } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 25ff37aab00f..41d463e5327c 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -50,7 +50,7 @@ #include #include -#include /* COMMAND_LINE_SIZE */ +#include /* COMMAND_LINE_SIZE and kaslr_offset() */ #include "trace.h" #include "trace_output.h" @@ -4193,7 +4193,7 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) * safe to use if the array has delta offsets * Force printing via the fields. */ - if ((tr->text_delta || tr->data_delta) && + if ((tr->text_delta) && event->type > __TRACE_LAST_TYPE) return print_event_fields(iter, event); @@ -5990,7 +5990,7 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, static void update_last_data(struct trace_array *tr) { - if (!tr->text_delta && !tr->data_delta) + if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) return; /* @@ -6003,7 +6003,8 @@ static void update_last_data(struct trace_array *tr) /* Using current data now */ tr->text_delta = 0; - tr->data_delta = 0; + + tr->flags &= ~TRACE_ARRAY_FL_LAST_BOOT; } /** @@ -6821,8 +6822,17 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t seq_buf_init(&seq, buf, 64); - seq_buf_printf(&seq, "text delta:\t%ld\n", tr->text_delta); - seq_buf_printf(&seq, "data delta:\t%ld\n", tr->data_delta); + /* + * Do not leak KASLR address. This only shows the KASLR address of + * the last boot. When the ring buffer is started, the LAST_BOOT + * flag gets cleared, and this should only report "current". + * Otherwise it shows the KASLR address from the previous boot which + * should not be the same as the current boot. + */ + if (tr->flags & TRACE_ARRAY_FL_LAST_BOOT) + seq_buf_printf(&seq, "%lx\t[kernel]\n", tr->kaslr_addr); + else + seq_buf_puts(&seq, "# Current\n"); return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq)); } @@ -9206,8 +9216,10 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size tr->range_addr_start, tr->range_addr_size); - ring_buffer_last_boot_delta(buf->buffer, - &tr->text_delta, &tr->data_delta); +#ifdef CONFIG_RANDOMIZE_BASE + if (ring_buffer_last_boot_delta(buf->buffer, &tr->kaslr_addr)) + tr->text_delta = kaslr_offset() - tr->kaslr_addr; +#endif /* * This is basically the same as a mapped buffer, * with the same restrictions. @@ -10455,7 +10467,7 @@ __init static void enable_instances(void) * to it. */ if (start) { - tr->flags |= TRACE_ARRAY_FL_BOOT; + tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT; tr->ref++; } diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 9c21ba45b7af..abe8169c3e87 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -348,8 +348,8 @@ struct trace_array { unsigned int mapped; unsigned long range_addr_start; unsigned long range_addr_size; + unsigned long kaslr_addr; long text_delta; - long data_delta; struct trace_pid_list __rcu *filtered_pids; struct trace_pid_list __rcu *filtered_no_pids; @@ -433,9 +433,10 @@ struct trace_array { }; enum { - TRACE_ARRAY_FL_GLOBAL = BIT(0), - TRACE_ARRAY_FL_BOOT = BIT(1), - TRACE_ARRAY_FL_MOD_INIT = BIT(2), + TRACE_ARRAY_FL_GLOBAL = BIT(0), + TRACE_ARRAY_FL_BOOT = BIT(1), + TRACE_ARRAY_FL_LAST_BOOT = BIT(2), + TRACE_ARRAY_FL_MOD_INIT = BIT(3), }; #ifdef CONFIG_MODULES From patchwork Sat Feb 15 03:43:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975934 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D90E15696E; Sat, 15 Feb 2025 03:43:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=SOxVAlbShccp3Q4Ba6NlaNblOn4tFYv9O6Yht2HIbAoXXU4iJRDisraFiJ5o3/MwpmHyV1gBRGkeF63ExSkAVaG+wCP33nxwWe28Giz3q/hlJ87xi1I+1w25Uzxdzm/rbK361VENx2HMHwVE+XySUaBWRa1tFRvUrvI0BHpu9n0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=dds1X/njzJTJPZKVsC94j/ArbGRYYDvZN0IZTA+bkLs=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=mUlK2LRZTV2CoukYGXsO1jWV2/G3Ju1jzfURW9QvPmcaYU4QgFFVyhDBwVzvJQcg1GJLTqs6adPqi6fwkLgjHKXhImkveIFvoe2sm0QKEjHz9LvcO/4/Lf//HfbQmQbmL6jujmi3CbnHNjg2ZX0inqJTCTIW7H5oqQXNo1z+KUw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9CFE7C4CEE8; Sat, 15 Feb 2025 03:43:50 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj964-00000002gur-2G4E; Fri, 14 Feb 2025 22:44:04 -0500 Message-ID: <20250215034404.391036666@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:03 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH v2 2/8] ring-buffer: Add buffer meta data for persistent ring buffer References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Instead of just having a meta data at the first page of each sub buffer that has duplicate data, add a new meta page to the entire block of memory that holds the duplicate data and remove it from the sub buffer meta data. This will open up the extra memory in this first page to be used by the tracer for its own persistent data. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ring_buffer.c | 171 ++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 52 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 1bf1228caf0e..bd37e14990a3 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -49,7 +49,12 @@ static void update_pages_handler(struct work_struct *work); struct ring_buffer_meta { int magic; - int struct_size; + int struct_sizes; + unsigned long total_size; + unsigned long buffers_offset; +}; + +struct ring_buffer_cpu_meta { unsigned long kaslr_addr; unsigned long first_buffer; unsigned long head_buffer; @@ -517,7 +522,7 @@ struct ring_buffer_per_cpu { struct mutex mapping_lock; unsigned long *subbuf_ids; /* ID to subbuf VA */ struct trace_buffer_meta *meta_page; - struct ring_buffer_meta *ring_meta; + struct ring_buffer_cpu_meta *ring_meta; /* ring buffer pages to update, > 0 to add, < 0 to remove */ long nr_pages_to_update; @@ -550,6 +555,8 @@ struct trace_buffer { unsigned long range_addr_start; unsigned long range_addr_end; + struct ring_buffer_meta *meta; + unsigned long kaslr_addr; unsigned int subbuf_size; @@ -1270,7 +1277,7 @@ static void rb_head_page_activate(struct ring_buffer_per_cpu *cpu_buffer) rb_set_list_to_head(head->list.prev); if (cpu_buffer->ring_meta) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; meta->head_buffer = (unsigned long)head->page; } } @@ -1568,7 +1575,7 @@ static void rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) static unsigned long rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs) { - addr += sizeof(struct ring_buffer_meta) + + addr += sizeof(struct ring_buffer_cpu_meta) + sizeof(int) * nr_subbufs; return ALIGN(addr, subbuf_size); } @@ -1579,19 +1586,22 @@ rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs) static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu) { int subbuf_size = buffer->subbuf_size + BUF_PAGE_HDR_SIZE; - unsigned long ptr = buffer->range_addr_start; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; + struct ring_buffer_meta *bmeta; + unsigned long ptr; int nr_subbufs; - if (!ptr) + bmeta = buffer->meta; + if (!bmeta) return NULL; + ptr = (unsigned long)bmeta + bmeta->buffers_offset; + meta = (struct ring_buffer_cpu_meta *)ptr; + /* When nr_pages passed in is zero, the first meta has already been initialized */ if (!nr_pages) { - meta = (struct ring_buffer_meta *)ptr; nr_subbufs = meta->nr_subbufs; } else { - meta = NULL; /* Include the reader page */ nr_subbufs = nr_pages + 1; } @@ -1623,7 +1633,7 @@ static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu) } /* Return the start of subbufs given the meta pointer */ -static void *rb_subbufs_from_meta(struct ring_buffer_meta *meta) +static void *rb_subbufs_from_meta(struct ring_buffer_cpu_meta *meta) { int subbuf_size = meta->subbuf_size; unsigned long ptr; @@ -1639,7 +1649,7 @@ static void *rb_subbufs_from_meta(struct ring_buffer_meta *meta) */ static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx) { - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; unsigned long ptr; int subbuf_size; @@ -1664,15 +1674,74 @@ static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx) return (void *)ptr; } +/* + * See if the existing memory contains a valid meta section. + * if so, use that, otherwise initialize it. + */ +static bool rb_meta_init(struct trace_buffer *buffer) +{ + unsigned long ptr = buffer->range_addr_start; + struct ring_buffer_meta *bmeta; + unsigned long total_size; + int struct_sizes; + + bmeta = (struct ring_buffer_meta *)ptr; + buffer->meta = bmeta; + + total_size = buffer->range_addr_end - buffer->range_addr_start; + + struct_sizes = sizeof(struct ring_buffer_cpu_meta); + struct_sizes |= sizeof(*bmeta) << 16; + + /* The first buffer will start word size after the meta page */ + ptr += sizeof(*bmeta); + ptr = ALIGN(ptr, sizeof(long)); + + if (bmeta->magic != RING_BUFFER_META_MAGIC) { + pr_info("Ring buffer boot meta mismatch of magic\n"); + goto init; + } + + if (bmeta->struct_sizes != struct_sizes) { + pr_info("Ring buffer boot meta mismatch of struct size\n"); + goto init; + } + + if (bmeta->total_size != total_size) { + pr_info("Ring buffer boot meta mismatch of total size\n"); + goto init; + } + + if (bmeta->buffers_offset > bmeta->total_size) { + pr_info("Ring buffer boot meta mismatch of offset outside of total size\n"); + goto init; + } + + if (bmeta->buffers_offset != (void *)ptr - (void *)bmeta) { + pr_info("Ring buffer boot meta mismatch of first buffer offset\n"); + goto init; + } + + return true; + + init: + bmeta->magic = RING_BUFFER_META_MAGIC; + bmeta->struct_sizes = struct_sizes; + bmeta->total_size = total_size; + bmeta->buffers_offset = (void *)ptr - (void *)bmeta; + + return false; +} + /* * See if the existing memory contains valid ring buffer data. * As the previous kernel must be the same as this kernel, all * the calculations (size of buffers and number of buffers) * must be the same. */ -static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, - struct trace_buffer *buffer, int nr_pages, - unsigned long *subbuf_mask) +static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, + struct trace_buffer *buffer, int nr_pages, + unsigned long *subbuf_mask) { int subbuf_size = PAGE_SIZE; struct buffer_data_page *subbuf; @@ -1683,20 +1752,6 @@ static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, if (!subbuf_mask) return false; - /* Check the meta magic and meta struct size */ - if (meta->magic != RING_BUFFER_META_MAGIC || - meta->struct_size != sizeof(*meta)) { - pr_info("Ring buffer boot meta[%d] mismatch of magic or struct size\n", cpu); - return false; - } - - /* The subbuffer's size and number of subbuffers must match */ - if (meta->subbuf_size != subbuf_size || - meta->nr_subbufs != nr_pages + 1) { - pr_info("Ring buffer boot meta [%d] mismatch of subbuf_size/nr_pages\n", cpu); - return false; - } - buffers_start = meta->first_buffer; buffers_end = meta->first_buffer + (subbuf_size * meta->nr_subbufs); @@ -1742,7 +1797,7 @@ static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, return true; } -static int rb_meta_subbuf_idx(struct ring_buffer_meta *meta, void *subbuf); +static int rb_meta_subbuf_idx(struct ring_buffer_cpu_meta *meta, void *subbuf); static int rb_read_data_buffer(struct buffer_data_page *dpage, int tail, int cpu, unsigned long long *timestamp, u64 *delta_ptr) @@ -1809,7 +1864,7 @@ static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu) /* If the meta data has been validated, now validate the events */ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; struct buffer_page *head_page; unsigned long entry_bytes = 0; unsigned long entries = 0; @@ -1890,7 +1945,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) } } -static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) +static void rb_meta_init_text_addr(struct ring_buffer_cpu_meta *meta) { #ifdef CONFIG_RANDOMIZE_BASE meta->kaslr_addr = kaslr_offset(); @@ -1901,10 +1956,12 @@ static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) { - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; + struct ring_buffer_meta *bmeta; unsigned long *subbuf_mask; unsigned long delta; void *subbuf; + bool valid = false; int cpu; int i; @@ -1912,12 +1969,17 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) subbuf_mask = bitmap_alloc(nr_pages + 1, GFP_KERNEL); /* If subbuf_mask fails to allocate, then rb_meta_valid() will return false */ + if (rb_meta_init(buffer)) + valid = true; + + bmeta = buffer->meta; + for (cpu = 0; cpu < nr_cpu_ids; cpu++) { void *next_meta; meta = rb_range_meta(buffer, nr_pages, cpu); - if (rb_meta_valid(meta, cpu, buffer, nr_pages, subbuf_mask)) { + if (valid && rb_cpu_meta_valid(meta, cpu, buffer, nr_pages, subbuf_mask)) { /* Make the mappings match the current address */ subbuf = rb_subbufs_from_meta(meta); delta = (unsigned long)subbuf - meta->first_buffer; @@ -1935,9 +1997,6 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) memset(meta, 0, next_meta - (void *)meta); - meta->magic = RING_BUFFER_META_MAGIC; - meta->struct_size = sizeof(*meta); - meta->nr_subbufs = nr_pages + 1; meta->subbuf_size = PAGE_SIZE; @@ -1966,7 +2025,7 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) static void *rbm_start(struct seq_file *m, loff_t *pos) { struct ring_buffer_per_cpu *cpu_buffer = m->private; - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; unsigned long val; if (!meta) @@ -1991,7 +2050,7 @@ static void *rbm_next(struct seq_file *m, void *v, loff_t *pos) static int rbm_show(struct seq_file *m, void *v) { struct ring_buffer_per_cpu *cpu_buffer = m->private; - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; unsigned long val = (unsigned long)v; if (val == 1) { @@ -2040,7 +2099,7 @@ int ring_buffer_meta_seq_init(struct file *file, struct trace_buffer *buffer, in static void rb_meta_buffer_update(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_page *bpage) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; if (meta->head_buffer == (unsigned long)bpage->page) cpu_buffer->head_page = bpage; @@ -2055,7 +2114,7 @@ static int __rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, long nr_pages, struct list_head *pages) { struct trace_buffer *buffer = cpu_buffer->buffer; - struct ring_buffer_meta *meta = NULL; + struct ring_buffer_cpu_meta *meta = NULL; struct buffer_page *bpage, *tmp; bool user_thread = current->mm != NULL; gfp_t mflags; @@ -2179,7 +2238,7 @@ static struct ring_buffer_per_cpu * rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu) { struct ring_buffer_per_cpu *cpu_buffer; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; struct buffer_page *bpage; struct page *page; int ret; @@ -2350,10 +2409,18 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, /* If start/end are specified, then that overrides size */ if (start && end) { + unsigned long buffers_start; unsigned long ptr; int n; - size = end - start; + /* Make sure that start is word aligned */ + start = ALIGN(start, sizeof(long)); + + /* Subtract the buffer meta data and word aligned */ + buffers_start = start + sizeof(struct ring_buffer_cpu_meta); + buffers_start = ALIGN(buffers_start, sizeof(long)); + + size = end - buffers_start; size = size / nr_cpu_ids; /* @@ -2363,7 +2430,7 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, * needed, plus account for the integer array index that * will be appended to the meta data. */ - nr_pages = (size - sizeof(struct ring_buffer_meta)) / + nr_pages = (size - sizeof(struct ring_buffer_cpu_meta)) / (subbuf_size + sizeof(int)); /* Need at least two pages plus the reader page */ if (nr_pages < 3) @@ -2371,8 +2438,8 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, again: /* Make sure that the size fits aligned */ - for (n = 0, ptr = start; n < nr_cpu_ids; n++) { - ptr += sizeof(struct ring_buffer_meta) + + for (n = 0, ptr = buffers_start; n < nr_cpu_ids; n++) { + ptr += sizeof(struct ring_buffer_cpu_meta) + sizeof(int) * nr_pages; ptr = ALIGN(ptr, subbuf_size); ptr += subbuf_size * nr_pages; @@ -3098,7 +3165,7 @@ static void rb_inc_iter(struct ring_buffer_iter *iter) } /* Return the index into the sub-buffers for a given sub-buffer */ -static int rb_meta_subbuf_idx(struct ring_buffer_meta *meta, void *subbuf) +static int rb_meta_subbuf_idx(struct ring_buffer_cpu_meta *meta, void *subbuf) { void *subbuf_array; @@ -3110,7 +3177,7 @@ static int rb_meta_subbuf_idx(struct ring_buffer_meta *meta, void *subbuf) static void rb_update_meta_head(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_page *next_page) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; unsigned long old_head = (unsigned long)next_page->page; unsigned long new_head; @@ -3127,7 +3194,7 @@ static void rb_update_meta_head(struct ring_buffer_per_cpu *cpu_buffer, static void rb_update_meta_reader(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_page *reader) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; void *old_reader = cpu_buffer->reader_page->page; void *new_reader = reader->page; int id; @@ -3756,7 +3823,7 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer) rb_page_write(cpu_buffer->commit_page)); rb_inc_page(&cpu_buffer->commit_page); if (cpu_buffer->ring_meta) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; meta->commit_buffer = (unsigned long)cpu_buffer->commit_page->page; } /* add barrier to keep gcc from optimizing too much */ @@ -6020,7 +6087,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) if (cpu_buffer->mapped) { rb_update_meta_page(cpu_buffer); if (cpu_buffer->ring_meta) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; meta->commit_buffer = meta->head_buffer; } } @@ -6054,7 +6121,7 @@ static void reset_disabled_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu) { struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; if (!cpumask_test_cpu(cpu, buffer->cpumask)) return; @@ -6092,7 +6159,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); void ring_buffer_reset_online_cpus(struct trace_buffer *buffer) { struct ring_buffer_per_cpu *cpu_buffer; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; int cpu; /* prevent another thread from changing buffer sizes */ From patchwork Sat Feb 15 03:43:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975935 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D9531581F1; Sat, 15 Feb 2025 03:43:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=mHfwIz+shdL1yDsxxoMHNie2+Fx/0lln/zh5HEK68OTueDhF/y3x1pbtA1T6AvZKvyZfyGheBrZ6M103w4+h2lzH/9MFLc8cqpMNifvceHAAylhE097ViaMXRzFLaa6Ryt0lfwSaOS9eA1LZICW/EltK9ZTJ9Bf1JN4/BmmYA+o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=EBEd3PhYAn7ciL0rW/SKGezKfyxVltrfB4AMI0bdWbs=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=Ou+32nt0+vPMeQQHck+g99ETpOOvTLW2C/XSNgcWA5jkaUI/w7u/NSK31+MGpRkbRCbQNBB7wgn4I4dGphnxsBgDKncXAqFh3PnICkd3xi4+x0BxaXbhvI6oExH+zwQTGd1REvQsfuE8UrJL7c6z8SAdOLVLgKBA6Jw+uKGLNKw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id C8FA2C4CEE7; Sat, 15 Feb 2025 03:43:50 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj964-00000002gvL-2xpV; Fri, 14 Feb 2025 22:44:04 -0500 Message-ID: <20250215034404.558793959@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:04 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH v2 3/8] ring-buffer: Add ring_buffer_meta_scratch() References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Now that there's one meta data at the start of the persistent memory used by the ring buffer, allow the caller to request some memory right after that data that it can use as its own persistent memory. Also fix some white space issues with ring_buffer_alloc(). Signed-off-by: Steven Rostedt (Google) --- include/linux/ring_buffer.h | 6 ++++-- kernel/trace/ring_buffer.c | 34 ++++++++++++++++++++++++++++------ kernel/trace/trace.c | 2 +- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 8de035f4f0d9..019b59a0bbc9 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -92,9 +92,11 @@ __ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *k struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flags, int order, unsigned long start, unsigned long range_size, + unsigned long scratch_size, struct lock_class_key *key); bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr); +void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size); /* * Because the ring buffer is generic, if other users of the ring buffer get @@ -112,11 +114,11 @@ bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kas * traced by ftrace, it can produce lockdep warnings. We need to keep each * ring buffer's lock class separate. */ -#define ring_buffer_alloc_range(size, flags, order, start, range_size) \ +#define ring_buffer_alloc_range(size, flags, order, start, range_size, s_size) \ ({ \ static struct lock_class_key __key; \ __ring_buffer_alloc_range((size), (flags), (order), (start), \ - (range_size), &__key); \ + (range_size), (s_size), &__key); \ }) typedef bool (*ring_buffer_cond_fn)(void *data); diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index bd37e14990a3..2df74f3f0086 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1678,7 +1678,7 @@ static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx) * See if the existing memory contains a valid meta section. * if so, use that, otherwise initialize it. */ -static bool rb_meta_init(struct trace_buffer *buffer) +static bool rb_meta_init(struct trace_buffer *buffer, int scratch_size) { unsigned long ptr = buffer->range_addr_start; struct ring_buffer_meta *bmeta; @@ -1696,6 +1696,7 @@ static bool rb_meta_init(struct trace_buffer *buffer) /* The first buffer will start word size after the meta page */ ptr += sizeof(*bmeta); ptr = ALIGN(ptr, sizeof(long)); + ptr += scratch_size; if (bmeta->magic != RING_BUFFER_META_MAGIC) { pr_info("Ring buffer boot meta mismatch of magic\n"); @@ -1730,6 +1731,9 @@ static bool rb_meta_init(struct trace_buffer *buffer) bmeta->total_size = total_size; bmeta->buffers_offset = (void *)ptr - (void *)bmeta; + /* Zero out the scatch pad */ + memset((void *)bmeta + sizeof(*bmeta), 0, bmeta->buffers_offset - sizeof(*bmeta)); + return false; } @@ -1954,7 +1958,7 @@ static void rb_meta_init_text_addr(struct ring_buffer_cpu_meta *meta) #endif } -static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) +static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages, int scratch_size) { struct ring_buffer_cpu_meta *meta; struct ring_buffer_meta *bmeta; @@ -1969,7 +1973,7 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) subbuf_mask = bitmap_alloc(nr_pages + 1, GFP_KERNEL); /* If subbuf_mask fails to allocate, then rb_meta_valid() will return false */ - if (rb_meta_init(buffer)) + if (rb_meta_init(buffer, scratch_size)) valid = true; bmeta = buffer->meta; @@ -2367,6 +2371,7 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, int order, unsigned long start, unsigned long end, + unsigned long scratch_size, struct lock_class_key *key) { struct trace_buffer *buffer; @@ -2416,10 +2421,15 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, /* Make sure that start is word aligned */ start = ALIGN(start, sizeof(long)); + /* scratch_size needs to be aligned too */ + scratch_size = ALIGN(scratch_size, sizeof(long)); + /* Subtract the buffer meta data and word aligned */ buffers_start = start + sizeof(struct ring_buffer_cpu_meta); buffers_start = ALIGN(buffers_start, sizeof(long)); + buffers_start += scratch_size; + /* Calculate the size for the per CPU data */ size = end - buffers_start; size = size / nr_cpu_ids; @@ -2456,7 +2466,7 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, buffer->range_addr_start = start; buffer->range_addr_end = end; - rb_range_meta_init(buffer, nr_pages); + rb_range_meta_init(buffer, nr_pages, scratch_size); } else { /* need at least two pages */ @@ -2509,7 +2519,7 @@ struct trace_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *key) { /* Default buffer page size - one system page */ - return alloc_buffer(size, flags, 0, 0, 0,key); + return alloc_buffer(size, flags, 0, 0, 0, 0, key); } EXPORT_SYMBOL_GPL(__ring_buffer_alloc); @@ -2531,9 +2541,11 @@ EXPORT_SYMBOL_GPL(__ring_buffer_alloc); struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flags, int order, unsigned long start, unsigned long range_size, + unsigned long scratch_size, struct lock_class_key *key) { - return alloc_buffer(size, flags, order, start, start + range_size, key); + return alloc_buffer(size, flags, order, start, start + range_size, + scratch_size, key); } /** @@ -2557,6 +2569,16 @@ bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kas return true; } +void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size) +{ + if (!buffer || !buffer->meta) + return NULL; + + *size = PAGE_SIZE - sizeof(*buffer->meta); + + return (void *)buffer->meta + sizeof(*buffer->meta); +} + /** * ring_buffer_free - free a ring buffer. * @buffer: the buffer to free. diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 41d463e5327c..69dcd7edaf26 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -9214,7 +9214,7 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size if (tr->range_addr_start && tr->range_addr_size) { buf->buffer = ring_buffer_alloc_range(size, rb_flags, 0, tr->range_addr_start, - tr->range_addr_size); + tr->range_addr_size, 0); #ifdef CONFIG_RANDOMIZE_BASE if (ring_buffer_last_boot_delta(buf->buffer, &tr->kaslr_addr)) From patchwork Sat Feb 15 03:43:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975936 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6961A1624EF; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=Kku1ujD+khgNnUV+AIBaIJLu/MqJb2/Uun97AcxioetRHIal4KNKAmiYiEJlCrCvJTXGyFt995LxLbGx+wCYqPeP8r5gTDG1qxGDKMxBswCbTQJBqRuN2P60dWSgERCS5A7u+X0IxyrwAdlXwS0TYdooLaXTfZiAZst6rALjYpM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=SnHPkIN7jZLK1JoJWXIbz+jIhK2seXuJ+sdHCfQJ278=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=pie39m82KDWS55vXqwFjbPDhVJGL6Hgu0oESLHW0NEapd4q6klj39y7z9JTKLDELyPwD9YaO503PDMTwYn45jlGwOXtOtsPdrMupvVhwsnfZ6vbpDxuQKmj6dc/SgE3ax9zKz28qZcU/HAodgegnA1JQTbABFkK8uGnGv1pPjfw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED9D6C4CEED; Sat, 15 Feb 2025 03:43:50 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj964-00000002gvp-3hRP; Fri, 14 Feb 2025 22:44:04 -0500 Message-ID: <20250215034404.730029975@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:05 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH v2 4/8] tracing: Have persistent trace instances save KASLR offset References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt There's no reason to save the KASLR offset for the ring buffer itself. That is used by the tracer. Now that the tracer has a way to save data in the persistent memory of the ring buffer, have the tracing infrastructure take care of the saving of the KASLR offset. Signed-off-by: Steven Rostedt (Google) --- include/linux/ring_buffer.h | 1 - kernel/trace/ring_buffer.c | 59 +++++++------------------------------ kernel/trace/trace.c | 37 +++++++++++++++++++---- kernel/trace/trace.h | 6 ++-- 4 files changed, 46 insertions(+), 57 deletions(-) diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 019b59a0bbc9..56e27263acf8 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -95,7 +95,6 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag unsigned long scratch_size, struct lock_class_key *key); -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr); void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size); /* diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 2df74f3f0086..3e8aab15ffd8 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -55,7 +55,6 @@ struct ring_buffer_meta { }; struct ring_buffer_cpu_meta { - unsigned long kaslr_addr; unsigned long first_buffer; unsigned long head_buffer; unsigned long commit_buffer; @@ -557,8 +556,6 @@ struct trace_buffer { struct ring_buffer_meta *meta; - unsigned long kaslr_addr; - unsigned int subbuf_size; unsigned int subbuf_order; unsigned int max_data_size; @@ -1949,15 +1946,6 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) } } -static void rb_meta_init_text_addr(struct ring_buffer_cpu_meta *meta) -{ -#ifdef CONFIG_RANDOMIZE_BASE - meta->kaslr_addr = kaslr_offset(); -#else - meta->kaslr_addr = 0; -#endif -} - static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages, int scratch_size) { struct ring_buffer_cpu_meta *meta; @@ -1990,7 +1978,6 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages, int sc meta->first_buffer += delta; meta->head_buffer += delta; meta->commit_buffer += delta; - buffer->kaslr_addr = meta->kaslr_addr; continue; } @@ -2007,7 +1994,6 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages, int sc subbuf = rb_subbufs_from_meta(meta); meta->first_buffer = (unsigned long)subbuf; - rb_meta_init_text_addr(meta); /* * The buffers[] array holds the order of the sub-buffers @@ -2548,35 +2534,22 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag scratch_size, key); } -/** - * ring_buffer_last_boot_delta - return the delta offset from last boot - * @buffer: The buffer to return the delta from - * @text: Return text delta - * @data: Return data delta - * - * Returns: The true if the delta is non zero - */ -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr) -{ - if (!buffer) - return false; - - if (!buffer->kaslr_addr) - return false; - - *kaslr_addr = buffer->kaslr_addr; - - return true; -} - void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size) { + struct ring_buffer_meta *meta; + void *ptr; + if (!buffer || !buffer->meta) return NULL; - *size = PAGE_SIZE - sizeof(*buffer->meta); + meta = buffer->meta; - return (void *)buffer->meta + sizeof(*buffer->meta); + ptr = (void *)ALIGN((unsigned long)meta + sizeof(*meta), sizeof(long)); + + if (size) + *size = (void *)meta + meta->buffers_offset - ptr; + + return ptr; } /** @@ -6143,7 +6116,6 @@ static void reset_disabled_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu) { struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; - struct ring_buffer_cpu_meta *meta; if (!cpumask_test_cpu(cpu, buffer->cpumask)) return; @@ -6162,11 +6134,6 @@ void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu) atomic_dec(&cpu_buffer->record_disabled); atomic_dec(&cpu_buffer->resize_disabled); - /* Make sure persistent meta now uses this buffer's addresses */ - meta = rb_range_meta(buffer, 0, cpu_buffer->cpu); - if (meta) - rb_meta_init_text_addr(meta); - mutex_unlock(&buffer->mutex); } EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); @@ -6181,7 +6148,6 @@ EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); void ring_buffer_reset_online_cpus(struct trace_buffer *buffer) { struct ring_buffer_per_cpu *cpu_buffer; - struct ring_buffer_cpu_meta *meta; int cpu; /* prevent another thread from changing buffer sizes */ @@ -6209,11 +6175,6 @@ void ring_buffer_reset_online_cpus(struct trace_buffer *buffer) reset_disabled_cpu_buffer(cpu_buffer); - /* Make sure persistent meta now uses this buffer's addresses */ - meta = rb_range_meta(buffer, 0, cpu_buffer->cpu); - if (meta) - rb_meta_init_text_addr(meta); - atomic_dec(&cpu_buffer->record_disabled); atomic_sub(RESET_BIT, &cpu_buffer->resize_disabled); } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 69dcd7edaf26..12a359c293c6 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5988,8 +5988,14 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, return __tracing_resize_ring_buffer(tr, size, cpu_id); } +struct trace_scratch { + unsigned long kaslr_addr; +}; + static void update_last_data(struct trace_array *tr) { + struct trace_scratch *tscratch; + if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) return; @@ -6004,6 +6010,17 @@ static void update_last_data(struct trace_array *tr) /* Using current data now */ tr->text_delta = 0; + if (!tr->scratch) + return; + + tscratch = tr->scratch; + + /* Set the persistent ring buffer meta data to this address */ +#ifdef CONFIG_RANDOMIZE_BASE + tscratch->kaslr_addr = kaslr_offset(); +#else + tscratch->kaslr_addr = 0; +#endif tr->flags &= ~TRACE_ARRAY_FL_LAST_BOOT; } @@ -6817,6 +6834,7 @@ static ssize_t tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct trace_array *tr = filp->private_data; + struct trace_scratch *tscratch = tr->scratch; struct seq_buf seq; char buf[64]; @@ -6829,8 +6847,8 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t * Otherwise it shows the KASLR address from the previous boot which * should not be the same as the current boot. */ - if (tr->flags & TRACE_ARRAY_FL_LAST_BOOT) - seq_buf_printf(&seq, "%lx\t[kernel]\n", tr->kaslr_addr); + if (tscratch && (tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) + seq_buf_printf(&seq, "%lx\t[kernel]\n", tscratch->kaslr_addr); else seq_buf_puts(&seq, "# Current\n"); @@ -9206,6 +9224,8 @@ static int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size) { enum ring_buffer_flags rb_flags; + struct trace_scratch *tscratch; + unsigned int scratch_size; rb_flags = tr->trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0; @@ -9214,12 +9234,19 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size if (tr->range_addr_start && tr->range_addr_size) { buf->buffer = ring_buffer_alloc_range(size, rb_flags, 0, tr->range_addr_start, - tr->range_addr_size, 0); + tr->range_addr_size, + sizeof(*tscratch)); + + tscratch = ring_buffer_meta_scratch(buf->buffer, &scratch_size); + if (tscratch) { + tr->scratch = tscratch; + tr->scratch_size = scratch_size; #ifdef CONFIG_RANDOMIZE_BASE - if (ring_buffer_last_boot_delta(buf->buffer, &tr->kaslr_addr)) - tr->text_delta = kaslr_offset() - tr->kaslr_addr; + if (tscratch->kaslr_addr) + tr->text_delta = kaslr_offset() - tscratch->kaslr_addr; #endif + } /* * This is basically the same as a mapped buffer, * with the same restrictions. diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index abe8169c3e87..3a020fb82a34 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -348,8 +348,11 @@ struct trace_array { unsigned int mapped; unsigned long range_addr_start; unsigned long range_addr_size; - unsigned long kaslr_addr; long text_delta; + void *scratch; /* pointer in persistent memory */ + int scratch_size; + + int buffer_disabled; struct trace_pid_list __rcu *filtered_pids; struct trace_pid_list __rcu *filtered_no_pids; @@ -367,7 +370,6 @@ struct trace_array { * CONFIG_TRACER_MAX_TRACE. */ arch_spinlock_t max_lock; - int buffer_disabled; #ifdef CONFIG_FTRACE_SYSCALLS int sys_refcount_enter; int sys_refcount_exit; From patchwork Sat Feb 15 03:43:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975938 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 846831624F5; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=ngyG8kH0F1UFVdtruqKmcw5RQejnIGOpKGvURvUh2UvAywXVpwOo6QOSnQeJsvwxVCXqxQmzdCF++j20p3YMLfhyyRv9ELfUrOoMngvnS5Y2lyDVmZcCiSp7/H6s3onjJuPhQTxlB6LBv0ifabZi5BuOnYJwsfd13x0ETmgqaTw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=uJnQyG8i5lyHH/RkjjPSKWtqaqlnhy1DWyeFiqlXDKo=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=CS2yzl78yybG55E51o9x3SQ0QJrJkRM+oR2MOf593BSGiebiBGxmmGDCD6YIrstNKGc692B39Nv0Sn3pmmkCmHDDEXvHgNXOcz5sw6sKsf1BQp9dbDGWOHXzA3O3sjrqm6pNPo24NdUDc+Jk8g8s8QK5XKlvYaIdP6tmqHlYC0o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0E72AC4CEE6; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj965-00000002gwJ-0Dzx; Fri, 14 Feb 2025 22:44:05 -0500 Message-ID: <20250215034404.902259250@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:06 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Luis Chamberlain , Petr Pavlu , Sami Tolvanen , Daniel Gomez , linux-modules@vger.kernel.org Subject: [PATCH v2 5/8] module: Add module_for_each_mod() function References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt The tracing system needs a way to save all the currently loaded modules and their addresses into persistent memory so that it can evaluate the addresses on a reboot from a crash. When the persistent memory trace starts, it will load the module addresses and names into the persistent memory. To do so, it will call the module_for_each_mod() function and pass it a function and data structure to get called on each loaded module. Then it can record the memory. This only implements that function. Cc: Luis Chamberlain Cc: Petr Pavlu Cc: Sami Tolvanen Cc: Daniel Gomez Cc: linux-modules@vger.kernel.org Signed-off-by: Steven Rostedt (Google) --- include/linux/module.h | 6 ++++++ kernel/module/main.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/linux/module.h b/include/linux/module.h index 30e5b19bafa9..9a71dd2cb11f 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -782,6 +782,8 @@ static inline void *module_writable_address(struct module *mod, void *loc) return __module_writable_address(mod, loc); } +void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data); + #else /* !CONFIG_MODULES... */ static inline struct module *__module_address(unsigned long addr) @@ -894,6 +896,10 @@ static inline void *module_writable_address(struct module *mod, void *loc) { return loc; } + +static inline void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data) +{ +} #endif /* CONFIG_MODULES */ #ifdef CONFIG_SYSFS diff --git a/kernel/module/main.c b/kernel/module/main.c index 1fb9ad289a6f..ea1fe313fb89 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -3809,6 +3809,20 @@ bool is_module_text_address(unsigned long addr) return ret; } +void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data) +{ + struct module *mod; + + preempt_disable(); + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; + if (func(mod, data)) + break; + } + preempt_enable(); +} + /** * __module_text_address() - get the module whose code contains an address. * @addr: the address. From patchwork Sat Feb 15 03:43:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975939 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B3E8617799F; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=JdoKstQQpdKwJwdntCnouyNVIacIyD1Zx0ck4FfbPNYI3sBXSXKc9sj5K2xEL8zjeYbV2a9lCoHwqoJRuhP8PfF34u7jEoPXE0N7kZrh9AaOndu2ugBhvXzcEkcbGP07R+DcASznRj0RSA/gutxa2zoKuZvFkwu8VAoSMmOH5To= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=dXr+X5dJgcrNCEwc2EpFMguMKGBFbGy9DrYu4JVp6HA=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=cJ5ktQn4IuXanifwt20yZ4KgU8IynUzap0566sDVbhDjB7b70Ji07SoxPT7NBd0zaV/Whh/1OmiCeBjUlx02tkESP/AAeUE+qDMKMSKUjtcXTet9BpYna70YHUPzjqssdBpjy3hZ6L1MmGN1uTF53xyVsfSSqEeER8VSEBoDyks= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5AE56C4CEE4; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj965-00000002gwn-0wNh; Fri, 14 Feb 2025 22:44:05 -0500 Message-ID: <20250215034405.074476251@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:07 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH v2 6/8] tracing: Have persistent trace instances save module addresses References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt For trace instances that are mapped to persistent memory, have them use the scratch area to save the currently loaded modules. This will allow where the modules have been loaded on the next boot so that their addresses can be deciphered by using where they were loaded previously. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 98 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 9 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 12a359c293c6..6674dc985e52 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5988,14 +5988,60 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, return __tracing_resize_ring_buffer(tr, size, cpu_id); } +struct trace_mod_entry { + unsigned long mod_addr; + char mod_name[MODULE_NAME_LEN]; +}; + struct trace_scratch { unsigned long kaslr_addr; + unsigned long nr_entries; + struct trace_mod_entry entries[]; }; +static int save_mod(struct module *mod, void *data) +{ + struct trace_array *tr = data; + struct trace_scratch *tscratch; + struct trace_mod_entry *entry; + unsigned int size; + + tscratch = tr->scratch; + if (!tscratch) + return -1; + size = tr->scratch_size; + + if (struct_size(tscratch, entries, tscratch->nr_entries + 1) > size) + return -1; + + entry = &tscratch->entries[tscratch->nr_entries]; + + tscratch->nr_entries++; + + entry->mod_addr = (unsigned long)mod->mem[MOD_TEXT].base; + strscpy(entry->mod_name, mod->name); + + return 0; +} + static void update_last_data(struct trace_array *tr) { struct trace_scratch *tscratch; + if (!(tr->flags & TRACE_ARRAY_FL_BOOT)) + return; + + /* Reset the module list and reload them */ + if (tr->scratch) { + struct trace_scratch *tscratch = tr->scratch; + + memset(tscratch->entries, 0, + flex_array_size(tscratch, entries, tscratch->nr_entries)); + tscratch->nr_entries = 0; + + module_for_each_mod(save_mod, tr); + } + if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) return; @@ -9220,6 +9266,46 @@ static struct dentry *trace_instance_dir; static void init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer); +static void setup_trace_scratch(struct trace_array *tr, + struct trace_scratch *tscratch, unsigned int size) +{ + struct trace_mod_entry *entry; + + if (!tscratch) + return; + + tr->scratch = tscratch; + tr->scratch_size = size; + +#ifdef CONFIG_RANDOMIZE_BASE + if (tscratch->kaslr_addr) + tr->text_delta = kaslr_offset() - tscratch->kaslr_addr; +#endif + + if (struct_size(tscratch, entries, tscratch->nr_entries) > size) + goto reset; + + /* Check if each module name is a valid string */ + for (int i = 0; i < tscratch->nr_entries; i++) { + int n; + + entry = &tscratch->entries[i]; + + for (n = 0; n < MODULE_NAME_LEN; n++) { + if (entry->mod_name[n] == '\0') + break; + if (!isprint(entry->mod_name[n])) + goto reset; + } + if (n == MODULE_NAME_LEN) + goto reset; + } + return; + reset: + /* Invalid trace modules */ + memset(tscratch, 0, size); +} + static int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size) { @@ -9232,21 +9318,15 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size buf->tr = tr; if (tr->range_addr_start && tr->range_addr_size) { + /* Add scratch buffer to handle 128 modules */ buf->buffer = ring_buffer_alloc_range(size, rb_flags, 0, tr->range_addr_start, tr->range_addr_size, - sizeof(*tscratch)); + struct_size(tscratch, entries, 128)); tscratch = ring_buffer_meta_scratch(buf->buffer, &scratch_size); - if (tscratch) { - tr->scratch = tscratch; - tr->scratch_size = scratch_size; + setup_trace_scratch(tr, tscratch, scratch_size); -#ifdef CONFIG_RANDOMIZE_BASE - if (tscratch->kaslr_addr) - tr->text_delta = kaslr_offset() - tscratch->kaslr_addr; -#endif - } /* * This is basically the same as a mapped buffer, * with the same restrictions. From patchwork Sat Feb 15 03:43:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975937 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 882D51624FB; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=FWWVsJ1PwIVup3xa4Wjl7QvDtfiwHYU+9sj0RljtmjTU+REwLGROVzihujRW3Ql+RP8Sry+3hP+Qr1VnoROXK4aQMXYYBtEsAFFTeYBeAGcy/2FcoMa59AOkjYzTUioOdsYR0hY8ZT81G0mxFTwj90ahOQxWZhQ7XD/2JpE3BPM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=7w5oaea+L+7n9clu6OmpQtZSCfDQNtPY3onQai/m8Ho=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=mGEuLvy9DmcVvknUSGRWrajL5LH7LAGTRmtzjhfRbiFkOKSx7dTH7Tuu4bmRAm9HzMJcKUxGmiWuPh2HqLpBq0uAU0AmsunCKWXruZTlF4IcOyUjJj052UtUrJ+JeTcc/CFAycFejWMkQcBEoLV0dGqU2MyXWmi2fRfLIo1z4nk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 66B0DC4CEE7; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj965-00000002gxH-1e3B; Fri, 14 Feb 2025 22:44:05 -0500 Message-ID: <20250215034405.244453188@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:08 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH v2 7/8] tracing: Show module names and addresses of last boot References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Add the last boot module's names and addresses to the last_boot_info file. This only shows the module information from a previous boot. If the buffer is started and is recording the current boot, this file still will only show "current". ~# cat instances/boot_mapped/last_boot_info 10c00000 [kernel] ffffffffc00ca000 usb_serial_simple ffffffffc00ae000 usbserial ffffffffc008b000 bfq ~# echo function > instances/boot_mapped/current_tracer ~# cat instances/boot_mapped/last_boot_info # Current Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 103 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 13 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 6674dc985e52..fe65a256c193 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5999,6 +5999,8 @@ struct trace_scratch { struct trace_mod_entry entries[]; }; +static DEFINE_MUTEX(scratch_mutex); + static int save_mod(struct module *mod, void *data) { struct trace_array *tr = data; @@ -6006,6 +6008,8 @@ static int save_mod(struct module *mod, void *data) struct trace_mod_entry *entry; unsigned int size; + guard(mutex)(&scratch_mutex); + tscratch = tr->scratch; if (!tscratch) return -1; @@ -6876,15 +6880,47 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf, return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } -static ssize_t -tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +#define LAST_BOOT_HEADER ((void *)1) + +static void *l_next(struct seq_file *m, void *v, loff_t *pos) { - struct trace_array *tr = filp->private_data; + struct trace_array *tr = m->private; struct trace_scratch *tscratch = tr->scratch; - struct seq_buf seq; - char buf[64]; + unsigned int index = *pos; + + (*pos)++; + + if (*pos == 1) + return LAST_BOOT_HEADER; + + /* Only show offsets of the last boot data */ + if (!tscratch || !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) + return NULL; - seq_buf_init(&seq, buf, 64); + /* *pos 0 is for the header, 1 is for the first module */ + index--; + + if (index >= tscratch->nr_entries) + return NULL; + + return &tscratch->entries[index]; +} + +static void *l_start(struct seq_file *m, loff_t *pos) +{ + mutex_lock(&scratch_mutex); + + return l_next(m, NULL, pos); +} + +static void l_stop(struct seq_file *m, void *p) +{ + mutex_unlock(&scratch_mutex); +} + +static void show_last_boot_header(struct seq_file *m, struct trace_array *tr) +{ + struct trace_scratch *tscratch = tr->scratch; /* * Do not leak KASLR address. This only shows the KASLR address of @@ -6894,11 +6930,52 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t * should not be the same as the current boot. */ if (tscratch && (tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) - seq_buf_printf(&seq, "%lx\t[kernel]\n", tscratch->kaslr_addr); + seq_printf(m, "%lx\t[kernel]\n", tscratch->kaslr_addr); else - seq_buf_puts(&seq, "# Current\n"); + seq_puts(m, "# Current\n"); +} + +static int l_show(struct seq_file *m, void *v) +{ + struct trace_array *tr = m->private; + struct trace_mod_entry *entry = v; + + if (v == LAST_BOOT_HEADER) { + show_last_boot_header(m, tr); + return 0; + } - return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq)); + seq_printf(m, "%lx\t%s\n", entry->mod_addr, entry->mod_name); + return 0; +} + +static const struct seq_operations last_boot_seq_ops = { + .start = l_start, + .next = l_next, + .stop = l_stop, + .show = l_show, +}; + +static int tracing_last_boot_open(struct inode *inode, struct file *file) +{ + struct trace_array *tr = inode->i_private; + struct seq_file *m; + int ret; + + ret = tracing_check_open_get_tr(tr); + if (ret) + return ret; + + ret = seq_open(file, &last_boot_seq_ops); + if (ret) { + trace_array_put(tr); + return ret; + } + + m = file->private_data; + m->private = tr; + + return 0; } static int tracing_buffer_meta_open(struct inode *inode, struct file *filp) @@ -7527,10 +7604,10 @@ static const struct file_operations trace_time_stamp_mode_fops = { }; static const struct file_operations last_boot_fops = { - .open = tracing_open_generic_tr, - .read = tracing_last_boot_read, - .llseek = generic_file_llseek, - .release = tracing_release_generic_tr, + .open = tracing_last_boot_open, + .read = seq_read, + .llseek = seq_lseek, + .release = tracing_seq_release, }; #ifdef CONFIG_TRACER_SNAPSHOT From patchwork Sat Feb 15 03:43:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13975940 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B792217B50B; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; cv=none; b=BZyEjUi2ibLIhjruQ3iLnQzrtM+biyUSCoC4vQoAsJfvl+tYT/NKNfSTRE3w9Brp2o4LcwaZ1tVWVZ/V6DVuBrs+dlOA1dqH/BkDWYdD7kRCTkCk6xzST21yYC1XEbzDC5RPHKHnZNBXpMtsjKlcyNmLQno13T4XN3LIFOWsKN8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739591031; c=relaxed/simple; bh=7hwoSzxe5VpOXzoRHtdURWklqJCT/Gf+Eu14WGwmWbY=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=aBO9BjGFP+j4CVvyTL1TI78RrPkGl4Itgd7m4kYlxQ0lHJCkp1QArenRVxRh/BdmmnNxrdF0KdppGdGc0ig9Ta0jg2RQTFiuBwaarYVsBO1olz2fgx6AE+aJFfCt1vhBO64ZP0zJ0RDq9iHLiJjsBByPIq9/rr9hwPpQUQWr1w0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9DB4DC4CEE5; Sat, 15 Feb 2025 03:43:51 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tj965-00000002gxm-2NFq; Fri, 14 Feb 2025 22:44:05 -0500 Message-ID: <20250215034405.414999988@goodmis.org> User-Agent: quilt/0.68 Date: Fri, 14 Feb 2025 22:43:09 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH v2 8/8] tracing: Update modules to persistent instances when loaded References: <20250215034301.624019422@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt When a module is loaded and a persistent buffer is actively tracing, add it to the list of modules in the persistent memory. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 25 +++++++++++++++++++++++ kernel/trace/trace.h | 2 ++ kernel/trace/trace_events.c | 40 ++++++++++++++++++++++++++----------- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index fe65a256c193..4d4ac9de14a8 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -10084,6 +10084,30 @@ static void trace_module_remove_evals(struct module *mod) static inline void trace_module_remove_evals(struct module *mod) { } #endif /* CONFIG_TRACE_EVAL_MAP_FILE */ +static bool trace_array_active(struct trace_array *tr) +{ + if (tr->current_trace != &nop_trace) + return true; + + /* 0 is no events, 1 is all disabled */ + return trace_events_enabled(tr, NULL) > 1; +} + +static void trace_module_record(struct module *mod) +{ + struct trace_array *tr; + + list_for_each_entry(tr, &ftrace_trace_arrays, list) { + /* Update any persistent trace array that has already been started */ + if ((tr->flags & (TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT)) == + TRACE_ARRAY_FL_BOOT) { + /* Only update if the trace array is active */ + if (trace_array_active(tr)) + save_mod(mod, tr); + } + } +} + static int trace_module_notify(struct notifier_block *self, unsigned long val, void *data) { @@ -10092,6 +10116,7 @@ static int trace_module_notify(struct notifier_block *self, switch (val) { case MODULE_STATE_COMING: trace_module_add_evals(mod); + trace_module_record(mod); break; case MODULE_STATE_GOING: trace_module_remove_evals(mod); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 3a020fb82a34..90493220c362 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -786,6 +786,8 @@ extern void trace_find_cmdline(int pid, char comm[]); extern int trace_find_tgid(int pid); extern void trace_event_follow_fork(struct trace_array *tr, bool enable); +extern int trace_events_enabled(struct trace_array *tr, const char *system); + #ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; extern unsigned long ftrace_number_of_pages; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 4cb275316e51..107767afe0ab 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1811,28 +1811,28 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, return cnt; } -static ssize_t -system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, - loff_t *ppos) +/* + * Returns: + * 0 : no events exist? + * 1 : all events are disabled + * 2 : all events are enabled + * 3 : some events are enabled and some are enabled + */ +int trace_events_enabled(struct trace_array *tr, const char *system) { - const char set_to_char[4] = { '?', '0', '1', 'X' }; - struct trace_subsystem_dir *dir = filp->private_data; - struct event_subsystem *system = dir->subsystem; struct trace_event_call *call; struct trace_event_file *file; - struct trace_array *tr = dir->tr; - char buf[2]; int set = 0; - int ret; - mutex_lock(&event_mutex); + guard(mutex)(&event_mutex); + list_for_each_entry(file, &tr->events, list) { call = file->event_call; if ((call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) || !trace_event_name(call) || !call->class || !call->class->reg) continue; - if (system && strcmp(call->class->system, system->name) != 0) + if (system && strcmp(call->class->system, system) != 0) continue; /* @@ -1848,7 +1848,23 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, if (set == 3) break; } - mutex_unlock(&event_mutex); + + return set; +} + +static ssize_t +system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, + loff_t *ppos) +{ + const char set_to_char[4] = { '?', '0', '1', 'X' }; + struct trace_subsystem_dir *dir = filp->private_data; + struct event_subsystem *system = dir->subsystem; + struct trace_array *tr = dir->tr; + char buf[2]; + int set; + int ret; + + set = trace_events_enabled(tr, system ? system->name : NULL); buf[0] = set_to_char[set]; buf[1] = '\n';