Set up interrupt dispatching

Set up APIC. Timer setup atrociously close.
Bochs keeps giving the god damn triple fault (IDT broken)??
This commit is contained in:
secXsQuared 2016-06-12 21:11:38 -07:00
parent 8d7590ace4
commit bc49a854dd
19 changed files with 46478 additions and 354 deletions

45764
x64/kernel.dasm Normal file

File diff suppressed because it is too large Load Diff

View File

@ -40,8 +40,9 @@ typedef struct {
} module_info_t;
typedef struct {
char cpu_vendor_string[13];
mem_info_t* mem_info; // all available memory info
module_info_t* module_info; // all kernel modules loaded
} boot_info_t;
} k_hal_info_t;
#endif

180
x64/src/hal/hal_arch.asm Normal file
View File

@ -0,0 +1,180 @@
; Copyright 2016 secXsQuared
; Distributed under GPL license
; See COPYING under root for details
;Functions preserve the registers rbx, rsp, rbp, r12, r13, r14, and 15
;rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11 are scratch registers.
;function parameter: rdi,rsi,rdx,rcx,r8,r9
[SECTION .text]
[BITS 64]
;======================
global hal_flush_gdt
hal_flush_gdt:
push rbp
mov rbp,rsp
lgdt [rdi]
;reload cs
push rdx ; data_slct : ss
push rbp ; rsp
pushfq
pop rax
push rax ; eflags
push rsi ; cs
push qword .reload ;eip
iretq
.reload:
mov es,dx
mov fs,dx
mov gs,dx
mov ds,dx
mov rsp,rbp
pop rbp
ret
;======================
global hal_flush_tlb
;void flush_tlb(void)
hal_flush_tlb:
mov rax,cr3
mov cr3,rax
ret
;======================
global hal_flush_idt
hal_flush_idt:
lidt [rdi]
ret
;======================
global hal_read_cr3
hal_read_cr3:
mov rax,cr3
ret
;======================
global hal_write_cr3
hal_write_cr3:
mov cr3,rdi
ret
; ============================
; uint64_t KAPI hal_interlocked_exchange(uint64_t* dst, uint64_t val);
global hal_interlocked_exchange
hal_interlocked_exchange:
lock xchg qword [rdi], rsi
mov rax, rsi
ret
; ============================
; extern void KAPI hal_cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx);
global hal_cpuid
hal_cpuid:
push rbp
mov rbp,rsp
; preserve rbx,rcx,rdx
push rbx
push rcx
push rdx
; cpuid parameters eax,ecx
mov eax, dword [rdi]
mov ecx, dword [rdx]
cpuid
; write results back to memory
mov dword [rdi], eax
mov dword [rsi], ebx
pop r11
mov dword [r11], ecx
pop r11
mov dword [r11], edx
pop rbx
mov rsp,rbp
pop rbp
ret
;====================
global hal_write_port
hal_write_port:
mov rdx,rdi
mov rax,rsi
out dx,eax
nop
nop
ret
;====================
global hal_read_port
hal_read_port:
mov rdx,rdi
xor rax,rax
in eax,dx
nop
nop
ret
;====================
global hal_write_mem_32
; (void* target, uint32_t* data)
hal_write_mem_32:
mov dword [rdi], esi
ret
;====================
global hal_write_mem_64
; (void* target, uint64_t data)
hal_write_mem_64:
mov qword [rdi], rsi
ret
;====================
global hal_disable_interrupt
hal_disable_interrupt:
cli
ret
;====================
global hal_enable_interrupt
hal_enable_interrupt:
sti
ret
;====================
global hal_halt_cpu
hal_halt_cpu:
.loop:
hlt
jmp .loop
;====================
global hal_bochs_magic_breakpoint
hal_bochs_magic_breakpoint:
xchg bx,bx
ret
;====================
;(uint32_t *ecx, uint32_t* edx, uint32_t* eax)
global hal_read_msr
hal_read_msr:
; preserve rdx
push rdx
mov ecx, dword [rdi]
rdmsr
mov dword [rdi], ecx
mov dword [rsi], edx
pop r11
mov dword [r11], eax
ret
;====================
;(uint32_t *ecx, uint32_t* edx, uint32_t* eax)
global hal_write_msr
hal_write_msr:
mov ecx, dword [rdi]
mov eax, dword [rdx]
mov edx, dword [rsi]
wrmsr
ret

View File

@ -1,11 +0,0 @@
; Copyright 2016 secXsQuared
; Distributed under GPL license
; See COPYING under root for details
;============================
;uint64_t _KERNEL_ABI hal_interlocked_exchange(_IN _OUT uint64_t* dst, _IN uint64_t val);
global hal_interlocked_exchange;
hal_interlocked_exchange:
lock xchg qword [rdi], rsi
mov rax, rsi
ret

View File

@ -13,7 +13,7 @@ MULTIBOOT_HEADER_ALIGNMENT equ 8
MULTIBOOT_LOADED_MAGIC equ 0x36d76289
MULTIBOOT_MAGIC_NUMBER equ 0xE85250D6
MULTIBOOT_ARCH equ 0
MULTIBOOT_CHECK_SUM equ - (MULTIBOOT_MAGIC_NUMBER + MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCH)
MULTIBOOT_CHECK_SUM equ -(MULTIBOOT_MAGIC_NUMBER + MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCH)
;align MULTIBOOT_HEADER_ALIGNMENT
MULTIBOOT_HEADER:

View File

