Reading perf counters inside the kernel

2022-05-24 | Tags: #research #perf #perf-counters #linux

I couldn't find any helpful resources about reading hardware performance counters inside the kernel (i mean tracking other processes inside kernel module or driver). But suddenly, i saw a project called qemu-deterministic-play which I will give huge credit on this blog post. That project using a function called perf_event_create_kernel_counter . This is interesting because we can use perf even in the kernel level. Also, this function has been already used by some other kernel drivers like:

/linux-hwe-5.11-5.11.0/drivers/oprofile/nmi_timer_int.c
/linux-hwe-5.11-5.11.0/kernel/watchdog_hld.c

Actually using this function is very similar to userspace perf tool. So first of all we need to define our performance attributes in a perf_event_attr struct. While I'm doing this, i was researching on a how we can track cache misses inside a virtual machine. So my attr struct looks like that:

struct perf_event_attr attr = 
{
    .type = PERF_TYPE_HW_CACHE,
    .size = sizeof(attr),
    .exclude_host = 1,
    .exclude_user = 0,
    .exclude_kernel = 0,
    .config = (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
};

After creating that struct, I used perf_event_create_kernel_counter to create kernel counter. Unlike from userspace perf we need to add a overflow handler for that function.

static void kvm_sandbox_perf_overflow_handler(struct perf_event *perf_event,
        struct perf_sample_data *data, struct pt_regs *regs)
{
    u64 enabled, running, counter;
    counter = perf_event_read_value(perf_event, &enabled, &running);
    printk("counter: %llx\n", counter);
}

event = perf_event_create_kernel_counter(&attr, -1, current,
                        kvm_sandbox_perf_overflow_handler, vcpu);

These codes will complete our init phase. After we can create that counter with perf_event_read_value function.


This was the end of the blog post. You can reach me via email umusasadik at gmail com