Reload GDT + reboot

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
rubymonk
Posts: 14
Joined: Sat Mar 03, 2012 6:31 am

Reload GDT + reboot

Post 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
;--------------------------------------------------------------------
Last edited by rubymonk on Sat Mar 03, 2012 6:46 am, edited 1 time in total.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Reload GDT + reboot

Post by bluemoon »

You don't have ORG, do you have linker script that specify the base address of your labels?
rubymonk
Posts: 14
Joined: Sat Mar 03, 2012 6:31 am

Re: Reload GDT + reboot

Post 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 = .;
}
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Reload GDT + reboot

Post by bluemoon »

As a general advice. Get bochs to work. It's much easier to deal with such issues with a debugger-enabled emulator.
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: Reload GDT + reboot

Post 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.
Enjoy my life!------A fish with a tattooed retina
rubymonk
Posts: 14
Joined: Sat Mar 03, 2012 6:31 am

Re: Reload GDT + reboot

Post 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.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Reload GDT + reboot

Post 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.
rubymonk
Posts: 14
Joined: Sat Mar 03, 2012 6:31 am

Re: Reload GDT + reboot

Post by rubymonk »

Fixed, thank you, it was about the way I was calculating the GDT address.
Thanks
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Re: Reload GDT + reboot

Post 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.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Reload GDT + reboot

Post 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.
Last edited by bluemoon on Mon Mar 05, 2012 11:50 am, edited 1 time in total.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Reload GDT + reboot

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
rubymonk
Posts: 14
Joined: Sat Mar 03, 2012 6:31 am

Re: Reload GDT + reboot

Post by rubymonk »

Anyhow, thanks a lot for all those tips and info :)
Post Reply