Skip to content

Commit d3ac186

Browse files
committed
KVM: arm64: kcov: Add kcov support in EL2 object
Change-Id: Ib1556c1194a0bae23438746bd3175ac780fae727
1 parent 1ef935c commit d3ac186

File tree

11 files changed

+561
-1
lines changed

11 files changed

+561
-1
lines changed

arch/arm64/include/asm/kvm_asm.h

+7
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ enum __kvm_host_smccc_func {
7979
__KVM_HOST_SMCCC_FUNC___pkvm_init_vm,
8080
__KVM_HOST_SMCCC_FUNC___pkvm_init_vcpu,
8181
__KVM_HOST_SMCCC_FUNC___pkvm_teardown_vm,
82+
83+
/* Hypercalls available if CONFIG_NVHE_KCOV is set */
84+
__KVM_HOST_SMCCC_FUNC___pkvm_kcov_init_buffer,
85+
__KVM_HOST_SMCCC_FUNC___pkvm_kcov_buffer_add_page,
86+
__KVM_HOST_SMCCC_FUNC___pkvm_kcov_teardown_buffer,
87+
__KVM_HOST_SMCCC_FUNC___pkvm_kcov_enable,
88+
__KVM_HOST_SMCCC_FUNC___pkvm_kcov_disable,
8289
};
8390

8491
#define DECLARE_KVM_VHE_SYM(sym) extern char sym[]

arch/arm64/include/asm/kvm_host.h

+13
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,19 @@ extern s64 kvm_nvhe_sym(hyp_physvirt_offset);
424424
extern u64 kvm_nvhe_sym(hyp_cpu_logical_map)[NR_CPUS];
425425
#define hyp_cpu_logical_map CHOOSE_NVHE_SYM(hyp_cpu_logical_map)
426426

