Page 5 of 6

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 6:56 pm
by Techflash
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.
Alright then. That just sounds like a major size issue though.

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 7:51 pm
by Octocontrabass
Techflash wrote:That just sounds like a major size issue though.
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:

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)
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.

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

Posted: Tue Aug 09, 2022 8:13 pm
by Techflash
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:

Code: Select all

...
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.

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.
Few things to note:
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?

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 8:24 pm
by Octocontrabass
Techflash wrote:1. Why does the code subtract 128 from the interrupt number? Is it needed for the stack alignment?
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: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].
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!)

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 8:27 pm
by Techflash
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.
Ah, ok. I'll just need to add 128 to the value in the handler.
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!)
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.

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?

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 8:41 pm
by Octocontrabass
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?
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:4. How would the array be accessed in the C code for the loop that sets the IDT values?
Something like this:

Code: Select all

extern const uint64_t ISRStubArray[256];

(...)

    for( int i = 0; i < 256; i++ )
    {
        IDTSetGate(i, &ISRStubArray[i], 0x08, 0x8E);
    }
Feel free to define it as some other type if you want to make the pointer arithmetic more explicit.
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.
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

Posted: Tue Aug 09, 2022 8:46 pm
by Techflash
Octocontrabass 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 ok then. Also I will add that .align 8
Octocontrabass wrote:
Techflash wrote:4. How would the array be accessed in the C code for the loop that sets the IDT values?
Something like this:

Code: Select all

extern const uint64_t ISRStubArray[256];
...
        IDTSetGate(i, &ISRStubArray[i], 0x08, 0x8E);
    }
Ah. Thanks! I wasn't sure what type it should be and what I should put in the loop.
Octocontrabass wrote:There are still errors if you're getting a triple fault, they just don't appear with your current log settings.
Alright. I'll modify my Bochs log settings to show more info and I'll post the results.

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 8:52 pm
by Techflash
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:

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*
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.

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 9:02 pm
by Octocontrabass
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.

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 9:07 pm
by Techflash
Octocontrabass 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.
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 logged

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 9:11 pm
by Octocontrabass
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

Posted: Tue Aug 09, 2022 9:15 pm
by Techflash
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"?
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.

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 9:26 pm
by Octocontrabass
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.

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 9:52 pm
by Techflash
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.
It just breaks once for every "fetch_raw_descriptor" error. It gives no info on when it triple faults.

Re: Issues with interrupts

Posted: Tue Aug 09, 2022 10:24 pm
by Octocontrabass
Okay... and what are the contents of the stack when you hit that breakpoint for the first time?