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) {