Skip to content

How does RegMon work

Dr.-Ing. Thomas Hühn edited this page Jul 28, 2015 · 1 revision

How does RegMon work

The Linux kernel function 'readl()' is called to read the current register value at the memory address that was passed to it, respecting different host endianness and memory mapping specifics. For every register read, we store the current timestamp and the raw hexadecimal register values. Each column, except the first one holding the current timestamp, represents a register address specified through debugfs from the user-space. In our current implementation, we can monitor up to 12 registers in parallel. The main limiting factor for the number of registers is the memory footprint of the data structure to hold these values in the kernel.

The in-kernel register sampling consists of three parts:

  1. Reading registers via read_registers():
  • The function getnstimeofday() is called to get current UNIX time in nanoseconds and store the returned timestamp.
  • Iterating through the register file list in debugfs, each register's own memory address is used to call the corresponding driver's read register function and store the returned register content.
  • Registers will be triggered via a kernel timer event. With the high resolution timers used, sampling rates of 20.000Hz and more are feasible.
  1. Assembling the userspace output is triggered when a read operation to debugfs file is requested from the userspace. Then, all the new rows are written as formatted string into a debugfs log file.
  2. Initialization and de-initialization:
  • At device initialization, each WiFi interface creates its own debugfs RegMon folder and files.
  • All data structures and initial timer event registrations are performed.
  • At device de-initialization, all data structures are freed and all debugfs entries are removed.

By reading the debugfs log file, we get access to the content of the desired registers. We store these values in a ring buffer between kernel and user-space. This allows compensating for slower and possibly non-deterministic read cycles in the user-space while the content of the array is constantly updated in-kernel. Our current implementation uses max_row value of 30000 rows, which was under all circumstances sufficiently large to support register reading rates up to 30 kHz.