ANDROID: KVM: arm64: Enable in-pKVM-module in-hyp event tracing
pKVM modules? pKVM tracing? Why not both? Bring the tracing flexibility
to pKVM module developers. Just need to follow this recipe:
A. Declare the hyp events in separated events.h file.
B. Define the hyp events for the host (They will be automatically
registered for the host by the module loader)
#define HYP_EVENT_FILE events.h
#include <asm/kvm_define_hypevents.h>
C. Define the hyp events for the hypervisor
#define HYP_EVENT_FILE events,h
#include <nvhe/define_events.h>
D. Register hyp_event_ids from the hypervisor
ops->register_hyp_event_ids(__hyp_event_ids_start,
__hyp_event_ids_end);
E. Define tracing functions (tracing_{reserve,commit}_entry) using pkvm_module_ops callbacks
void *tracing_reserve_entry (unsigned long length)
{
return ops->tracing_reserve_commit(length);
}
...
F. Call your newly created events
#include <nvhe/trace.h>
trace_my_module_event();
Bug: 357781595
Bug: 268495982
Change-Id: I20ec67767afae65f82cba43159e282e0b0b3d103
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/include/asm/kvm_pkvm_module.h b/arch/arm64/include/asm/kvm_pkvm_module.h
index 75b2ebb..b11062c 100644
--- a/arch/arm64/include/asm/kvm_pkvm_module.h
+++ b/arch/arm64/include/asm/kvm_pkvm_module.h
@@ -164,6 +164,9 @@ struct pkvm_module_ops {
phys_addr_t (*hyp_pa)(void *x);
void* (*hyp_va)(phys_addr_t phys);
unsigned long (*kern_hyp_va)(unsigned long x);
+ int (*register_hyp_event_ids)(unsigned long start, unsigned long end);
+ void* (*tracing_reserve_entry)(unsigned long length);
+ void (*tracing_commit_entry)(void);
};
int __pkvm_load_el2_module(struct module *this, unsigned long *token);
diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile.module b/arch/arm64/kvm/hyp/nvhe/Makefile.module
index d3ad446..9736d44 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile.module
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile.module
@@ -4,3 +4,5 @@
$(call if_changed_dep,cpp_lds_S)
include $(srctree)/arch/arm64/kvm/hyp/nvhe/Makefile.nvhe
+
+ccflags-y += -I$(srctree)/arch/arm64/kvm/hyp/include/nvhe/trace/
diff --git a/arch/arm64/kvm/hyp/nvhe/modules.c b/arch/arm64/kvm/hyp/nvhe/modules.c
index 918b3cd..6673fd6 100644
--- a/arch/arm64/kvm/hyp/nvhe/modules.c
+++ b/arch/arm64/kvm/hyp/nvhe/modules.c
@@ -10,6 +10,7 @@
#include <nvhe/mm.h>
#include <nvhe/serial.h>
#include <nvhe/spinlock.h>
+#include <nvhe/trace/trace.h>
#include <nvhe/trap_handler.h>
static void __kvm_flush_dcache_to_poc(void *addr, size_t size)
@@ -117,6 +118,9 @@ const struct pkvm_module_ops module_ops = {
.hyp_pa = hyp_virt_to_phys,
.hyp_va = hyp_phys_to_virt,
.kern_hyp_va = __kern_hyp_va,
+ .register_hyp_event_ids = register_hyp_event_ids,
+ .tracing_reserve_entry = tracing_reserve_entry,
+ .tracing_commit_entry = tracing_commit_entry,
};
int __pkvm_init_module(void *module_init)
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 08f8f4e..657fda8 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -23,6 +23,7 @@
#include <asm/setup.h>
#include "hyp_constants.h"
+#include "hyp_trace.h"
DEFINE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
@@ -777,6 +778,7 @@ int __pkvm_load_el2_module(struct module *this, unsigned long *token)
{ &mod->text, KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_X },
{ &mod->bss, KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W },
{ &mod->rodata, KVM_PGTABLE_PROT_R },
+ { &mod->event_ids, KVM_PGTABLE_PROT_R },
{ &mod->data, KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W },
};
void *start, *end, *hyp_va;
@@ -846,6 +848,12 @@ int __pkvm_load_el2_module(struct module *this, unsigned long *token)
kmemleak_no_scan(this->mem[MOD_RODATA].base);
}
+ ret = hyp_trace_init_mod_events(mod->hyp_events,
+ mod->event_ids.start,
+ mod->nr_hyp_events);
+ if (ret)
+ kvm_err("Failed to init module events: %d\n", ret);
+
ret = pkvm_map_module_sections(secs_map + secs_first, hyp_va,
ARRAY_SIZE(secs_map) - secs_first);
if (ret) {