Complete refactor of craps I wrote. Especially when constructing GDT / Page table.

Need:
1. Map page depending on current memory
2. ELF loader
This commit is contained in:
HyperAssembler 2015-02-03 23:55:38 -08:00
parent 7810a74741
commit c886d569cd
13 changed files with 218 additions and 521 deletions

View File

@ -1,6 +1,45 @@
extern hk_main
[SECTION .entry]
[BITS 32] ;on stack: multiboot_info*
; no, no interrupt please.
cli
; disable paging first
mov eax, cr0 ; Set the A-register to control register 0.
and eax, 01111111111111111111111111111111b ; Clear the PG-bit, which is bit 31.
mov cr0, eax ; Set control register 0 to the A-register.
ret
xchg bx,bx ; pure magic
; enable PAE
mov eax, cr4 ; Set the A-register to control register 4.
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
mov cr4, eax ; Set control register 4 to the A-register.
; enable x86_64
mov ecx, 0xC0000080 ; Set the C-register to 0xC0000080, which is the EFER MSR.
rdmsr ; Read from the model-specific register.
or eax, 1 << 8 ; Set the LM-bit which is the 9th bit (bit 8).
wrmsr ; Write to the model-specific register.
; let cr3 point at page table
mov eax,;page table addr
mov cr3,eax
; enable paging, enter compatibility mode
mov eax, cr0 ; Set the A-register to control register 0.
or eax, 1 << 31 ; Set the PG-bit, which is bit 31.
mov cr0, eax ; Set control register 0 to the A-register.
ret
; enter x64
lgdt [g_gdt_ptr_64]
jmp 8:entry_64
[SECTION .text]
[BITS 64]
entry_64:
cli
;hard code for now
mov ax,24

View File

