Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Well, this simply can't work. For one, you are initializing only the first sixteen entries. That is not even enough to cover the exception range. For two, you make no distinction between exceptions with and without error code (you cannot simply iret from exceptions with error code, you have to remove the error code first). And finally, you enable interrupts not having initialized any interrupt controllers. So what is going to happen? Very quickly some sort of timer interrupt will fire on some unknown vector that is likely beyond the size of the IDT. This will invoke the double fault interrupt, which luckily you have, but you immediately iret from it. Leaving aside that there is probably an error code (not quite sure on that off the cuff), the processor manual states that you cannot trust the RIP portion of the interrupt frame to point to anything sensible for a double fault (since DF is an Abort type exception). If you look at, say, Linux, you will see that it handles double fault by testing for one known case where they can happen (but then the RIP can be set to something well known), and in all other cases, they will just panic.
So, putting it all together: You must initialize all 256 IDT entries to something slightly more comprehensive that "iret", and you must not "sti" until you have discovered and initialized all interrupt controllers, because otherwise you will not know what an interrupt means.
nullplan wrote:Well, this simply can't work. For one, you are initializing only the first sixteen entries. That is not even enough to cover the exception range. For two, you make no distinction between exceptions with and without error code (you cannot simply iret from exceptions with error code, you have to remove the error code first). And finally, you enable interrupts not having initialized any interrupt controllers. So what is going to happen? Very quickly some sort of timer interrupt will fire on some unknown vector that is likely beyond the size of the IDT. This will invoke the double fault interrupt, which luckily you have, but you immediately iret from it. Leaving aside that there is probably an error code (not quite sure on that off the cuff), the processor manual states that you cannot trust the RIP portion of the interrupt frame to point to anything sensible for a double fault (since DF is an Abort type exception). If you look at, say, Linux, you will see that it handles double fault by testing for one known case where they can happen (but then the RIP can be set to something well known), and in all other cases, they will just panic.
So, putting it all together: You must initialize all 256 IDT entries to something slightly more comprehensive that "iret", and you must not "sti" until you have discovered and initialized all interrupt controllers, because otherwise you will not know what an interrupt means.
For testing purposes, can I not use "sti", but invoke #PF via accessing an address outside of range I've previously mapped (first 1MB)?
Also, should I change idt_entry#TypeAttr field per entry, does it ever differ (I wasn't really sure what to set it to and I figured out this value might be appropriate looking at other people's reference code)?
And finally, how big is the error code? - Found the answer myself.
Sorry if I'm asking trivial questions. I just found the interrupt tutorial very confusing in many ways.
angods wrote:Also, should I change idt_entry#TypeAttr field per entry, does it ever differ (I wasn't really sure what to set it to and I figured out this value might be appropriate looking at other people's reference code)?
You may set it to either an interrupt gate or a trap gate. The only difference between the two is that interrupt gates guarantee interrupts are disabled when the handler is called. If you're not sure, just use interrupt gates for now. You can always go back and change it later. (Where exactly did you see someone using 0x88? That's not a valid descriptor type.)
angods wrote:Also, should I change idt_entry#TypeAttr field per entry, does it ever differ (I wasn't really sure what to set it to and I figured out this value might be appropriate looking at other people's reference code)?
You may set it to either an interrupt gate or a trap gate. The only difference between the two is that interrupt gates guarantee interrupts are disabled when the handler is called. If you're not sure, just use interrupt gates for now. You can always go back and change it later. (Where exactly did you see someone using 0x88? That's not a valid descriptor type.)
I can't remember where I saw someone using it, but I was just experimenting.. I forgot to change it to 'normal' (0x8e) before sending the code.
Last edited by angods on Sun Oct 31, 2021 3:39 pm, edited 1 time in total.