Page 2 of 2

Re: GDT reloading problem

Posted: Sun Mar 27, 2011 12:19 am
by Chandra
berkus wrote:
wilson wrote: this line permit to copy the GDT table at the adresse 0x0 here is its prototype
And the reason for doing this copy (over RM IVT) is?
That exactly is the problem.

You have copied whole GDT to address 0x00 but you didn't update the GDT Base.

Code: Select all

gdt_ptr.base = (u32_int)&gdt_entries;
Did you see it? Your gdt_ptr.base is still pointing to the initial GDT Base.
replace this with,

Code: Select all

gdt_ptr.base=0;
and that should work (IMO).

Cheers.

Re: GDT reloading problem

Posted: Sun Mar 27, 2011 7:07 pm
by wilson
I changed the gdt pointer base, but the bug remains !!
I decided to use only this instruction

Code: Select all

 asm("lgdtl (gdt_ptr)");
and everything is OK! but please tell me why do the bug come when i use this :

Code: Select all

 asm("lgdtl (gdt_ptr)");
asm("   movw $0x10, %ax   \n \
            movw %ax, %ds   \n \
            movw %ax, %es   \n \
            movw %ax, %fs   \n \
            movw %ax, %gs   \n \
            ljmp $0x08, $next   \n \
            next:      \n");

Re: GDT reloading problem

Posted: Mon Mar 28, 2011 12:20 am
by Chandra

Code: Select all

asm("lgdtl (gdt_ptr)");
asm("   movw $0x10, %ax   \n \
            movw %ax, %ds   \n \
            movw %ax, %es   \n \
            movw %ax, %fs   \n \
            movw %ax, %gs   \n \
            ljmp $0x08, $next   \n \
            next:      \n");
It is likely that the compiler is shuffling things around.
Merge these two asm statements as one, like this:

Code: Select all

