Page 1 of 2
Global Descriptor Table Issues
Posted: Thu Jan 21, 2010 5:09 pm
by cjhawley
Hi,
I have been holding back to ask this question for about a week trying to figure out what is going on by my self, but, no luck.
I am following the JamesM tutorial on kernels and have gotten stuck at flushing the old GDT loaded by grub out and replacing it with my new one.
This is not working however and I do not know why.
Code: Select all
gdt_flush2:
lgdt [gdt_ptr_struct] //get the structure from C
mov ax, 0x10 //offset to data
mov ds, ax //load segment selector
mov es, ax //load segment selector
mov fs, ax //load segment selector
mov gs, ax //load segment selector
mov ss, ax //load segment selector
jmp 0x08:flush2 //will cause cs to be loaded as well
flush2:
ret //back to C
I have tried returning to my C code at different places to see where things are going wrong and it is right after mov ax, 0x10 and before mov ds, ax.
Any help would be appreciated.
Here is a bochs dump:
Code: Select all
00209657525i[CPU0 ] CS.d_b = 16 bit
00209657525i[CPU0 ] SS.d_b = 16 bit
00209657525i[CPU0 ] EFER = 0x00000000
00209657525i[CPU0 ] | RAX=0000000000000000 RBX=0000000000000000
00209657525i[CPU0 ] | RCX=000000000009e080 RDX=0000000000000014
00209657525i[CPU0 ] | RSP=000000000000ff98 RBP=000000000000ffb0
00209657525i[CPU0 ] | RSI=00000000000e472c RDI=000000000000ffac
00209657525i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00209657525i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00209657525i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00209657525i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00209657525i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df IF tf SF zf AF PF CF
00209657525i[CPU0 ] | SEG selector base limit G D
00209657525i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00209657525i[CPU0 ] | CS:f000( 0004| 0| 0) 000f0000 0000ffff 0 0
00209657525i[CPU0 ] | DS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00209657525i[CPU0 ] | SS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00209657525i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00209657525i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00209657525i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00209657525i[CPU0 ] | MSR_FS_BASE:0000000000000000
00209657525i[CPU0 ] | MSR_GS_BASE:0000000000000000
00209657525i[CPU0 ] | RIP=000000000000fea6 (000000000000fea6)
00209657525i[CPU0 ] | CR0=0x60000010 CR2=0x0000000000000000
00209657525i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00209657525i[CPU0 ] 0x000000000000fea6>> push eax : 6650
Re: Global Descriptor Table Issues
Posted: Thu Jan 21, 2010 7:32 pm
by thepowersgang
Well, instead of doing a ret, I would suggest using the bochs magic breakpoint (xchg bx,bx)
Either that, or explicitly setting one in the debugger.
Also, are you actually in protected mode when you are running this code? The bochs register dump seems to say that the current segment values have a limit of 16K (also cs.d_b should be 32-bit in PMode)
Re: Global Descriptor Table Issues
Posted: Thu Jan 21, 2010 7:42 pm
by cjhawley
Yes, I am in protected mode. I have been pretty much following along with the tutorial, but with that being said, I have been spending a good deal of time creating standard functions (Sort of my reason to go into OS Dev...Lame reason, I know).
Re: Global Descriptor Table Issues
Posted: Thu Jan 21, 2010 8:43 pm
by thepowersgang
so, why is that bochs dump saying you're in real mode (heck 66 50 == push AX in PMode)
Could you make sure that the dump is from the correct place, and I also suggest putting in some magic breaks and then single-stepping until it crashes.
Re: Global Descriptor Table Issues
Posted: Thu Jan 21, 2010 9:00 pm
by neon
His bochs log is probably right after a triple fault. cs:eip seems to indicate its in the BIOS. cr0.pm bit is 0 so its a clear indication that you are in real mode at the time you took the bochs log. Please repost it.
Re: Global Descriptor Table Issues
Posted: Thu Jan 21, 2010 9:20 pm
by cjhawley
Apologies,
Code: Select all
Booting from 0000:7c00
00051033458i[BIOS ] int13_harddisk: function 41, unmapped device for ELDL=80
00051038235i[BIOS ] int13_harddisk: function 08, unmapped device for ELDL=80
00051042888i[BIOS ] *** int 15h function AX=00c0, BX=0000 not yet supported!
00056846830e[CPU0 ] load_seg_reg(DS, 0x0010): invalid segment
00056846830e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00056846830e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00056846830i[CPU0 ] CPU is in protected mode (active)
00056846830i[CPU0 ] CS.d_b = 32 bit
00056846830i[CPU0 ] SS.d_b = 32 bit
00056846830i[CPU0 ] EFER = 0x00000000
00056846830i[CPU0 ] | RAX=0000000000000010 RBX=000000000002d000
00056846830i[CPU0 ] | RCX=0000000000000002 RDX=00000000000003d5
00056846830i[CPU0 ] | RSP=0000000000067e7c RBP=0000000000067ea8
00056846830i[CPU0 ] | RSI=0000000000053c99 RDI=0000000000053c9a
00056846830i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00056846830i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00056846830i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00056846830i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00056846830i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf ZF af PF cf
00056846830i[CPU0 ] | SEG selector base limit G D
00056846830i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00056846830i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
00056846830i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00056846830i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00056846830i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00056846830i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00056846830i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00056846830i[CPU0 ] | MSR_FS_BASE:0000000000000000
00056846830i[CPU0 ] | MSR_GS_BASE:0000000000000000
00056846830i[CPU0 ] | RIP=000000000010002b (000000000010002b)
00056846830i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00056846830i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00056846830i[CPU0 ] 0x000000000010002b>> mov ds, ax : 8ED8
00056846830e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
EDIT: nasm 2.05.01, ld 2.20, gcc 4.41
Re: Global Descriptor Table Issues
Posted: Fri Jan 22, 2010 3:37 am
by thepowersgang
Ok, break into the debugger just after the LGDT and do "info gdt" and show us the result.
Re: Global Descriptor Table Issues
Posted: Fri Jan 22, 2010 6:00 pm
by cjhawley
I use GDB to debug with qemu (more simple I think) and I do not have the option 'info gdt' but here is a register dump:
Code: Select all
eax 0xe 14
ecx 0x2 2
edx 0x3d5 981
ebx 0x2d000 184320
esp 0x67e7c 0x67e7c
ebp 0x67ea8 0x67ea8
esi 0x53cb1 343217
edi 0x53cb2 343218
eip 0x100020 0x100020 <gdt_flush2>
eflags 0x46 [ PF ZF ]
cs 0x8 8
ss 0x10 16
ds 0x10 16
es 0x10 16
fs 0x10 16
gs 0x10 16
Re: Global Descriptor Table Issues
Posted: Fri Jan 22, 2010 6:18 pm
by neon
The value of GDTR might give us some info. If I was to guess id suspect that either the GDT is invalid or gdt_ptr_struct points to an invalid structure or invalid address. You can find out if its pointing to your GDTR structure by debugging. Else posting your structures and more code might help.
Re: Global Descriptor Table Issues
Posted: Fri Jan 22, 2010 6:27 pm
by cjhawley
Code: Select all
typedef struct gdt_entry gdt_entry;
struct gdt_entry {
unsigned short low_limit;
unsigned short low_base;
unsigned char middle_base;
unsigned char high_base;
unsigned char access;
unsigned char gran;
}__attribute__((packed));
typedef struct gdt_ptr gdt_ptr;
struct gdt_ptr {
unsigned short limit;
unsigned int base;
}__attribute__((packed));
gdt_entry gdt_struct[3];
gdt_ptr gdt_ptr_struct;
Code: Select all
gdt_set_gate(0,0,0,0,0);
gdt_set_gate(1,0,0,0,0);
gdt_set_gate(2,0,0,0,0);
gdt_ptr_struct.limit = (sizeof(gdt_entry) * 3) - 1;
gdt_ptr_struct.base = &gdt_struct;
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
As you can see I really am just following the tutorial.
Re: Global Descriptor Table Issues
Posted: Fri Jan 22, 2010 10:11 pm
by neon
Use Bochs and do what was suggested earlier. With Bochs debugger, break right after the ldgt and do info gdt 0 4 and post the results here.
Re: Global Descriptor Table Issues
Posted: Fri Jan 22, 2010 11:58 pm
by cjhawley
Here it is:
Code: Select all
Global Descriptor Table (base=0x00000000, limit=65535):
GDT[0x00]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x01]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x02]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x03]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x04]=32-Bit TSS (Available) at 0xf087f000, length 0x0fea5
Re: Global Descriptor Table Issues
Posted: Sat Jan 23, 2010 2:37 am
by Brendan
Hi,
cjhawley wrote:Code: Select all
Global Descriptor Table (base=0x00000000, limit=65535):
GDT[0x00]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x01]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x02]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x03]=Code segment, base=0xf053f000, limit=0x0000ff53, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x04]=32-Bit TSS (Available) at 0xf087f000, length 0x0fea5
The CPU thinks that the GDT is at 0x00000000, and the descriptor entries look like they contain values left over from the real mode IVT. Either the GDT isn't at 0x00000000 (and your "gdt_ptr" is wrong), or the GDT is meant to be at 0x00000000 but you forgot to copy or create the GDT at this address.
Cheers,
Brendan
Re: Global Descriptor Table Issues
Posted: Sat Jan 23, 2010 7:36 am
by computafreak
Are you passing a pointer to the GDT? If you're just passing the GDT itself, LGDT will load the null descriptor as if it's an address. My assembly stub does pretty much the same as yours and I call it like so:
Re: Global Descriptor Table Issues
Posted: Sat Jan 23, 2010 1:50 pm
by cjhawley
Yes, that is how I am calling it now.
Code: Select all
gdt_flush2((unsigned int)&gdt_ptr_struct);
I changed my asm code to grab the parameter.
I also moved my instantiation of my pointer and my gdt structure into the gdt C file instead of keeping them in my header file.
It now crashes at the mov ss, ax
Huh, cool.