OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 2:24 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: JamesM GDT & IDT tutorial causes triple fault in long mode.
PostPosted: Thu Jul 28, 2022 10:52 pm 
Offline
Member
Member

Joined: Sun May 08, 2022 2:10 am
Posts: 70
I have used James Molloy's GDT & IDT tutorial as a base for getting interrupts set up.
I get a triple fault when running the `lgdt` instruction. Bochs produced some logs that might be useful to diagnose the issue:
Code:
07797480380e[CPU0  ] interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0
07797480380e[CPU0  ] interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0
(0).[7797480380] [0x00000010fe3a] 0008:ffffffffffe02e3a (unk. ctxt): lgdt %ds:(%rax)           ; 0f0110
07797480380p[CPU0  ] >>PANIC<< exception(): 3rd (13) exception with no resolution

After a little bit of poking around. It seems that the following things are happening leading up the the lgdt call:
1. The function is called
2. We dereference the stack pointer + 4 bytes and move that into rax [The result I got in rax just before the lgdt call was 00000000_ffffffff in the bochs debugger, this seems wrong]
3. We dereference rax and lgdt that [00000000_ffffffff]

I have no idea what is going on that is making this break so horribly. I have pushed the current code to my GitHub repo if you want to see what's going on. The related code is in kernel/hardware/CPU/interrupts.
The github repo is https://github.com/techflashYT/Techflash-OS


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Thu Jul 28, 2022 11:19 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Techflash wrote:
2. We dereference the stack pointer + 4 bytes and move that into rax [The result I got in rax just before the lgdt call was 00000000_ffffffff in the bochs debugger, this seems wrong]

It seems wrong because it is wrong. James Molloy's tutorial uses the System V i386 psABI, but your compiler is using the System V x86-64 psABI. In the x86-64 psABI, the parameter is passed in the EDI register, not on the stack.

You might want to read the overview of calling conventions on the wiki or this list of x86 calling conventions on Wikipedia. If you're interested in reading the ABI documentation itself, here is the i386 psABI and you can click the "download" icon on this page to get the x86-64 psABI. There's also plenty of example code out there; just ask your favorite search engine for parameter passing in x86-64 assembly.

Speaking of James Molloy's tutorial, it has quite a few bugs.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Thu Jul 28, 2022 11:23 pm 
Offline
Member
Member

Joined: Sun May 08, 2022 2:10 am
Posts: 70
Octocontrabass wrote:
Techflash wrote:
2. We dereference the stack pointer + 4 bytes and move that into rax [The result I got in rax just before the lgdt call was 00000000_ffffffff in the bochs debugger, this seems wrong]

It seems wrong because it is wrong. James Molloy's tutorial uses the System V i386 psABI, but your compiler is using the System V x86-64 psABI. In the x86-64 psABI, the parameter is passed in the EDI register, not on the stack.

You might want to read the overview of calling conventions on the wiki or this list of x86 calling conventions on Wikipedia. If you're interested in reading the ABI documentation itself, here is the i386 psABI and you can click the "download" icon on this page to get the x86-64 psABI. There's also plenty of example code out there; just ask your favorite search engine for parameter passing in x86-64 assembly.

Speaking of James Molloy's tutorial, it has quite a few bugs.


Ahh. I didn't know there was a difference between x86 and x86_64 calling conventions. And I knew it was using the System V ABI.

Also yup, I read that page already. I didn't use that tutorial as the entire base. I just used it for interrupts.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Thu Jul 28, 2022 11:32 pm 
Offline
Member
Member

Joined: Sun May 08, 2022 2:10 am
Posts: 70
UPDATE:
Well now it seems to be reading the GDT correctly. But it has a new issue:
It gets past the lgdt line alright.
But when it tries to move ax [0x10] into ds:
Code:
07097422515e[CPU0  ] load_seg_reg(DS, 0x0010): segment not present
07097422515e[CPU0  ] interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0
07097422515e[CPU0  ] interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0
(0).[7097422515] [0x00000010fe3d] 0008:ffffffffffe02e3d (unk. ctxt): mov ds, ax                ; 8ed8
07097422515p[CPU0  ] >>PANIC<< exception(): 3rd (13) exception with no resolution

It can't seem to find the new data segment? It then complains about the IDT (which hasn't yet been set up, since the code is still working on the GDT).
I'm starting to think this is going to be a much bigger rabbit hole than I originally thought.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Thu Jul 28, 2022 11:38 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Techflash wrote:
It can't seem to find the new data segment?

Yeah, that sounds about right when you're throwing away half of the GDT base address. (In long mode, the base is 64 bits instead of 32.)


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Thu Jul 28, 2022 11:48 pm 
Offline
Member
Member

Joined: Sun May 08, 2022 2:10 am
Posts: 70
Octocontrabass wrote:
Techflash wrote:
It can't seem to find the new data segment?

Yeah, that sounds about right when you're throwing away half of the GDT base address. (In long mode, the base is 64 bits instead of 32.)


Ahh. Fixed that. But it still gives the same error. Could these lines be at fault? That's the only other related part I could think of that could be an issue still.
Code:
   gdtEntries[num].baseLow = (base & 0xFFFF);
   gdtEntries[num].baseMiddle = (base >> 16) & 0xFF;
   gdtEntries[num].baseHigh = (base >> 24) & 0xFF;


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Thu Jul 28, 2022 11:56 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
In 64-bit mode, the base is ignored for the CS, DS, ES, and SS registers, so it doesn't matter what you put there - the CPU will ignore it.

But you still need the correct number of bits for that unused space. The comment is correct, but the structure doesn't match the comment.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Thu Jul 28, 2022 11:58 pm 
Offline
Member
Member

Joined: Sun May 08, 2022 2:10 am
Posts: 70
Octocontrabass wrote:
In 64-bit mode, the base is ignored for the CS, DS, ES, and SS registers, so it doesn't matter what you put there - the CPU will ignore it.

But you still need the correct number of bits for that unused space. The comment is correct, but the structure doesn't match the comment.

Huh. Nice catch. Must have made a typo when I was fixing the types from the non standard "u*int" that the JamesM tutorials use. I'll update this post with the results once it finishes compiling.

UPDATE: Same error again. Honestly kinda surprised. I would have thought that it would give a different error at some point.
UPDATE 2: Just double checked the original code. It matches now. But a little math shows that the combination of "baseLow", "baseMiddle", and "baseHigh", only gives 32-bits.... Would doubling each of the types to: uint32_t, uint16_t, uint16_t respectively work correctly then?
UPDATE 3: Nope, that didn't work.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Fri Jul 29, 2022 12:40 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Techflash wrote:
UPDATE: Same error again. Honestly kinda surprised. I would have thought that it would give a different error at some point.

Huh. I didn't see any other obvious mistakes that would lead to a non-present segment. Sounds like you'll have to dig a little bit deeper with your debugger. (I hear the Bochs debugger can dump the GDT...)

Techflash wrote:
But a little math shows that the combination of "baseLow", "baseMiddle", and "baseHigh", only gives 32-bits.... Would doubling each of the types to: uint32_t, uint16_t, uint16_t respectively work correctly then?

No. Since there's no segmentation in 64-bit mode, AMD decided to leave those fields the same size.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Fri Jul 29, 2022 12:54 am 
Offline
Member
Member

Joined: Sun May 08, 2022 2:10 am
Posts: 70
Octocontrabass wrote:
Techflash wrote:
UPDATE: Same error again. Honestly kinda surprised. I would have thought that it would give a different error at some point.

Huh. I didn't see any other obvious mistakes that would lead to a non-present segment. Sounds like you'll have to dig a little bit deeper with your debugger. (I hear the Bochs debugger can dump the GDT...)

Techflash wrote:
But a little math shows that the combination of "baseLow", "baseMiddle", and "baseHigh", only gives 32-bits.... Would doubling each of the types to: uint32_t, uint16_t, uint16_t respectively work correctly then?

No. Since there's no segmentation in 64-bit mode, AMD decided to leave those fields the same size.


Alright. I switched the types back, and I found a command that looks like it dumps something related to the GDT:
Code:
es:0x0010, dh=0x00809300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0x0fffffff, Read/Write, Accessed
cs:0x0008, dh=0x00209900, dl=0x0000ffff, valid=1
        Code segment, base=0x00000000, limit=0x0000ffff, Execute-Only, Non-Conforming, Accessed, 64-bit
ss:0x0010, dh=0x00809300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0x0fffffff, Read/Write, Accessed
ds:0x0010, dh=0x00809300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0x0fffffff, Read/Write, Accessed
fs:0x0010, dh=0x00809300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0x0fffffff, Read/Write, Accessed
gs:0x0010, dh=0x00809300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0x0fffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0xffffffffffffffff, limit=0xffff
idtr:base=0x0000000000000000, limit=0x3ff

This was taken just before moving ax into ds.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Fri Jul 29, 2022 1:04 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Techflash wrote:
Code:
gdtr:base=0xffffffffffffffff, limit=0xffff

Well, that's obviously wrong.

And I think I see the problem. Addresses are 64 bits, that should be RDI instead of EDI.


Top
 Profile  
 
 Post subject: Re: JamesM GDT & IDT tutorial causes triple fault in long mo
PostPosted: Fri Jul 29, 2022 1:09 am 
Offline
Member
Member

Joined: Sun May 08, 2022 2:10 am
Posts: 70
Octocontrabass wrote:
Techflash wrote:
Code:
gdtr:base=0xffffffffffffffff, limit=0xffff

Well, that's obviously wrong.

And I think I see the problem. Addresses are 64 bits, that should be RDI instead of EDI.

Ahh. That makes a lot more sense. One sec while I try it.
UPDATE: YAY! It now finally triple faults yet again but in the IDT [likely very similar issues]
UPDATE 2: After applying similar patches the the IDT code (switching the bases to uint64s, and swapping some code around in the assembly loader), it now works correctly! Thanks for all the help. I probably would have never figured this out otherwise.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Amazonbot [bot], Bing [Bot] and 66 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group