Alright then. That just sounds like a major size issue though.Octocontrabass wrote:That won't work for exceptions. You need to know which IDT entry the CPU used in order to tell which exception occurred.
It might work for IRQs, but it'll be a lot slower than looking up the interrupt number in your registers struct.
Issues with interrupts
Re: Issues with interrupts
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Issues with interrupts
Instead of using 256 unique symbols for each of the stubs, you can make them all the same size and initialize your IDT with a loop. That should come out smaller overall. Borrowing some excellent ideas from earlier in this thread, I came up with this:Techflash wrote:That just sounds like a major size issue though.
Code: Select all
.macro ISR_NOERR num
.align 8
push $\num-128
jmp ISRCommonStubNoErr
.align 8
.endm
.macro ISR_ERR num
.align 8
push $\num-128
jmp ISRCommonStubErr
.align 8
.endm
.global ISRStubArray
ISRStubArray:
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_ERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_ERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_ERR 29
ISR_ERR 30
ISR_NOERR 31
.set i,32
.rept 256-32
ISR_NOERR i
.set i,i+1
.endr
ISRCommonStubNoErr:
pushq (%rsp) # copy interrupt number to the correct location
ISRCommonStubErr:
push %r15
push %r14
(etc)
Also, while I was writing this post, I spotted a typo in your macros: you need a $ prefix on the three push instructions to use an immediate operand instead of a memory operand.
Re: Issues with interrupts
Few things to note:Octocontrabass wrote: Instead of using 256 unique symbols for each of the stubs, you can make them all the same size and initialize your IDT with a loop. That should come out smaller overall. Borrowing some excellent ideas from earlier in this thread, I came up with this:
The usual "I haven't actually tested this so no guarantees it's correct" applies. This code is subtracting 128 from the interrupt number before pushing it onto the stack - you'll have to take that into account when you use the interrupt number in your struct.Code: Select all
...
Also, while I was writing this post, I spotted a typo in your macros: you need a $ prefix on the three push instructions to use an immediate operand instead of a memory operand.
1. Why does the code subtract 128 from the interrupt number? Is it needed for the stack alignment?
2. I fixed that typo already in the current version (not yet committed) it still seems broken [Although there's no more read memory errors, just the triple fault remains].
3. How would the "ISRStubsArray" not be ended immediately by the first macro? Don't labels in ASM typically end once there is another label definition?
4. How would the array be accessed in the C code for the loop that sets the IDT values?
Last edited by Techflash on Tue Aug 09, 2022 8:24 pm, edited 1 time in total.
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Issues with interrupts
It's needed to keep all of the stubs under 8 bytes. The PUSH instruction is two bytes long when the immediate value is between -128 and 127, but five bytes long for immediate values outside that range.Techflash wrote:1. Why does the code subtract 128 from the interrupt number? Is it needed for the stack alignment?
I haven't gone out of my way to comb through the code looking for mistakes. I'd need more details about the exception to track it down. (This is why exception handlers are important!)Techflash wrote:2. I fixed that typo already in the current version (not yet committed) it still seems broken [Although there's no more read memory errors, just the triple fault remains].
Re: Issues with interrupts
Ah, ok. I'll just need to add 128 to the value in the handler.Octocontrabass wrote:It's needed to keep all of the stubs under 8 bytes. The PUSH instruction is two bytes long when the immediate value is between -128 and 127, but five bytes long for immediate values outside that range.
The triple fault wasn't with that code yet. I was just mentioning that fixing that typo alone fixed the errors, but not the triple fault.Octocontrabass wrote:I haven't gone out of my way to comb through the code looking for mistakes. I'd need more details about the exception to track it down. (This is why exception handlers are important!)
Also, what about the other 2 questions:
How would the "ISRStubsArray" not be ended immediately by the first macro? Don't labels in ASM typically end once there is another label definition?
And: How would the array be accessed in the C code for the loop that sets the IDT values?
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Issues with interrupts
There isn't another label definition. Even if there were, it wouldn't matter: the label only needs to provide a symbolic name for the address where it appears, I'm not using it for anything that depends on size or scope. (But now that you mention it, I think I forgot an ".align 8" directive before that label.)Techflash wrote:3. How would the "ISRStubsArray" not be ended immediately by the first macro? Don't labels in ASM typically end once there is another label definition?
Something like this:Techflash wrote:4. How would the array be accessed in the C code for the loop that sets the IDT values?
Code: Select all
extern const uint64_t ISRStubArray[256];
(...)
for( int i = 0; i < 256; i++ )
{
IDTSetGate(i, &ISRStubArray[i], 0x08, 0x8E);
}
There are still errors if you're getting a triple fault, they just don't appear with your current log settings.Techflash wrote:The triple fault wasn't with that code yet. I was just mentioning that fixing that typo alone fixed the errors, but not the triple fault.
Re: Issues with interrupts
Ah ok then. Also I will add that .align 8Octocontrabass wrote:There isn't another label definition. Even if there were, it wouldn't matter: the label only needs to provide a symbolic name for the address where it appears, I'm not using it for anything that depends on size or scope. (But now that you mention it, I think I forgot an ".align 8" directive before that label.)
Ah. Thanks! I wasn't sure what type it should be and what I should put in the loop.Octocontrabass wrote:Something like this:Techflash wrote:4. How would the array be accessed in the C code for the loop that sets the IDT values?Code: Select all
extern const uint64_t ISRStubArray[256]; ... IDTSetGate(i, &ISRStubArray[i], 0x08, 0x8E); }
Alright. I'll modify my Bochs log settings to show more info and I'll post the results.Octocontrabass wrote:There are still errors if you're getting a triple fault, they just don't appear with your current log settings.
Re: Issues with interrupts
Well, it doesn't quite work. The exact code I'm using at the moment is live on GitHub if you want to check it out. But according to bochs:
So I think either me or my PC must be getting memory loss, because I could have sworn we already fixed the GDT somewhere in this thread. I really cannot say what any of these messages mean.
Code: Select all
fetch_raw_descriptor: GDT: index (38d7) 71a > limit (27)
fetch_raw_descriptor: GDT: index (ff77) 1fee > limit (27)
fetch_raw_descriptor: GDT: index (fec7) 1fd8 > limit (27)
fetch_raw_descriptor: GDT: index (fe17) 1fc2 > limit (27)
fetch_raw_descriptor: GDT: index (fd67) 1fac > limit (27)
fetch_raw_descriptor: GDT: index (fcb7) 1f96 > limit (27)
fetch_raw_descriptor: GDT: index (fc07) 1f80 > limit (27)
fetch_raw_descriptor: GDT: index (fb57) 1f6a > limit (27)
fetch_raw_descriptor: GDT: index (faa7) 1f54 > limit (27)
fetch_raw_descriptor: GDT: index (f9f7) 1f3e > limit (27)
fetch_raw_descriptor: GDT: index (f947) 1f28 > limit (27)
fetch_raw_descriptor: GDT: index (f897) 1f12 > limit (27)
fetch_raw_descriptor: GDT: index (f7e7) 1efc > limit (27)
fetch_raw_descriptor: GDT: index (f737) 1ee6 > limit (27)
fetch_raw_descriptor: GDT: index (f687) 1ed0 > limit (27)
fetch_raw_descriptor: GDT: index (f5d7) 1eba > limit (27)
fetch_raw_descriptor: GDT: index (f527) 1ea4 > limit (27)
fetch_raw_descriptor: GDT: index (f477) 1e8e > limit (27)
fetch_raw_descriptor: GDT: index (f3c7) 1e78 > limit (27)
fetch_raw_descriptor: GDT: index (f317) 1e62 > limit (27)
fetch_raw_descriptor: GDT: index (f267) 1e4c > limit (27)
fetch_raw_descriptor: GDT: index (f1b7) 1e36 > limit (27)
fetch_raw_descriptor: GDT: index (f107) 1e20 > limit (27)
*triple fault*
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Issues with interrupts
You only have 31 out of the 256 ISR stubs in the array. You didn't copy the code to generate the ones above 31, and you have one missing here.
I don't know if that's the problem, though. It's hard to say what's going on with no information about what code caused those exceptions.
I don't know if that's the problem, though. It's hard to say what's going on with no information about what code caused those exceptions.
Re: Issues with interrupts
Fixed, those issues, same errors, here's the log you asked for with more info: Pastebin of everything from the moment the bootloader ends to the end of the log with everything but "debug" level events being loggedOctocontrabass wrote:You only have 31 out of the 256 ISR stubs in the array. You didn't copy the code to generate the ones above 31, and you have one missing here.
I don't know if that's the problem, though. It's hard to say what's going on with no information about what code caused those exceptions.
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Issues with interrupts
That log does not include a register dump from the first exception, so I can't tell what's going on. Does Bochs not have anything equivalent to QEMU's "-d int"?
Re: Issues with interrupts
I can't seem to find any way to make it halt on the first exception. Althought a quick google search shows that the "14" in the exception line means that somehow there's a page fault going on.Octocontrabass wrote:That log does not include a register dump from the first exception, so I can't tell what's going on. Does Bochs not have anything equivalent to QEMU's "-d int"?
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Issues with interrupts
Unfortunately, that only tells you that there's eventually a page fault.
You might be able to set a breakpoint on ISRHandler() to see what's up.
You might be able to set a breakpoint on ISRHandler() to see what's up.
Re: Issues with interrupts
It just breaks once for every "fetch_raw_descriptor" error. It gives no info on when it triple faults.Octocontrabass wrote:Unfortunately, that only tells you that there's eventually a page fault.
You might be able to set a breakpoint on ISRHandler() to see what's up.
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Issues with interrupts
Okay... and what are the contents of the stack when you hit that breakpoint for the first time?