@ -5,7 +5,7 @@
#include "multiboot.h"
extern uint64_t text_pos;
void HYPKERNEL64 hk_main(multiboot_info_t* multiboot_info)
void HYPKERNEL64 hk_main(void)
{
hk_clear_screen();
hk_print_str("Welcome to HYP OS. Kernel is now running in x64 mode.\n");

View File

@ -5,6 +5,10 @@
#define BOCHS_MAGIC_BREAKPOINT asm("xchg bx,bx");
#define SEG_SELECTOR(Index,RPL) (((Index) << 3) + (RPL))
#define HLT_CPU asm("hlt");
#define NULL ((void*)0)
#endif

View File

@ -1,83 +1,100 @@
#include "kdef.h"
#include "mem.h"
void HYPKERNEL64 hk_write_pml4_entry(uint8_t * const base, pml4_entry_t const * const p_entry)
void HYPKERNEL64 hk_write_pt_entry(void * const base, uint64_t const p_addr, uint64_t const attr)
{
if(base == NULL || p_entry == NULL)
if(base == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->Sz & 0x1) << 7));
base[1] = (uint8_t)(((p_entry->base >> 12) & 0xF) << 4); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
uint64_t entry = (p_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t*)base)[0] = (uint8_t)(entry & 0xFF);
((uint8_t*)base)[1] = (uint8_t)((entry >> 8) & 0xFF);
((uint8_t*)base)[2] = (uint8_t)((entry >> 16) & 0xFF);
((uint8_t*)base)[3] = (uint8_t)((entry >> 24) & 0xFF);
((uint8_t*)base)[4] = (uint8_t)((entry >> 32) & 0xFF);
((uint8_t*)base)[5] = (uint8_t)((entry >> 40) & 0xFF);
((uint8_t*)base)[6] = (uint8_t)((entry >> 48) & 0xFF);
((uint8_t*)base)[7] = (uint8_t)((entry >> 56) & 0xFF);
return;
}
void HYPKERNEL64 hk_write_pdpt_entry(uint8_t * const base, pdpt_entry_t const * const p_entry)
void HYPKERNEL64 hk_write_pd_entry(void * const base, uint64_t const pt_addr, uint64_t const attr)
{
if(base == NULL || p_entry == NULL)
if(base == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->Sz & 0x1) << 7));
base[1] = (uint8_t)(((p_entry->base >> 12) & 0xF) << 4); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
uint64_t entry = (pt_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t*)base)[0] = (uint8_t)(entry & 0xFF);
((uint8_t*)base)[1] = (uint8_t)((entry >> 8) & 0xFF);
((uint8_t*)base)[2] = (uint8_t)((entry >> 16) & 0xFF);
((uint8_t*)base)[3] = (uint8_t)((entry >> 24) & 0xFF);
((uint8_t*)base)[4] = (uint8_t)((entry >> 32) & 0xFF);
((uint8_t*)base)[5] = (uint8_t)((entry >> 40) & 0xFF);
((uint8_t*)base)[6] = (uint8_t)((entry >> 48) & 0xFF);
((uint8_t*)base)[7] = (uint8_t)((entry >> 56) & 0xFF);
return;
}
void HYPKERNEL64 hk_write_pd_entry(uint8_t * const base, pd_entry_t const * const p_entry)
void HYPKERNEL64 hk_write_pdpt_entry(void * const base, uint64_t const pd_addr, uint64_t const attr)
{
if(base == NULL || p_entry == NULL)
if(base == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->Sz & 0x1) << 7));
base[1] = (uint8_t)(((p_entry->base >> 12) & 0xF) << 4); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
uint64_t entry = (pd_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t*)base)[0] = (uint8_t)(entry & 0xFF);
((uint8_t*)base)[1] = (uint8_t)((entry >> 8) & 0xFF);
((uint8_t*)base)[2] = (uint8_t)((entry >> 16) & 0xFF);
((uint8_t*)base)[3] = (uint8_t)((entry >> 24) & 0xFF);
((uint8_t*)base)[4] = (uint8_t)((entry >> 32) & 0xFF);
((uint8_t*)base)[5] = (uint8_t)((entry >> 40) & 0xFF);
((uint8_t*)base)[6] = (uint8_t)((entry >> 48) & 0xFF);
((uint8_t*)base)[7] = (uint8_t)((entry >> 56) & 0xFF);
return;
}
void HYPKERNEL64 hk_write_pt_entry(uint8_t * const base, pt_entry_t const * const p_entry)
void HYPKERNEL64 hk_write_pml4_entry(void * const base, uint64_t const pdpt_addr, uint64_t const attr)
{
if(base == NULL || p_entry == NULL)
if(base == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->dirty & 0x1) << 6) + ((p_entry->PAT & 0x1) << 7));
base[1] = (uint8_t)((((p_entry->base >> 12) & 0xF) << 4) + (p_entry->Gl & 0x1)); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
uint64_t const entry = (pdpt_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t*)base)[0] = (uint8_t)(entry & 0xFF);
((uint8_t*)base)[1] = (uint8_t)((entry >> 8) & 0xFF);
((uint8_t*)base)[2] = (uint8_t)((entry >> 16) & 0xFF);
((uint8_t*)base)[3] = (uint8_t)((entry >> 24) & 0xFF);
((uint8_t*)base)[4] = (uint8_t)((entry >> 32) & 0xFF);
((uint8_t*)base)[5] = (uint8_t)((entry >> 40) & 0xFF);
((uint8_t*)base)[6] = (uint8_t)((entry >> 48) & 0xFF);
((uint8_t*)base)[7] = (uint8_t)((entry >> 56) & 0xFF);
return;
}
void HYPKERNEL64 hk_write_segment_descriptor(uint8_t *const gdt, segment_descriptor_t const *const seg_desc)
void HYPKERNEL64 hk_write_segment_descriptor(void * const gdt, uint32_t const base, uint32_t const limit, uint64_t const attr)
{
if (gdt == NULL || seg_desc == NULL)
return;
gdt[0] = (uint8_t)(seg_desc->limit & 0xFF);
gdt[1] = (uint8_t)((seg_desc->limit >> 8) & 0xFF);
gdt[6] = gdt[6] | (uint8_t)((seg_desc->limit >> 16) & 0xFF);
if (gdt == NULL)
return;
uint64_t const seg_desc = (((uint64_t)base & 0xFFFF) << 16) | ((((uint64_t)base >> 16) & 0xFF) << 32) | ((((uint64_t)base >> 24) & 0xFF) << 56) | ((uint64_t)limit & 0xFFFF) | ((((uint64_t)limit >> 16) & 0xF) << 48) | attr;
((uint8_t*)gdt)[0] = (uint8_t)(seg_desc & 0xFF);
((uint8_t*)gdt)[1] = (uint8_t)((seg_desc >> 8) & 0xFF);
((uint8_t*)gdt)[2] = (uint8_t)((seg_desc >> 16) & 0xFF);
((uint8_t*)gdt)[3] = (uint8_t)((seg_desc >> 24) & 0xFF);
((uint8_t*)gdt)[4] = (uint8_t)((seg_desc >> 32) & 0xFF);
((uint8_t*)gdt)[5] = (uint8_t)((seg_desc >> 40) & 0xFF);
((uint8_t*)gdt)[6] = (uint8_t)((seg_desc >> 48) & 0xFF);
((uint8_t*)gdt)[7] = (uint8_t)((seg_desc >> 56) & 0xFF);
return;
}
gdt[2] = (uint8_t)(seg_desc->base & 0xFF);
gdt[3] = (uint8_t)((seg_desc->base >> 8) & 0xFF);
gdt[4] = (uint8_t)((seg_desc->base >> 16) & 0xFF);
gdt[7] = (uint8_t)((seg_desc->base >> 24) & 0xFF);
gdt[5] = (uint8_t)((seg_desc->type & 0xF) + ((seg_desc->Sys & 0x1) << 4) + ((seg_desc->DPL & 0x3) << 5) + ((seg_desc->Pr & 0x1 ) << 7));
gdt[6] = gdt[6] | (uint8_t)(((seg_desc->Acc & 0x1) + ((seg_desc->x64 & 0x1) << 1) + ((seg_desc->Sz & 0x1) << 2) + ((seg_desc->Gr & 0x1) << 3)) << 4);
return;
void HYPKERNEL64 hk_map_page(void * const pml4_base, uint64_t const p_addr, uint64_t const v_addr, uint64_t const attr)
{
//wait a sec, we actually need maximum memory information here for effectively map crap
if(pml4_base == NULL || p_addr << 52 || v_addr << 52)
return;
//ASSUME: little endian
uint64_t const pml4_index = (v_addr >> 39) & 0x1FF;
void * const pml4_addr = (void*)((uint64_t*)pml4_base + pml4_index);
uint64_t const pml4_entry = *(uint64_t*)pml4_addr;
if(!(pml4_entry & PML4_PRESENT))
{
hk_write_pml4_entry(pml4_addr, (uint64_t)pml4_base + 512*8, PML4_PRESENT | PML4_WRITE);
}
}
void HYPKERNEL64 hk_mem_cpy(void* src, void* dst, uint64_t size)

