Accessing GDT when using GRUB

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.
User avatar
mrjbom
Member
Member
Posts: 322
Joined: Sun Jul 21, 2019 7:34 am

Accessing GDT when using GRUB

Post by mrjbom »

Hi.
I am trying to create a user space(I will only use ring 0 and 3), this article says that I should create 2 new entries in GDT and configure them to ring 3.
But I didn't create GDT. I have an IDT with working interrupts and exceptions. As far as I understand, GRUB created GDT instead of me.
How can I manage the GDT that GRUB made? Or do I need to create my own?
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Accessing GDT when using GRUB

Post by PeterX »

I assume we are talking about 32bit mode.

The Grub GDT is not meant to be used as the normal kernel GDT. So you have to setup two or three ring 0 segments (code, data, stack). And similar with ring 3.

This is a good time to thoroughly design the memory layout and the GDT.

Greetings
Peter
User avatar
iansjack
Member
Member
Posts: 4834
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Accessing GDT when using GRUB

Post by iansjack »

The OP might want to re-read the multiboot specification.
the OS image must not load any segment registers (even just reloading the same values!) until it sets up its own ‘GDT’.
User avatar
mrjbom
Member
Member
Posts: 322
Joined: Sun Jul 21, 2019 7:34 am

Re: Accessing GDT when using GRUB

Post by mrjbom »

iansjack wrote:The OP might want to re-read the multiboot specification.
the OS image must not load any segment registers (even just reloading the same values!) until it sets up its own ‘GDT’.
Now, in my "loader" code, before passing control to kmain(), I configure my own GDT this way:

Code: Select all

global gdt_desc
start:
  cli
  mov esp, stack_top
  push ebx
  push eax

  jmp load_gdt

  ;global descriptor table
  gdt:

  gdt_null:
  dq 0

  gdt_code:
  dw 0FFFFh
  dw 0

  db 0
  db 10011010b
  db 11001111b
  db 0

  gdt_data:
  dw 0FFFFh
  dw 0

  db 0
  db 10010010b
  db 11001111b
  db 0

  gdt_end:

  gdt_desc:
  dw gdt_end - gdt - 1
  dd gdt

  load_gdt:
  lgdt [gdt_desc]  ;load GDT
  mov ax, 0x10
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  mov ss, ax
  jmp 0x08:.setcs
  .setcs:
  
  call kmain
  .hltloop:
  hlt
  jmp .hltloop
In C code I declared gdt address:

Code: Select all

extern char gdt_desc[];
Is that right?
How do I create a new structure for GDT? I can use it to manage GDT, right?
Can I now use the gdt_desc variable to manage gdt?
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Accessing GDT when using GRUB

Post by PeterX »

No, you normally don't use the GDT-"descriptor" as you name it. It is used only to tell the CPU where the GDT is.

You use it as you do, by setting CS, DS etc. to 0x08 (CS by a far JMP) and 0x10 (DS etc. and SS). But you need to set ESP (32bit stack pointer), too. But you are doing it right so far.

EDIT: Just add two more entries in the GDT for ring 3.
Last edited by PeterX on Sun Jul 05, 2020 10:26 am, edited 1 time in total.
User avatar
mrjbom
Member
Member
Posts: 322
Joined: Sun Jul 21, 2019 7:34 am

Re: Accessing GDT when using GRUB

Post by mrjbom »

PeterX wrote:No, you normally don't use the GDT-"descriptor" as you name it. It is used only to tell the CPU where the GDT is..
What kind of variable should I use to control the GDT?

Address of the "gdt:" tag ?
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Accessing GDT when using GRUB

Post by PeterX »

mrjbom wrote:
PeterX wrote:No, you normally don't use the GDT-"descriptor" as you name it. It is used only to tell the CPU where the GDT is..
What kind of variable should I use to control the GDT?

Address of the "gdt:" tag ?
I am not aware of any use case, where you would want to access the GDT later on from C. But maybe I over-simplify things here?
User avatar
mrjbom
Member
Member
Posts: 322
Joined: Sun Jul 21, 2019 7:34 am

Re: Accessing GDT when using GRUB

Post by mrjbom »

PeterX wrote:I am not aware of any use case, where you would want to access the GDT later on from C. But maybe I over-simplify things here?
The article that talks about the transition to ring 3 talks about the need to create two new entries in GDT.
mrjbom wrote:this article says that I should create 2 new entries in GDT and configure them to ring 3
I don't know exactly how to create entries in GDT because I don't know where to find the pointer...