__asm__ __volatile__("lgdtl (gdt_ptr)\n \
            movw $0x10, %ax   \n \
            movw %ax, %ds   \n \
            movw %ax, %es   \n \
            movw %ax, %ss   \n \     \\ You ommited this line. Looks fine in your initial post
            movw %ax, %fs   \n \
            movw %ax, %gs   \n \
            ljmp $0x08, $next   \n \
            next:      \n");
You seem to ignore both os64dev's and Combuster's advice.
Here's another source of error:

Code: Select all

void gdt_set_gate(int num, u32_int base, u32_int limite, u8_int access, u8_int gran)
{
   gdt_entries[num].base_low = (base & 0xFFFF);
   gdt_entries[num].base_middle = (base >> 16) & 0xFF;
   gdt_entries[num].base_hight = (base >> 24) & 0xFF;

   gdt_entries[num].limite_low = (limite & 0xFFFF);
   gdt_entries[num].granularity = (limite >> 16) & 0x0F;

   gdt_entries[num].granularity |= gran & 0xF0;
   gdt_entries[num].access = access;
}
It seems as if you're treating gdt_entries as an array without first declaring it as an array.
Here's the change required:

Code: Select all

struct struct_entry_gdt
{
   u16_int limite_low;
   u16_int base_low;
   u8_int base_middle;
   u8_int base_hight;
   u8_int access;
   u8_int granularity;
} __attribute__((packed));

typedef struct struct_entry_gdt gdt_entry_t[5];    // Can hold 5 entries now.

struct gdt_ptr_struct
{
   u16_int limite;
   u32_int base;
} __attribute__((packed));

typedef struct gdt_ptr_struct gdt_ptr_t;
And oh!, you don't need to copy your descriptor tables to somewhere else. If you worry about overwriting your GDT, copy it to some safe location(and not 0x0, because real mode IVT resides there). And remember to update your gdt_base.ptr to point to your new GDT location(As I said before).

Best Regards,
Chandra

Re: GDT reloading problem

Posted: Mon Mar 28, 2011 1:41 pm
by wilson
I did everything you said, but it doesn't work, I don't know why, this is the code

gdt.h

Code: Select all

#ifndef _GDT_H
#define _GDT_H

#ifndef _TYPES_H
#include <types.h>
#endif

struct gdt_entry
{
	u16_int		limite;		/* bits 0-15 (limite) */
	u16_int		base_lo;	/* bits 0_23 (base) */
	u8_int		base_mid;	
	u8_int		flags;		/* bits flags */
	u8_int		gran;		/* bits granularite */
	u8_int		base_hi;	/* bits 24_32 (base) */
}__attribute__((packed));

typedef struct gdt_entry gdt_entry_t;


struct gdt_ptr
{
	u16_int		lim;		/* bits 0_15 limite */
	u32_int		base;		/* bits 16_48 base */
}__attribute__((packed));

typedef struct gdt_ptr gdt_ptr_t;


#endif
gdt.c

Code: Select all

#include <sys/gdt.h>
#include <types.h>
#include <string.h>

/* définition des structures */
gdt_entry_t gdt_entries[5];		/* une GDT de 5 descriptors */
gdt_ptr_t gdt_ptr;			/* le pointeur de GDT */

extern void gdt_init();

static void set_gdt_desc(int i, u32_int base, u32_int _limite, u16_int _flags, u8_int granularite)
{
	/* la base */
	gdt_entries[i].base_lo = (base & 0xFFFF);
	gdt_entries[i].base_mid = (base >> 16) & 0xFF;
	gdt_entries[i].base_hi = (base >> 24) & 0xFF;

	/* la limite */
	gdt_entries[i].limite = (_limite & 0xFFFF);
	gdt_entries[i].gran = (_limite >> 16) & 0x0F;

	/* flags et granularité */
	gdt_entries[i].flags = _flags;
	gdt_entries[i].gran |= granularite & 0xF0;
}

void gdt_init()
{
	gdt_ptr.lim = (sizeof(gdt_entry_t) * 5) - 1;
	gdt_ptr.base = (u32_int)&gdt_entries;

	/* segment nul */
	set_gdt_desc(0, 0, 0, 0, 0);	

	/* segment code (mode noyau) */
	set_gdt_desc(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);

	/* segment de données (mode noyau) */
	set_gdt_desc(2, 0, 0xFFFFFFFF, 0x92, 0xCF);

	/* segment de code (mode utilisateur) */
	set_gdt_desc(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
	
	/* segment de données (mode utilisateur) */
	set_gdt_desc(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
	

	__asm__ __volatile__("lgdtl (gdt_ptr)\n \
            movw $0x10, %ax   \n \
            movw %ax, %ds   \n \
            movw %ax, %es   \n \
	    movw %ax, %ss   \n \
	    movw %ax, %fs   \n \
            movw %ax, %gs   \n \
            ljmp $0x08, $next   \n \
            next:      \n");
}
and the main.c

Code: Select all

#include <stdio.h>
#include <boot/header.h>
#include <sys/gdt.h>

void main(struct multiboot_info *mbi)
{
	clrscr();
	print("Welcome!\n");
	print("informations systemes :\n");
	print("-> RAM : (lower)");
	print_int((int) mbi->low_mem);
	print("ko (upper)");
	print_int((int) mbi->high_mem);
	print("ko");
	asm volatile("cli");
	gdt_init();
	print("GDT initialise !\n");
	while(1);
}
and the screenshot

Re: GDT reloading problem

Posted: Mon Mar 28, 2011 5:59 pm
by wilson
I just tried to boot with bochs, because i was using qemu, and when I boot with bochs, then it reboots and display this

Code: Select all

SEG selector     base    limit G D
00448214464i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00448214464i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00448214464i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00448214464i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00448214464i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00448214464i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00448214464i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00448214464i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00448214464i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00448214464i[CPU0 ] | RIP=0000000000100641 (0000000000100641)
00448214464i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00448214464i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00448214464i[CPU0 ] 0x0000000000100641>> mov ds, ax : 8ED8
00448214464e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting

Re: GDT reloading problem

Posted: Mon Mar 28, 2011 10:09 pm
by Chandra
From what I see in Bochs dump, your GDT is setup properly. I think, somehow the return is messed.
Just place hlt after

Code: Select all

.....
ljmp $0x08, $next   \n \
next:      \n\
cli          \n\           // Disable interrupts to clear the interrupt flag
hlt       \n");            // to be placed
and see if Bochs reports hlt intruction (Warning: HLT instruction with IF=0!) or not. If it does, things will be interesting.

Edit: Found it!
00448214464i[CPU0 ] 0x0000000000100641>> mov ds, ax : 8ED8
00448214464e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
The exception is fired, as soon as you setup the segment registers. This is causing Triple Fault which in turn is causing Bochs to reboot.
One workaround might be to start you main(..) function with gdt_init(); If it doesn't help, basically you've two options:
1. Export whole the Segment setup stuff to the assembly file and later link the binary with the kernel.
2. Rely on someone more accustomed with such situtations.

Cheers.

Re: GDT reloading problem

Posted: Tue Mar 29, 2011 3:17 pm
by wilson
I did like you said, the gdt setup in another assembly file, but the bug stills. this is the assembly code

Code: Select all

global init_gdt

init_gdt:
	cli	
	lgdt [gdt_ptr]
	jmp 0x08:pmode

pmode:
	mov ax, 0x10
	mov ds, ax
	mov ss, ax
	mov es, ax
	mov gs, ax
	mov fs, ax	
	

gdt_start:

null_seg:
	dd 0
	dd 0

code_seg:
	dw 0xffff
	dw 0
	db 0
	db 10011010b
	db 11001111b
	db 0

data_seg:
	dw 0xffff
	dw 0
	db 0
	db 10010010b
	db 11001111b
	db 0

gdt_end:

gdt_ptr:
	dw gdt_end - gdt_start -1
	dd gdt_start

if I use only the lgdt [gdt_ptr], is it a not correct ? I ask this because, when I use this, the code execute itself correctly and there is no bug or triple failt.

Re: GDT reloading problem

Posted: Tue Mar 29, 2011 8:13 pm
by Chandra
wilson wrote: if I use only the lgdt [gdt_ptr], is it a not correct ?

Since you are using GRUB, you never know how your GDT looks like. I think it's working because the segment registers are untouched which means that they carry their original values(0, in most cases). You seem to add User Code segment and User Data segment descriptors in your GDT(acc. to your previous post), so you've to overwrite the GDT anyway.
I did like you said, the gdt setup in another assembly file
Much better, actually.

Code: Select all

[Bits 32]               ; You need 32 bit code.

global init_gdt

init_gdt:
cli 
lgdt [gdt_ptr]
jmp 0x08:pmode

pmode:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov es, ax
mov gs, ax
mov fs, ax 
ret              ; You missed ret. How are you supposed to return to the calling procedure?


gdt_start:

null_seg:
dd 0
dd 0

code_seg:
dw 0xffff
dw 0
db 0
db 10011010b
db 11001111b
db 0

data_seg:
dw 0xffff
dw 0
db 0
db 10010010b
db 11001111b
db 0

gdt_end:

gdt_ptr:
dw gdt_end - gdt_start -1
dd gdt_start

Actually, I'm trying to help you as much as I can, but somehow, the circumstances aren't in your favour. Cheers.

Re: GDT reloading problem

Posted: Wed Mar 30, 2011 5:21 pm
by wilson
circumstances are in my favour thanks to you! everything is ok! you're right I forgot the ret instruction, thank you so much !!