-2

I am working on Linux kernel 4.19.2. I want to read performance counters available without using perf or any such tool.

From the userspace, I use code as follows.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>

#define rdpmc(counter,low,high) \
     __asm__ __volatile__("rdpmc" \
        : "=a" (low), "=d" (high) \
        : "c" (counter))

void test(){
    printf(".");


}


static long
perf_event_open (struct perf_event_attr *hw_event, pid_t pid,
         int cpu, int group_fd, unsigned long flags)
{
  int ret;

  ret = syscall (__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
  return ret;
}





int
main ()
{
  unsigned long values1, values2;
  unsigned int fixed0, low, high;
  struct perf_event_attr pe;
  int fd, i;

  fixed0 = (1 << 30);

  memset (&pe, 0, sizeof (struct perf_event_attr));
  pe.type = PERF_TYPE_HARDWARE;
  pe.size = sizeof (struct perf_event_attr);
  pe.config = PERF_COUNT_HW_INSTRUCTIONS;
  pe.disabled = 1;
  pe.exclude_kernel = 0;
  pe.exclude_user = 0;
  pe.exclude_hv = 0;
  pe.exclude_idle = 0;

  fd = perf_event_open (&pe, 0, -1, -1, 0);
  if (fd == -1)
    {
      fprintf (stderr, "Error opening leader %llx\n", pe.config);
      exit (EXIT_FAILURE);
    }
for (i=1; i<=50; i++)
{
  ioctl (fd, PERF_EVENT_IOC_RESET, 0);
  ioctl (fd, PERF_EVENT_IOC_ENABLE, 0);

  rdpmc (fixed0, low, high);
  values1 = ((unsigned long) high << 32) + (unsigned long) low;

  test();

  rdpmc (fixed0, low, high);
  values2 = ((unsigned long) high << 32) + (unsigned long) low;

  ioctl (fd, PERF_EVENT_IOC_DISABLE, 0);
  printf (" %lu\n", values2 );  
}
  close (fd);
}

Now I want to implement the same thing in the kernel code.

My goal is that, at every context switch get the count of an event and store it in the task structure. Hence eventually I want the counter to be called from the context_switch() function in the kernel. If I do it from the kernel then I will have the advantage of always running in the context of the current thread.

I think most of the code can be reused from the kernel as well. I am not sure about the ioctl() part though.

closed as unclear what you're asking by dirkt, sourcejedi, Mr Shunz, ilkkachu, Jeff Schaller Mar 13 at 17:48

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • @sourcejedi This ioctl() would be calling something in the kernel right? I want to do it from there directly. Am I missing something here? – Nikhilesh Singh Mar 13 at 11:08
  • 1
    @NikhileshSingh I assume that doesn't crash, but your program does not explain unambiguously on its own. You are reading a per-cpu counter. You have not shown what your intention is v.s. Linux choosing to migrate your process between different cpus while it is running. Your english language description doesn't say anything about which CPU(s) you want counter values from either. – sourcejedi Mar 13 at 12:06
  • 1
    Also you still haven't explained why you think you can do the __NR_perf_event_open() part from the kernel. Why are you confident about that part, but you need to ask about ioctl() ? That would be a nice clear way to show "where you got stuck", and the specific answer you seem to be looking for. – sourcejedi Mar 13 at 12:10
  • 1
    I was going to suggest if this should have been on SO, but you seem to have already posted this there, too: stackoverflow.com/q/55100453/6372809 – ilkkachu Mar 13 at 14:57
  • 1
    @NikhileshSingh please be aware that cross-posting like this is a specific reason for getting your question closed - sometimes on both sites! If you ask a complex question in two different places at the same time, it can lead to duplicated effort. It is not very respectful. If you manage to cross-post the question without some necessary detail, which was present in the older question, that's not great either. – sourcejedi Mar 13 at 18:33
1

Technically, it may be possible to call ioctl inside kernel code. It is called ksys_ioctl().[*] Notice how init/ is the only other code that calls ksys_ioctl(). This is an unusual thing to do, to put it mildly. Calling perf ioctls inside the kernel sounds even more dubious.

To start understanding why this is unusual, I would point out that ksys_ioctl() still takes an fd argument. This is the number of a file descriptor within the context of the current task (process/thread).

[edit] My goal is that, at every context switch get the count of an event and store it in the task structure. Hence eventually I want the counter to be called from the context_switch() function in the kernel.

AAAHHH.

So you did not want to call ioctl() from the kernel. (You would not have a file descriptor to call ioctl() on. And I do not believe you want to start opening file descriptors into the file table of the current task during every context_switch(). Even if you close them afterwards).

At this point, you are asking about implementing (a smaller version of) the Linux perf sub-system. The perf subsystem owns the performance counters. If you want to use the performance counters without the perf subsystem, you should start by disabling perf support in the kernel. At some later point in the process you should spend time looking at relevant material in the SDM (or related manuals - I have not checked which).


[*] Sidenote: there are limitations when you pass pointers into ksys_*() functions. Basically they expect __user memory, not kernel memory, unless you play games using set_fs()..


Working on the perf code would be a different matter. You can easily find the code to start looking at there, e.g. by clicking on PERF_EVENT_IOC_RESET . As well as the specific line, that will give you a source file (and directory) to look at, and you can also keep clicking around :-). Therefore I assume that is not your question.

  • perf does a lot of sampling and is quite complicated. I just want a mechanism to get some counter values while I am running in the context of a given thread. What do you exactly mean by compiling out perf code, as it's quite complicated. – Nikhilesh Singh Mar 13 at 19:04
  • 1
    @NikhileshSingh cateee.net/lkddb/web-lkddb/PERF_COUNTERS.html – sourcejedi Mar 13 at 19:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.