irq: move doc to readme.

Cleanup, interlink, retest and update observations.
This commit is contained in:
Ciro Santilli
2018-05-12 10:52:38 +01:00
parent 0c15778e14
commit d1f676a680
4 changed files with 142 additions and 50 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
# Extensions and prefixes.
*.tmp
tmp.*
*~
?*.gitignore
gitignore*

View File

@@ -487,7 +487,7 @@ except that you don't need to know what is the maximum level.
....
head kernel_module/modulename.c
grep 'modulename\.' README.adoc
grep 'insmod /modulename\.ko' README.adoc
....
Many of the modules have userland test scripts / executables with the same name as the module, e.g. form inside the guest:
@@ -730,7 +730,7 @@ ls /lib/modules/*/extra/
Kernel modules built from the Linux mainline tree with `CONFIG_SOME_MOD=m`, are automatically available with `modprobe`, e.g.:
....
modprobe dummy-irq
modprobe dummy-irq irq=1
....
==== myinsmod
@@ -2638,6 +2638,129 @@ insmod /warn_on.ko
Can also be activated with the `panic_on_warn` boot parameter.
=== IRQ
==== irq.ko
Brute force monitor every shared interrupt that will accept us:
....
./run -F 'insmod /irq.ko' -x
....
Now try the following:
* press a keyboard key and then release it after a few seconds
* press a mouse key, and release it after a few seconds
* move the mouse around
Outcome: dmesg shows which IRQ was fired for each action throug messages of type:
....
handler irq = 1 dev = 250
....
`dev` is the character device for the module and never changes, as can be confirmed by:
....
cat /proc/devices | grep lkmc_irq
....
The IRQs that we observe are:
* `1` for keyboard press and release.
+
If you hold the key down for a while, it starts firing at a constant rate. So this happens at the hardware level!
* `12` mouse actions
This only works if for IRQs for which the other handlers are registered as `IRQF_SHARED`.
We can see which ones are those, either via dmesg messages of type:
....
genirq: Flags mismatch irq 0. 00000080 (myirqhandler0) vs. 00015a00 (timer)
request_irq irq = 0 ret = -16
request_irq irq = 1 ret = 0
....
which indicate that `0` is not, but `1` is, or with:
....
cat /proc/interrupts
....
which shows:
....
0: 31 IO-APIC 2-edge timer
1: 9 IO-APIC 1-edge i8042, myirqhandler0
....
so only `1` has `myirqhandler0` attached but not `0`.
TODO: properly understand how each IRQ maps to what number.
==== dummy-irq
The Linux kernel v4.16 mainline also has a `dummy-irq` module at `drivers/misc/dummy-irq.c` for monitoring a single IRQ.
We build it by default with:
....
CONFIG_DUMMY_IRQ=m
....
And then you can do
....
./run -x
....
and in guest:
....
modprobe dummy-irq irq=1
....
Outcome: when you click a key on the keyboard, dmesg shows:
....
dummy-irq: interrupt occurred on IRQ 1
....
However, this module is intended to fire only once as can be seen from its source:
....
static int count = 0;
if (count == 0) {
printk(KERN_INFO "dummy-irq: interrupt occurred on IRQ %d\n",
irq);
count++;
}
....
and furthermore interrupt `1` and `12` happen immediately TODO why, were they somehow pending?
So so see something interesting, you need to monitor an interrupt that is more rare than the keyboard, e.g. <<platform_device>>.
==== /proc/interrupts
In the guest on <<graphic-mode>>:
....
watch -n 1 cat /proc/interrupts
....
Then see how clicking the mouse and keyboard affect the interrupt counts.
This confirms that:
* 1: keyboard
* 12: mouse click and drags
The module also shows which handlers are registered for each IRQ, as we have observed at <<irq-ko>>
=== Linux kernel tracing
Good overviews:
@@ -3361,6 +3484,19 @@ devmem 0x101e9000 w 0x12345678
which touches the register from userland through `/dev/mem`.
We can also observe the interrupt with <<dummy-irq>>:
....
modprobe dummy-irq irq=34
insmod /platform_device.ko
....
The IRQ number `34` was found by on the dmesg after:
....
insmod /platform_device.ko
....
==== gem5 educational hardware models
TODO
@@ -5684,6 +5820,7 @@ Theory:
* https://rwmj.wordpress.com/ awesome red hatter
* https://lwn.net
* http://www.makelinux.net
* https://notes.shichao.io/lkd/
Awesome lists:

View File

@@ -78,6 +78,7 @@ CONFIG_VIRTIO_NET=y
# Misc
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_DUMMY_IRQ=m
## Networking
@@ -177,21 +178,6 @@ CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PL061=y
# In target:
#
# modprobe dummy-irq irq=34
# insmod /platform_device.ko
#
# Outcome:
#
# lkmc_platform_device_write offset=0 value=12345678 size=4
# dummy-irq: interrupt occurred on IRQ 34
#
# When the device generates an IRQ, the dummy module also snoops it.
#
# The IRQ number 34 was found by via dmesg on a previous "insmod /platform_device.ko".
CONFIG_DUMMY_IRQ=m
# Like CONFIG_X86_PTDUMP for ARM.
CONFIG_ARM64_PTDUMP=y

View File

@@ -1,42 +1,10 @@
/*
Brute force monitor every shared interrupt that will accept us.
I.e. only works if for IRQs for which the other handlers are registered as IRQF_SHARED.
Usage:
1. insmod and then use the keyboard and mouse. Those handlers are shared,
and the messages show up whenever you do something.
Does not work in text mode of course.
2. insmod some module that generates interrupts after insmod irq.,
e.g. pci_min or platform_device.
TODO: why does insmod in ARM lead to infinitely many interrupts handler irq = 45 dev = 252
and blocks the board? Is the ARM timer shared, and x86 isn't?
TODO: properly understand how each IRQ maps to what.
The Linux kernel mainline also has dummy-irq for monitoring a single IRQ.
Inside QEMU, also try:
watch -n 1 cat /proc/interrupts
Then see how clicking the mouse and keyboard affect the interrupts. This will point you to:
- 1: keyboard
- 12: mouse click and drags
*/
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h> /* copy_from_user, copy_to_user */
#define NAME "lkmc_character_device"
#define NAME "lkmc_irq"
#define MAX_IRQS 256
static int irqs[MAX_IRQS];