-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Comments for "https://os.phil-opp.com/hardware-interrupts/" #480
Comments
Hi, I'd be interested in writing the small scancode_set1 crate! You can reach me at trinioler at gmail.com if you want to continue the discussion out of band. :) |
@ZerothLaw Awesome, I'll write you an email! |
I’m following your tutorials, and (am currently) creating an API for device drivers. Thanks for the amazing work! |
@rybot666 You're welcome! What are your plans for the API design? |
I'm curious if you have any plans for how to do APIC, as it doesn't look like there is a crate for it. |
@phil-opp I’m planning on using traits to implement it (I’ve got a EDIT: Forgot the link |
I wrote a crate called pc-keyboard which handles raw access to a UK 105 key PS/2 keyboard generating scan code set 2. Happy for patches to make it work with set 1 and other keyboard layouts. |
@thejpster Awesome! cc @ZerothLaw |
@rybot666 Ah, so that devices can register and unregister for certain interrupts at runtime? |
@donald-pinckney Nothing specific yet, just some vague ideas. |
@phil-opp Exactly. Currently (as in right now) trying to get rid of errors about not being able to send Fn(...) types across threads |
@rybot666 I think you need to add the |
@phil-opp Yea, I have and it seems to have fixed that. Although my current device isn't very good (an iPad and the Github editor). |
Hey @thejpster I'll see about sending you a PR with scancode set 1 sometime soon. |
"As already mentioned, the 8259 APIC has been superseded by the APIC" Perhaps "8259 PIC" was intended here? |
Isn't bad that the |
@GrayJack I understand your concerns, but the crate is rather small and I don't see anything problematic in the code. Also, I contacted the owner before I used the crate for this post, and they said that they're still willing to maintain this crate. |
There is a small mistake in the code examples in the implementation and enabling interrupts sections. The last code example under |
@JoshMcguigan Thanks! Fixed in 2e16cc4. |
I am really enjoying this series. I'm currently working on adding a simply network layer utilizing virtio to xv6 and it's been really cool comparing the two implementations. I'm learning a ton from the in depth explanations as well since there in't a lot of information regarding this except for the osdev wiki and the intel manuals. |
@bIgBV Great to hear that! |
As Rust beginner, this line |
a note for anyone using the latest version (0.5.0) of pc-keyboard, you'll need to make a change. use pc_keyboard::{Keyboard, ScancodeSet1, DecodedKey, layouts, HandleControl }; // new ... Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore)); //new which causes some odd behavior in the number pad (might be bug in pc-keyboard. or Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::MapLettersToUnicode)); which works better, but now the control key is a modifier to be used with another key and returns unicode. which means you lose direct access to the control key. |
This feature is called pattern matching and is normally used in combination with a
You can use any variable name in the pattern, including the same variable name as used on the right side. If you use the same name, the original variable is shadowed and only the new variable can be used inside the block. For more information see the official documentation which includes a shadowed variable in the example ( So to answer the second part of your question: Yes, a different variable name like I hope this answers your question! I opened issue #572 to add an explanation like the above to the post. |
I read about pattern matching and |
I don't think so. My understanding of Spin::Mutex is that when locked,
it will release the mutex after it leaves scope. The only possible way
I could see a deadlock occurring is if the PIC is faulty or two
interrupts for the keyboard get sent simultaneously. Even then, the
handler would be called twice, and both calls woudl happen almost
together, and therefore, one would wait while the other finished. Then
that one would get handled, kind of like a queue. Using this setup I
can't really imagine an actual deadlock occurring in practice. (I
rewrote my keyboard handler so this doesn't apply to me, but my
handler is fully asynchronous and does involve locks, so if there is a
deadlock that can be caused, I'd love to know a definitive answer to
this question too.)
…On 7/21/19, Mark Aufflick ***@***.***> wrote:
Is there a possible deadlock in `keyboard_interrupt_handler` since
`notify_end_of_interrupt` will get called before the `KEYBOARD` lock falls
out of scope?
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#480 (comment)
--
Signed,
Ethin D. Probst
|
@aufflick The @ethindp We currently use only a single core and the legacy PIC, so no two interrupts can run at the same time. So a deadlock could occur if we the "keep interrupts enabled" flag for the IDT entry of the keyboard handler. |
Ah. I could also see something liek a deadlock happening once we use
an APIC and/or enter SMP mode -- that will be problematic, and I'll
have to rewrite my current IDT code. Ug
…On 7/22/19, Philipp Oppermann ***@***.***> wrote:
@aufflick The `notify_end_of_interrupt` function only signals to the
interrupt controller that we're finished handling the interrupt, so that it
can send the next one when possible. However, interrupts stay disabled on
the CPU by default until the interrupt handler returns. So even if the
interrupt controller raises an interrupt right after the
`notify_end_of_interrupt` call, the CPU would not start to handle it until
the handler returns.
@ethindp We currently use only a single core and the legacy PIC, so no two
interrupts can run at the same time. So a deadlock could occur if we the
"keep interrupts enabled" flag for the IDT entry of the keyboard handler.
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#480 (comment)
--
Signed,
Ethin D. Probst
|
As long as we don't make the keyboard handler nested by reenabling interrupts before it is finished, I don't think it will cause issues. And there is no reason to do so because we want to handle keyboard input sequentially anyway. |
There shouldn’t be a deadlock here even with SMP. If two interrupts happen on different CPUs at the same time, one will take the keyboard lock and the other will be forced to wait until it’s finished. APIC has a similar EOI mechanism but uses MMIO instead of in/out, as the 8259 PIC does - it shouldn’t be that hard to replace. Basically the main thing you need to avoid is locking something twice from the same CPU. As a side note, there’s really no reason for the PIC to take a lock here as far as I see it, it’s not mutating anything. |
It's mutating the internal state of the interrupt controller, isn't it? |
Yes but it doesn’t need to - it treats writing to a port as a mutation. It’s not modifying any actual data. |
I guess that a question of the mental model. What I meant is that the port write has a side effect, even without modifying any data. Before it, the internal state of the interrupt controller is that the interrupt is still processed. Afterwards, the interrupt controller is in a different internal state, namely that the handling of the interrupt has finished. For me this sounds like some internal register of the interrupt controller changes its value as a result of that port write. |
How would we even set up aPIC and SMP support anyway? I've read up on
th aPIC and SMP on OSDev but can't:
1) figure out how to read ACPI tables (I know I can read pointers and
all that, but if I read the memory at 0x40E (I think that's the right
one), will I get a memory address which I then need to read at?).
2) Enable SMP. I've read the Intel SDMs on this, but still don't know
how to send the appropriate commands to the processors.
…On 7/22/19, Philipp Oppermann ***@***.***> wrote:
I guess that a question of the mental model. What I meant is that the port
write has a side effect, even without modifying any data. Before it, the
internal state of the interrupt controller is that the interrupt is still
processed. Afterwards, the interrupt controller is in a different internal
state, namely that the handling of the interrupt has finished. For me this
sounds like some internal register of the interrupt controller changes its
value as a result of that port write.
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#480 (comment)
--
Signed,
Ethin D. Probst
|
There is no easy walkthrough that I’m aware of. OSDev wiki explains what you need to do to get the ACPI tables. Here’s a useful reference that helped me with SMP before: https://nemez.net/osdev/lapic.txt |
This is great, maybe I can finally output a keyboard handler that handles chords.. ie when you hold down DOWN and RIGHT, it will continuously repeat DOWN then RIGHT so diagonal scrolling comes for free. |
Is there any reason to implement InterruptIndex::as_usize as |
Getting the APIC and all of that working shouldn't be too difficult (the x86 crate lets us set up the XAPIC or X2APIC, as well as sending IPIs. I don't know how to tell the processors where to start execution though. And it doesn't help with ACPI either. |
@JohnDowson Casting with |
@ethindp I plan to look into the APIC more closely soon as part of adding UEFI support. I'll update the blog with some instructions then. |
I'm having an issue that as soon as I add the PIC initialize code and enable interrupts, the double fault message doesn't print fully. Instead, it seems to hang in the middle of the InterruptStackFrame structure. If I don't include the structure in the output, it prints the whole thing. I cloned your blog_os repo and checkout out the post-07 branch, and if I induce a double fault there (by causing a stack overflow in _start), the system apparently triple faults (reboots endlessly), with again only a partial double fault message printed. There too not including the stack frame in the output causes the reboot loop to go away. Any idea what could be causing this? |
Ok, I had a thought after noticing that this didn't happen when running the release profile. I tried increasing the size of the double fault handler's stack, and that solved the issue. It seems that when compiling without optimizations, the Debug formatter for InterruptStackFrame overflows the 4kb stack. What that ends up doing (hang vs. reboot loop) seems to depend on what's at the address it ends up accessing after that. |
@SvenGroot Thanks for reporting! You're completely right that this is caused by a stack overflow on the double fault stack. See #449 (comment) for more information. I now pushed 0425bd3 and 817e36c to increase the stack size to |
I made a switch from ubuntu to arch linux, which gave me a much newer version of QEMU. and suddenly my code double-faults whenever i press a key. If I mask out the interrupt on the PIC the issue goes away although then I am unable to type anything (except in my serial console which still doesn't fire interrupts). This issue was present ever since I updated from the QEMU on ubuntu to the version of QEMU available on Arch Linux. |
Could you tell us what's your QEMU version now, so that we can try to reproduce the problem? |
The Qemu version that Arch Linux has is the latest version (5.1.0-1) |
Hey, in the Also, according to what I have understood, we don't need to get the writer's lock manually, we only need to disable interrupts during the test. So this should be enough: #[test_case]
fn test_println_output() {
- use core::fmt::Write;
use x86_64::instructions::interrupts;
let s = "Some test string that fits on a single line";
interrupts::without_interrupts(|| {
- let mut writer = WRITER.lock();
- writeln!(writer, "\n{}", s).expect("writeln failed");
+ println!("\n{}", s);
for (i, c) in s.chars().enumerate() {
let screen_char = writer.buffer.chars[BUFFER_HEIGHT - 2][i].read();
assert_eq!(char::from(screen_char.ascii_character), c);
}
});
} By the way, great tutorials! |
@divykj Thanks for your comment (and sorry for the late reply!). You're completely right that we are no longer testing the I'm currently in the process of rewriting the screen output code (pixel-based framebuffer instead of VGA text buffer), so the |
Hi. Thank you for this great tutorial series, your explanations are detailed and well written. When trying to reproduce the deadlock by having the interrupt try to acquire the already locked Writer, I ran into something that confused me.
rather that using
After changing this, the kernel deadlocks as expected. |
@phil-opp I am trying to setup serial interrupts too. As far as I can see the uart_16550 crate already enables serial port interrupts and they should arrive at IRQ4 or IDT index 36, but none of it happens. Have you an idea why? |
@krummelur I'm not quite sure if that's what you mean, but if you have |
@luis-hebendanz I never set up serial interrupts so I don't have any idea what could be the problem, sorry. But please let us know if you figure it out! |
@phil-opp I got it to work turns out I had to unmask the interrupt in the pic controller by writing a 0 to port 0x21 at bit index 2. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
This is a general purpose comment thread for the “Hardware Interrupts” post.
The text was updated successfully, but these errors were encountered: