OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 7:34 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: [SOLVED] Triple-fault on loading a GDT
PostPosted: Wed Apr 19, 2017 3:10 pm 
Offline
Member
Member

Joined: Sun Sep 06, 2015 5:40 am
Posts: 47
I am trying to load a GDT. I have an array of entries, with each entry created like so:
Code:
static uint64_t gdtEntries[NUM_GDT_ENTRIES];
static struct gdt_pointer
{
  uint16_t limit;
  uint32_t firstEntryAddr;
} gdtPtr;

static uint64_t CreateGDTEntry(uint32_t base, uint32_t limit, uint16_t type)
{
  uint64_t entry = 0u;
  entry = limit & 0x000F0000;
  entry |= (type << 8u) & 0x00F0FF00;
  entry |= (base >> 16u) & 0x000000FF;
  entry |= base & 0xFF000000;

  entry <<= 32u;

  entry |= base << 16u;
  entry |= limit & 0x0000FFFF;

  return entry;
}

extern void FlushGDT(uint32_t);
void InitGDT()
{
  gdtPtr.limit = sizeof(uint64_t) * NUM_GDT_ENTRIES;
  gdtPtr.firstEntryAddr = (uint32_t)&gdtEntries;

  gdtEntries[0u] = CreateGDTEntry(0u, 0u, 0u);            // Null segment
  gdtEntries[1u] = CreateGDTEntry(0u, 0xFFFFFFFF, 0x9A);  // Kernel code segment
  gdtEntries[2u] = CreateGDTEntry(0u, 0xFFFFFFFF, 0x92);  // Kernel data segment

  FlushGDT((uint32_t)&gdtPtr);
}


I then load the GDT and switch to the new code and data segment like so:
Code:
; Inputs: Physical address of GDT to be loaded
FlushGDT:
  mov eax, [esp+4]
  lgdt [eax]

  ; We can now switch to the new data selectors (0x10 is the selector for the new kernel data segment)
  mov ax, 0x10
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  mov ss, ax

  ; We now do a far jump to the new kernel code segment (0x08 is the selector for the new code segment)
  jmp 0x08:.flush
.flush:
  ret


It triple faults, but not where I thought it would (the far jump). Instead, it seems to start executing some random code after `mov ds, ax` (which is weird because I haven't changed the CS yet??). I usually try to be fairly self-sufficient with debugging, but I can't find the relevant part of the Intel manual and the wiki seems to have slightly conflicting methods. I would appreciate some pointers in what I've done wrong; thanks in advance!

_________________
OS on Github | My Rust ACPI library


Last edited by isaacwoods on Thu Apr 20, 2017 3:57 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Triple-fault on loading a GDT
PostPosted: Wed Apr 19, 2017 3:32 pm 
Offline
Member
Member
User avatar

Joined: Fri Feb 17, 2017 4:01 pm
Posts: 641
Location: Ukraine, Bachmut
this
Code:
static struct gdt_pointer
{
  uint16_t limit;
  uint32_t firstEntryAddr;
} gdtPtr;


I am not into x86 now, but this structure won't be a 6-byte entity expected by lgdt instruction. Because of alignment. No? Make it packed or better define some union.

_________________
ANT - NT-like OS for x64 and arm64.
efify - UEFI for a couple of boards (mips and arm). suspended due to lost of all the target park boards (russians destroyed our town).


Top
 Profile  
 
 Post subject: Re: Triple-fault on loading a GDT
PostPosted: Thu Apr 20, 2017 2:51 am 
Offline
Member
Member

Joined: Sun Sep 06, 2015 5:40 am
Posts: 47
Okay, so I made that structure packed, and also realised I wasn't subtracting one from the size of the table, so I changed that line to:
Code:
gdtPtr.limit = (sizeof(uint64_t) * NUM_GDT_ENTRIES) - 1u;


The GDT is now loaded correctly and DS,ES,FS,GS and SS are all set to 0x10. However, on the far jump (`jmp 0x08:.flush`), CS is set to 0xf000 and it starts executing code at 0xe05b (.flush is at 0x10022c), causing a triple-fault.
Thanks for the help anyways!

_________________
OS on Github | My Rust ACPI library


Top
 Profile  
 
 Post subject: Re: Triple-fault on loading a GDT
PostPosted: Thu Apr 20, 2017 3:17 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5103
BaconWraith wrote:
However, on the far jump (`jmp 0x08:.flush`), CS is set to 0xf000 and it starts executing code at 0xe05b (.flush is at 0x10022c), causing a triple-fault.

The far jump to 0xF000:E05B is the result of a triple-fault, not the cause of it.

It looks like the triple fault is caused because your code segment descriptor is invalid. Are you sure you're calling CreateGDTEntry with the correct arguments?


Top
 Profile  
 
 Post subject: Re: Triple-fault on loading a GDT
PostPosted: Thu Apr 20, 2017 3:56 am 
Offline
Member
Member

Joined: Sun Sep 06, 2015 5:40 am
Posts: 47
Okay, I've been dissecting the actual GDT entries and found I hadn't set the Sz bit of the flags, so I guess it was trying to use 16-bit addresses. It now works, so thank you very much and sorry for the oversight.

_________________
OS on Github | My Rust ACPI library


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 291 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