ANDROID: KVM: arm64: add support for early enablement nVHE hyp events

Set hyp_event="event1,event2" in the commandline to start tracing as
soon as possible the nVHE hypervisor.

Bug: 229972309
Change-Id: I878e342a8758a78a01d6ddf26355020945b2df33
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
Vincent Donnefort
2022-10-18 15:44:27 +01:00
parent a7640ce6cf
commit 8f1f4a1b65
2 changed files with 89 additions and 9 deletions

View File

@@ -8,12 +8,15 @@
#include <asm/kvm_host.h>
#include <asm/kvm_hypevents_defs.h>
#include <asm/setup.h>
#include "hyp_trace.h"
#define HYP_EVENT_NAME_MAX 32
struct hyp_event {
struct trace_event_call *call;
char name[32];
char name[HYP_EVENT_NAME_MAX];
bool *enabled;
};
@@ -81,12 +84,41 @@ extern struct hyp_event __stop_hyp_events[];
extern struct hyp_event_id __hyp_event_ids_start[];
extern struct hyp_event_id __hyp_event_ids_end[];
static struct hyp_event *find_hyp_event(const char *name)
{
struct hyp_event *event = __start_hyp_events;
for (; (unsigned long)event < (unsigned long)__stop_hyp_events;
event++) {
if (!strncmp(name, event->name, HYP_EVENT_NAME_MAX))
return event;
}
return NULL;
}
static int enable_hyp_event(struct hyp_event *event, bool enable)
{
unsigned short id = event->call->event.type;
int ret;
if (enable == *event->enabled)
return 0;
ret = kvm_call_hyp_nvhe(__pkvm_enable_event, id, enable);
if (ret)
return ret;
*event->enabled = enable;
return 0;
}
static ssize_t
hyp_event_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
{
struct seq_file *seq_file = (struct seq_file *)filp->private_data;
struct hyp_event *evt = (struct hyp_event *)seq_file->private;
unsigned short id = evt->call->event.type;
bool enabling;
int ret;
char c;
@@ -108,13 +140,9 @@ hyp_event_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *
return -EINVAL;
}
if (enabling != *evt->enabled) {
ret = kvm_call_hyp_nvhe(__pkvm_enable_event, id, enabling);
if (ret)
return ret;
}
*evt->enabled = enabling;
ret = enable_hyp_event(evt, enabling);
if (ret)
return ret;
return cnt;
}
@@ -163,6 +191,51 @@ static const struct file_operations hyp_event_id_fops = {
.release = single_release,
};
static char early_events[COMMAND_LINE_SIZE];
static __init int setup_hyp_event_early(char *str)
{
strscpy(early_events, str, COMMAND_LINE_SIZE);
return 1;
}
__setup("hyp_event=", setup_hyp_event_early);
bool kvm_hyp_events_enable_early(void)
{
char *token, *buf = early_events;
bool enabled = false;
while (true) {
token = strsep(&buf, ",");
if (!token)
break;
if (*token) {
struct hyp_event *event;
int ret;
event = find_hyp_event(token);
if (event) {
ret = enable_hyp_event(event, true);
if (ret)
pr_warn("Couldn't enable hyp event %s:%d\n",
token, ret);
else
enabled = true;
} else {
pr_warn("Couldn't find hyp event %s\n", token);
}
}
if (buf)
*(buf - 1) = ',';
}
return enabled;
}
void kvm_hyp_init_events_tracefs(struct dentry *parent)
{
struct hyp_event *event = __start_hyp_events;

View File

@@ -730,12 +730,14 @@ static void hyp_tracefs_create_cpu_file(const char *file_name,
}
void kvm_hyp_init_events_tracefs(struct dentry *parent);
bool kvm_hyp_events_enable_early(void);
int init_hyp_tracefs(void)
{
struct dentry *d, *root_dir, *per_cpu_root_dir;
char per_cpu_name[16];
unsigned long cpu;
int err;
if (!is_protected_kvm_enabled())
return 0;
@@ -784,6 +786,11 @@ int init_hyp_tracefs(void)
}
kvm_hyp_init_events_tracefs(root_dir);
if (kvm_hyp_events_enable_early()) {
err = hyp_start_tracing();
if (err)
pr_warn("Failed to start early events tracing: %d\n", err);
}
return 0;
}