arch/arm64/kvm/hyp/nvhe/trace.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/hyp/nvhe/trace.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/hyp/nvhe/trace.c
Extension
.c
Size
7044 bytes
Lines
312
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source 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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2025 Google LLC
 * Author: Vincent Donnefort <vdonnefort@google.com>
 */

#include <nvhe/clock.h>
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>
#include <nvhe/trace.h>

#include <asm/percpu.h>
#include <asm/kvm_mmu.h>
#include <asm/local.h>

#include "simple_ring_buffer.c"

static DEFINE_PER_CPU(struct simple_rb_per_cpu, __simple_rbs);

static struct hyp_trace_buffer {
	struct simple_rb_per_cpu __percpu	*simple_rbs;
	void					*bpages_backing_start;
	size_t					bpages_backing_size;
	hyp_spinlock_t				lock;
} trace_buffer = {
	.simple_rbs = &__simple_rbs,
	.lock = __HYP_SPIN_LOCK_UNLOCKED,
};

static bool hyp_trace_buffer_loaded(struct hyp_trace_buffer *trace_buffer)
{
	return trace_buffer->bpages_backing_size > 0;
}

void *tracing_reserve_entry(unsigned long length)
{
	return simple_ring_buffer_reserve(this_cpu_ptr(trace_buffer.simple_rbs), length,
					  trace_clock());
}

void tracing_commit_entry(void)
{
	simple_ring_buffer_commit(this_cpu_ptr(trace_buffer.simple_rbs));
}

static int __admit_host_mem(void *start, u64 size)
{
	if (!PAGE_ALIGNED(start) || !PAGE_ALIGNED(size) || !size)
		return -EINVAL;

	if (!is_protected_kvm_enabled())
		return 0;

	return __pkvm_host_donate_hyp(hyp_virt_to_pfn(start), size >> PAGE_SHIFT);
}

static void __release_host_mem(void *start, u64 size)
{
	if (!is_protected_kvm_enabled())
		return;

	WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(start), size >> PAGE_SHIFT));
}

static int hyp_trace_buffer_load_bpage_backing(struct hyp_trace_buffer *trace_buffer,
					       struct hyp_trace_desc *desc)
{
	void *start = (void *)kern_hyp_va(desc->bpages_backing_start);
	size_t size = desc->bpages_backing_size;
	int ret;

	ret = __admit_host_mem(start, size);
	if (ret)
		return ret;

	memset(start, 0, size);

	trace_buffer->bpages_backing_start = start;
	trace_buffer->bpages_backing_size = size;

	return 0;
}

static void hyp_trace_buffer_unload_bpage_backing(struct hyp_trace_buffer *trace_buffer)
{
	void *start = trace_buffer->bpages_backing_start;
	size_t size = trace_buffer->bpages_backing_size;

	if (!size)
		return;

Annotation

Implementation Notes