Commit e645535a authored by Steven Rostedt (Google)'s avatar Steven Rostedt (Google)
Browse files

tracing: Add option to use memmapped memory for trace boot instance

Add an option to the trace_instance kernel command line parameter that
allows it to use the reserved memory from memmap boot parameter.

  memmap=12M$0x284500000 trace_instance=boot_mapped@0x284500000:12M

The above will reserves 12 megs at the physical address 0x284500000.
The second parameter will create a "boot_mapped" instance and use the
memory reserved as the memory for the ring buffer.

That will create an instance called "boot_mapped":

  /sys/kernel/tracing/instances/boot_mapped

Note, because the ring buffer is using a defined memory ranged, it will
act just like a memory mapped ring buffer. It will not have a snapshot
buffer, as it can't swap out the buffer. The snapshot files as well as any
tracers that uses a snapshot will not be present in the boot_mapped
instance.

Link: https://lkml.kernel.org/r/20240612232026.329660169@goodmis.org



Cc: linux-mm@kvack.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Vincent Donnefort <vdonnefort@google.com>
Cc: Joel Fernandes <joel@joelfernandes.org>
Cc: Daniel Bristot de Oliveira <bristot@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vineeth Pillai <vineeth@bitbyteword.org>
Cc: Youssef Esmat <youssefesmat@google.com>
Cc: Beau Belgrave <beaub@linux.microsoft.com>
Cc: Alexander Graf <graf@amazon.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Ross Zwisler <zwisler@google.com>
Cc: Kees Cook <keescook@chromium.org>
Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent 5f3b6e83
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -6754,6 +6754,15 @@
			the same thing would happen if it was left off). The irq_handler_entry
			event, and all events under the "initcall" system.

			If memory has been reserved (see memmap for x86), the instance
			can use that memory:

				memmap=12M$0x284500000 trace_instance=boot_map@0x284500000:12M

			The above will create a "boot_map" instance that uses the physical
			memory at 0x284500000 that is 12Megs. The per CPU buffers of that
			instance will be split up accordingly.

	trace_options=[option-list]
			[FTRACE] Enable or disable tracer options at boot.
			The option-list is a comma delimited list of options
+69 −6
Original line number Diff line number Diff line
@@ -9504,6 +9504,31 @@ static int instance_mkdir(const char *name)
	return ret;
}

static u64 map_pages(u64 start, u64 size)
{
	struct page **pages;
	phys_addr_t page_start;
	unsigned int page_count;
	unsigned int i;
	void *vaddr;

	page_count = DIV_ROUND_UP(size, PAGE_SIZE);

	page_start = start;
	pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
	if (!pages)
		return 0;

	for (i = 0; i < page_count; i++) {
		phys_addr_t addr = page_start + i * PAGE_SIZE;
		pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
	}
	vaddr = vmap(pages, page_count, VM_MAP, PAGE_KERNEL);
	kfree(pages);

	return (u64)(unsigned long)vaddr;
}

/**
 * trace_array_get_by_name - Create/Lookup a trace array, given its name.
 * @name: The name of the trace array to be looked up/created.
@@ -10350,6 +10375,7 @@ __init static void enable_instances(void)
{
	struct trace_array *tr;
	char *curr_str;
	char *name;
	char *str;
	char *tok;

@@ -10358,18 +10384,55 @@ __init static void enable_instances(void)
	str = boot_instance_info;

	while ((curr_str = strsep(&str, "\t"))) {
		unsigned long start = 0;
		unsigned long size = 0;
		unsigned long addr = 0;

		tok = strsep(&curr_str, ",");
		name = strsep(&tok, "@");
		if (tok) {
			start = memparse(tok, &tok);
			if (!start) {
				pr_warn("Tracing: Invalid boot instance address for %s\n",
					name);
				continue;
			}
		}

		if (start) {
			if (*tok != ':') {
				pr_warn("Tracing: No size specified for instance %s\n", name);
				continue;
			}
			tok++;
			size = memparse(tok, &tok);
			if (!size) {
				pr_warn("Tracing: Invalid boot instance size for %s\n",
					name);
				continue;
			}
			addr = map_pages(start, size);
			if (addr) {
				pr_info("Tracing: mapped boot instance %s at physical memory 0x%lx of size 0x%lx\n",
					name, start, size);
			} else {
				pr_warn("Tracing: Failed to map boot instance %s\n", name);
				continue;
			}
		} else {
			/* Only non mapped buffers have snapshot buffers */
			if (IS_ENABLED(CONFIG_TRACER_MAX_TRACE))
			do_allocate_snapshot(tok);
				do_allocate_snapshot(name);
		}

		tr = trace_array_get_by_name(tok, NULL);
		tr = trace_array_create_systems(name, NULL, addr, size);
		if (!tr) {
			pr_warn("Failed to create instance buffer %s\n", curr_str);
			pr_warn("Tracing: Failed to create instance buffer %s\n", curr_str);
			continue;
		}
		/* Allow user space to delete it */

		/* Only allow non mapped buffers to be deleted */
		if (!start)
			trace_array_put(tr);

		while ((tok = strsep(&curr_str, ","))) {