-
Notifications
You must be signed in to change notification settings - Fork 265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Documentation: lectures: Add draft 'Interrupts' lecture #30
Conversation
|
||
+-----------+ NMI | ||
| | | ||
| <----------+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it looks better if you don't put the arrow inside the line:
--+
|
| <-------
|
Also there is no need to use + for the start of the arrow, you can use something like this:
<----- device0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tavip Ok, will try. Did you use any tool for drawing the pictures? I usee http://asciiflow.com/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I did it manually. asciiflow looks like a nice tool :)
|
||
* Interrupts and exceptions (Linux) | ||
|
||
* Defferable work |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: defferable -> deferrable
63 47 42 32 | ||
+------------------------------+-+--+----+--+-------------------+ | ||
| | |D | | | | | ||
| offset (16..31 |P|P | |T | | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it looks better if you use a space between the lines and letters, i.e.:
| | D |
| P | P |
| | L |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
| | segment selector | | offset| | PL | | | ||
| +----+-------------+ +---+----+ +------+ | | ||
| | | | | ||
+----------------------------------------------+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybw use a + where lines intersect:
| segment selector |
+-----+------------+
|
--------+--------------------------
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditaa gets confused by + and mangles the rectangles :)
|
||
Each IRQ line can be individually disabled. This allows simplifying design by making sure that | ||
interrupt handlers are always executed serially. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is worth adding a slide here or after the APIC slide, with about how can interrupts can be enabled or disabled:
- at the PIC level (programming the PIC)
- at the CPU level (using the CLI/STI)
especially since you mention IF in one of the slides below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is a good idea.
I have some questions on this topic.
I know most of this is hardware dependent but I want to make sure I got the correct idea.
- Lets say a PIC has 8 IRQ lines. What happens at PIC level when IRQ0 is asserted? PIC tries to notify the CPU via INTR pin, in this time any interrupt arriving on IRQ0...7 is ignored until the PIC ACK's IRQ0.
I assume that the interrupts arriving until the PIC ACK's IRQ0 are not lost but remembered some how and delivered after PIC gets the ACK from CPU.
-
cli/sti - disable/enable the interrupts only on local CPU? Or this is global? If a maskable interrupt arrives while it is masked the kernel still keeps track of it and delivers it when interrupts are unmasked,right?
-
disable_irq(irq), disables irq globally. What happens if an interrupts arrives while it was disabled? The core kernel code will still deliver it (by calling the irq handler) later?
Now, the following slide says that there are 3 phases in the process
of handling an interrupt:
https://linux-kernel-labs.github.io/pull/30/lectures/interrupts-slides.html#15
a) critical, i think this is the PIC level handling when all IRQ lines are disabled.
b) immediate, i think this is the CPU level handling only when the given IRQ line is disabled.
c) deferred, all IRQ are enabled.
Another set of questions:
- While an interrupt handler runs as a result of IRQ0, is that handler running only with IRQ0
disabled locally(?)/globally(?) but with the rest of IRQ enabled?
This means that when an interrupt handler runs, it can be interrupted by another interrupt but not by the same interrupt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets say a PIC has 8 IRQ lines. What happens at PIC level when IRQ0 is asserted? PIC tries to notify the CPU via INTR pin, in this time any interrupt arriving on IRQ0...7 is ignored until the PIC ACK's IRQ0.
Any new interrupts are "buffered" by the PIC until it gets an ACK from the CPU.
cli/sti - disable/enable the interrupts only on local CPU? Or this is global? If a maskable interrupt arrives while it is masked the kernel still keeps track of it and delivers it when interrupts are unmasked,right?
cli/sti is per CPU/core. Yes, the interrupt will be "buffered" until STI when the interrupt will be triggered.
disable_irq(irq), disables irq globally. What happens if an interrupts arrives while it was disabled? The core kernel code will still deliver it (by calling the irq handler) later?
Yes, it is disabled globally since it is done at the PIC level. disable_irq() makes sure there are no pending interrupts after the function returns. There is a disable_irq_nosync() which does not guarantee this.
Now, the following slide says that there are 3 phases in the process
of handling an interrupt:
https://linux-kernel-labs.github.io/pull/30/lectures/interrupts-slides.html#15
a) critical, i think this is the PIC level handling when all IRQ lines are disabled.
b) immediate, i think this is the CPU level handling only when the given IRQ line is disabled.
c) deferred, all IRQ are enabled.
For both a) and b) local CPU interrupts (IF flag) are disabled. Before e58aa3d("genirq: Run irq handlers with interrupts disabled") b) was running with CPU interrupts enabled.
The individual IRQ line is most likely (depends on the arch and PIC) still enabled during a) and it may get disabled during a) (e.g. for a level edge interrupt) or it may get disabled during b) (e.g. network drivers using NAPI).
While an interrupt handler runs as a result of IRQ0, is that handler running only with IRQ0
disabled locally(?)/globally(?) but with the rest of IRQ enabled?
See above.
* init: open_softirq() | ||
* activation: raise_softirq() | ||
* execution: do_softirq() | ||
* runs when: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it runs:
- after an interrupt handler
- from the ksoftirqd kernel hread
With multicore systems, each core has a local APIC used to process interrupts | ||
from locally connected devices like timers or thermals sensors. | ||
|
||
I/O APIC is used to distributed IRQ from external devices to CPU cores. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also add a short note about IPI (inter processor interrupts).
| | | ||
+----------------+ | ||
|
||
Defferable actions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: defferable -> deferrable
| +-----+ | - IRQ enabled | | ||
+-----------------+ +----> - execute later| | ||
| | | ||
+----------------+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is worth adding a slide about how Linux specifics about handling interrupts: common interrupt entry, shared handlers, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely, but I haven't understood it well enough.
|
||
* after finishing handling an interrupt | ||
* by the ksoftirqd thread | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a slide about ksoftirqd
Signed-off-by: Daniel Baluta <[email protected]>
Send v2 of the pull request after addressing Tavi's comments. Still on TODO list: add info about IPI and interrupt flow in Linux. |
In nsim_fib_init(), if register_fib_notifier failed, nsim_fib_net_ops should be unregistered before return. In nsim_fib_exit(), unregister_fib_notifier should be called before nsim_fib_net_ops be unregistered, otherwise may cause use-after-free: BUG: KASAN: use-after-free in nsim_fib_event_nb+0x342/0x570 [netdevsim] Read of size 8 at addr ffff8881daaf4388 by task kworker/0:3/3499 CPU: 0 PID: 3499 Comm: kworker/0:3 Not tainted 5.3.0-rc7+ linux-kernel-labs#30 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 Workqueue: ipv6_addrconf addrconf_dad_work [ipv6] Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xa9/0x10e lib/dump_stack.c:113 print_address_description+0x65/0x380 mm/kasan/report.c:351 __kasan_report+0x149/0x18d mm/kasan/report.c:482 kasan_report+0xe/0x20 mm/kasan/common.c:618 nsim_fib_event_nb+0x342/0x570 [netdevsim] notifier_call_chain+0x52/0xf0 kernel/notifier.c:95 __atomic_notifier_call_chain+0x78/0x140 kernel/notifier.c:185 call_fib_notifiers+0x30/0x60 net/core/fib_notifier.c:30 call_fib6_entry_notifiers+0xc1/0x100 [ipv6] fib6_add+0x92e/0x1b10 [ipv6] __ip6_ins_rt+0x40/0x60 [ipv6] ip6_ins_rt+0x84/0xb0 [ipv6] __ipv6_ifa_notify+0x4b6/0x550 [ipv6] ipv6_ifa_notify+0xa5/0x180 [ipv6] addrconf_dad_completed+0xca/0x640 [ipv6] addrconf_dad_work+0x296/0x960 [ipv6] process_one_work+0x5c0/0xc00 kernel/workqueue.c:2269 worker_thread+0x5c/0x670 kernel/workqueue.c:2415 kthread+0x1d7/0x200 kernel/kthread.c:255 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352 Allocated by task 3388: save_stack+0x19/0x80 mm/kasan/common.c:69 set_track mm/kasan/common.c:77 [inline] __kasan_kmalloc.constprop.3+0xa0/0xd0 mm/kasan/common.c:493 kmalloc include/linux/slab.h:557 [inline] kzalloc include/linux/slab.h:748 [inline] ops_init+0xa9/0x220 net/core/net_namespace.c:127 __register_pernet_operations net/core/net_namespace.c:1135 [inline] register_pernet_operations+0x1d4/0x420 net/core/net_namespace.c:1212 register_pernet_subsys+0x24/0x40 net/core/net_namespace.c:1253 nsim_fib_init+0x12/0x70 [netdevsim] veth_get_link_ksettings+0x2b/0x50 [veth] do_one_initcall+0xd4/0x454 init/main.c:939 do_init_module+0xe0/0x330 kernel/module.c:3490 load_module+0x3c2f/0x4620 kernel/module.c:3841 __do_sys_finit_module+0x163/0x190 kernel/module.c:3931 do_syscall_64+0x72/0x2e0 arch/x86/entry/common.c:296 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 3534: save_stack+0x19/0x80 mm/kasan/common.c:69 set_track mm/kasan/common.c:77 [inline] __kasan_slab_free+0x130/0x180 mm/kasan/common.c:455 slab_free_hook mm/slub.c:1423 [inline] slab_free_freelist_hook mm/slub.c:1474 [inline] slab_free mm/slub.c:3016 [inline] kfree+0xe9/0x2d0 mm/slub.c:3957 ops_free net/core/net_namespace.c:151 [inline] ops_free_list.part.7+0x156/0x220 net/core/net_namespace.c:184 ops_free_list net/core/net_namespace.c:182 [inline] __unregister_pernet_operations net/core/net_namespace.c:1165 [inline] unregister_pernet_operations+0x221/0x2a0 net/core/net_namespace.c:1224 unregister_pernet_subsys+0x1d/0x30 net/core/net_namespace.c:1271 nsim_fib_exit+0x11/0x20 [netdevsim] nsim_module_exit+0x16/0x21 [netdevsim] __do_sys_delete_module kernel/module.c:1015 [inline] __se_sys_delete_module kernel/module.c:958 [inline] __x64_sys_delete_module+0x244/0x330 kernel/module.c:958 do_syscall_64+0x72/0x2e0 arch/x86/entry/common.c:296 entry_SYSCALL_64_after_hwframe+0x49/0xbe Reported-by: Hulk Robot <[email protected]> Fixes: 59c84b9 ("netdevsim: Restore per-network namespace accounting for fib entries") Signed-off-by: YueHaibing <[email protected]> Acked-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
This is a draft version for the 'Interrupts' lecture. The slides should be almost ready, the content of the lecture has a lot of things to be added.
Anyhow, if the slides are in a good shape we are good to go.
Signed-off-by: Daniel Baluta [email protected]