#ifndef _KERNEL_ARCH_X86_32_DESCRIPTORS_H
#define _KERNEL_ARCH_X86_32_DESCRIPTORS_H
#define KERNEL_CODE_SEGMENT 1
#define KERNEL_DATA_SEGMENT 2
#define USER_CODE_SEGMENT 3
#define USER_DATA_SEGMENT 4
#define BOOT_GDT_SEGMENT_COUNT (USER_DATA_SEGMENT + 2)
#define APM_CODE32_SEGMENT 5
#define APM_CODE16_SEGMENT 6
#define APM_DATA_SEGMENT 7
#define BIOS_DATA_SEGMENT 8
#define TSS_SEGMENT 9
#define DOUBLE_FAULT_TSS_SEGMENT 10
#define KERNEL_TLS_SEGMENT 11
#define USER_TLS_SEGMENT 12
#define APM_SEGMENT 13
#define GDT_SEGMENT_COUNT 14
#define KERNEL_CODE_SELECTOR ((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL)
#define KERNEL_DATA_SELECTOR ((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL)
#define USER_CODE_SELECTOR ((USER_CODE_SEGMENT << 3) | DPL_USER)
#define USER_DATA_SELECTOR ((USER_DATA_SEGMENT << 3) | DPL_USER)
#define KERNEL_TLS_SELECTOR ((KERNEL_TLS_SEGMENT << 3) | DPL_KERNEL)
#ifndef _ASSEMBLER
struct segment_descriptor {
uint16 limit_00_15;
uint16 base_00_15;
uint32 base_23_16 : 8;
uint32 type : 4;
uint32 desc_type : 1;
uint32 privilege_level : 2;
uint32 present : 1;
uint32 limit_19_16 : 4;
uint32 available : 1;
uint32 zero : 1;
uint32 d_b : 1;
uint32 granularity : 1;
uint32 base_31_24 : 8;
};
struct interrupt_descriptor {
uint32 a;
uint32 b;
};
struct tss {
uint16 prev_task;
uint16 unused0;
uint32 sp0;
uint32 ss0;
uint32 sp1;
uint32 ss1;
uint32 sp2;
uint32 ss2;
uint32 cr3;
uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
uint32 es, cs, ss, ds, fs, gs;
uint32 ldt_seg_selector;
uint16 unused1;
uint16 io_map_base;
};
typedef segment_descriptor global_descriptor_table[GDT_SEGMENT_COUNT];
extern global_descriptor_table gGDTs[];
static inline void
clear_segment_descriptor(segment_descriptor* desc)
{
*(long long*)desc = 0;
}
static inline void
set_segment_descriptor_base(segment_descriptor* desc, addr_t base)
{
desc->base_00_15 = (addr_t)base & 0xffff;
desc->base_23_16 = ((addr_t)base >> 16) & 0xff;
desc->base_31_24 = ((addr_t)base >> 24) & 0xff;
}
static inline void
set_segment_descriptor(segment_descriptor* desc, addr_t base, uint32 limit,
uint8 type, uint8 privilegeLevel)
{
set_segment_descriptor_base(desc, base);
if (limit & 0xfff00000) {
desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff;
desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf;
desc->granularity = 1;
} else {
desc->limit_00_15 = (addr_t)limit & 0x0ffff;
desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf;
desc->granularity = 0;
}
desc->type = type;
desc->desc_type = DT_CODE_DATA_SEGMENT;
desc->privilege_level = privilegeLevel;
desc->present = 1;
desc->available = 0;
desc->d_b = 1;
desc->zero = 0;
}
static inline void
set_tss_descriptor(segment_descriptor* desc, addr_t base, uint32 limit)
{
set_segment_descriptor_base(desc, base);
desc->limit_00_15 = (addr_t)limit & 0x0ffff;
desc->limit_19_16 = 0;
desc->type = DT_TSS;
desc->desc_type = DT_SYSTEM_SEGMENT;
desc->privilege_level = DPL_KERNEL;
desc->present = 1;
desc->granularity = 0;
desc->available = 0;
desc->d_b = 0;
desc->zero = 0;
}
static inline segment_descriptor*
get_gdt(int32 cpu)
{
return gGDTs[cpu];
}
#endif
#endif