View File

@ -3,50 +3,49 @@
#include "type.h"
#include "kdef.h"
#define PML4_PRESENT ((uint64_t)1 << 0)
#define PML4_WRITE ((uint64_t)1 << 1)
#define PML4_USER ((uint64_t)1 << 2)
#define PML4_WRITE_THROUGH ((uint64_t)1 << 3)
#define PML4_CACHE_DISABLED ((uint64_t)1 << 4)
#define PML4_ACCESSED ((uint64_t)1 << 5)
#define PML4_EXECUTION_DISABLED ((uint64_t)1 << 63)
typedef struct __attribute__ ((packed))
{
uint64_t Pr;
uint64_t RW;
uint64_t USU;
uint64_t PWT;
uint64_t PCD;
uint64_t Acc;
uint64_t Sz; //must be 0
uint64_t base; // Since 4KB-aligned, 12 bits are useless, 52(total) - 12 = 40 bits left
// will ignore the low 12 bits as well as the high 12 bits of this field
uint64_t XD;
} pml4_entry_t, pdpt_entry_t, pd_entry_t;
#define PDPT_PRESENT ((uint64_t)1 << 0)
#define PDPT_WRITE ((uint64_t)1 << 1)
#define PDPT_USER ((uint64_t)1 << 2)
#define PDPT_WRITE_THROUGH ((uint64_t)1 << 3)
#define PDPT_CACHE_DISABLED ((uint64_t)1 << 4)
#define PDPT_ACCESSED ((uint64_t)1 << 5)
#define PDPT_EXECUTION_DISABLED ((uint64_t)1 << 63)
typedef struct __attribute__ ((packed))
{
uint64_t Pr;
uint64_t RW;
uint64_t USU;
uint64_t PWT;
uint64_t PCD;
uint64_t Acc;
uint64_t dirty;
uint64_t PAT;
uint64_t Gl;
uint64_t base; // Since 4KB-aligned, 12 bits are useless, 52(total) - 12 = 40 bits left
// will ignore the low 12 bits as well as the high 12 bits of this field
uint64_t XD;
} pt_entry_t;
#define PD_PRESENT ((uint64_t)1 << 0)
#define PD_WRITE ((uint64_t)1 << 1)
#define PD_USER ((uint64_t)1 << 2)
#define PD_WRITE_THROUGH ((uint64_t)1 << 3)
#define PD_CACHE_DISABLED ((uint64_t)1 << 4)
#define PD_ACCESSED ((uint64_t)1 << 5)
#define PD_EXECUTION_DISABLED ((uint64_t)1 << 63)
typedef struct __attribute__ ((packed))
{
uint64_t base;
uint64_t limit;
uint64_t type;
uint64_t DPL;
uint64_t Gr;
uint64_t Acc;
uint64_t Pr;
uint64_t Sz; //32 bits = 1, 16 bits = 0
uint64_t x64;
uint64_t Sys; //System = 0, code/data = 1
} segment_descriptor_t;
#define PT_PRESENT ((uint64_t)1 << 0)
#define PT_WRITE ((uint64_t)1 << 1)
#define PT_USER ((uint64_t)1 << 2)
#define PT_WRITE_THROUGH ((uint64_t)1 << 3)
#define PT_CACHE_DISABLED ((uint64_t)1 << 4)
#define PT_ACCESSED ((uint64_t)1 << 5)
#define PT_DIRTY ((uint64_t)1 << 6)
#define PT_ATTRIBUTE_TABLE ((uint64_t)1 << 7)
#define PT_GLOBAL ((uint64_t)1 << 8)
#define PT_EXECUTION_DISABLED ((uint64_t)1 << 63)
#define SEG_GRANULARITY ((uint64_t)1 << 55)
#define SEG_LONG ((uint64_t)1 << 53)
#define SEG_DPL(dpl) (((uint64_t)(dpl) & 0x3) << 45)
#define SEG_PRESENT ((uint64_t)1 << 47)
#define SEG_CODE_DATA ((uint64_t)1 << 44)
#define SEG_TYPE(type) (((uint64_t)(type) & 0xF) << 40)
#define SEG_AVAILABLE ((uint64_t)1 << 52)
#define SEG_32_BITS ((uint64_t)1 << 54)
typedef struct __attribute__ ((packed))
{
@ -60,7 +59,7 @@ typedef struct __attribute__ ((packed))
uint64_t base;
} idt_ptr_t;
void HYPKERNEL64 hk_write_segment_descriptor(uint8_t *const gdt, segment_descriptor_t const *const seg_desc);
void HYPKERNEL64 hk_write_segment_descriptor(void *const gdt, uint32_t const base, uint32_t const limit, uint64_t const attr);
//extern void HYPKERNEL64 hk_load_gdt(gdt_ptr_t const *const ptr, uint16_t const sel_code, uint16_t const sel_data);
@ -70,12 +69,12 @@ void HYPKERNEL64 hk_mem_move(void *src, void *dst, uint64_t size);
void HYPKERNEL64 hk_mem_set(void *src, int8_t const val, uint64_t size);
void HYPKERNEL64 hk_write_pt_entry(uint8_t *const base, pt_entry_t const *const p_entry);
void HYPKERNEL64 hk_write_pml4_entry(void *const base, uint64_t const pdpt_addr, uint64_t const attr);
void HYPKERNEL64 hk_write_pd_entry(uint8_t *const base, pd_entry_t const *const p_entry);
void HYPKERNEL64 hk_write_pdpt_entry(void *const base, uint64_t const pd_addr, uint64_t const attr);
void HYPKERNEL64 hk_write_pdpt_entry(uint8_t *const base, pdpt_entry_t const *const p_entry);
void HYPKERNEL64 hk_write_pd_entry(void *const base, uint64_t const pt_addr, uint64_t const attr);
void HYPKERNEL64 hk_write_pml4_entry(uint8_t *const base, pml4_entry_t const *const p_entry);
void HYPKERNEL64 hk_write_pt_entry(void *const base, uint64_t const p_addr, uint64_t const attr);
#endif

