arch/arm64/kvm/hyp_trace.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/hyp_trace.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/hyp_trace.c
Extension
.c
Size
11128 bytes
Lines
446
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations hyp_trace_write_event_fops = {
	.write	= hyp_trace_write_event_write,
};

static int hyp_trace_init_tracefs(struct dentry *d, void *priv)
{
	if (!tracefs_create_file("write_event", 0200, d, NULL, &hyp_trace_write_event_fops))
		return -ENOMEM;

	return tracefs_create_file("trace_clock", 0440, d, NULL, &hyp_trace_clock_fops) ?
		0 : -ENOMEM;
}

static struct trace_remote_callbacks trace_remote_callbacks = {
	.init			= hyp_trace_init_tracefs,
	.load_trace_buffer	= hyp_trace_load,
	.unload_trace_buffer	= hyp_trace_unload,
	.enable_tracing		= hyp_trace_enable_tracing,
	.swap_reader_page	= hyp_trace_swap_reader_page,
	.reset			= hyp_trace_reset,
	.enable_event		= hyp_trace_enable_event,
};

static const char *__hyp_enter_exit_reason_str(u8 reason);

#include <asm/kvm_define_hypevents.h>

static const char *__hyp_enter_exit_reason_str(u8 reason)
{
	static const char strs[][12] = {
		"smc",
		"hvc",
		"psci",
		"host_abort",
		"guest_exit",
		"eret_host",
		"eret_guest",
		"unknown",
	};

	return strs[min(reason, HYP_REASON_UNKNOWN)];
}

static void __init hyp_trace_init_events(void)
{
	struct hyp_event_id *hyp_event_id = __hyp_event_ids_start;
	struct remote_event *event = __hyp_events_start;
	int id = 0;

	/* Events on both sides hypervisor are sorted */
	for (; event < __hyp_events_end; event++, hyp_event_id++, id++)
		event->id = hyp_event_id->id = id;
}

int __init kvm_hyp_trace_init(void)
{
	int cpu;

	if (is_kernel_in_hyp_mode())
		return 0;

	for_each_possible_cpu(cpu) {
		const struct arch_timer_erratum_workaround *wa =
			per_cpu(timer_unstable_counter_workaround, cpu);

		if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND) &&
		    wa && wa->read_cntvct_el0) {
			pr_warn("hyp trace can't handle CNTVCT workaround '%s'\n", wa->desc);
			return -EOPNOTSUPP;
		}
	}

	hyp_trace_init_events();

	return trace_remote_register("hypervisor", &trace_remote_callbacks, &trace_buffer,
				     __hyp_events_start, __hyp_events_end - __hyp_events_start);
}

Annotation

Implementation Notes