427+
#ifdef CONFIG_NVHE_KCOV
428+
extern u64 kvm_nvhe_sym(hyp_kimage_voffset);
429+
#define hyp_kimage_voffset CHOOSE_NVHE_SYM(hyp_kimage_voffset)
430+
431+
extern u64 kvm_nvhe_sym(hyp_kimage_vaddr);
432+
#define hyp_kimage_vaddr CHOOSE_NVHE_SYM(hyp_kimage_vaddr)
433+
434+
/* This function will fill in the previous two variable at setup time */
435+
void init_hyp_kcov_layout(void);
436+
#else
437+
static inline void init_hyp_kcov_layout(void){}
438+
#endif
439+
427440
struct vcpu_reset_state {
428441
unsigned long pc;
429442
unsigned long r0;

arch/arm64/kvm/Kconfig

+19
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,23 @@ config PROTECTED_NVHE_STACKTRACE
7171

7272
If unsure, or not using protected nVHE (pKVM), say N.
7373

74+
config NVHE_KCOV
75+
bool "Enable KCOV on the EL2 object"
76+
depends on NVHE_EL2_DEBUG && KCOV
77+
select PID_IN_CONTEXTIDR
78+
select ARCH_HAS_HYPERVISOR_KCOV
79+
default y
80+
help
81+
Provide KCOV support at EL2. Enables support for the KCOV_ENABLE_HYP
82+
option (for buffers initialized with KCOV_INIT_HYP_TRACE)
83+
84+
config NVHE_KCOV_NUM_BUFFERS
85+
int "Number of KCOV buffers in the EL2 object"
86+
depends on NVHE_KCOV
87+
default 10
88+
help
89+
The maximum number of buffers simultaneous initialized at EL2. Those
90+
are KCOV buffers intialized with KCOV_INIT_HYP_TRACE instead of
91+
KCOV_INIT_TRACE.
92+
7493
endif # VIRTUALIZATION

arch/arm64/kvm/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
2323
vgic/vgic-its.o vgic/vgic-debug.o
2424

2525
kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o
26+
kvm-$(CONFIG_NVHE_KCOV) += nvhe_kcov.o
2627

2728
always-y := hyp_constants.h hyp-constants.s
2829

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2021 Google LLC
4+
* Author: Thibaut Pérami <[email protected]>
5+
*/
6+
7+
#ifndef __ARM64_KVM_NVHE_KCOV_H__
8+
#define __ARM64_KVM_NVHE_KCOV_H__
9+
10+
#include <nvhe/pkvm.h>
11+
12+
13+
#ifdef CONFIG_NVHE_KCOV
14+
15+
/** Initialize a kcov buffer and returns an index. Negative values for errors. */
16+
u64 __pkvm_kcov_init_buffer(uint size);
17+
18+
/** Map the next page in a kcov buffer */
19+
u64 __pkvm_kcov_buffer_add_page(u64 idx, u64 pfn);
20+
21+
/** Tear down a kcov buffer by index */
22+
int __pkvm_kcov_teardown_buffer(u64 idx);
23+
24+
/** Enable tracing for the current user thread, on the buffer at that index */
25+
int __pkvm_kcov_enable(u64 idx);
26+
27+
/** Disable tracing for the current user thread. One cannot disable tracing
28+
* enabled by another thread */
29+
int __pkvm_kcov_disable(void);
30+
31+
/** Call it on each EL2 entry point from host that require tracing, e.g. not
32+
* asynchronous exceptions */
33+
void pkvm_kcov_enter_from_host(void);
34+
35+
/** Call it on each EL2 exit to the host */
36+
void pkvm_kcov_exit_to_host(void);
37+
38+
#else
39+
40+
static inline u64 __pkvm_kcov_init_buffer(uint){
41+
return -ENOSYS;
42+
}
43+
static inline u64 __pkvm_kcov_buffer_add_page(u64 idx, u64 pfn){
44+
return -ENOSYS;
45+
}
46+
static inline u64 __pkvm_kcov_teardown_buffer(u64)
47+
{
48+
return -ENOSYS;
49+
}
50+
static inline u64 __pkvm_kcov_enable(u64)
51+
{
52+
return -ENOSYS;
53+
}
54+
static inline u64 __pkvm_kcov_disable(void)
55+
{
56+
return -ENOSYS;
57+
}
58+
59+
static inline void pkvm_kcov_enter_from_host(void) {}
60+
static inline void pkvm_kcov_exit_to_host(void) {}
61+
62+
#endif /* CONFIG_NVHE_KCOV */
63+
64+
#endif /* __ARM64_KVM_NVHE_KCOV_H__ */

arch/arm64/kvm/hyp/include/nvhe/memory.h

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static inline phys_addr_t hyp_virt_to_phys(void *addr)
2929

3030
#define hyp_phys_to_pfn(phys) ((phys) >> PAGE_SHIFT)
3131
#define hyp_pfn_to_phys(pfn) ((phys_addr_t)((pfn) << PAGE_SHIFT))
32+
#define hyp_pfn_to_virt(pfn) (__hyp_va(hyp_pfn_to_phys(pfn)))
3233
#define hyp_phys_to_page(phys) (&hyp_vmemmap[hyp_phys_to_pfn(phys)])
3334
#define hyp_virt_to_page(virt) hyp_phys_to_page(__hyp_pa(virt))
3435
#define hyp_virt_to_pfn(virt) hyp_phys_to_pfn(__hyp_pa(virt))

arch/arm64/kvm/hyp/nvhe/Makefile

+5-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ lib-objs := $(addprefix ../../../lib/, $(lib-objs))
2323
hyp-obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o \
2424
hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \
2525
cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o
26+
hyp-obj-$(CONFIG_NVHE_KCOV) += kcov.o
2627
hyp-obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \
2728
../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o
2829
hyp-obj-$(CONFIG_DEBUG_LIST) += list_debug.o
@@ -105,7 +106,10 @@ GCOV_PROFILE := n
105106
KASAN_SANITIZE := n
106107
KCSAN_SANITIZE := n
107108
UBSAN_SANITIZE := n
108-
KCOV_INSTRUMENT := n
109+
KCOV_INSTRUMENT := $(if $(CONFIG_NVHE_KCOV),y,n)
110+
111+
# Don't self instrument the kcov file
112+
KCOV_INSTRUMENT_kcov.nvhe.o := n
109113

110114
# Skip objtool checking for this directory because nVHE code is compiled with
111115
# non-standard build rules.

arch/arm64/kvm/hyp/nvhe/hyp-main.c

+44
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <nvhe/mm.h>
1818
#include <nvhe/pkvm.h>
1919
#include <nvhe/trap_handler.h>
20+
#include <nvhe/kcov.h>
2021

2122
DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
2223

@@ -294,6 +295,40 @@ static void handle___pkvm_teardown_vm(struct kvm_cpu_context *host_ctxt)
294295
cpu_reg(host_ctxt, 1) = __pkvm_teardown_vm(handle);
295296
}
296297