@ -11,16 +11,22 @@
#include "hal_var.h"
#include "k_sys_info.h"
#include "std_lib.h"
#include "hal_arch.h"
boot_info_t *KAPI hal_init(char *m_info)
static void KAPI _hal_obtain_cpu_info(k_hal_info_t *hal_info)
{
if (m_info == NULL || (uint64_t) m_info & bit_field_mask_64(0, 2))
return NULL;
if(hal_info == NULL)
return;
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
hal_cpuid(&eax,&ebx,&ecx,&edx);
mem_cpy(&ebx, &hal_info->cpu_vendor_string[0], sizeof(uint32_t));
mem_cpy(&edx, &hal_info->cpu_vendor_string[4], sizeof(uint32_t));
mem_cpy(&ecx, &hal_info->cpu_vendor_string[8], sizeof(uint32_t));
hal_info->cpu_vendor_string[12] = 0;
}
// set up kernel heap;
hal_alloc_init();
boot_info_t *boot_info = (boot_info_t *) halloc(sizeof(boot_info_t));
static void KAPI _hal_init_gdt()
{
text_pos = get_pos(0, 0);
// get gdt ready
@ -47,140 +53,157 @@ boot_info_t *KAPI hal_init(char *m_info)
SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
SEG_TYPE_DATA_RW);
g_gdt_ptr.base = (uint64_t) g_gdt;
g_gdt_ptr.limit = 8 * 9 - 1;
g_gdt_ptr.limit = GDT_ENTRY_NUM * GDT_ENTRY_SIZE - 1;
hal_flush_gdt(&g_gdt_ptr, seg_selector(1, 0), seg_selector(2, 0));
};
// get idt ptr ready
g_idt_ptr.base = (uint64_t) g_idt;
g_idt_ptr.limit = 21 * 16 - 1;
hal_flush_idt(&g_idt_ptr);
k_hal_info_t *KAPI hal_init(char *m_info)
{
if (m_info == NULL || (uint64_t) m_info & bit_field_mask_64(0, 2))
return NULL;
// set up kernel heap;
hal_alloc_init();
// set up GDT
_hal_init_gdt();
// init interrupt
if(hal_interrupt_init() != 0)
{
hal_halt_cpu();
}
k_hal_info_t *hal_info = (k_hal_info_t *) halloc(sizeof(k_hal_info_t));
mem_set(hal_info, 0, sizeof(k_hal_info_t));
_hal_obtain_cpu_info(hal_info);
mem_set(boot_info, 0, sizeof(boot_info_t));
// obtain boot information
// memory info
if (m_info->flags & (1 << 6))
{
boot_info->mem_info = (mem_info_t *) halloc(sizeof(mem_info_t));
hal_assert(boot_info->mem_info != NULL, "Unable to allocate memory for mem_info.");
boot_info->mem_info->mem_available = 0;
boot_info->mem_info->mem_installed = 0;
boot_info->mem_info->free_page_list = (linked_list_t *) halloc((sizeof(linked_list_t)));
boot_info->mem_info->occupied_page_list = (linked_list_t *) halloc((sizeof(linked_list_t)));
hal_assert(boot_info->mem_info->free_page_list != NULL &&
boot_info->mem_info->occupied_page_list != NULL, "Unable to allocate memory for mem_info_lists.");
linked_list_init(boot_info->mem_info->free_page_list);
linked_list_init(boot_info->mem_info->occupied_page_list);
multiboot_memory_map_t *mem_map = (multiboot_memory_map_t *) (uint64_t) m_info->mmap_addr;
uint64_t mem_map_size = m_info->mmap_length / sizeof(multiboot_memory_map_t);
for (uint64_t i = 0; i < mem_map_size; i++)
{
hal_printf("==Base: 0x%X, Length: %u, Type: %s==\n", (mem_map + i)->addr, (mem_map + i)->len,
(mem_map + i)->type == MULTIBOOT_MEMORY_AVAILABLE ? "AVL" : "RSV");
if ((mem_map + i)->type == MULTIBOOT_MEMORY_AVAILABLE)
{
uint64_t base_addr = (mem_map + i)->addr;
uint64_t end_addr = base_addr + (mem_map + i)->len;
// if (m_info->flags & (1 << 6))
// {
// boot_info->mem_info = (mem_info_t *) halloc(sizeof(mem_info_t));
// hal_assert(boot_info->mem_info != NULL, "Unable to allocate memory for mem_info.");
// boot_info->mem_info->mem_available = 0;
// boot_info->mem_info->mem_installed = 0;
// boot_info->mem_info->free_page_list = (linked_list_t *) halloc((sizeof(linked_list_t)));
// boot_info->mem_info->occupied_page_list = (linked_list_t *) halloc((sizeof(linked_list_t)));
// hal_assert(boot_info->mem_info->free_page_list != NULL &&
// boot_info->mem_info->occupied_page_list != NULL, "Unable to allocate memory for mem_info_lists.");
// linked_list_init(boot_info->mem_info->free_page_list);
// linked_list_init(boot_info->mem_info->occupied_page_list);
// multiboot_memory_map_t *mem_map = (multiboot_memory_map_t *) (uint64_t) m_info->mmap_addr;
// uint64_t mem_map_size = m_info->mmap_length / sizeof(multiboot_memory_map_t);
// for (uint64_t i = 0; i < mem_map_size; i++)
// {
// hal_printf("==Base: 0x%X, Length: %u, Type: %s==\n", (mem_map + i)->addr, (mem_map + i)->len,
// (mem_map + i)->type == MULTIBOOT_MEMORY_AVAILABLE ? "AVL" : "RSV");
// if ((mem_map + i)->type == MULTIBOOT_MEMORY_AVAILABLE)
// {
// uint64_t base_addr = (mem_map + i)->addr;
// uint64_t end_addr = base_addr + (mem_map + i)->len;
//
// // align head
// uint64_t aligned_base_addr = align_up(base_addr, PHYSICAL_PAGE_SIZE);
// // align tail
// uint64_t aligned_end_addr = align_down(end_addr, PHYSICAL_PAGE_SIZE);
//
//
// uint64_t page_count = (aligned_end_addr - aligned_base_addr) / PHYSICAL_PAGE_SIZE;
//
// if (page_count == 0)
// continue;
//
// // strip kernel-occupied pages
// // TODO: Finished this.
// uint64_t aligned_kernel_base = ALIGN_DOWN((uint64_t) kernel_start, PHYSICAL_PAGE_SIZE);
// uint64_t aligned_kernel_end = ALIGN_UP((uint64_t) kernel_end, PHYSICAL_PAGE_SIZE);
// if (IS_OVERLAP(aligned_base_addr, aligned_end_addr, aligned_kernel_base, aligned_kernel_end))
// {
// uint64_t overlap_pages = (MIN(aligned_kernel_end, aligned_end_addr)
// - MAX(aligned_kernel_base, aligned_base_addr)) / PHYSICAL_PAGE_SIZE;
//
// if (overlap_pages != 0)
// {
// // if there is overlap, add to occupied list
// memory_descriptor_node_t *occupied_desc = (memory_descriptor_node_t *) hal_alloc(
// sizeof(memory_descriptor_node_t));
// hal_assert(occupied_desc != NULL, "Unable to allocate memory for memory_descriptor.");
// occupied_desc->base_addr = aligned_kernel_base;
// occupied_desc->page_count = overlap_pages;
// linked_list_add(boot_info->mem_info->occupied_page_list, &occupied_desc->list_node);
//
// // also adjust corresponding segment
// page_count = page_count - overlap_pages;
// if (page_count == 0) // if kernel occupies the whole segment, continue
// continue;
//
// }
// }
//
// memory_descriptor_node_t *each_desc = (memory_descriptor_node_t *) halloc(
// sizeof(memory_descriptor_node_t));
// hal_assert(each_desc != NULL, "Unable to allocate memory for memory_descriptor.");
// each_desc->page_count = page_count;
// each_desc->base_addr = aligned_base_addr;
// linked_list_push_back(boot_info->mem_info->free_page_list, &each_desc->list_node);
// boot_info->mem_info->mem_available += aligned_end_addr - aligned_base_addr;
// }
// boot_info->mem_info->mem_installed += (mem_map + i)->len;
// }
// }
// else
// {
// // halt machine
// hal_printf("HAL: Cannot detect memory information.");
// hal_halt_cpu();
// }
//
// // loaded kernel modules
// if (m_info->flags & (1 << 3))
// {
// boot_info->module_info = (module_info_t *) halloc(sizeof(module_info_t));
// hal_assert(boot_info->module_info != NULL, "Unable to allocate memory for module_info.");
// boot_info->module_info->module_count = 0;
// boot_info->module_info->module_list = (linked_list_t *) halloc(sizeof(linked_list_t));
// hal_assert(boot_info->module_info->module_list != NULL, "Unable to allocate memory for module_list.");
// linked_list_init(boot_info->module_info->module_list);
// multiboot_module_t *mods_list = (multiboot_module_t * )(uint64_t)
// m_info->mods_addr;
// boot_info->module_info->module_count = m_info->mods_count;
// for (uint64_t i = 0; i < boot_info->module_info->module_count; i++)
// {
// module_descriptor_node_t *each_module = (module_descriptor_node_t *) halloc(
// sizeof(module_descriptor_node_t));
// hal_assert(each_module != NULL, "Unable to allocate memory for module_descriptor.");
// each_module->base_addr = (mods_list + i)->mod_start;
// each_module->size = (mods_list + i)->mod_end - (mods_list + i)->mod_start;
// each_module->name = (char *) halloc((size_t) str_len((char *) (uint64_t) (mods_list + i)->cmdline) + 1);
// hal_assert(each_module->name != NULL, "Unable to allocate memory for module name string.");
// mem_cpy((void *) (uint64_t) (mods_list + i)->cmdline, each_module->name,
// str_len((char *) (uint64_t) (mods_list + i)->cmdline) + 1);
// linked_list_push_back(boot_info->module_info->module_list, &each_module->list_node);
// }
// }
//
// // detect APIC
// cpuid_t cpuid_info;
// cpuid_info.eax = 1;
// cpuid_info.ebx = 0;
// cpuid_info.ecx = 0;
// cpuid_info.edx = 0;
// hal_cpuid(&cpuid_info.eax, &cpuid_info.ebx, &cpuid_info.ecx, &cpuid_info.edx);
// if (cpuid_info.edx & 1 << 9)
// {
// //TODO: detected.
// }
// else
// {
// // halt machine
// hal_printf("HAL: Cannot detect APIC.");
// hal_halt_cpu();
// }
// align head
uint64_t aligned_base_addr = align_up(base_addr, PHYSICAL_PAGE_SIZE);
// align tail
uint64_t aligned_end_addr = align_down(end_addr, PHYSICAL_PAGE_SIZE);
uint64_t page_count = (aligned_end_addr - aligned_base_addr) / PHYSICAL_PAGE_SIZE;
if (page_count == 0)
continue;
// strip kernel-occupied pages
// TODO: Finished this.
uint64_t aligned_kernel_base = ALIGN_DOWN((uint64_t) kernel_start, PHYSICAL_PAGE_SIZE);
uint64_t aligned_kernel_end = ALIGN_UP((uint64_t) kernel_end, PHYSICAL_PAGE_SIZE);
if (IS_OVERLAP(aligned_base_addr, aligned_end_addr, aligned_kernel_base, aligned_kernel_end))
{
uint64_t overlap_pages = (MIN(aligned_kernel_end, aligned_end_addr)
- MAX(aligned_kernel_base, aligned_base_addr)) / PHYSICAL_PAGE_SIZE;
if (overlap_pages != 0)
{
// if there is overlap, add to occupied list
memory_descriptor_node_t *occupied_desc = (memory_descriptor_node_t *) hal_alloc(
sizeof(memory_descriptor_node_t));
hal_assert(occupied_desc != NULL, "Unable to allocate memory for memory_descriptor.");
occupied_desc->base_addr = aligned_kernel_base;
occupied_desc->page_count = overlap_pages;
linked_list_add(boot_info->mem_info->occupied_page_list, &occupied_desc->list_node);
// also adjust corresponding segment
page_count = page_count - overlap_pages;
if (page_count == 0) // if kernel occupies the whole segment, continue
continue;
}
}
memory_descriptor_node_t *each_desc = (memory_descriptor_node_t *) halloc(
sizeof(memory_descriptor_node_t));
hal_assert(each_desc != NULL, "Unable to allocate memory for memory_descriptor.");
each_desc->page_count = page_count;
each_desc->base_addr = aligned_base_addr;
linked_list_push_back(boot_info->mem_info->free_page_list, &each_desc->list_node);
boot_info->mem_info->mem_available += aligned_end_addr - aligned_base_addr;
}
boot_info->mem_info->mem_installed += (mem_map + i)->len;
}
}
else
{
// halt machine
hal_printf("HAL: Cannot detect memory information.");
hal_halt_cpu();
}
// loaded kernel modules
if (m_info->flags & (1 << 3))
{
boot_info->module_info = (module_info_t *) halloc(sizeof(module_info_t));
hal_assert(boot_info->module_info != NULL, "Unable to allocate memory for module_info.");
boot_info->module_info->module_count = 0;
boot_info->module_info->module_list = (linked_list_t *) halloc(sizeof(linked_list_t));
hal_assert(boot_info->module_info->module_list != NULL, "Unable to allocate memory for module_list.");
linked_list_init(boot_info->module_info->module_list);
multiboot_module_t *mods_list = (multiboot_module_t * )(uint64_t)
m_info->mods_addr;
boot_info->module_info->module_count = m_info->mods_count;
for (uint64_t i = 0; i < boot_info->module_info->module_count; i++)
{
module_descriptor_node_t *each_module = (module_descriptor_node_t *) halloc(
sizeof(module_descriptor_node_t));
hal_assert(each_module != NULL, "Unable to allocate memory for module_descriptor.");
each_module->base_addr = (mods_list + i)->mod_start;
each_module->size = (mods_list + i)->mod_end - (mods_list + i)->mod_start;
each_module->name = (char *) halloc((size_t) str_len((char *) (uint64_t) (mods_list + i)->cmdline) + 1);
hal_assert(each_module->name != NULL, "Unable to allocate memory for module name string.");
mem_cpy((void *) (uint64_t) (mods_list + i)->cmdline, each_module->name,
str_len((char *) (uint64_t) (mods_list + i)->cmdline) + 1);
linked_list_push_back(boot_info->module_info->module_list, &each_module->list_node);
}
}
// detect APIC
cpuid_t cpuid_info;
cpuid_info.eax = 1;
cpuid_info.ebx = 0;
cpuid_info.ecx = 0;
cpuid_info.edx = 0;
hal_cpuid(&cpuid_info.eax, &cpuid_info.ebx, &cpuid_info.ecx, &cpuid_info.edx);
if (cpuid_info.edx & 1 << 9)
{
//TODO: detected.
}
else
{
// halt machine
hal_printf("HAL: Cannot detect APIC.");
hal_halt_cpu();
}
return boot_info;
return hal_info;
}

