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 */
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(®);
}
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
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