[C++] Gdt errors

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
Zerkan
Posts: 14
Joined: Fri Jul 26, 2013 5:46 am

[C++] Gdt errors

Post by Zerkan »

Hi everyone,

I try to develop a kernel in C++ but i am stuck since 3 days, at the beginning with the GDT load.
I can't find what is bad in this code.

Here is the header.

Code: Select all

#ifndef I386_GDT_MANAGER_HH
# define I386_GDT_MANAGER_HH

# include <stdint.h>

# define GDT_DPL_0 0x0
# define GDT_DPL_3 0x3
# define GDT_DATA_RW 0x2
# define GDT_CODE 0xA
# define GDT_NOT_SYSTEM 0x1

# define KERNEL_CODE 1
# define KERNEL_DATA 2
# define USER_CODE 3
# define USER_DATA 4

namespace memory
{
    class GdtManager
    {
        struct __entry
        {
            uint64_t    seg_lim_015 : 16,
                        base_add_015 : 16,
                        base_add_1623 : 8,
                        type : 4,
                        descriptor : 1,
                        dpl : 2,
                        present : 1,
                        seg_limit_1619 : 4,
                        avl : 1,
                        l : 1,
                        granularity : 1,
                        op_size : 1,
                        base_add_2431 : 8;
        } __attribute__ ((__packed__));

        public:
            struct gdtr_register
            {
                uint16_t limit;
                uint32_t base;
            }__attribute__ ((__packed__));

            GdtManager();

            void load_gdt();

        private:
            void __setup_entries();
            void __setup_entry(uint8_t entry_num, uint32_t limit,
                               uint32_t base, uint8_t type, uint8_t desc,
                               uint8_t dpl);

        private:
            __entry gdt_entries_[3];
    };
} // namespace memory

extern "C" void __asm__load_gdt(memory::GdtManager::gdtr_register*);

extern memory::GdtManager gdt;

#endif /* !I386_GDT_MANAGER_HH */
And here is the code:

Code: Select all

#include <arch/memory/gdt-manager.hh>

namespace memory
{
    GdtManager::GdtManager()
    {}

    void GdtManager::load_gdt()
    {
        __setup_entries();

        gdtr_register reg;

        reg.limit = sizeof(__entry) * 3 - 1;
        reg.base = (uint32_t)&gdt_entries_;

        __asm__load_gdt(&reg);
    }

    void GdtManager::__setup_entries()
    {
        __setup_entry(0, 0x0, 0x0, 0x0, 0x0, 0x0);
        __setup_entry(KERNEL_CODE, 0x0, 0xFFFFFFFF,
                      GDT_CODE, GDT_NOT_SYSTEM, GDT_DPL_0);
        __setup_entry(KERNEL_DATA, 0x0, 0xFFFFFFFF,
                      GDT_DATA_RW, GDT_NOT_SYSTEM, GDT_DPL_0);
    }

    void GdtManager::__setup_entry(uint8_t entry_num,
                                   uint32_t limit,
                                   uint32_t base,
                                   uint8_t type,
                                   uint8_t desc,
                                   uint8_t dpl)
    {
        gdt_entries_[entry_num].seg_lim_015 = limit & 0xFFFF;
        gdt_entries_[entry_num].seg_limit_1619 = (limit >> 16);
        gdt_entries_[entry_num].base_add_015 = base & 0xFFFF;
        gdt_entries_[entry_num].base_add_1623 = (base >> 16) & 0xFF;
        gdt_entries_[entry_num].base_add_2431 = (base >> 24) & 0xFF;
        gdt_entries_[entry_num].type = type & 0xF;
        gdt_entries_[entry_num].descriptor = desc & 0x1;
        gdt_entries_[entry_num].dpl = dpl & 0x3;
        gdt_entries_[entry_num].present = 1;
        gdt_entries_[entry_num].avl = 0;
        gdt_entries_[entry_num].l = 0;
        gdt_entries_[entry_num].granularity = 1;
        gdt_entries_[entry_num].op_size = 1;
    }
} // namespace memory
And here is the asm code of __asm__load_gdt function

Code: Select all

global __asm__load_gdt

__asm__load_gdt:
    push ebp
    mov ebp, esp
    mov ebx, [esp + 8]
    lgdt [ebx]
    mov eax, cr0
    or ax, 1
    mov cr0, eax
    mov eax, 0x10
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    jmp 0x08:p_mode

p_mode:
    pop ebp
    ret
Thanks
Last edited by Zerkan on Fri Jul 26, 2013 10:12 am, edited 1 time in total.
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: [C++] Gdt errors

Post by thepowersgang »

A short read does not show anything too strange... but:
1. How does this fail?
2. Have you tried the Bochs debugger's 'info gdt' command?
3. Are you sure the __entry structure is correct (bit field order is implementation defined)
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Zerkan
Posts: 14
Joined: Fri Jul 26, 2013 5:46 am

Re: [C++] Gdt errors

Post by Zerkan »