View File

@ -5,6 +5,18 @@
uint64_t text_pos;
void HYPKERNEL64 hk_map_page(void * base, uint64_t const physcial_addr, uint64_t const linear_addr, uint64_t attr)
{
if(physcial_addr << 52 || linear_addr << 52)
{
return;
}
uint64_t const pml4_idx = (linear_addr >> 39) & 0x1FF; //9bits
}
uint64_t HYPKERNEL64 hk_str_len(char const * str)
{
uint32_t length = 0;

View File

@ -4,8 +4,8 @@ typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned long long uint64_t;
typedef unsigned char uint8_t;
typedef int int32_t;
typedef short int16_t;
typedef long long int64_t;
typedef signed int int32_t;
typedef signed short int16_t;
typedef signed long long int64_t;
typedef char int8_t;
#endif

View File

@ -45,37 +45,4 @@ popfd
push ebx
call hk_main
add esp,4 ; We are actually not coming back here. But out of courtesy...
[SECTION .text]
[BITS 32]
hk_entry_comp:
; no, no interrupt please.
cli
; disable paging first
call hk_disable_paging
xchg bx,bx ; pure magic
; enable PAE
mov eax, cr4 ; Set the A-register to control register 4.
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
mov cr4, eax ; Set control register 4 to the A-register.
; enable x86_64
mov ecx, 0xC0000080 ; Set the C-register to 0xC0000080, which is the EFER MSR.
rdmsr ; Read from the model-specific register.
or eax, 1 << 8 ; Set the LM-bit which is the 9th bit (bit 8).
wrmsr ; Write to the model-specific register.
; let cr3 point at page table
mov eax,0x200000
mov cr3,eax
; enable paging, enter compatibility mode
call hk_enable_paging
; enter x64
lgdt [g_gdt_ptr_64]
jmp 8:0x100000
add esp,4 ; We are actually not coming back here. But out of courtesy...

View File

@ -5,9 +5,6 @@
#include "print.h"
uint8_t g_gdt[8 * 8];
gdt_ptr_t g_gdt_ptr;
gdt_ptr_64_t g_gdt_ptr_64;
//x86 stuff
uint8_t g_idt[8 * 256];
idt_ptr_t g_idt_ptr;
@ -16,31 +13,24 @@ extern void hk_entry_comp(void);
void HYPKERNEL32 hk_init_x86(multiboot_info_t const * const multiboot_info)
{
segment_descriptor_t desc_dummy = {.DPL = 0, .Pr = 0, .x64 = 0, .Sys = 0, .type = 0, .Sz = 0, .limit = 0, .Gr = 0, .base = 0, .Acc = 0};
segment_descriptor_t desc = {.Gr = 1, .Pr = 1, .Sz = 1, .Acc = 0, .Sys = 1, .x64 = 0, .base = 0, .limit = 0xFFFFF};
hk_print_str("*Setting up GDT...");
//dummy descriptor
hk_write_segment_descriptor(&g_gdt[0], &desc_dummy);
hk_write_segment_descriptor((void*)(&g_gdt[0]), 0, 0, 0);
//ring 0 code seg, non-conforming
desc.type = 10;
desc.DPL = 0;
hk_write_segment_descriptor(&g_gdt[8], &desc);
hk_write_segment_descriptor((void*)(&g_gdt[8]), 0, 0xFFFFF, SEG_TYPE(10) | SEG_CODE_DATA | SEG_32_BITS | SEG_GRANULARITY | SEG_PRESENT | SEG_DPL(0));
//ring 3 code seg
desc.DPL = 3;
hk_write_segment_descriptor(&g_gdt[16], &desc);
hk_write_segment_descriptor((void*)(&g_gdt[16]), 0, 0xFFFFF, SEG_TYPE(10) | SEG_CODE_DATA | SEG_32_BITS | SEG_GRANULARITY | SEG_PRESENT | SEG_DPL(3));
//ring 0 data RW
desc.DPL = 0;
desc.type = 2;
hk_write_segment_descriptor(&g_gdt[24], &desc);
hk_write_segment_descriptor((void*)(&g_gdt[24]), 0, 0xFFFFF, SEG_TYPE(2) | SEG_CODE_DATA | SEG_32_BITS | SEG_GRANULARITY | SEG_PRESENT | SEG_DPL(0));
//ring 3 data
desc.DPL = 3;
hk_write_segment_descriptor(&g_gdt[32], &desc);
hk_write_segment_descriptor((void*)(&g_gdt[24]), 0, 0xFFFFF, SEG_TYPE(2) | SEG_CODE_DATA | SEG_32_BITS | SEG_GRANULARITY | SEG_PRESENT | SEG_DPL(3));
g_gdt_ptr.limit = 8 * 8 - 1;
g_gdt_ptr.base = (uint32_t) g_gdt;
hk_load_gdt(&g_gdt_ptr, SEGMENT_SELECTOR(1, 0), SEGMENT_SELECTOR(3, 0));
hk_load_gdt(&g_gdt_ptr, SEG_SELECTOR(1, 0), SEG_SELECTOR(3, 0));
hk_print_str(" - Done.\n\n");
BOCHS_MAGIC_BREAKPOINT
//check memory, definitely < 32 so we assume that
hk_print_str("*Checking memory information...\n");
if(multiboot_info->flags & (1 << 6))
@ -118,154 +108,17 @@ void HYPKERNEL32 hk_init_x86(multiboot_info_t const * const multiboot_info)
void HYPKERNEL32 hk_init_x64(multiboot_info_t const * const multiboot_info)
{
//Setup x64
segment_descriptor_t desc_dummy = {.DPL = 0, .Pr = 0, .x64 = 0, .Sys = 0, .type = 0, .Sz = 0, .limit = 0, .Gr = 0, .base = 0, .Acc = 0};
segment_descriptor_t desc = {.Gr = 1, .Pr = 1, .Sz = 0, .Acc = 0, .Sys = 1, .x64 = 1, .base = 0, .limit = 0};
hk_print_str("*Setting up GDT ...");
//dummy descriptor
hk_write_segment_descriptor(&g_gdt[0], &desc_dummy);
//ring 0 code seg, non-conforming
desc.type = 10;
desc.DPL = 0;
hk_write_segment_descriptor(&g_gdt[8], &desc);
//ring 3 code seg
desc.DPL = 3;
hk_write_segment_descriptor(&g_gdt[16], &desc);
//ring 0 data RW
desc.DPL = 0;
desc.type = 2;
hk_write_segment_descriptor(&g_gdt[24], &desc);
//ring 3 data
desc.DPL = 3;
hk_write_segment_descriptor(&g_gdt[32], &desc);
g_gdt_ptr_64.limit = 8 * 8 - 1;
g_gdt_ptr_64.base = (uint64_t)g_gdt;
hk_print_str(" - Done.\n\n");
//check memory, definitely < 32 so we assume that
hk_print_str("*Checking memory information...\n");
if(multiboot_info->flags & (1 << 6))
{
multiboot_memory_map_t const *mem_map = (multiboot_memory_map_t *) multiboot_info->mmap_addr;
uint32_t const mem_map_size = multiboot_info->mmap_length / sizeof(multiboot_memory_map_t);
hk_print_str("BaseAddr - Length - Type\n");
uint32_t total_available_mem = 0;
uint32_t total_reserved_mem = 0;
uint32_t i = 0;
for (i = 0; i < mem_map_size; i++)
{
hk_print_hex((uint32_t)((mem_map + i)->addr));
hk_print_str(" - ");
hk_print_hex((uint32_t)((mem_map + i)->len));
hk_print_str(" - ");
hk_print_hex((mem_map + i)->type);
hk_print_str("\n");
if((mem_map + i)->type == MULTIBOOT_MEMORY_RESERVED)
{
total_reserved_mem += (uint32_t) ((mem_map + i)->len);
}
else if ((mem_map + i)->type == MULTIBOOT_MEMORY_AVAILABLE)
{
total_available_mem += (uint32_t) ((mem_map + i)->len);
}
}
hk_print_str("Total available memory: ");
hk_print_int(total_available_mem);
hk_print_str("B = ");
hk_print_int(total_available_mem/1024);
hk_print_str("KB = ");
hk_print_int(total_available_mem/1024/1024);
hk_print_str("MB\n");
hk_print_str("Total reserved memory: ");
hk_print_int(total_reserved_mem);
hk_print_str("B = ");
hk_print_int(total_reserved_mem/1024);
hk_print_str("KB = ");
hk_print_int(total_reserved_mem/1024/1024);
hk_print_str("MB\n\n");
}
else
{
hk_print_str("Memory information is currently unavailable.\n\n");
}
//check modules
hk_print_str("*Checking loaded kernel modules...\n");
if(multiboot_info->flags & (1 << 3))
{
multiboot_module_t const * mods_list = (multiboot_module_t *)multiboot_info->mods_addr;
uint32_t const mods_count = multiboot_info->mods_count;
hk_print_int(mods_count);
hk_print_str(" module(s) loaded:\n");
hk_print_str("Name - StartAddr - EndAddr\n");
uint32_t i = 0;
for (i = 0; i < mods_count; i++)
{
hk_print_str((char *) (mods_list + i)->cmdline);
hk_print_str(" - ");
hk_print_hex((mods_list + i)->mod_start);
hk_print_str(" - ");
hk_print_hex((mods_list + i)->mod_end);
hk_print_str("\n");
}
hk_print_str("\n");
}
else
{
hk_print_str("Module information is currently unavailable.\n\n");
}
//Setup identity x64 PAE paging
hk_print_str("*Setting up paging for x64...");
//Setup
//TODO: check for available memory and only allocate stuff needed(should not be really hard)
uint32_t addr = 0x200000;
pml4_entry_t pml4_entry = {.base = 0x201000,.Acc = 0, .PWT = 1, .PCD = 0,.Pr = 1,.USU = 0, .XD = 0, .RW = 1, .Sz = 0};
while(addr < 0x201000)
{
hk_write_pml4_entry((uint8_t *) addr,&pml4_entry);
//only map first 512 gigs for obvious reasons.
pml4_entry.base = 0;
pml4_entry.Pr = 0;
addr += 8;
}
addr = 0x201000;
pdpt_entry_t pdpt_entry = {.base = 0x202000,.Acc = 0, .PWT = 1, .PCD = 0,.Pr = 1,.USU = 0, .XD = 0, .RW = 1, .Sz = 0};
while(addr < 0x202000)
{
hk_write_pdpt_entry((uint8_t*) addr, &pdpt_entry);
//only map first 1 gig for obvious reasons.
pdpt_entry.Pr = 0;
pdpt_entry.base = 0;
addr += 8;
}
addr = 0x202000;
pd_entry_t pd_entry = {.base = 0x203000,.Acc = 0, .PWT = 1, .PCD = 0,.Pr = 1,.USU = 0, .XD = 0, .RW = 1, .Sz = 0};
while(addr < 0x203000)
{
hk_write_pd_entry((uint8_t *) addr, &pd_entry);
//ah. no more laziness. At least we need to map first gig.
pd_entry.base += 0x1000; // increment for every 512 entries * 8 bytes each
addr += 8;
}
addr = 0x203000;
pt_entry_t pt_entry = {.base = 0, .Acc = 0, .Pr = 1, .RW = 1, .USU = 0, .PWT = 1,.PCD = 0, .dirty = 0,.Gl = 0, .PAT = 0,.XD = 0};
while(addr < (0x203000 + 512 * 0x1000))
{
hk_write_pt_entry((uint8_t *) addr, &pt_entry);
pt_entry.base += 0x1000;
addr += 8;
}
hk_print_str(" - Done.\n\n");
hk_entry_comp();
//CHECK MODULE AND LOAD ELF
HLT_CPU
}
void HYPKERNEL32 hk_main(multiboot_info_t const * const multiboot_info)
{
//init text_position
text_pos = 0;
hk_load_gdt(&g_gdt_ptr, SEG_SELECTOR(1, 0), SEG_SELECTOR(3, 0));
hk_print_str(" - Done.\n\n");
//detect architecture
hk_print_str("*Checking architecture...\n");
if (hk_support_x64() == 0)
@ -280,6 +133,3 @@ void HYPKERNEL32 hk_main(multiboot_info_t const * const multiboot_info)
}
return;
}

View File

@ -4,10 +4,11 @@
#define HYPKERNEL32 __attribute__((cdecl))
#define BOCHS_MAGIC_BREAKPOINT asm("xchg bx,bx");
#define HLT_CPU asm("hlt");
#define NULL ((void*)0)
#define SEGMENT_SELECTOR(Index,RPL) (((Index) << 3) + (RPL))
#define SEG_SELECTOR(Index,RPL) (((Index) << 3) + (RPL))
#endif

View File

@ -1,138 +1,20 @@
#include "kdef.h"
#include "mem.h"
#include "print.h"
void HYPKERNEL32 hk_map_page_64(uint8_t * base, uint64_t const physcial_addr, uint64_t const linear_addr, pml4_entry_t* pml4_entry, pdpt_entry_t* pdpt_entry, pd_entry_t pd_entry_t, pt_entry_t* pt_entry)
void HYPKERNEL32 hk_write_segment_descriptor(void * const gdt, uint32_t const base, uint32_t const limit, uint64_t const attr)
{
// all the paging structures serve as supplementary, i.e. when the page entry does not exist.
if(physcial_addr << 52 || linear_addr << 52)
{
return;
}
uint64_t const pml4_idx = (linear_addr >> 39) & 0x1FF; //9bits
}
void HYPKERNEL32 hk_write_pml4_entry(uint8_t * const base, pml4_entry_t const * const p_entry)
{
if(base == NULL || p_entry == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->Sz & 0x1) << 7));
base[1] = (uint8_t)(((p_entry->base >> 12) & 0xF) << 4); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
return;
}
void HYPKERNEL32 hk_write_pdpt_entry(uint8_t * const base, pdpt_entry_t const * const p_entry)
{
if(base == NULL || p_entry == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->Sz & 0x1) << 7));
base[1] = (uint8_t)(((p_entry->base >> 12) & 0xF) << 4); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
return;
}
void HYPKERNEL32 hk_write_pd_entry(uint8_t * const base, pd_entry_t const * const p_entry)
{
if(base == NULL || p_entry == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->Sz & 0x1) << 7));
base[1] = (uint8_t)(((p_entry->base >> 12) & 0xF) << 4); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
return;
}
void HYPKERNEL32 hk_write_pt_entry(uint8_t * const base, pt_entry_t const * const p_entry)
{
if(base == NULL || p_entry == NULL)
return;
base[0] = (uint8_t)((p_entry->Pr & 0x1) + ((p_entry->RW & 0x1) << 1) + ((p_entry->USU & 0x1) << 2) + ((p_entry->PWT & 0x1) << 3) + ((p_entry->PCD & 0x1) << 4) + ((p_entry->Acc & 0x1) << 5) + ((p_entry->dirty & 0x1) << 6) + ((p_entry->PAT & 0x1) << 7));
base[1] = (uint8_t)((((p_entry->base >> 12) & 0xF) << 4) + (p_entry->Gl & 0x1)); // 4 bits
base[2] = (uint8_t)((p_entry->base >> 16) & 0xFF); // 8 bits
base[3] = (uint8_t)((p_entry->base >> 24) & 0xFF); // 8 bits
base[4] = (uint8_t)((p_entry->base >> 32) & 0xFF); // 8 bits
base[5] = (uint8_t)((p_entry->base >> 40) & 0xFF); // 8 bits
base[6] = (uint8_t)((p_entry->base >> 48) & 0xF); // 4 bits
base[7] = (uint8_t)((p_entry->XD & 0x1) << 7);
return;
}
void HYPKERNEL32 hk_write_segment_descriptor(uint8_t *const gdt, segment_descriptor_t const *const seg_desc)
{
if (gdt == NULL || seg_desc == NULL)
if (gdt == NULL)
return;
gdt[0] = (uint8_t)(seg_desc->limit & 0xFF);
gdt[1] = (uint8_t)((seg_desc->limit >> 8) & 0xFF);
gdt[6] = gdt[6] | (uint8_t)((seg_desc->limit >> 16) & 0xFF);
gdt[2] = (uint8_t)(seg_desc->base & 0xFF);
gdt[3] = (uint8_t)((seg_desc->base >> 8) & 0xFF);
gdt[4] = (uint8_t)((seg_desc->base >> 16) & 0xFF);
gdt[7] = (uint8_t)((seg_desc->base >> 24) & 0xFF);
gdt[5] = (uint8_t)((seg_desc->type & 0xF) + ((seg_desc->Sys & 0x1) << 4) + ((seg_desc->DPL & 0x3) << 5) + ((seg_desc->Pr & 0x1 ) << 7));
gdt[6] = gdt[6] | (uint8_t)(((seg_desc->Acc & 0x1) + ((seg_desc->x64 & 0x1) << 1) + ((seg_desc->Sz & 0x1) << 2) + ((seg_desc->Gr & 0x1) << 3)) << 4);
return;
}
void HYPKERNEL32 hk_write_interrupt_gate(uint8_t *const dst, interrupt_gate_t const *int_gate)
{
if(dst == NULL || int_gate == NULL)
return;
dst[0] = (uint8_t)(int_gate->offset & 0xFF);
dst[1] = (uint8_t)((int_gate->offset >> 8) & 0xFF);
dst[6] = (uint8_t)((int_gate->offset >> 16) & 0xFF);
dst[7] = (uint8_t)((int_gate->offset >> 24) & 0xFF);
dst[2] = (uint8_t)(int_gate->seg_sel & 0xFF);
dst[3] = (uint8_t)((int_gate->seg_sel >> 8) & 0xFF);;
dst[4] = 0;
dst[5] = (uint8_t)(6 + ((int_gate->Sz & 0x1) << 3) + ((int_gate->DPL & 0x3) << 5) + ((int_gate->Pr & 0x1 ) << 7));
return;
}
void HYPKERNEL32 hk_write_trap_gate(uint8_t *const dst, trap_gate_t const *tr_gate)
{
if(dst == NULL || tr_gate == NULL)
return;
dst[0] = (uint8_t)(tr_gate->offset & 0xFF);
dst[1] = (uint8_t)((tr_gate->offset >> 8) & 0xFF);
dst[6] = (uint8_t)((tr_gate->offset >> 16) & 0xFF);
dst[7] = (uint8_t)((tr_gate->offset >> 24) & 0xFF);
dst[2] = (uint8_t)(tr_gate->seg_sel & 0xFF);
dst[3] = (uint8_t)((tr_gate->seg_sel >> 8) & 0xFF);;
dst[4] = 0;
dst[5] = (uint8_t)(7 + ((tr_gate->Sz & 0x1) << 3) + ((tr_gate->DPL & 0x3) << 5) + ((tr_gate->Pr & 0x1 ) << 7));
return;
}
void HYPKERNEL32 hk_write_task_gate(uint8_t *const dst, task_gate_t const *int_gate)
{
if(dst == NULL || int_gate == NULL)
return;
dst[0] = 0;
dst[1] = 0;
dst[6] = 0;
dst[7] = 0;
dst[2] = (uint8_t)(int_gate->tss_sel & 0xFF);
dst[3] = (uint8_t)((int_gate->tss_sel >> 8) & 0xFF);
dst[4] = 0;
dst[5] = (uint8_t)(5 + ((int_gate->DPL & 0x3) << 5) + ((int_gate->Pr & 0x1 ) << 7));
uint64_t const seg_desc = (((uint64_t)base & 0xFFFF) << 16) | ((((uint64_t)base >> 16) & 0xFF) << 32) | ((((uint64_t)base >> 24) & 0xFF) << 56) | ((uint64_t)limit & 0xFFFF) | ((((uint64_t)limit >> 16) & 0xF) << 48) | attr;
((uint8_t*)gdt)[0] = (uint8_t)(seg_desc & 0xFF);
((uint8_t*)gdt)[1] = (uint8_t)((seg_desc >> 8) & 0xFF);
((uint8_t*)gdt)[2] = (uint8_t)((seg_desc >> 16) & 0xFF);
((uint8_t*)gdt)[3] = (uint8_t)((seg_desc >> 24) & 0xFF);
((uint8_t*)gdt)[4] = (uint8_t)((seg_desc >> 32) & 0xFF);
((uint8_t*)gdt)[5] = (uint8_t)((seg_desc >> 40) & 0xFF);
((uint8_t*)gdt)[6] = (uint8_t)((seg_desc >> 48) & 0xFF);
((uint8_t*)gdt)[7] = (uint8_t)((seg_desc >> 56) & 0xFF);
return;
}

