-
Notifications
You must be signed in to change notification settings - Fork 138
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
Examples in documentation #60
Comments
Hello, sorry for the missing examples! I try to add some soon. The CPU only pushes an error code for some exceptions such as the page fault or the general protection fault exception. See https://wiki.osdev.org/Exceptions for an overview over all exception types that shows which exceptions push an error code. This crate tries to enforce this in the IDT type by expecting a You can trigger a software interrupt through the unsafe fn int(number: u8) {
asm!("int $0" :: "r" (number) :: "volatile");
} (I didn't test the above code.) This function should allow you to trigger any interrupt handler (I don't know from the top of my head if it's possible to also trigger exceptions). I hope this helps! |
@phil-opp Thanks for your help !
I think it is related to the fact that inline asm is still an experimental and buggy feature (issue #29722). |
extern "x86-interrupt" fn(stack_frame: &mut ExceptionStackFrame) The The only alternative is to use
Ah, makes sense. The
Because nobody implemented other |
@phil-opp I am not sure I understand everything, but I think I got the essential :) I would like to help you with this crate, but I feel when the const generics will be available for use, it will only take you 5mins to implement the |
You want to pass arguments to your interrupt handler? There isn't really an easy way to do this because of the fundamental differences between function calls and interrupts: interrupts happen asynchronously, so the caller ofter doesn't even know when an interrupt is invoked, so it can't pass any arguments. The best way to pass data on synchronous interrupts (software interrupts or system calls), is to put the data into registers before invoking the
Yes, because the Let me know if you have further questions! |
Rust does not support asynchronous tasks ? Or is it part of the standard library so we cannot use it in a Your proposition of creating an |
I'm a bit confused here. Do you want to use interrupts for implementing asynchronous tasks? This won't really work because the Interrupts from the hardware, on the other hand, are asynchronous because they can occur at any time, so that the interrupted code doesn't know when it might be interrupted. Interrupt handlers can't receive any additional arguments because the hardware doesn't set any additional arguments. This isn't a limitation of Rust, but a fundamental property of the x86 architecture. And other architectures do it in a similar way, as far as I know. If you want to implement an asynchronous task system you have two possibilities:
I hope this helps! |
No no don't worry, it was just a question ^^
I really look forward for this feature to be stable, although it would be more relevant in a computer network context, with a TCP/IP stack, than as a parto of an IPC mechanism.
I think i'll go for this solution, because I need to scheduler to be able to preempt jobs at any time. I'll do more research to understand what I have to implement. Do you think I have to save all the registers ? Does it mean I have to create a |
Yes, you typically want to save all general purpose registers. The reason is that you have to save all registers that the interrupted job uses, so that it can continue later. Note that you need to also save the SSE registers if you enable SSE at some point. Implementing context switches is a bit tricky because you have to be very careful to not accidentally overwrite registers before saving them. One way to do this is to make the interrupt handler a
You probably want to use a different interrupt stack (like we did for the double fault exception) to avoid the race condition between step 3 and 4. Note that this is only a high-level overview and only one way of doing it. For the blog I plan to use a different approach but I'm not sure if it works out yet. |
Oh my gosh I can feel the unsafeness from here. I will read the https://osdev.org articles a bit further and try to create something that works, while keeping your steps as a template. Why do you plan to use a different approach ? I'll try to figure out how to enable SSE. I don't remember if your OS has it enabled, maybe I could do a pull request once I've figured it out ? |
Yes, I added it a few days ago.
Because of the unsafeness and the need to write assembly code. My idea is to modify the exception stack frame that is passed as an argument to the interrupt handler. The problem is that this doesn't preserve the register values. To solve this, we can add an additional layer by adding an "outer" interrupt handler that does the register saving. In pseudo-code:
The disadvantage of this approach is that it is less efficient since some registers are saved in both outer and inner. But I think that it's easier to understand and less error-prone, therefore a good fit for the blog. |
Enabling SSE is simple: Just set some bit in a configuration register. We deliberately don't enable it because we would then need to save and restore the SSE registers on every interrupt, which is very expensive since the SSE registers are very large. See https://os.phil-opp.com/disable-simd/ for more information. |
Alright, thanks for all the info. Concerning the inner/outer interrupts system, why is it not possible to only save the relevant registers ? |
The RTC is a separate controller, right? I think it makes more sense as a separate crate then.
Yes, they are. The 32
We know nothing about the program that was interrupted, so we don't know which registers hold values that are needed later. For this reason we need to restore all registers to their previous value before continuing it. The |
Hello
I am working with this crate to complete my honours project, but I encountered problems a couple of things.
I looked on the documentation on www.docs.rs, but I could not find any examples, and even worse I am new to Rust, so I'm a bit lost.
How can I add to the IDT an exception handler of the type
HandlerFuncWithErrCode
?Apparently the IDT structure only expects a
HandlerFunc
handler.And how would you trigger a custom exception in the code (a kind of
throw
instruction) ?Or maybe are you waiting for the stable release
1.0.0
to write the examples ?The text was updated successfully, but these errors were encountered: