Page 1 of 1
Reload GDT + reboot
Posted: Sat Mar 03, 2012 6:37 am
by rubymonk
Hello,
I can't figure out why...
My kernel is loaded by grub, so naturally, the first thing I want to do is to reload the gdt.
reloading the GDT goes well, by something is certainly messed up since when the line
Code: Select all
jmp dword 0x8:jmp_code_segment ; reinit code seg
is run, the system reboots (triple fault?).
Any insights/criticism please?
Thank you.
Code: Select all
[BITS 32]
[SECTION .text]
GLOBAL kmain
kmain:
;Init gdt pointer
mov eax, gdtend ; calc of GDT size
mov ebx, gdt
sub eax, ebx
mov word [gdtptr], ax
xor eax, eax ; calc linear address of GDT
xor ebx, ebx
mov ax, ds
mov ecx, eax
shl ecx, 4
mov ebx, gdt
add ecx, ebx
mov dword [gdtptr+2], ecx
lgdt [gdtptr] ; load GDT
jmp dword 0x8:jmp_code_segment ; reinit code seg
jmp_code_segment:
xor eax, eax
mov ax,0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp,8000h
end:
jmp end
;--------------------------------------------------------------------
gdt:
db 0, 0, 0, 0, 0, 0, 0, 0
gdt_cs:
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
gdt_ds:
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
gdtend:
;--------------------------------------------------------------------
gdtptr:
dw 0 ; limit
dd 0 ; base
;--------------------------------------------------------------------
Re: Reload GDT + reboot
Posted: Sat Mar 03, 2012 6:45 am
by bluemoon
You don't have ORG, do you have linker script that specify the base address of your labels?
Re: Reload GDT + reboot
Posted: Sat Mar 03, 2012 6:48 am
by rubymonk
Sorry, yes:
Code: Select all
ENTRY(start)
SECTIONS
{
.text 0x100000 :
{
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data :
{
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
Re: Reload GDT + reboot
Posted: Sat Mar 03, 2012 9:30 am
by bluemoon
As a general advice. Get bochs to work. It's much easier to deal with such issues with a debugger-enabled emulator.
Re: Reload GDT + reboot
Posted: Sat Mar 03, 2012 9:52 am
by lemonyii
what a mess is your code!
1st, GDT.Limit will be GDT.Len-1, but you didn't;
2nd, GRUB load a system with DS as a GDT selector (hope i'm not wrong), whose base is 0 and limit is 4G-1, so you don't need to add (DS<<4) to your GDT.Base.
3rd, as metioned upstairs, check ORG and linkscript;
4th, make sure 0x8 is right for your GDT.CodeSeg;
5th, ensure your GDT is aligned to maybe 4 byte edge, i don't know if this is necessarily.
i may have made mistakes for i haven't work with such things for long. figure it out if you find any.
Re: Reload GDT + reboot
Posted: Sat Mar 03, 2012 10:54 am
by rubymonk
Hello and thanks for your answers.
bluemoon:
I have trouble with bochs.
I connected gdb to qemu but whichever one I use (emulator), debugging a code that keeps rebooting....
Quick question, using -g option in nasm allows to set breakpoints on assembly labels or is there something else to do?
lemonyii:
My code is a mess? okay, what do you call messy and how can I arrange this? Any tip?
Thank you.
1) GDTLen-1, ok corrected.
2) Commented shl line, ok.
3) This ld script comes from James website, I just am not sure how he came with 0x10000 in the first place, ain't that a standard grub place for the kernel to be loaded by grub?
4) Yes, 0x8 should be the right for CS as it's the second entry in the GDT, so starting at the 9th byte.
5) 4 bytes alignment doesn't seem required it's only for performance as far I get it, before trying to troubleshoot this, I had an ALIGN 4 but I removed.
Thanks to the both of you.
Re: Reload GDT + reboot
Posted: Sat Mar 03, 2012 12:34 pm
by bluemoon
rubymonk wrote:Quick question, using -g option in nasm allows to set breakpoints on assembly labels or is there something else to do?
I'm using QEmu too, so that's fine. To make use of gdb with qemu:
1. you compile/assemble with -g flag
2. create a symbol file, something like @$(OBJCOPY) --only-keep-debug kernel.bin kernel.sym
3. start qemu with -s -S (enable gdb, and suspend when start)
4. open up another terminal and launch gdb with something like:
Code: Select all
i586-elf-gdb \
--directory=kernel/ --symbols=../usr/bin/kernel.sym \
--eval-command="set disassembly-flavor intel" \
--eval-command="set history save on" \
--eval-command="target remote localhost:1234"
As lemonyii pointed out, we guess that you boot using grub multiboot mechanism, which puts the computer into 32-bit protected mode.
So you don't calculate the linear address with DS<<4 as DS is a protected mode selector, maybe 0x10 in value.
Re: Reload GDT + reboot
Posted: Sun Mar 04, 2012 12:49 pm
by rubymonk
Fixed, thank you, it was about the way I was calculating the GDT address.
Thanks
Re: Reload GDT + reboot
Posted: Mon Mar 05, 2012 11:37 am
by evoex
rubymonk wrote:5) 4 bytes alignment doesn't seem required it's only for performance as far I get it, before trying to troubleshoot this, I had an ALIGN 4 but I removed.
I don't think this is true. It certainly sometimes is, and sometimes isn't: aligned operations are only better performance wise, while page tables must actually be page-aligned. I'm quite sure the GDT MUST be dword aligned, though to be fair the only source I have regarding that is having read it somewhere.
Re: Reload GDT + reboot
Posted: Mon Mar 05, 2012 11:48 am
by bluemoon
Always read the manual:
3.5.1 Segment Descriptor Tables
The GDT is not a segment itself; instead, it is a data structure in linear address space. The base linear address and limit of the GDT must be loaded into the GDTR register (see Section 2.4, “Memory-Management Registers”). The base addresses of the GDT should be aligned on an eight-byte boundary to yield the best processor performance. The limit value for the GDT is expressed in bytes.
When it say should, it actually mean must, or your code may break someday.
Re: Reload GDT + reboot
Posted: Mon Mar 05, 2012 11:49 am
by Combuster
Actually, it's explicitly allowed:
AMD64 Architecture Programmers Manual wrote:The GDT can be located at any byte address in virtual memory, but system software
should align the GDT on a doubleword boundary to avoid the potential performance penalties
associated with accessing unaligned data.
Note that the best minimum alignment is actually on a quadword boundary to avoid crossing cache lines on a single GDT entry.
Re: Reload GDT + reboot
Posted: Mon Mar 05, 2012 3:58 pm
by rubymonk
Anyhow, thanks a lot for all those tips and info