View File

@ -1,77 +1,16 @@
#ifndef _MEM_32_H_
#define _MEM_32_H_
#ifndef _MEM_H_
#define _MEM_H_
#include "type.h"
#include "kdef.h"
typedef struct __attribute__ ((packed))
{
uint32_t Pr;
uint32_t RW;
uint32_t USU;
uint32_t PWT;
uint32_t PCD;
uint32_t Acc;
uint32_t Sz; //must be 0
uint64_t base; // Since 4KB-aligned, 12 bits are useless, 52(total) - 12 = 40 bits left
// will ignore the low 12 bits as well as the high 12 bits of this field
uint32_t XD;
} pml4_entry_t, pdpt_entry_t, pd_entry_t;
typedef struct __attribute__ ((packed))
{
uint32_t Pr;
uint32_t RW;
uint32_t USU;
uint32_t PWT;
uint32_t PCD;
uint32_t Acc;
uint32_t dirty;
uint32_t PAT;
uint32_t Gl;
uint64_t base; // Since 4KB-aligned, 12 bits are useless, 52(total) - 12 = 40 bits left
// will ignore the low 12 bits as well as the high 12 bits of this field
uint32_t XD;
} pt_entry_t;
typedef struct __attribute__ ((packed))
{
uint32_t offset;
uint32_t seg_sel;
uint32_t Pr;
uint32_t DPL;
uint32_t Sz;
} interrupt_gate_t;
typedef struct __attribute__ ((packed))
{
uint32_t offset;
uint32_t seg_sel;
uint32_t Pr;
uint32_t DPL;
uint32_t Sz;
} trap_gate_t;
typedef struct __attribute__ ((packed))
{
uint32_t tss_sel;
uint32_t DPL;
uint32_t Pr;
} task_gate_t;
typedef struct __attribute__ ((packed))
{
uint32_t base;
uint32_t limit;
uint32_t type;
uint32_t DPL;
uint32_t Gr;
uint32_t Acc;
uint32_t Pr;
uint32_t Sz; //32 bits = 1, 16 bits = 0
uint32_t x64;
uint32_t Sys; //System = 0, code/data = 1
} segment_descriptor_t;
#define SEG_GRANULARITY ((uint64_t)1 << 55)
#define SEG_LONG ((uint64_t)1 << 53)
#define SEG_DPL(dpl) (((uint64_t)(dpl) & 0x3) << 45)
#define SEG_PRESENT ((uint64_t)1 << 47)
#define SEG_CODE_DATA ((uint64_t)1 << 44)
#define SEG_TYPE(type) (((uint64_t)(type) & 0xF) << 40)
#define SEG_AVAILABLE ((uint64_t)1 << 52)
#define SEG_32_BITS ((uint64_t)1 << 54)
typedef struct __attribute__ ((packed))
{
@ -79,31 +18,18 @@ typedef struct __attribute__ ((packed))
uint32_t base;
} gdt_ptr_t;
typedef struct __attribute__ ((packed))
{
uint16_t limit;
uint64_t base;
} gdt_ptr_64_t;
typedef struct __attribute__ ((packed))
{
uint16_t limit;
uint32_t base;
} idt_ptr_t;
void HYPKERNEL32 hk_write_segment_descriptor(uint8_t *const gdt, segment_descriptor_t const *const seg_desc);
void HYPKERNEL32 hk_write_segment_descriptor(void *const gdt, uint32_t const base, uint32_t const limit, uint64_t const attr);
extern void HYPKERNEL32 hk_load_gdt(gdt_ptr_t const * const ptr, uint16_t const sel_code, uint16_t const sel_data);
void HYPKERNEL32 hk_write_interrupt_gate(uint8_t *const dst, interrupt_gate_t const *int_gate);
void HYPKERNEL32 hk_write_trap_gate(uint8_t *const dst, trap_gate_t const *tr_gate);
void HYPKERNEL32 hk_write_task_gate(uint8_t *const dst, task_gate_t const *int_gate);
void HYPKERNEL32 hk_mem_cpy(void* src, void* dst, uint32_t size);
void HYPKERNEL32 hk_mem_move(void* src, void* dst, uint32_t size);
extern int32_t HYPKERNEL32 hk_support_x64(void);
extern void hk_disable_paging(void);
extern void hk_enable_paging(void);
void HYPKERNEL32 hk_mem_set(void* src, int8_t const val,uint32_t size);
void HYPKERNEL32 hk_write_pt_entry(uint8_t * const base, pt_entry_t const * const p_entry);
void HYPKERNEL32 hk_write_pd_entry(uint8_t * const base, pd_entry_t const * const p_entry);
void HYPKERNEL32 hk_write_pdpt_entry(uint8_t * const base, pdpt_entry_t const * const p_entry);
void HYPKERNEL32 hk_write_pml4_entry(uint8_t * const base, pml4_entry_t const * const p_entry);
#endif

View File

@ -4,8 +4,8 @@ typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned long long uint64_t;
typedef unsigned char uint8_t;
typedef int int32_t;
typedef short int16_t;
typedef long long int64_t;
typedef signed int int32_t;
typedef signed short int16_t;
typedef signed long long int64_t;
typedef char int8_t;
#endif