ANDROID: KVM: arm64: Add common "trace_pipe" file for hyp tracing

Like the common "trace" file introduced previously, that new common
file aggregates a pipe version for all CPUs, similarly to the tracefs
root file of the same name.

Bug: 249050813
Change-Id: I1872bf3cfeef637902fcdfa5f589a903c0121d04
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
Vincent Donnefort
2023-02-23 12:07:26 +00:00
parent acfc8ff1d6
commit bd0f72e4ee

View File

@@ -732,23 +732,58 @@ static const struct file_operations hyp_trace_fops = {
.release = hyp_trace_release,
};
/*
* TODO: should be merged with the ring_buffer_iterator version
*/
static void *trace_buffer_peek(struct ht_iterator *iter)
static struct ring_buffer_event *__ht_next_pipe_event(struct ht_iterator *iter)
{
struct ring_buffer_event *evt = NULL;
int cpu = iter->cpu;
if (cpu != RING_BUFFER_ALL_CPUS) {
if (ring_buffer_empty_cpu(hyp_trace_buffer, cpu))
return NULL;
iter->ent_cpu = cpu;
return ring_buffer_peek(hyp_trace_buffer, cpu, &iter->ts,
&iter->lost_events);
}
iter->ts = LLONG_MAX;
for_each_cpu(cpu, iter->cpus) {
struct ring_buffer_event *_evt;
unsigned long lost_events;
u64 ts;
if (ring_buffer_empty_cpu(hyp_trace_buffer, cpu))
continue;
_evt = ring_buffer_peek(hyp_trace_buffer, cpu, &ts,
&lost_events);
if (!_evt)
continue;
if (ts >= iter->ts)
continue;
iter->ts = ts;
iter->ent_cpu = cpu;
iter->lost_events = lost_events;
evt = _evt;
}
return evt;
}
static void *ht_next_pipe_event(struct ht_iterator *iter)
{
struct ring_buffer_event *event;
if (ring_buffer_empty_cpu(iter->trace_buffer, iter->cpu))
return NULL;
event = ring_buffer_peek(iter->trace_buffer, iter->cpu, &iter->ts, &iter->lost_events);
event = __ht_next_pipe_event(iter);
if (!event)
return NULL;
iter->ent = (struct hyp_entry_hdr *)&event->array[1];
iter->ent_size = event->array[0];
iter->ent_cpu = iter->cpu;
return iter;
}
@@ -758,21 +793,19 @@ hyp_trace_pipe_read(struct file *file, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
struct ht_iterator *iter = (struct ht_iterator *)file->private_data;
struct trace_buffer *trace_buffer = iter->trace_buffer;
int ret;
trace_seq_init(&iter->seq);
again:
ret = ring_buffer_wait(trace_buffer, iter->cpu, 0);
ret = ring_buffer_wait(hyp_trace_buffer, iter->cpu, 0);
if (ret < 0)
return ret;
hyp_trace_read_start(iter->cpu);
while (trace_buffer_peek(iter)) {
unsigned long lost_events;
while (ht_next_pipe_event(iter)) {
ht_print_trace_fmt(iter);
ring_buffer_consume(iter->trace_buffer, iter->cpu, NULL, &lost_events);
ring_buffer_consume(hyp_trace_buffer, iter->ent_cpu, NULL,
NULL);
}
hyp_trace_read_stop(iter->cpu);
@@ -787,10 +820,16 @@ static void __poke_reader(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct ht_iterator *iter;
int cpu;
iter = container_of(dwork, struct ht_iterator, poke_work);
WARN_ON_ONCE(ring_buffer_poke(iter->trace_buffer, iter->cpu));
if (iter->cpu == RING_BUFFER_ALL_CPUS) {
for_each_cpu(cpu, iter->cpus)
WARN_ON_ONCE(ring_buffer_poke(iter->trace_buffer, cpu));
} else {
WARN_ON_ONCE(ring_buffer_poke(iter->trace_buffer, iter->cpu));
}
schedule_delayed_work((struct delayed_work *)work,
msecs_to_jiffies(RB_POLL_MS));
@@ -810,10 +849,6 @@ static int hyp_trace_pipe_open(struct inode *inode, struct file *file)
goto unlock;
}
ret = ring_buffer_poke(hyp_trace_buffer, cpu);
if (ret)
goto unlock;
iter = kzalloc(sizeof(*iter), GFP_KERNEL);
if (!iter) {
ret = -ENOMEM;
@@ -822,15 +857,31 @@ static int hyp_trace_pipe_open(struct inode *inode, struct file *file)
iter->cpu = cpu;
iter->trace_buffer = hyp_trace_buffer;
file->private_data = iter;
if (cpu == RING_BUFFER_ALL_CPUS) {
if (!zalloc_cpumask_var(&iter->cpus, GFP_KERNEL)) {
ret = -ENOMEM;
goto unlock;
}
for_each_possible_cpu(cpu) {
if (!ring_buffer_poke(hyp_trace_buffer, cpu))
cpumask_set_cpu(cpu, iter->cpus);
}
} else {
ret = ring_buffer_poke(hyp_trace_buffer, cpu);
if (ret)
goto unlock;
}
INIT_DELAYED_WORK(&iter->poke_work, __poke_reader);
schedule_delayed_work(&iter->poke_work, msecs_to_jiffies(RB_POLL_MS));
file->private_data = iter;
hyp_inc_readers();
unlock:
mutex_unlock(&hyp_trace_lock);
if (ret)
kfree(iter);
return ret;
}
@@ -841,6 +892,7 @@ static int hyp_trace_pipe_release(struct inode *inode, struct file *file)
cancel_delayed_work_sync(&iter->poke_work);
free_cpumask_var(iter->cpus);
kfree(iter);
mutex_lock(&hyp_trace_lock);
@@ -980,6 +1032,10 @@ int init_hyp_tracefs(void)
TRACEFS_MODE_WRITE, &hyp_trace_fops,
root_dir);
hyp_tracefs_create_cpu_file("trace_pipe", RING_BUFFER_ALL_CPUS,
TRACEFS_MODE_READ, &hyp_trace_pipe_fops,
root_dir);
per_cpu_root_dir = tracefs_create_dir("per_cpu", root_dir);
if (!per_cpu_root_dir) {
pr_err("Failed to create tracefs "TRACEFS_DIR"/per_cpu/\n");