View File

@ -2,7 +2,7 @@
; Distributed under GPL license
; See COPYING under root for details
%macro pushaq 0
%macro PUSHAQ 0
push rax ;save current rax
push rbx ;save current rbx
push rcx ;save current rcx
@ -20,7 +20,7 @@
push r15 ;save current r15
%endmacro
%macro popaq 0
%macro POPAQ 0
pop r15 ;restore current r15
pop r14 ;restore current r14
pop r13 ;restore current r13
@ -38,58 +38,89 @@
pop rax ;restore current rax
%endmacro
%macro hal_interrupt_handler 1
global hal_interrupt_handler_%1
hal_interrupt_handler_%1:
; save top of stack
; NOW STACK:
; +40 SS
; +32 RSP
; +24 RFLAGS
; +16 CS
; +8 RIP
; +0 RBP
push rbp
mov rbp,rsp
PUSHAQ
cld
mov rdi, %1 ; INT VEC #
mov rsi, rbp ; PTR to RIP
add rsi, 8
mov rdx, 0 ; ERROR = 0, in this case
call hal_interrupt_dispatcher
POPAQ
pop rbp
iretq
%endmacro
%macro hal_interrupt_err_handler 1
global hal_interrupt_handler_%1
hal_interrupt_handler_%1:
; save top of stack
; NOW STACK:
; +48 SS
; +40 RSP
; +32 RFLAGS
; +24 CS
; +16 RIP
; +8 ERROR CODE
; +0 RBP
push rbp
mov rbp,rsp
PUSHAQ
cld
mov rdi, %1 ; INT VEC #
mov rsi, rbp ; PTR to RIP
add rsi, 16
mov rdx, qword [rbp + 8] ; ERRPO CODE
call hal_interrupt_dispatcher
POPAQ
pop rbp
add rsp, 8 ; skip the error code
iretq
%endmacro
[SECTION .text]
[BITS 64]
;====================
global hal_write_port
hal_write_port:
mov rdx,rdi
mov rax,rsi
out dx,eax
nop
nop
ret
;====================
global hal_read_port
hal_read_port:
mov rdx,rdi
xor rax,rax
in eax,dx
nop
nop
ret
;====================
global hal_disable_interrupt
hal_disable_interrupt:
cli
ret
;====================
global hal_enable_interrupt
hal_enable_interrupt:
sti
ret
;====================
global hal_interrupt_handler
extern hal_interrupt_dispatcher
hal_interrupt_handler:
pushaq
cld
call hal_interrupt_dispatcher
popaq
iretq
;====================
global hal_halt_cpu
hal_halt_cpu:
hlt
ret
hal_interrupt_handler 0
hal_interrupt_handler 1
hal_interrupt_handler 2
hal_interrupt_handler 3
hal_interrupt_handler 4
hal_interrupt_handler 5
hal_interrupt_handler 6
hal_interrupt_handler 7
hal_interrupt_err_handler 8
hal_interrupt_err_handler 10
hal_interrupt_err_handler 11
hal_interrupt_err_handler 12
hal_interrupt_err_handler 13
hal_interrupt_err_handler 14
hal_interrupt_handler 16
hal_interrupt_err_handler 17
hal_interrupt_handler 18
hal_interrupt_handler 19
hal_interrupt_handler 20
;====================
global hal_bochs_magic_breakpoint
hal_bochs_magic_breakpoint:
xchg bx,bx
ret
; user defined
hal_interrupt_handler 32
hal_interrupt_handler 33
hal_interrupt_handler 34
hal_interrupt_handler 35
hal_interrupt_handler 36
hal_interrupt_handler 37
hal_interrupt_handler 38
hal_interrupt_handler 39

