OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Apr 24, 2024 7:53 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 27 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 11:38 am 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 300
PeterX wrote:
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:
global gdt
gdt:

Yes, I've already done that. Now I think I'll be able to manage the GDT.

As far as I understand, for each userland process I have to configure a separate LDT, will I be able to make system calls in LDT?


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 12:17 pm 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1071
The LDT is obselete. Use address spaces with paging instead.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 12:29 pm 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 300
PeterX wrote:
Like this:

Code:
;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:



I wrote this code:
Code:
global gdt
start:
  cli
  mov esp, stack_top
  push ebx
  push eax

  jmp load_gdt

  gdt:
  ;global descriptor table (kernel)
  gdt_kernel:

  gdt_null:
  dq 0

  gdt_kernel_code:
  ;Kernel Space code (Offset: 0x8 bytes)
   dw 0FFFFh          ;limit low
   dw 0                 ;base low
   db 0                 ;base middle
   db 10011010b      ;access - Notice that bits 5 and 6 (privilege level) are 0 for Ring 0
   db 11001111b      ;granularity
   db 0               ;base high

  gdt_kernel_data:
  ;Kernel Space data (Offset: 16 (0x10) bytes
   dw 0FFFFh          ;limit low
   dw 0                 ;base low
   db 0                 ;base middle
   db 10010010b       ;access - Notice that bits 5 and 6 (privilege level) are 0 for Ring 0
   db 11001111b       ;granularity
   db 0                ;base high
  gdt_kernel_end:

  gdt_userspace:
  gdt_userspace_code:
  ;User Space code (Offset: 24 (0x18) bytes)
   dw 0FFFFh          ;limit low
   dw 0                 ;base low
   db 0                 ;base middle
   db 11111010b      ;access - Notice that bits 5 and 6 (privilege level) are 11b for Ring 3
   db 11001111b       ;granularity
   db 0                 ;base high
gdt_userspace_data:
  ;User Space data (Offset: 32 (0x20) bytes
   dw 0FFFFh          ;limit low (Same as code)10:56 AM 7/8/2007
   dw 0                 ;base low
   db 0                 ;base middle
   db 11110010b       ;access - Notice that bits 5 and 6 (privilege level) are 11b for Ring 3
   db 11001111b       ;granularity
   db 0                ;base high
  gdt_userspace_end:
  gdt_end:

  gdt_kernel_desc:
  dw gdt_kernel_end - gdt_kernel - 1
  dd gdt_kernel

  load_gdt:
  lgdt [gdt_kernel_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


By default, I load GDT only for the kernel (see load_gdt:).

When I want to run a userland task, I will need to load gdt_userland.
Is that right?


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 1:24 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
mrjbom wrote:
By default, I load GDT only for the kernel (see load_gdt:).

When I want to run a userland task, I will need to load gdt_userland.
Is that right?
You load kernel segments. The GDT stays the same. Before you switch to user mode, load user segments into DS, ES, FS, and GS (though I do not know the significance of user data segments). SS and CS are set by the IRET into user space. You should probably put the code to switch segments into the code that enters and leaves the kernel, i.e. the interrupt/syscall code.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 1:34 pm 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
mrjbom wrote:
When I want to run a userland task, I will need to load gdt_userland.
Is that right?

Your code looks right for me. (Though I haven't checked every GDT bit.)

Yes, you need to get gdt_userland's offset (0x18 and 0x20) into CS and DS.

Someone wrote in this forum that you need to apply a trick to get into ring 3. Unfortunately I can't find that thread.

@nexos: Are you sure LDT is obsolete?

Greetings
Peter


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 2:02 pm 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 300
PeterX wrote:
mrjbom wrote:
When I want to run a userland task, I will need to load gdt_userland.
Is that right?

Your code looks right for me. (Though I haven't checked every GDT bit.)

If you want to use this code, check the bits, and if you find an error, please write me.
I'm not quite sure about the bits.

Thank you so much for your help.
I will try to read something to solve my problem(get to Ring 3 and back).


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 2:36 pm 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
I found this:
https://wiki.osdev.org/Getting_to_Ring_3
viewtopic.php?f=15&t=35195


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Sun Jul 05, 2020 4:48 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5144
nullplan wrote:
Before you switch to user mode, load user segments into DS, ES, FS, and GS (though I do not know the significance of user data segments).

IRET will set DS/ES/FS/GS to the null segment if you don't load them with user segments. FS and GS are typically used as pointers to per-thread data; the details depend on the ABI.

PeterX wrote:
Are you sure LDT is obsolete?

I'm sure. There's usually only one per-thread descriptor that needs to be updated, so it's faster to have the per-thread descriptor in the (per-CPU) GDT and update it there instead of dealing with a LDT.


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Mon Jul 06, 2020 5:42 am 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1071
In my OS, I ignore segmentation as much as possible. I have 5 segments in the GDT, which are kernel code, kernel data, user code, user data (which are flat segements), and one TSS. The LDT has been obsolete for 35 years now (since the release of the 386 and paging). Modern compiler are not aware of segmentation. I love OS development, but there is one word that makes me cringe, and it is segmentation.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Mon Jul 06, 2020 8:01 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
nexos wrote:
I have 5 segments in the GDT, which are kernel code, kernel data, user code, user data (which are flat segements), and one TSS.
If I were you, I would add an FS and GS segment, switching out the base address when switching tasks, and provide a syscall to set at least the base address (limit isn't really needed). This allows user space to implement a very cheap thread pointer. In 64-bit mode, the actual FS and GS selector doesn't matter, either, there you have FS and GS base as MSR. Actually, you could probably just set FS and GS to their respective selectors at the start, and then just reload them when switching tasks. Unlike DS and ES, FS and GS are not used normally by the C compiler, so you can just leave them whatever they were when switching to kernel mode.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Mon Jul 06, 2020 11:37 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5144
nullplan wrote:
FS and GS are not used normally by the C compiler,

They are used to implement thread-local variables, following the appropriate ABI.


Top
 Profile  
 
 Post subject: Re: Accessing GDT when using GRUB
PostPosted: Mon Jul 06, 2020 12:23 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
Octocontrabass wrote:
They are used to implement thread-local variables, following the appropriate ABI.
Yes, but that is typically not supported (and not reasonably supportable) in a kernel. You need to use special syntax for this (namely "__thread"), so if you avoid that, the code will never use FS or GS. Now, in long mode, I use GS to store the CPU pointer (pointer to CPU-local stuff), but then, I can get that pointer loaded quickly with "swapgs". Which is an option not available to the OP, since their base ISA does not include "swapgs".

However, I just realized that with the proposed scheme, they will need a CPU-local GDT, anyway, since multiple CPUs will run different processes with different FS/GS base addresses. So you might as well add a kernel data segment with a base address for CPU-local data.

_________________
Carpe diem!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 27 posts ]  Go to page Previous  1, 2

All times are UTC - 6 hours


Who is online

Users browsing this forum: darkavengr and 218 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