<div dir="ltr"><div>Hi,<br></div><div><br></div><div>>  Ah, you are not using the ftrace framework nor relayfs? Mmiotrace<br> used to be relayfs at one point and then converted to ftrace.</div><div><br></div><div>Yes, I considered these when I started working on KernelStrider but finally borrowed ideas from Perf and implemented them. A mmapped ring buffer does its job well and has a higher throughput than Ftrace in my case.</div>
<div class="gmail_extra"><br>> Are you saying that you intercept function calls, and *never* rely<br></div><div class="gmail_extra">> on page faulting?<br>
</div><div class="gmail_extra"><br></div><div class="gmail_extra">The system intercepts both function calls *and* memory operations made by the driver itself. Yes, it never relies on page faulting.</div><div class="gmail_extra">
<br> > Does that mean that if a driver does the ugly thing and</div><div class="gmail_extra"> > dereferences an iomem pointer directly, you won't catch that?</div><div class="gmail_extra"><br></div><div class="gmail_extra">
It will be caught. </div><div class="gmail_extra"><br></div><div class="gmail_extra">What my system actually does is as follows.</div><div class="gmail_extra"><br></div><div class="gmail_extra">When the target kernel module has been loaded into memory but before it has begun its initialization, KernelStrider processes it, function after function. It creates an instrumented variant of each function in the module mapping space and places a jump at the beginning of the original function to point to the instrumented one. After instrumentation is done, the target driver may start executing.</div>
<div class="gmail_extra"><br></div><div class="gmail_extra">If some original function of the driver contained, say,</div><div class="gmail_extra"><br></div><div class="gmail_extra">  mov 0xabcd (%rax), %rsi</div><div class="gmail_extra">
  mov %rbx, 0xbeeffeed (%rsi)</div><div class="gmail_extra"><br></div><div class="gmail_extra">that will be transformed to something like </div><div class="gmail_extra"><br></div><div class="gmail_extra">  lea  0xabcd (%rax), %rbx</div>
<div class="gmail_extra">  mov %rbx, <local_storage1></div><div class="gmail_extra">  mov 0xabcd (%rax), %rsi </div><div class="gmail_extra">  lea  0xbeeffeed (%rsi), %rbx</div><div class="gmail_extra">  mov %rbx, <local_storage2> </div>
<div class="gmail_extra">  mov %rbx, 0xbeeffeed (%rsi) </div><div class="gmail_extra">  ...</div><div class="gmail_extra">  <send the local_storage to the output system></div><div class="gmail_extra"><br></div><div class="gmail_extra">
That is, the address which is about to be accessed is determined and stored in 'local_storage', a special memory structure. At the end of the block of instructions, the information from the local storage is sent to the output system. So the addresses and sizes of the accessed memory areas as well as the types of the accesses (read/write/update) will be available for reading from the user space.</div>
<div class="gmail_extra"><br></div><div class="gmail_extra">It is actually more complex than that (KernelStrider has to deal with register allocation, relocations and other things) but the principle is as I described.</div>
<div class="gmail_extra"><br></div><div class="gmail_extra">The function calls are processed too so that we can set our own handlers to execute at the beginning of a function and right before its exit.</div><div class="gmail_extra">
<br></div><div class="gmail_extra">Yes, the functions like read[bwql]() and write[bwlq]() are usually inline but they pose no problem: on x86 they compile to ordinary MOV instructions and the like which are handled as I described above.</div>
<div class="gmail_extra"><br></div><div class="gmail_extra">The instrumented code will access the ioremapped area the same way as the original code would, no need for single-stepping or emulation in this case.</div><div class="gmail_extra">
<br></div><div class="gmail_extra">What I wrote in my previous letter is that there is a special case when the target driver uses some non-inline function provided by the kernel proper or by another driver and that function accesses the ioremapped memory area of interest. </div>
<div class="gmail_extra"><br></div><div class="gmail_extra">KernelStrider needs to track all such functions in order not to miss some memory accesses to that ioremapped area. Perhaps, that's manageable. There are not too many such functions, aren't they?</div>
<div class="gmail_extra"><br>> I don't really know. I guess everything could be possible in<br>> proprietary drivers, but you can look at the instruction decoding<br>> code in mmiotrace, which digs up the type and size of access and<br>
> the value. That has been enough so far.<br>
<br>
</div><div class="gmail_extra">Yes, I will take a closer look on that part of MmioTrace, thanks for the point.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Regards,</div><div class="gmail_extra"><br></div>
<div class="gmail_extra">Eugene</div><div class="gmail_extra"><br></div></div>