Global descriptor table

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.
Post Reply
Reverted
Posts: 3
Joined: Sat Feb 28, 2015 7:25 am

Global descriptor table

Post by Reverted »

Hello, I recently started to play with OS-Development. As tutorials suggested I am using GRUB multiboot to get booted kernel witch A20 line on and protected mode set on. Although I want to set my own GDT (for training). I read on wiki that extended memory starts at 0x01000000 address, and I set qemu to run with 3Gb of RAM (-m 3G switch). After GDT flush I want to use only upper memory and use only 1Gb of it (for code and data only for now). Here is my code for GDT flush (GAS synatx):

Code: Select all

.equ NULL_DESCRIPTOR,  0x0000000000000000

.equ CODE,          0x01C09A0000000000
.equ DATA,          0x01C0930000000000
.equ PLACE_HOLD1,          0x01C0930000000000
.equ PLACE_HOLD2,          0x01C09A0000000000
.section .data
     GDT:
        .quad NULL_DESCRIPTOR
        .quad CODE
        .quad DATA
        .quad PLACE_HOLD1
        .quad PLACE_HOLD2
    _GDT:
        .word 24
        .long GDT

.section .text

.global flushGDT
.type flushGDT, @function

flushGDT:
    lgdt _GDT
    xor %eax, %eax
    mov $0x10, %ax
    mov %ax, %ss
    mov %ax, %ds
    mov %ax, %gs
    mov %ax, %fs
    mov %ax, %es
    jmp $0x08 ,$leaveToKernel 
leaveToKernel:  
ret
Please don't mind PLACE_HOLD1 and PLACE_HOLD2, as name says it is just place holder for something ( probably TSS).
Problem with this code is that as soon as jump is performed CPU triple faults. I get that this is caused by trying to access invalid memory, but I do not get why RAM described in selectors is invalid. I will really appreciate your help in this matter.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Global descriptor table

Post by SpyderTL »

At first glance, I think your GDT size needs to be 23. If I remember correctly, the length should be -1...

Also, is the GDT pointer address 64-bit or 32-bit?

Edit: Also, where is this code loaded in memory? If you don't include this code's address in your code segment, you'll instantly make this code GPF, as it will no longer be available.
Last edited by SpyderTL on Mon May 18, 2015 7:29 pm, edited 1 time in total.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: Global descriptor table

Post by Octocontrabass »

Reverted wrote:but I do not get why RAM described in selectors is invalid.
The CPU doesn't know what is and is not valid RAM. Trying to access RAM that doesn't exist will not cause a CPU exception.

Your first problem is assuming that there is 1GB of contiguous RAM available. While this may be true on the emulator you have chosen, it will not be true of all hardware. (Where's the fun in writing an OS that only works in emulators?)

Let's move on to your GDT. The fault happens when you jump to the new code segment, so there is probably something wrong there. Let's check out the value you're using for your code segment.

Code: Select all

01 C 0 9A 000000 0000
Base: 0x01000000
Limit: 0x00000FFF

The obvious problem is the limit. The fault probably occurs when you jump well outside the 4KiB limit you've specified.

The less obvious problem is the base. If you don't correct the jump destination to take into account the change in base address, you'll end up jumping somewhere other than where you intended and most likely fault soon after.


(And yes, the length should be 23, not 24.)
Reverted
Posts: 3
Joined: Sat Feb 28, 2015 7:25 am

Re: Global descriptor table

Post by Reverted »

Thanks for tips. I have made some changes in GDT and a linker script to be sure that code will be present in new segment. Here is the new code descriptor:

Code: Select all

.equ CODE_P0,          0x01409A0000000000
Here is part of liker script with new section:

Code: Select all

.upper_code ALIGN(0x01000000) : ALIGN(0x01000000)
{
	*(.leaveToKernel)
}
Also I changed code by putting

Code: Select all

.section .upper_code
before

Code: Select all

.leaveToKernel
label. Problem still occurs, triple fault after jump in to new segment. I am sure that memory described in descriptor is available. I am sorry for this beginner/silly questions but I got really confused and I have no idea where i gone wrong.
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Global descriptor table

Post by kzinti »

Reverted wrote:ALIGN(0x01000000)
That can't possibly be right. Surely you meant to set the address for the section and not align on that crazy big number?
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: Global descriptor table

Post by Octocontrabass »

Code: Select all

01 4 0 9A 000000 0000
Base: 0x01000000
Limit: 0x00000000

I fail to see how a one-byte code segment will be at all useful.

There's another problem I didn't mention in my previous post: how will "ret" function? Even if you do set up the stack to point to the same location as it was previously, the address it pops off the stack won't be correct because the segment base has changed.
Post Reply