Code: Select all

//gdt data from bootloader.asm
extern char gdt[];

struct gdt_ptr_struct
{
	unsigned short limit;
	unsigned int base;
};
struct gdt_ptr_struct* GDT = (struct gdt_ptr_struct*)gdt;
I want to try this:

Will this work as I need it? If I can create a new entry in the GDT?
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Accessing GDT when using GRUB

Post by PeterX »

Like this:

Code: Select all

 ;global descriptor table
  gdt:

  gdt_null:
  dq 0

  gdt_code:
  dw 0FFFFh
  dw 0

  db 0
  db 10011010b
  db 11001111b
  db 0

  gdt_data:
  dw 0FFFFh
  dw 0

  db 0
  db 10010010b
  db 11001111b
  db 0

gdt_ring3_code:
dw ...
...

gdt_ring3_data:
dw ...
...
  gdt_end:
EDIT: OK, maybe it's better to use LDT? Just a suggestion.

I fear I am wrong here regarding GDT only setting up once.
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Accessing GDT when using GRUB

Post by nexos »

You should set up the GDT in C. It will make life easier. Make it the first thing you setup. The LDT has to do with process memory management and could not replace the GDT.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
User avatar
mrjbom
Member
Member
Posts: 322
Joined: Sun Jul 21, 2019 7:34 am

Re: Accessing GDT when using GRUB

Post by mrjbom »

nexos wrote:You should set up the GDT in C. It will make life easier. Make it the first thing you setup. The LDT has to do with process memory management and could not replace the GDT.
I'm trying to configure GDT in C.
That is, I load GDT in bootloader.asm and then I want to be able to manage GDT from C code.

Here I have a pointer to GDT(I hope this is it), can I create new entries there? Or did I make a mistake somewhere?

Code: Select all

//gdt data from bootloader.asm
extern char gdt[];

struct gdt_ptr_struct
{
   unsigned short limit;
   unsigned int base;
};
struct gdt_ptr_struct* GDT = (struct gdt_ptr_struct*)gdt;
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Accessing GDT when using GRUB

Post by PeterX »

My GDT knowledge comes from enabling pmode in a bootloader. So I am not aware of all aspects of pmode kernels. Sorry if I gace wrong advice.

I thought (and I maybe wrong) that you setup the GDT only once and that is easier in Asm than in C.

If you really need to access GDT in C, don't you the struct you mentioed, but use an ordinary pointer to the beginning of the GDT.

Greetings
Peter.
User avatar
mrjbom
Member
Member
Posts: 322
Joined: Sun Jul 21, 2019 7:34 am

Re: Accessing GDT when using GRUB

Post by mrjbom »

PeterX wrote:Like this:

Code: Select all

 ;global descriptor table
  gdt:

  gdt_null:
  dq 0

  gdt_code:
  dw 0FFFFh
  dw 0

  db 0
  db 10011010b
  db 11001111b
  db 0

  gdt_data:
  dw 0FFFFh
  dw 0

  db 0
  db 10010010b
  db 11001111b
  db 0

gdt_ring3_code:
dw ...
...

gdt_ring3_data:
dw ...
...
  gdt_end:
Do you suggest using regular gdt for core tasks, and gdt_ring3 for userspace tasks?
I would be able to load gdt_ring3 while switching to a userspace task, and load gdt for the kernel when switching back to the core.
Is this a viable approach?
PeterX wrote:EDIT: OK, maybe it's better to use LDT? Just a suggestion.
In this case, can I use gdt for core tasks and ldt for userspace tasks?
User avatar
mrjbom
Member
Member
Posts: 322
Joined: Sun Jul 21, 2019 7:34 am

Re: Accessing GDT when using GRUB

Post by mrjbom »

PeterX wrote: I thought (and I maybe wrong) that you setup the GDT only once and that is easier in Asm than in C.
I install GDT once only in asm code.
PeterX wrote: If you really need to access GDT in C, don't you the struct you mentioed, but use an ordinary pointer to the beginning of the GDT.
How do I find this pointer? Is it "gdt:" (asm code) or something else?
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Accessing GDT when using GRUB

Post by PeterX »

mrjbom wrote:
PeterX wrote: If you really need to access GDT in C, don't you the struct you mentioed, but use an ordinary pointer to the beginning of the GDT.
How do I find this pointer? Is it "gdt:" (asm code) or something else?
Yes, type something like:

Code: Select all

global gdt
gdt:
Post Reply