Double Faults #1005
Replies: 84 comments 12 replies
-
Awesome stuff, waiting for more :) |
Beta Was this translation helpful? Give feedback.
-
@pbn4 Thank you :) |
Beta Was this translation helpful? Give feedback.
-
This is awesome -- thank you for the amazing work @phil-opp! I had a newbie question: I understand why these handlers are useful in preventing everything from ending up in a restart loop, but differences would an actual implementation have? For example, if a user is running a program that results in a page fault in their shell, the handler must be reporting that back to the application so it can surface it to the user, right? |
Beta Was this translation helpful? Give feedback.
-
@mtn Thank you!
Depends on the OS implementation and the fault type. For example, if the exception is caused because a userspace process tried to execute a privileged instruction, the kernel would simply kill the process (and the shell would report to the user that the process was killed). For a page fault, the kernel can react in multiple ways. If it's just an out of bound access to unmapped memory (like we do in the blog post), the kernel would kill the user program with a segmentation fault. However, most operating systems have a mechanism called swapping, where parts of the memory are moved to disk when the main memory becomes too full. Then a legitimate memory access could cause a page fault because the accessed data is no longer in memory. The OS can handle this page fault by loading the contents of the memory page from disk and continuing the interrupted process. This technique is called demand paging and allows to run programs that wouldn't fit completely into memory. |
Beta Was this translation helpful? Give feedback.
-
Yeah! That you showed for us is what we have learned from OS course. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the post, Phil. I am going to catch up on your posts now that I have completed a B.Sc. in technology. I am going to continue for a master in computer science and your material is very helpful for understanding operating systems. Small typo maybe: You spell it |
Beta Was this translation helpful? Give feedback.
-
@montao Congratulations on your degree!
Thanks! Fixed in f551116. |
Beta Was this translation helpful? Give feedback.
-
Where should I go next after completing your tutorial ? I am neither a beginner nor an expert in Rust but I am interested in OS development and have followed your tutorial thoroughly, I would like to proceed further Thanks for making this series :) |
Beta Was this translation helpful? Give feedback.
-
@siddharthsymphony The OSDev Wiki is one of the best online resources for OS development. If you want more theoretical knowledge, take a look at Modern Operating Systems by Andrew Tanenbaum |
Beta Was this translation helpful? Give feedback.
-
@siddharthsymphony I'm very interesting in System Development, any resources you recommend beside The OSDev Wiki and Modern Operating Systems by Andrew Tanenbaum ? |
Beta Was this translation helpful? Give feedback.
-
@phil-opp I’ve really enjoyed your blog! The way you express the concepts makes it easy for me to follow. Are you still planning on handling interrupts from external devices in next post? |
Beta Was this translation helpful? Give feedback.
-
@tnargy Thank you! Yes, the next post will be about hardware interrupts. It will explore the programmable interrupt controller, timer interrupts, and keyboard interrupts. I already created a first draft that you can preview here (it's still work in progress). |
Beta Was this translation helpful? Give feedback.
-
Awesome stuff. What was your source for learning this? If I wanted to contribute to the next posts while I'm having a go at them, do you have any recommended reading for that? |
Beta Was this translation helpful? Give feedback.
-
@Ben-PH Thanks! I don't have a single source. It's a mix of what I learned at university, the OSDev wiki, Wikipedia, the Intel/AMD manuals, and various other resources. If you're looking for a book about the fundamentional of operating systems, I can recommenend the free Three Easy Pieces. |
Beta Was this translation helpful? Give feedback.
-
Typo: becaues |
Beta Was this translation helpful? Give feedback.
-
Hey @phil-opp thanks again for the great tutorial. About the tests, I understand stack overflows are undefined behavior we should run it using the release mode, but I think we can add the optimization-level to the test profile and run the tests without use release mode. I did some tests on my end and I realize if we add the I added this change to my repo you can check it out if you want https://github.com/ferbass/gat_os/pull/1/files#diff-80398c5faae3c069e4e6aa2ed11b28c0R27 Do you think this is a valid setup to use or should we avoid Thank you in advanced -- |
Beta Was this translation helpful? Give feedback.
-
Hi @phil-opp, I have trouble understanding why a kernel code segment is needed. Adding a little footnote in the blog would be nice I think. Thanks in advance, and keep up the great work! :-) |
Beta Was this translation helpful? Give feedback.
-
In 64-bit mode, segmentation is mostly deactivated, apart from the Privilege level bits. In 16bit and 32 bit mode however, Segmentation is mandatory and correct cs ss and ds segments are usually needed, with correct bits (but often a 0 base address anyway). |
Beta Was this translation helpful? Give feedback.
-
Let me clarify my above comments a bit: Stack overflows on the main kernel stack are not undefined behavior because the bootloader creates a special unmapped page called guard page at the bottom ot this stack. Thus, a stack overflow results in a page fault and no memory is corrupted. The problem is/was that the double fault stack that we create in this post doesn't have such a guard page yet (we will improve this in a future post). Thus, a stack overflow is undefined behavior as it overwrites other data that might still be needed. While compiling with optimizations reduces stack size and can thus avoid these stack overflows in some cases, this is merely a workaround and not a valid solution to the problem. Instead, the double fault stack should still be large enough to work in debug mode too. For this reason I increased the stack size for the double fault stack, so that stack overflows should no longer occur even in debug mode, provided that you keep the double fault handler minimal. It's important to note that this problem is not exclusive to test. It can also occur on a normal execution, e.g. if we accidentally write a function with endless recursion. Since we don't want any undefined behavior in this case, even when running in debug mode, the double fault stack should be large enough for this. So changing the optimization level for tests is not a good solution for this problem because if a test fails in debug mode, a normal
In general, I don't think that changing the test optimization level is problematic. For example, it might be a valid way to speed up a test suite in some cases. However, the program/kernel/etc should still work in debug mode, so optimizing the tests only to avoid some runtime problems is not a good idea. |
Beta Was this translation helpful? Give feedback.
-
@luis-hebendanz As @GuillaumeDIDIER said, segmentation is mostly deactivated in 64-bit mode. The |
Beta Was this translation helpful? Give feedback.
-
Hi @phil-opp, thanks fo this amazing guide! I was wondering why stack size is fixed to
I think it would be nice if you could add a comment about that stack size in the post 😄 |
Beta Was this translation helpful? Give feedback.
-
I think |
Beta Was this translation helpful? Give feedback.
-
I followed the post up to the point where the basic double fault handler is implemented. Adding the I saw that you pushed some changes a few days ago. Might this be related? I am using the version PS. Thanks for this great blog. I learned a lot so far! |
Beta Was this translation helpful? Give feedback.
-
Hi @phil-opp, thank you for the great blogs! A compiler error. It complained on src/interrupts.rs Best regards! |
Beta Was this translation helpful? Give feedback.
-
When running this on my machine using QEMU, I kept getting double faults after the breakpoint handler ran. I fixed it by setting the segment descriptor register to zero: |
Beta Was this translation helpful? Give feedback.
-
Hello, Phil. Thank you for great tutorial! This is really cool stuff, it's much interesting than writing high level code. Thanks to you, i have enough knowledges to write school project about OSs. All the best! |
Beta Was this translation helpful? Give feedback.
-
Why does the TSS struct have Privilege Stack Table with three entries: Doesn't it have 4 privilege levels? (0-kernel, {1,2}-device drivers, 3-user) |
Beta Was this translation helpful? Give feedback.
-
Hi, thank you so much for making this tutorial with so much information as it has helped me learn about OS logic for the first time. When I ran |
Beta Was this translation helpful? Give feedback.
-
I tried the following scenario:
lazy_static! {
static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
// idt.breakpoint.set_handler_fn(breakpoint_handler);
// idt.double_fault.set_handler_fn(double_fault_handler);
idt.page_fault.set_handler_fn(page_fault_handler);
idt
};
} According to this
Page fault handler should be called, but rather it goes into restart mode. Also if I enable the double fault handler, then I am able to catch it. Am I missing something here? |
Beta Was this translation helpful? Give feedback.
-
in x86_64 package version 0.15.x the method |
Beta Was this translation helpful? Give feedback.
-
This is a general purpose comment thread for the “Double Faults” post.
Beta Was this translation helpful? Give feedback.
All reactions