OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Apr 24, 2024 11:12 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Kernel crashes when loading GDT segment selectors
PostPosted: Fri Jun 12, 2020 8:05 am 
Offline

Joined: Fri Jun 12, 2020 7:53 am
Posts: 17
I've been working on setting up my GDT, and though I've validated my entries several times, I seem to be crashing when trying to load any of the data segments. I think my actual entries seem to be correct; I've printed them out and the hex values look correct (and match examples I've seen online). The lgdt instruction is executed, but then my first load fails (e.g. "movw %ax, %ds"). I tried removing all of the data segment set calls, and only doing the longjump, and that does not crash.

I'm not super experienced with QEMU/Bochs so I don't have debug output yet - that's what I'm working on now. But in the meantime, I figured I would post in case I made some obvious boneheaded mistake (always a good bet). Any help would be much appreciated!

Here is my entry struct / gdt

Code:
#include <stdint.h>

struct gdt_entry_struct {

  uint16_t limit_low;
  uint16_t base_low;
  uint8_t base_middle;
  uint8_t access;
  uint8_t lim_high_and_gran;
  uint8_t base_high;
} __attribute__((packed));
typedef struct gdt_entry_struct gdt_entry_t;

struct gdt_ptr_struct {
  uint16_t size;
  uint32_t offset;
} __attribute__((packed));
typedef struct gdt_ptr_struct gdt_ptr_t;

void init_descriptor_tables();


Implementation:
Code:
#include "kernel/descriptor_table.h"


// For accessing assembly function
extern void gdt_flush(uint32_t);
// Internal function
static void init_gdt();
static void gdt_set_gate(int32_t idx, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran);

// We want 5 entries for our GDT: null, kernel code, kernel data, user code, user data
gdt_entry_t gdt_entries[5];
gdt_ptr_t gdt_ptr;


// Implementation
void init_descriptor_tables(){
  init_gdt();
}

static void init_gdt(){

  // Set up the actual ptr
  // The offset is the linear address of the table itself, which means that paging applies.
  // The size is the size of the table subtracted by 1. This is because the maximum value
  // of size is 65535, while the GDT can be up to 65536 bytes (a maximum of 8192 entries).
  gdt_ptr.size = (sizeof(gdt_entry_t) * 5) - 1;
  gdt_ptr.offset = (uint32_t)&gdt_entries[0];

  // Add entries to the table
  gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0);             // Null entry
  gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF);  // Kernel Code
  gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF);  // Kernel data
  gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF);  // User space code
  gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF);  // User space data

  gdt_flush((uint32_t)&gdt_ptr);
}

static void gdt_set_gate(int32_t idx, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {

  // First 2 bytes of base, then third byte of base, then fourth
  gdt_entries[idx].base_low    = (base & 0xFFFF);
  gdt_entries[idx].base_middle = (base >> 16) & 0xFF;
  gdt_entries[idx].base_high   = (base >> 24) & 0xFF;

  // Limit low is first 2 bytes
  // Limit high is first 4 bits of third byte
  // Setting lower 4 bits of lim_high_and_gran (the limit high bits)
  gdt_entries[idx].limit_low         = (limit & 0xFFFF);
  gdt_entries[idx].lim_high_and_gran = (limit >> 16) & 0x0F;

  // Set high 4 bits of lim_high_and_gran
  // These are the actual granularity bits
  gdt_entries[idx].lim_high_and_gran |= (gran & 0xF0);

  // Just set access directly
  gdt_entries[idx].access = access;
}



The assembly to load the GDT
Code:

   .section .text

   .globl gdt_flush
   .type gdt_flush, @function

gdt_flush:
   movl 4(%esp), %eax
   lgdt (%eax)

   movw 0x10, %ax
   movw %ax, %ds
   movw %ax, %es
   movw %ax, %fs
   movw %ax, %gs
   movw %ax, %ss
   jmp $0x08,$.flush
.flush:
   ret


And finally, the call to init_descriptor_tables() from kernel main

Code:
#include <stdio.h>

#include <kernel/tty.h>
#include <kernel/descriptor_table.h>

void kernel_main(void) {
   terminal_initialize();
   printf("Hello, kernel World!\n");
   init_descriptor_tables();
   printf("Initialized descriptor tables\n");
}


If it's easier to read this on GitHub, here's the repo: https://github.com/LukeRobbins2112/myos


Top
 Profile  
 
 Post subject: Re: Kernel crashes when loading GDT segment selectors
PostPosted: Sat Jun 13, 2020 1:23 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5144
Code:
   movw 0x10, %ax

In AT&T syntax, immediate values are prefixed with $. Without the prefix, that is a memory reference. I would guess the value in memory at that address is not a valid segment selector.


Top
 Profile  
 
 Post subject: Re: Kernel crashes when loading GDT segment selectors
PostPosted: Sat Jun 13, 2020 1:25 am 
Offline
Member
Member

Joined: Sat Aug 18, 2018 8:44 pm
Posts: 127
did you run it on bochs? if so can you post bochsout.txt?


Top
 Profile  
 
 Post subject: Re: Kernel crashes when loading GDT segment selectors
PostPosted: Sat Jun 13, 2020 7:30 am 
Offline

Joined: Fri Jun 12, 2020 7:53 am
Posts: 17
Octocontrabass wrote:
Code:
   movw 0x10, %ax

In AT&T syntax, immediate values are prefixed with $. Without the prefix, that is a memory reference. I would guess the value in memory at that address is not a valid segment selector.


Yep, that's it alright, thanks for pointing that out - boneheaded mistake indeed. Fixed up the immediate value and it's working.
ITChimp, thanks for your reply. I did run it on bochs but I'm still learning the ropes - reading through the bochsout.txt, I see the garbage %eax value.


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 124 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