Skip to content
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

Merged
merged 1 commit into from
Mar 13, 2018

Conversation

dbaluta
Copy link
Member

@dbaluta dbaluta commented Mar 11, 2018

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]

tavip pushed a commit to linux-kernel-labs/linux-kernel-labs.github.io that referenced this pull request Mar 11, 2018

+-----------+ NMI
| |
| <----------+
Copy link
Member

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

Copy link
Member Author

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/

Copy link
Member

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
Copy link
Member

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 | |
Copy link
Member

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 |

Copy link
Member Author

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 | |
| +----+-------------+ +---+----+ +------+ |
| | | |
+----------------------------------------------+
Copy link
Member

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 |
+-----+------------+
        |
--------+--------------------------
        |


Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

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.

  1. 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.

  1. 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?

  2. 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:

  1. 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.

Copy link
Member

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:
Copy link
Member

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.
Copy link
Member

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
Copy link
Member

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|
| |
+----------------+
Copy link
Member

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.

Copy link
Member Author

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

Copy link
Member

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

tavip pushed a commit to linux-kernel-labs/linux-kernel-labs.github.io that referenced this pull request Mar 12, 2018
@dbaluta
Copy link
Member Author

dbaluta commented Mar 12, 2018

Send v2 of the pull request after addressing Tavi's comments. Still on TODO list: add info about IPI and interrupt flow in Linux.

@dbaluta dbaluta merged commit ed8e26a into linux-kernel-labs:master Mar 13, 2018
dbaluta pushed a commit to dbaluta/linux that referenced this pull request Nov 7, 2019
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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants