Crash after loading GDT and flushing registers

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.
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Crash after loading GDT and flushing registers

Post by nexos »

You're still violating the ABI :) . You should be doing this:

Code: Select all

mov edx, dword [esp+4]
Right now, you're accessing the function return address (not the first parameter) if you just did

Code: Select all

pop edx
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
YDeeps1
Member
Member
Posts: 69
Joined: Tue Aug 31, 2021 7:25 am
Discord: speedy.dev
Contact:

Re: Crash after loading GDT and flushing registers

Post by YDeeps1 »

nexos wrote:You're still violating the ABI :) . You should be doing this:

Code: Select all

mov edx, dword [esp+4]
Right now, you're accessing the function return address (not the first parameter) if you just did

Code: Select all

pop edx
I am aware! Popped was the wrong word to use :lol: I was still accessing the parameter; not the return address. Thanks anyways.
YDeeps1
Member
Member
Posts: 69
Joined: Tue Aug 31, 2021 7:25 am
Discord: speedy.dev
Contact:

Re: Crash after loading GDT and flushing registers

Post by YDeeps1 »

I have done a little more debugging and I found QEMU very helpful.

Debugging by launching the VM with the debug flag set to log interrupts, the first interrupt appears to be a general protection fault (0xd - 13):

Code: Select all

check_exception old: 0xffffffff new 0xd
     0: v=0d e=0010 i=0 cpl=0 IP=0008:0010001b pc=0010001b SP=0010:00301fb4 env->regs[R_EAX]=00000010
Update - After sacrificing some of my sleep I have finally figured out the problem! My function which deals with split bits is incorrect and produces incorrect bits so I have converted my entry structure into a little bitfield and simply opted into hard coding the bits with a little assistance of a binary to hex converter and now my table works.

Code: Select all

GDT DefaultGDT = {
    {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
    {0x8000, 0x0, 0x0, 0x9A, 0x0, 0xC, 0x0},
    {0x8000, 0x0, 0x0, 0x92, 0x0, 0xC, 0x0},
    {0x8000, 0x0, 0x0, 0xFA, 0x0, 0xC, 0x0},
    {0x8000, 0x0, 0x0, 0xF2, 0x0, 0xC, 0x0}
};
And have also fixed up my far jump with the help of the wiki.

Thank you everyone for your contributions!
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Crash after loading GDT and flushing registers

Post by Octocontrabass »

YDeeps1 wrote:I have also logged the address of the GDT offset + size table address (decimal 18874372) which matches up with the EDX register, removing some possibilities.
Why is this address 17 megabytes above the start of your kernel? How big is your kernel, anyway?
YDeeps1
Member
Member
Posts: 69
Joined: Tue Aug 31, 2021 7:25 am
Discord: speedy.dev
Contact:

Re: Crash after loading GDT and flushing registers

Post by YDeeps1 »

Octocontrabass wrote:
YDeeps1 wrote:I have also logged the address of the GDT offset + size table address (decimal 18874372) which matches up with the EDX register, removing some possibilities.
Why is this address 17 megabytes above the start of your kernel? How big is your kernel, anyway?
I was about to answer that. My kernel is actually only a few kilobytes maximum but to avoid any possibility such as my stack doing something to the GDT like accidentally overwriting it due to some other critical mistake I have instead stored it in my heap which I set to be about 20M above to remove this doubt.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Crash after loading GDT and flushing registers

Post by Octocontrabass »

That's the address of your GDT descriptor, not your GDT. According to the register dump from earlier, your GDT lives in the .data section near your stack.

And anyway, you don't need the GDT descriptor after you've copied it into the GDTR with LGDT. You could allocate it on the stack instead.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Crash after loading GDT and flushing registers

Post by nullplan »

Small function to load GDT with GDTR on stack:

Code: Select all

;C interface: void load_gdt(const void *gdt, size_t sz);
global load_gdt
load_gdt:
  sub esp, 8
  mov eax, [esp+12]
  mov cx, [esp+16] ; if this exceeds 2 bytes, you have a problem, anyway
  dec cx
  mov [esp+4], eax
  mov [esp+2], cx
  lgdt [esp+2]
  add esp, 8
  ret
Carpe diem!
Post Reply