View File

@ -3,9 +3,12 @@
* See COPYING under root for details
*/
#include "bit_ops.h"
#include "hal_arch.h"
#include "hal_intr.h"
#include "hal_print.h"
#include "hal_mem.h"
#include "hal_var.h"
void KAPI hal_write_gate(void *const gate,
uint64_t const offset,
@ -34,8 +37,32 @@ void KAPI hal_write_gate(void *const gate,
void KAPI hal_set_interrupt_handler(uint64_t index,
void (*handler)(void))
{
hal_write_gate(g_idt + 16 * index, (uint64_t) handler, seg_selector(1, 0),
GATE_DPL_0 | GATE_PRESENT | GATE_TYPE_INTERRUPT);
if(index < IDT_ENTRY_NUM)
{
hal_write_gate(g_idt + 16 * index, (uint64_t) handler, seg_selector(1, 0),
GATE_DPL_0 | GATE_PRESENT | GATE_TYPE_INTERRUPT);
}
return;
}
void KAPI hal_register_interrupt_handler(uint64_t index,
void (*handler)(uint64_t pc,
uint64_t sp,
uint64_t error))
{
if(index < IDT_ENTRY_NUM)
{
g_intr_handler_table[index] = handler;
}
return;
}
void KAPI hal_deregister_interrupt_handler(uint64_t index)
{
if(index < IDT_ENTRY_NUM)
{
g_intr_handler_table[index] = NULL;
}
return;
}
@ -50,8 +77,109 @@ void KAPI hal_assert(int64_t expression,
return;
}
void KAPI hal_interrupt_dispatcher(void)
void KAPI hal_interrupt_dispatcher(uint64_t int_vec, hal_intr_context_t* context, uint64_t error_code)
{
hal_printf("Yep... That just happened, an interrupt...\n");
if(g_intr_handler_table[int_vec] == NULL)
{
hal_printf("Unhandled interrupt %d at 0x%X. Err: %d.\n", int_vec, context->rip, error_code);
}
else
{
g_intr_handler_table[int_vec](context->rip, context->rsp, int_vec);
}
return;
}
static void KAPI _hal_populate_idt()
{
hal_set_interrupt_handler(0, hal_interrupt_handler_0);
hal_set_interrupt_handler(1, hal_interrupt_handler_1);
hal_set_interrupt_handler(2, hal_interrupt_handler_2);
hal_set_interrupt_handler(3, hal_interrupt_handler_3);
hal_set_interrupt_handler(4, hal_interrupt_handler_4);
hal_set_interrupt_handler(5, hal_interrupt_handler_5);
hal_set_interrupt_handler(6, hal_interrupt_handler_6);
hal_set_interrupt_handler(7, hal_interrupt_handler_7);
hal_set_interrupt_handler(8, hal_interrupt_handler_8);
hal_set_interrupt_handler(10, hal_interrupt_handler_10);
hal_set_interrupt_handler(11, hal_interrupt_handler_11);
hal_set_interrupt_handler(12, hal_interrupt_handler_12);
hal_set_interrupt_handler(13, hal_interrupt_handler_13);
hal_set_interrupt_handler(14, hal_interrupt_handler_14);
hal_set_interrupt_handler(16, hal_interrupt_handler_16);
hal_set_interrupt_handler(17, hal_interrupt_handler_17);
hal_set_interrupt_handler(18, hal_interrupt_handler_18);
hal_set_interrupt_handler(19, hal_interrupt_handler_19);
hal_set_interrupt_handler(20, hal_interrupt_handler_20);
hal_set_interrupt_handler(32, hal_interrupt_handler_32);
hal_set_interrupt_handler(33, hal_interrupt_handler_33);
hal_set_interrupt_handler(34, hal_interrupt_handler_34);
hal_set_interrupt_handler(35, hal_interrupt_handler_35);
hal_set_interrupt_handler(36, hal_interrupt_handler_36);
hal_set_interrupt_handler(37, hal_interrupt_handler_37);
hal_set_interrupt_handler(38, hal_interrupt_handler_38);
hal_set_interrupt_handler(39, hal_interrupt_handler_39);
return;
}
int32_t KAPI hal_interrupt_init(void)
{
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
eax = 1;
hal_cpuid(&eax,&ebx,&ecx,&edx);
if(!(edx & bit_mask_32(9)))
{
hal_printf("ERROR: APIC not supported by CPU.\n");
return 1;
}
// get idt ptr ready
g_idt_ptr.base = (uint64_t) g_idt;
g_idt_ptr.limit = IDT_ENTRY_NUM * IDT_ENTRY_SIZE - 1;
// clear dispatch table
for(uint64_t i = 0; i < IDT_ENTRY_NUM; i++)
{
g_intr_handler_table[i] = NULL;
}
// hook asm interrupt handlers
_hal_populate_idt();
hal_flush_idt(&g_idt_ptr);
// disable PIC
hal_write_port(0xa1, 0xff);
hal_write_port(0x21, 0xff);
uint64_t apic_base_reg = 0;
uint64_t apic_base = 0;
ecx = MSR_IA32_APIC_BASE;
hal_read_msr(&ecx, &edx, &eax);
apic_base_reg = ((uint64_t)edx << 32) + (uint64_t)eax;
apic_base = apic_base_reg & bit_field_mask_64(12,35);
hal_printf("APIC Base: 0x%X\n", apic_base);
hal_printf("APIC Enabled: %s\n", apic_base_reg & bit_mask_64(11) ? "Yes" : "No");
hal_printf("BSP: %s\n", apic_base_reg & bit_mask_64(8) ? "Yes" : "No");
hal_printf("APIC Spour: 0x%X\n", *(uint32_t*)((char*)apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET));
// hardware enable APIC
ecx = MSR_IA32_APIC_BASE;
eax = (uint32_t)(apic_base_reg & bit_field_mask_64(0,31)) | bit_mask_32(11);
hal_write_msr(&ecx, &edx, &eax);
// software enable APIC
hal_write_mem_32((char*)apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET,
*(uint32_t*)((char*)apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET) | bit_mask_32(8));
// for(int i = 0; i < IDT_ENTRY_NUM; i++)
// {
// hal_printf("IDT%d: %d,%d,%d,%d",i, (uint64_t)g_idt);
// }
hal_trigger_interrupt(33);
hal_halt_cpu();
hal_enable_interrupt();
return 0;
}

View File

@ -1,81 +0,0 @@
; Copyright 2016 secXsQuared
; Distributed under GPL license
; See COPYING under root for details
;Functions preserve the registers rbx, rsp, rbp, r12, r13, r14, and 15
;rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11 are scratch registers.
;function parameter: rdi,rsi,rdx,rcx,r8,r9
[SECTION .text]
[BITS 64]
;======================
global hal_flush_gdt
hal_flush_gdt:
push rbp
mov rbp,rsp
lgdt [rdi]
;reload cs
push rdx ; data_slct : ss
push rbp ; rsp
pushfq
pop rax
push rax ; eflags
push rsi ; cs
push qword .reload ;eip
iretq
.reload:
mov es,dx
mov fs,dx
mov gs,dx
mov ds,dx
mov rsp,rbp
pop rbp
ret
;======================
global hal_flush_tlb
;void flush_tlb(void)
hal_flush_tlb:
mov rax,cr3
mov cr3,rax
ret
;======================
global hal_cpuid
;void get_cpuid(int64_t* rax, int64_t* rbx, int64_t* rcx, int64_t* rdx)
hal_cpuid:
mov rax,[rdi]
push rcx
mov rcx,[rdx]
cpuid
mov [rdi],rax
mov [rsi],rbx
mov [rdx],rcx
pop rcx
mov [rcx],rdx
ret
;======================
global hal_flush_idt
hal_flush_idt:
lidt [rdi]
ret
;======================
global hal_read_page_base
hal_read_page_base:
mov rax,cr3
mov r11,0xFFFFFFFFFF000
and rax,r11 ;keep bits 12-51
ret
;======================
global hal_write_page_base
hal_write_page_base:
mov r11,0xFFFFFFFFFF000
and rdi,r11 ;keep bits 12-51
mov cr3,rdi
ret

View File

@ -3,10 +3,12 @@
* See COPYING under root for details
*/
#include "hal_intr.h"
#include "hal_var.h"
uint8_t g_gdt[8*9];
uint8_t g_idt[21*16];
gdt_ptr_t g_gdt_ptr;
idt_ptr_t g_idt_ptr;
uint8_t g_idt[IDT_ENTRY_NUM*IDT_ENTRY_SIZE];
void (*g_intr_handler_table[IDT_ENTRY_SIZE])(uint64_t pc, uint64_t sp, uint64_t error);
hal_gdt_ptr_t g_gdt_ptr;
hal_idt_ptr_t g_idt_ptr;
uint64_t text_pos;

View File

@ -0,0 +1,53 @@
#ifndef _HAL_ARCH_H_
#define _HAL_ARCH_H_
#include "k_def.h"
typedef struct __attribute__ ((packed))
{
uint16_t limit;
uint64_t base;
} hal_gdt_ptr_t;
typedef struct __attribute__ ((packed))
{
uint16_t limit;
uint64_t base;
} hal_idt_ptr_t;
extern uint64_t KAPI hal_interlocked_exchange(uint64_t *dst, uint64_t val);
extern void KAPI hal_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
#define MSR_IA32_APIC_BASE 0x1B
extern void KAPI hal_read_msr(uint32_t *ecx, uint32_t *edx, uint32_t *eax);
extern void KAPI hal_write_msr(uint32_t *ecx, uint32_t *edx, uint32_t *eax);
extern void KAPI hal_enable_interrupt();
extern void KAPI hal_disable_interrupt();
extern void KAPI hal_halt_cpu();
extern void KAPI hal_write_port(uint64_t port, int64_t data);
extern int64_t KAPI hal_read_port(uint64_t port);
extern void KAPI hal_write_mem_32(void* target, uint32_t data);
extern void KAPI hal_write_mem_64(void* target, uint64_t data);
extern void KAPI hal_flush_gdt(hal_gdt_ptr_t *gdt_ptr, uint64_t code_slct, uint64_t data_slct);
extern void KAPI hal_flush_tlb();
#define hal_trigger_interrupt(x) __asm__ __volatile__ ("int "#x);
extern void KAPI hal_flush_idt(hal_idt_ptr_t *idt_ptr);
extern void KAPI hal_write_cr3(uint64_t base);
extern uint64_t KAPI hal_read_cr3();
#endif

View File

@ -1,6 +0,0 @@
#ifndef _HAL_ATOMIC_H_
#define _HAL_ATOMIC_H_
#include "k_def.h"
extern uint64_t KAPI hal_interlocked_exchange(uint64_t* dst, uint64_t val);
#endif

View File

@ -5,6 +5,7 @@
#ifndef _HAL_IO_H_
#define _HAL_IO_H_
#include "k_def.h"
#include "k_type.h"
@ -17,20 +18,71 @@
#define GATE_TYPE_INTERRUPT (14ull << 8)
#define GATE_TYPE_TRAP (15ull << 8)
extern void KAPI hal_write_port(uint64_t port, int64_t data);
extern int64_t KAPI hal_read_port(uint64_t port);
void KAPI hal_interrupt_handler_dispatcher();
#define IDT_ENTRY_NUM 40
#define IDT_ENTRY_SIZE 16
#define APIC_SPURIOUS_INT_VEC_REG_OFFSET 0xF0
#define APIC_LVT_CMCI_REG_OFFSET 0x2F0
#define APIC_LVT_TIMER_REG_OFFSET 0x320
#define APIC_LVT_THERMA_MONITOR_REG 0x330
#define APIC_LVT_PERFORMANCE_COUNTER_REG 0x340
#define APIC_LVT_LINT0_REG 0x350
#define APIC_LVT_LINT1_REG 0x360
#define APIC_LVT_ERROR_REG 0x370
// SYSTEM INTERRUPT HANDLERS
extern void hal_interrupt_handler_0(void);
extern void hal_interrupt_handler_1(void);
extern void hal_interrupt_handler_2(void);
extern void hal_interrupt_handler_3(void);
extern void hal_interrupt_handler_4(void);
extern void hal_interrupt_handler_5(void);
extern void hal_interrupt_handler_6(void);
extern void hal_interrupt_handler_7(void);
extern void hal_interrupt_handler_8(void);
extern void hal_interrupt_handler_10(void);
extern void hal_interrupt_handler_11(void);
extern void hal_interrupt_handler_12(void);
extern void hal_interrupt_handler_13(void);
extern void hal_interrupt_handler_14(void);
extern void hal_interrupt_handler_16(void);
extern void hal_interrupt_handler_17(void);
extern void hal_interrupt_handler_18(void);
extern void hal_interrupt_handler_19(void);
extern void hal_interrupt_handler_20(void);
// USER DEFINED INTERRUPT_HANDLERS
extern void hal_interrupt_handler_32(void);
extern void hal_interrupt_handler_33(void);
extern void hal_interrupt_handler_34(void);
extern void hal_interrupt_handler_35(void);
extern void hal_interrupt_handler_36(void);
extern void hal_interrupt_handler_37(void);
extern void hal_interrupt_handler_38(void);
extern void hal_interrupt_handler_39(void);
typedef struct
{
const uint64_t rip;
const uint64_t cs;
const uint64_t rflags;
const uint64_t rsp;
const uint64_t ss;
} hal_intr_context_t;
void KAPI hal_register_interrupt_handler(uint64_t index,
void (*handler)(uint64_t pc,
uint64_t sp,
uint64_t error));
void KAPI hal_deregister_interrupt_handler(uint64_t index);
void KAPI hal_set_interrupt_handler(uint64_t index, void (*handler)(void));
extern void KAPI hal_enable_interrupt();
extern void KAPI hal_disable_interrupt();
extern void KAPI hal_interrupt_handler_wrapper();
extern void KAPI hal_halt_cpu();
void KAPI hal_write_gate(void *const gate, uint64_t const offset, uint32_t const selector, uint32_t const attr);
//assert
void KAPI hal_assert(int64_t exp, char* message);
void KAPI hal_assert(int64_t exp, char *message);
int32_t KAPI hal_interrupt_init(void);
extern uint8_t g_idt[];
#endif

View File

@ -10,6 +10,9 @@
#include "k_type.h"
#include "linked_list.h"
#define GDT_ENTRY_SIZE 8
#define GDT_ENTRY_NUM 9
static inline uint32_t KAPI seg_selector(uint32_t index, uint32_t rpl)
{
@ -78,44 +81,12 @@ static inline uint32_t KAPI seg_selector(uint32_t index, uint32_t rpl)
#define PHYSICAL_PAGE_SIZE 4096
typedef struct __attribute__ ((packed))
{
uint16_t limit;
uint64_t base;
} gdt_ptr_t;
typedef struct __attribute__ ((packed))
{
uint16_t limit;
uint64_t base;
} idt_ptr_t;
typedef struct __attribute__((packed))
{
uint64_t eax;
uint64_t ebx;
uint64_t ecx;
uint64_t edx;
} cpuid_t;
void* KAPI halloc(uint32_t size);
void KAPI hfree(void *ptr);
void KAPI hal_alloc_init();
extern void KAPI hal_flush_gdt(gdt_ptr_t *gdt_ptr, uint64_t code_slct, uint64_t data_slct);
extern void KAPI hal_flush_tlb();
extern void KAPI hal_cpuid(uint64_t * eax, uint64_t * ebx, uint64_t* ecx, uint64_t* edx);
extern void KAPI hal_flush_idt(idt_ptr_t* idt_ptr);
extern void KAPI hal_write_page_base(void* base);
extern void*KAPI hal_read_page_base();
void KAPI hal_write_segment_descriptor(void *const gdt, uint32_t const base, uint32_t const limit, uint64_t const attr);
void KAPI hal_write_pml4_entry(void *const base, uint64_t const pdpt_addr, uint64_t const attr);

View File

@ -8,11 +8,14 @@
#include "hal_mem.h"
#include "linked_list.h"
#include "hal_arch.h"
#include "hal_intr.h"
extern uint8_t g_gdt[8*9];
extern uint8_t g_idt[21*16];
extern gdt_ptr_t g_gdt_ptr;
extern idt_ptr_t g_idt_ptr;
extern uint8_t g_gdt[];
extern uint8_t g_idt[];
extern void (*g_intr_handler_table[IDT_ENTRY_SIZE])(uint64_t pc, uint64_t sp, uint64_t error);
extern hal_gdt_ptr_t g_gdt_ptr;
extern hal_idt_ptr_t g_idt_ptr;
extern uint64_t text_pos;
#endif

View File

@ -14,7 +14,14 @@ extern void KAPI hal_enable_interrupt();
extern void KAPI hal_disable_interrupt();
extern void KAPI hal_mask_interrupt();
extern void KAPI hal_unmask_interrupt();
extern void KAPI hal_set_interrupt_handler(uint64_t index, void (*handler)(void));
extern void KAPI hal_register_interrupt_handler(uint64_t index,
void (*handler)(uint64_t pc,
uint64_t sp,
uint64_t error));
extern void KAPI hal_deregister_interrupt_handler(uint64_t index);
#define hal_trigger_interrupt(x) __asm__ __volatile__ ("int "#x);
// concurrency
extern uint64_t KAPI hal_interlocked_exchange(uint64_t* dst, uint64_t val);
@ -24,7 +31,7 @@ extern char kernel_start[];
extern char kernel_end[];
// hal init
extern boot_info_t* KAPI hal_init(void* m_info);
extern k_hal_info_t* KAPI hal_init(char* m_info);
// hal output
extern void KAPI hal_printf(char const *format, ...);

View File

@ -14,7 +14,7 @@ typedef uint64_t k_irql_t;
#define IRQL_APC 2
#define IRQL_USER 3
void KAPI k_set_interrupt_handler(uint64_t index, void (*handler)(void));
void KAPI k_register_interrupt_handler(uint64_t index, void (*handler)(uint64_t pc, uint64_t sp, uint64_t error));
void KAPI k_disable_interrupt();

View File

@ -3,16 +3,25 @@
* See COPYING under root for details
*/
#include <k_sys_info.h>
#include "k_def.h"
#include "k_hal.h"
#include "std_lib.h"
#include "k_lib_test.h"
// returning from this function results in halting the cpu
void KAPI kmain(void *multiboot_info)
{
boot_info_t* boot_info = hal_init(multiboot_info);
k_hal_info_t* boot_info = hal_init(multiboot_info);
if(boot_info == NULL)
{
hal_printf("HAL failed.\n");
hal_halt_cpu();
}
hal_printf("Kernel Loaded at 0x%X. Size: %uB, %uKB\n\n",kernel_start,(kernel_end-kernel_start),(kernel_end-kernel_start)/1024);
hal_printf("CPU Vendor:%s\n", boot_info->cpu_vendor_string);
linked_list_test();
avl_tree_test();
@ -50,13 +59,6 @@ void KAPI kmain(void *multiboot_info)
};
}
// setup interrupt
// for(uint64_t i = 0; i <= 21; i++)
// {
// hal_set_interrupt_handler(i, hal_interrupt_handler_wrapper);
// }
// hal_enable_interrupt();
hal_printf("KRNL: Kernel task finished.");
hal_halt_cpu();
}

View File

@ -1,9 +1,14 @@
#include "k_intr.h"
#include "k_hal.h"
void KAPI k_set_interrupt_handler(uint64_t index, void (*handler)(void))
void KAPI k_register_interrupt_handler(uint64_t index, void (*handler)(uint64_t pc, uint64_t sp, uint64_t error))
{
hal_set_interrupt_handler(index, handler);
hal_register_interrupt_handler(index, handler);
}
void KAPI k_deregister_interrupt_handler(uint64_t index, void (*handler)(uint64_t pc, uint64_t sp, uint64_t error))
{
hal_register_interrupt_handler(index, handler);
}
void KAPI k_disable_interrupt()