298+
static void handle___pkvm_kcov_init_buffer(struct kvm_cpu_context *host_ctxt)
299+
{
300+
DECLARE_REG(uint, size, host_ctxt, 1);
301+
302+
cpu_reg(host_ctxt, 1) = __pkvm_kcov_init_buffer(size);
303+
}
304+
305+
static void handle___pkvm_kcov_buffer_add_page(struct kvm_cpu_context *host_ctxt)
306+
{
307+
DECLARE_REG(u64, index, host_ctxt, 1);
308+
DECLARE_REG(u64, pfn, host_ctxt, 2);
309+
310+
cpu_reg(host_ctxt, 1) = __pkvm_kcov_buffer_add_page(index, pfn);
311+
}
312+
313+
static void handle___pkvm_kcov_teardown_buffer(struct kvm_cpu_context *host_ctxt)
314+
{
315+
DECLARE_REG(u64, index, host_ctxt, 1);
316+
317+
cpu_reg(host_ctxt, 1) = __pkvm_kcov_teardown_buffer(index);
318+
}
319+
320+
static void handle___pkvm_kcov_enable(struct kvm_cpu_context *host_ctxt)
321+
{
322+
DECLARE_REG(u64, index, host_ctxt, 1);
323+
324+
cpu_reg(host_ctxt, 1) = __pkvm_kcov_enable(index);
325+
}
326+
327+
static void handle___pkvm_kcov_disable(struct kvm_cpu_context *host_ctxt)
328+
{
329+
cpu_reg(host_ctxt, 1) = __pkvm_kcov_disable();
330+
}
331+
297332
typedef void (*hcall_t)(struct kvm_cpu_context *);
298333

299334
#define HANDLE_FUNC(x) [__KVM_HOST_SMCCC_FUNC_##x] = (hcall_t)handle_##x
@@ -326,6 +361,12 @@ static const hcall_t host_hcall[] = {
326361
HANDLE_FUNC(__pkvm_init_vm),
327362
HANDLE_FUNC(__pkvm_init_vcpu),
328363
HANDLE_FUNC(__pkvm_teardown_vm),
364+
365+
HANDLE_FUNC(__pkvm_kcov_init_buffer),
366+
HANDLE_FUNC(__pkvm_kcov_buffer_add_page),
367+
HANDLE_FUNC(__pkvm_kcov_teardown_buffer),
368+
HANDLE_FUNC(__pkvm_kcov_enable),
369+
HANDLE_FUNC(__pkvm_kcov_disable),
329370
};
330371

331372
static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
@@ -384,6 +425,8 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
384425
{
385426
u64 esr = read_sysreg_el2(SYS_ESR);
386427

428+
pkvm_kcov_enter_from_host();
429+
387430
switch (ESR_ELx_EC(esr)) {
388431
case ESR_ELx_EC_HVC64:
389432
handle_host_hcall(host_ctxt);
@@ -403,4 +446,5 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
403446
default:
404447
BUG();
405448
}
449+
pkvm_kcov_exit_to_host();
406450
}

0 commit comments

Comments
 (0)