FROMLIST: KVM: arm64: Add raw interface for hyp tracefs
The raw interface enables userspace tools such as trace-cmd to directly read the ring-buffer without any decoding by the kernel. Bug: 357781595 Link: https://lore.kernel.org/all/20240911093029.3279154-11-vdonnefort@google.com/ Change-Id: I337dc86a95e7182f60d9376d1a23f3e75fb20290 Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
committed by
Keir Fraser
parent
2dc09955d6
commit
532d6ef155
@@ -739,6 +739,85 @@ static const struct file_operations hyp_trace_pipe_fops = {
|
||||
.release = hyp_trace_pipe_release,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
hyp_trace_raw_read(struct file *file, char __user *ubuf,
|
||||
size_t cnt, loff_t *ppos)
|
||||
{
|
||||
struct ht_iterator *iter = (struct ht_iterator *)file->private_data;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
if (iter->copy_leftover)
|
||||
goto read;
|
||||
|
||||
again:
|
||||
ret = ring_buffer_read_page(iter->trace_buffer,
|
||||
(struct buffer_data_read_page *)iter->spare,
|
||||
cnt, iter->cpu, 0);
|
||||
if (ret < 0) {
|
||||
if (!ring_buffer_empty_cpu(iter->trace_buffer, iter->cpu))
|
||||
return 0;
|
||||
|
||||
ret = ring_buffer_wait(iter->trace_buffer, iter->cpu, 0, NULL,
|
||||
NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
goto again;
|
||||
}
|
||||
|
||||
iter->copy_leftover = 0;
|
||||
|
||||
read:
|
||||
size = PAGE_SIZE - iter->copy_leftover;
|
||||
if (size > cnt)
|
||||
size = cnt;
|
||||
|
||||
ret = copy_to_user(ubuf, iter->spare + PAGE_SIZE - size, size);
|
||||
if (ret == size)
|
||||
return -EFAULT;
|
||||
|
||||
size -= ret;
|
||||
*ppos += size;
|
||||
iter->copy_leftover = ret;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int hyp_trace_raw_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret = hyp_trace_pipe_open(inode, file);
|
||||
struct ht_iterator *iter;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iter = file->private_data;
|
||||
iter->spare = ring_buffer_alloc_read_page(iter->trace_buffer, iter->cpu);
|
||||
if (IS_ERR(iter->spare)) {
|
||||
ret = PTR_ERR(iter->spare);
|
||||
iter->spare = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hyp_trace_raw_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ht_iterator *iter = file->private_data;
|
||||
|
||||
ring_buffer_free_read_page(iter->trace_buffer, iter->cpu, iter->spare);
|
||||
|
||||
return hyp_trace_pipe_release(inode, file);
|
||||
}
|
||||
|
||||
static const struct file_operations hyp_trace_raw_fops = {
|
||||
.open = hyp_trace_raw_open,
|
||||
.read = hyp_trace_raw_read,
|
||||
.release = hyp_trace_raw_release,
|
||||
};
|
||||
|
||||
static int hyp_trace_clock_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_puts(m, "[boot]\n");
|
||||
@@ -793,6 +872,9 @@ int hyp_trace_init_tracefs(void)
|
||||
|
||||
tracefs_create_file("trace_pipe", TRACEFS_MODE_READ, per_cpu_dir,
|
||||
(void *)cpu, &hyp_trace_pipe_fops);
|
||||
|
||||
tracefs_create_file("trace_pipe_raw", TRACEFS_MODE_READ, per_cpu_dir,
|
||||
(void *)cpu, &hyp_trace_pipe_fops);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user