OSDev.org
https://forum.osdev.org/

GDT: Jumps to wrong memory after reloading registers
https://forum.osdev.org/viewtopic.php?f=1&t=32577
Page 1 of 1

Author:  Luca1 [ Sat Nov 18, 2017 3:45 pm ]
Post subject:  GDT: Jumps to wrong memory after reloading registers

Hello everyone,

after reading through a lot of the wiki pages/tutorials I decided to setup my own GDT, however as soon as I reload any of the registers ds, ss and cs there's a jump to a completely wrong address for some reason and that causes a crash.

To store the address and size used when executing "lgdt" i used this struct:
Code:
struct gdt_info {
   unsigned int address;
   unsigned short size;
} __attribute__((packed));

And to store a single gdt entry I used this struct:
Code:
struct gdt_entry {
   unsigned char upperBase; // Bits 24 to 31 of base address
   unsigned char config; //Flags in the upper 4 bits and Limit from 16-19 in the lower four
   unsigned char access; //Access byte
   unsigned char middleBase; // Bits 16 to 23 of base address
   unsigned short lowerBase; //Bits 0 to 15 of base address
   unsigned short limit; //Lower limit(Bits 0 to 15)
} __attribute__((packed));


Then I define an array of 3 of the structs containing the null descriptor, the kernel data segment and the kernel code segment:
Code:
struct gdt_entry nullDescriptor = {
      .upperBase = 0,
      .config = 0,
      .access = 0,
      .middleBase = 0,
      .lowerBase = 0,
      .limit = 0
   };
   gdt_entries[0] = nullDescriptor;
   /* 0x9A = 10011010 0xC=1100 */
   gdt_entries[1] = gdt_makeEntry(0, 0xFFFFF, 0x9A, 0xC);
   /* 0x92 = 10010010 */
   gdt_entries[2] = gdt_makeEntry(0, 0xFFFFF, 0x92, 0xC);


With make_entry doing this:
Code:
struct gdt_entry gdt_makeEntry(unsigned int base, unsigned int limit, unsigned char access, unsigned char flags){
   struct gdt_entry newEntry = {
      .upperBase = (base & 0xFF000000) >> 24,
      .config = ((flags & 0x0F) << 4) | ((limit & 0xF0000) >> 16),
      .access = access,
      .middleBase = (base & 0x00FF0000) >> 16,
      .lowerBase = (base & 0x0000FFFF),
      .limit = (limit & 0x0FFFF)
   };
   return newEntry;
}

I'm using following assembler functions to lgdt:
Code:
global load_gdt
;load_gdt Loads a GDT, with the first argument being the address to a gdt_info struct
;Stack: [esp+4] Address to gdt_info struct
;   [esp] Return address
load_gdt:
   mov eax, [esp+4]
   lgdt [eax]
   ret

When stepping through this with GDB I checked if eax contained the correct address and it did, and the size and address of the GDT were also correct.
Now here comes the problematic code:
Code:
global gdt_setRegisters
;gdt_setRegisters Sets the required cs, ss and ds registers
;Stack:
;   [esp] Return address
gdt_setRegisters:
   jmp 0x08:flush_cs ;And then flush it

flush_cs:
   ; And we are with cs = [esp+2]
   mov ax, 0x10
   mov ds, ax
   mov ss, ax
   ret

As soon as the jmp is executed the executions jumps to a seemingly random address in memory resulting, sooner or later, in a crash. I also tried swapping around the flushing of the CS register and the setting of ds and ss, but I still get the same Problem it jumps to a bogus address once reaching the first instructions that modifies any of cs, ds and ss.

While single stepping through GDB I also noticed that the "disassemble" command doesn't recognise the far jump, but instead displays (BAD).

I hope you can help me.

Regards,
Luca

Author:  iansjack [ Sat Nov 18, 2017 3:58 pm ]
Post subject:  Re: GDT: Jumps to wrong memory after reloading registers

The only reason I can think of for the code to jump to a seemingly random location is that you are getting an exception, but haven't set up the IDT and exception handlers.

Author:  Luca1 [ Sat Nov 18, 2017 4:01 pm ]
Post subject:  Re: GDT: Jumps to wrong memory after reloading registers

iansjack wrote:
The only reason I can think of for the code to jump to a seemingly random location is that you are getting an exception, but haven't set up the IDT and exception handlers.


I didn't, but from my last understanding this should Triple fault my CPU, shouldn't it?
And even then something is still wrong if I'm getting an exception and I'm quite confused why considering my GDT is seemingly correct(According to GDB, if you want I can post the path I followed)

Author:  MichaelPetch [ Sat Nov 18, 2017 9:17 pm ]
Post subject:  Re: GDT: Jumps to wrong memory after reloading registers

Luca1 wrote:
Code:
struct gdt_info {
   unsigned int address;
   unsigned short size;
} __attribute__((packed));
First thing I see here is that the size and address are reversed. Should be:
Code:
struct gdt_info {
   unsigned short size;
   unsigned int address;
} __attribute__((packed));
This is a known bug in the Little OS Book tutorial. I assume that you got this definition from that tutorial or someone who relied on that tutorial.

Author:  Luca1 [ Sun Nov 19, 2017 1:06 am ]
Post subject:  Re: GDT: Jumps to wrong memory after reloading registers

MichaelPetch wrote:
Luca1 wrote:
Code:
struct gdt_info {
   unsigned int address;
   unsigned short size;
} __attribute__((packed));
First thing I see here is that the size and address are reversed. Should be:
Code:
struct gdt_info {
   unsigned short size;
   unsigned int address;
} __attribute__((packed));
This is a known bug in the Little OS Book tutorial. I assume that you got this definition from that tutorial or someone who relied on that tutorial.


Yeah I kinda followed along this tutorial. I turned around the order of the gdt_info and gdt_entry structs and now it works perfectly!
Thank you very much!

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/