mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
ANDROID: KVM: arm64: RAW interface to the nVHE hyp tracing
This interface intends to be used by userspace tools to store raw version of events. In such case, the kernel does not decode anything. Bug: 229972309 Change-Id: Ib1fca21a34a308ad1361240ef598033ecab3b4ad Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
@@ -641,6 +641,85 @@ static const struct file_operations hyp_trace_pipe_fops = {
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
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;
|
||||
struct trace_buffer *trace_buffer = iter->trace_buffer;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
if (iter->copy_leftover)
|
||||
goto read;
|
||||
again:
|
||||
hyp_trace_read_start(iter->cpu);
|
||||
ret = ring_buffer_read_page(trace_buffer, &iter->spare,
|
||||
cnt, iter->cpu, 0);
|
||||
hyp_trace_read_stop(iter->cpu);
|
||||
if (ret < 0) {
|
||||
if (!ring_buffer_empty_cpu(iter->trace_buffer, iter->cpu))
|
||||
return 0;
|
||||
|
||||
ret = ring_buffer_wait(trace_buffer, iter->cpu, 0);
|
||||
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,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static void hyp_tracefs_create_cpu_file(const char *file_name,
|
||||
unsigned long cpu,
|
||||
const struct file_operations *fops,
|
||||
@@ -700,6 +779,8 @@ int init_hyp_tracefs(void)
|
||||
hyp_tracefs_create_cpu_file("trace", cpu, &hyp_trace_fops, dir);
|
||||
hyp_tracefs_create_cpu_file("trace_pipe", cpu,
|
||||
&hyp_trace_pipe_fops, dir);
|
||||
hyp_tracefs_create_cpu_file("trace_pipe_raw", cpu,
|
||||
&hyp_trace_raw_fops, dir);
|
||||
}
|
||||
|
||||
kvm_hyp_init_events_tracefs(root_dir);
|
||||
|
||||
@@ -12,6 +12,8 @@ struct ht_iterator {
|
||||
struct hyp_entry_hdr *ent;
|
||||
struct trace_seq seq;
|
||||
u64 ts;
|
||||
void *spare;
|
||||
size_t copy_leftover;
|
||||
size_t ent_size;
|
||||
struct delayed_work poke_work;
|
||||
unsigned long lost_events;
|
||||
|
||||
@@ -5729,9 +5729,6 @@ void *ring_buffer_alloc_read_page(struct trace_buffer *buffer, int cpu)
|
||||
unsigned long flags;
|
||||
struct page *page;
|
||||
|
||||
if (unlikely(has_ext_writer(buffer)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@@ -5846,9 +5843,6 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
|
||||
u64 save_timestamp;
|
||||
int ret = -1;
|
||||
|
||||
if (unlikely(has_ext_writer(buffer)))
|
||||
goto out;
|
||||
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
goto out;
|
||||
|
||||
@@ -5955,14 +5949,21 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
|
||||
cpu_buffer->read += rb_page_entries(reader);
|
||||
cpu_buffer->read_bytes += BUF_PAGE_SIZE;
|
||||
|
||||
/* swap the pages */
|
||||
rb_init_page(bpage);
|
||||
bpage = reader->page;
|
||||
reader->page = *data_page;
|
||||
local_set(&reader->write, 0);
|
||||
local_set(&reader->entries, 0);
|
||||
reader->read = 0;
|
||||
*data_page = bpage;
|
||||
if (unlikely(has_ext_writer(buffer))) {
|
||||
u64 commit = local_read(&reader->page->commit);
|
||||
|
||||
memcpy(bpage, reader->page,
|
||||
BUF_PAGE_HDR_SIZE + commit);
|
||||
} else {
|
||||
/* swap the pages */
|
||||
rb_init_page(bpage);
|
||||
bpage = reader->page;
|
||||
reader->page = *data_page;
|
||||
local_set(&reader->write, 0);
|
||||
local_set(&reader->entries, 0);
|
||||
reader->read = 0;
|
||||
*data_page = bpage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the real_end for the data size,
|
||||
|
||||
Reference in New Issue
Block a user