Add a selftest event that can be triggered from a `write_event` tracefs
file. This intends to be used by trace remote selftests.

Signed-off-by: Vincent Donnefort <vdonnef...@google.com>

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 79019e11f529..522cccef32b7 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -94,6 +94,7 @@ enum __kvm_host_smccc_func {
        __KVM_HOST_SMCCC_FUNC___pkvm_reset_tracing,
        __KVM_HOST_SMCCC_FUNC___pkvm_swap_reader_tracing,
        __KVM_HOST_SMCCC_FUNC___pkvm_enable_event,
+       __KVM_HOST_SMCCC_FUNC___pkvm_write_event,
 };
 
 #define DECLARE_KVM_VHE_SYM(sym)       extern char sym[]
diff --git a/arch/arm64/include/asm/kvm_hypevents.h 
b/arch/arm64/include/asm/kvm_hypevents.h
index ce3953bc884a..3d1244972869 100644
--- a/arch/arm64/include/asm/kvm_hypevents.h
+++ b/arch/arm64/include/asm/kvm_hypevents.h
@@ -24,4 +24,18 @@ HYP_EVENT(hyp_exit,
        ),
        HE_PRINTK()
 );
+
+#ifdef CONFIG_PKVM_SELFTESTS
+HYP_EVENT(selftest,
+       HE_PROTO(u64 id),
+       HE_STRUCT(
+               he_field(u64, id)
+       ),
+       HE_ASSIGN(
+               __entry->id = id;
+       ),
+       RE_PRINTK("id=%lld", __entry->id)
+);
 #endif
+
+#endif /* __ARM64_KVM_HYPEVENTS_H_ */
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index f7d1d8987cce..333824325c9e 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -46,6 +46,7 @@ menuconfig KVM
 config NVHE_EL2_DEBUG
        bool "Debug mode for non-VHE EL2 object"
        depends on KVM
+       select PKVM_SELFTESTS
        help
          Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
          Failure reports will BUG() in the hypervisor. This is intended for
@@ -83,6 +84,15 @@ config PTDUMP_STAGE2_DEBUGFS
 
          If in doubt, say N.
 
+config PKVM_SELFTESTS
+       bool "Protected KVM hypervisor selftests"
+       depends on KVM
+       default n
+       help
+         Say Y here to enable pKVM hypervisor testing infrastructure.
+
+         If unsure, say N.
+
 config PKVM_TRACING
        bool
        depends on KVM
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c 
b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 7d7d0c07a6d4..e6b45631c48b 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -628,6 +628,20 @@ static void handle___pkvm_enable_event(struct 
kvm_cpu_context *host_ctxt)
        cpu_reg(host_ctxt, 1) = __pkvm_enable_event(id, enable);
 }
 
+static void handle___pkvm_write_event(struct kvm_cpu_context *host_ctxt)
+{
+       int smc_ret = SMCCC_RET_NOT_SUPPORTED, ret = -EOPNOTSUPP;
+#ifdef CONFIG_PKVM_SELFTESTS
+       DECLARE_REG(u64, id, host_ctxt, 1);
+
+       trace_selftest(id);
+       smc_ret = SMCCC_RET_SUCCESS;
+       ret = 0;
+#endif
+       cpu_reg(host_ctxt, 0) = smc_ret;
+       cpu_reg(host_ctxt, 1) = ret;
+}
+
 typedef void (*hcall_t)(struct kvm_cpu_context *);
 
 #define HANDLE_FUNC(x) [__KVM_HOST_SMCCC_FUNC_##x] = (hcall_t)handle_##x
@@ -674,6 +688,7 @@ static const hcall_t host_hcall[] = {
        HANDLE_FUNC(__pkvm_reset_tracing),
        HANDLE_FUNC(__pkvm_swap_reader_tracing),
        HANDLE_FUNC(__pkvm_enable_event),
+       HANDLE_FUNC(__pkvm_write_event),
 };
 
 static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 70c0939ebc6a..5b5d17a47ecc 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -317,8 +317,34 @@ static int hyp_trace_clock_show(struct seq_file *m, void 
*v)
 }
 DEFINE_SHOW_ATTRIBUTE(hyp_trace_clock);
 
+#ifdef CONFIG_PKVM_SELFTESTS
+static ssize_t hyp_trace_write_event_write(struct file *f, const char __user 
*ubuf,
+                                          size_t cnt, loff_t *pos)
+{
+       unsigned long val;
+       int ret;
+
+       ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+       if (ret)
+               return ret;
+
+       ret = kvm_call_hyp_nvhe(__pkvm_write_event, val);
+       if (ret)
+               return ret;
+
+       return cnt;
+}
+
+static const struct file_operations hyp_trace_write_event_fops = {
+       .write  = hyp_trace_write_event_write,
+};
+#endif
+
 static int hyp_trace_init_tracefs(struct dentry *d, void *priv)
 {
+#ifdef CONFIG_PKVM_SELFTESTS
+       tracefs_create_file("write_event", 0200, d, NULL, 
&hyp_trace_write_event_fops);
+#endif
        return tracefs_create_file("trace_clock", 0440, d, NULL, 
&hyp_trace_clock_fops) ?
                0 : -ENOMEM;
 }
-- 
2.49.0.1101.gccaa498523-goog


Reply via email to