1) On both qemu and bochs the emulator reboot
2) bochs output strange gdt where I don't know my code could set up this
00042195377e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00042195377e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00042195377i[CPU0 ] CPU is in protected mode (active)
00042195377i[CPU0 ] CS.mode = 32 bit
00042195377i[CPU0 ] SS.mode = 32 bit
00042195377i[CPU0 ] EFER = 0x00000000
00042195377i[CPU0 ] | EAX=00000010 EBX=01feffa2 ECX=ffffffc0 EDX=00000008
00042195377i[CPU0 ] | ESP=01feff80 EBP=01feff80 ESI=00000000 EDI=00000000
00042195377i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00042195377i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00042195377i[CPU0 ] | CS:0020( 0004| 0| 0) 00000000 ffffffff 1 1
00042195377i[CPU0 ] | DS:0010( 0002| 0| 0) ffffffff 00000fff 1 1
00042195377i[CPU0 ] | SS:0010( 0002| 0| 0) ffffffff 00000fff 1 1
00042195377i[CPU0 ] | ES:0010( 0002| 0| 0) ffffffff 00000fff 1 1
00042195377i[CPU0 ] | FS:0010( 0002| 0| 0) ffffffff 00000fff 1 1
00042195377i[CPU0 ] | GS:0010( 0002| 0| 0) ffffffff 00000fff 1 1
00042195377i[CPU0 ] | EIP=00100583 (00100583)
00042195377i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
00042195377i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00042195377i[CPU0 ] 0x00100583>> jmp far 0008:0010058a : EA8A0510000800
00042195377e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
3) I rechecked the __entry thousands of times. I did not precise but i am working on intel 32bit i386
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: [C++] Gdt errors

Post by bluemoon »

Code: Select all

reg.base = (uint32_t)&gdt_entries_;
gdt_entries_ is an array, without an index it already meant the starting address.
Are you sure you want the & operator there?
Zerkan
Posts: 14
Joined: Fri Jul 26, 2013 5:46 am

Re: [C++] Gdt errors

Post by Zerkan »

Hum I tried so much things that I forgot to delete this "&", but with or without it the kernel still crash :(
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: [C++] Gdt errors

Post by dozniak »

You haven't posted your __asm__load_gdt function.
Learn to read.
Zerkan
Posts: 14
Joined: Fri Jul 26, 2013 5:46 am

Re: [C++] Gdt errors

Post by Zerkan »

Exact here it is (I will also put it in the main post)

Code: Select all

global __asm__load_gdt

__asm__load_gdt:
    push ebp
    mov ebp, esp
    mov ebx, [esp + 8]
    lgdt [ebx]
    mov eax, cr0
    or ax, 1
    mov cr0, eax
    mov eax, 0x10
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    jmp 0x08:p_mode

p_mode:
    pop ebp
    ret
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: [C++] Gdt errors

Post by HugeCode »

__setup_entry(KERNEL_CODE, 0x0, 0xFFFFFFFF, GDT_CODE, GDT_NOT_SYSTEM, GDT_DPL_0);

Code: Select all

 void GdtManager::__setup_entry(uint8_t entry_num,
                                   uint32_t limit,
                                   uint32_t base,
                                   uint8_t type,
                                   uint8_t desc,
                                   uint8_t dpl)
    {
Are you sure you want limit 0 and base 0xFFFFFFFF?
Zerkan
Posts: 14
Joined: Fri Jul 26, 2013 5:46 am

Re: [C++] Gdt errors

Post by Zerkan »

Like i said I tried thousands of things. I have 0xFFFFF which covered the max 4GB we can have on a 32 bits system.

By the way bochs with 0xFFFFF print a very wired GDT
00039338593i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00039338593i[CPU0 ] | CS:0020( 0004| 0| 0) 00000000 ffffffff 1 1
00039338593i[CPU0 ] | DS:0010( 0002| 0| 0) 000fffff 00000fff 1 1
00039338593i[CPU0 ] | SS:0010( 0002| 0| 0) 000fffff 00000fff 1 1
00039338593i[CPU0 ] | ES:0010( 0002| 0| 0) 000fffff 00000fff 1 1
00039338593i[CPU0 ] | FS:0010( 0002| 0| 0) 000fffff 00000fff 1 1
00039338593i[CPU0 ] | GS:0010( 0002| 0| 0) 000fffff 00000fff 1 1
It sounds like a part of the limit is considered as the base but I can't see where this bug can occured
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: [C++] Gdt errors

Post by HugeCode »

HugeCode wrote:Are you sure you want limit 0 and base 0xFFFFFFFF?
Zerkan
Posts: 14
Joined: Fri Jul 26, 2013 5:46 am

Re: [C++] Gdt errors

Post by Zerkan »

I did not understand your question...

I am such an idiot thank you very much... Such an idiot bug. Days of debugging just because I don't know how to read my own prototypes.
Anyway thank you very much!
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: [C++] Gdt errors

Post by HugeCode »

Try passing 0x0 for base and 0xFFFFFFFF for limit.
Post Reply