2016-05-24 07:27:26 +00:00
|
|
|
/* Copyright 2016 secXsQuared
|
|
|
|
* Distributed under GPL license
|
|
|
|
* See COPYING under root for details
|
|
|
|
*/
|
|
|
|
|
2016-06-14 06:33:31 +00:00
|
|
|
#include <hal_arch.h>
|
2016-06-13 04:11:38 +00:00
|
|
|
#include "bit_ops.h"
|
|
|
|
#include "hal_arch.h"
|
2016-06-01 05:00:29 +00:00
|
|
|
#include "hal_intr.h"
|
2016-05-22 01:54:29 +00:00
|
|
|
#include "hal_print.h"
|
|
|
|
#include "hal_mem.h"
|
2016-06-13 04:11:38 +00:00
|
|
|
#include "hal_var.h"
|
2015-04-22 08:06:15 +00:00
|
|
|
|
2016-06-01 05:00:29 +00:00
|
|
|
void KAPI hal_write_gate(void *const gate,
|
2016-05-17 19:03:18 +00:00
|
|
|
uint64_t const offset,
|
|
|
|
uint32_t const selector,
|
|
|
|
uint32_t const attr)
|
2015-04-22 08:06:15 +00:00
|
|
|
{
|
2015-11-14 22:53:30 +00:00
|
|
|
((uint8_t *) gate)[0] = (uint8_t) (offset & 0xFF);
|
|
|
|
((uint8_t *) gate)[1] = (uint8_t) ((offset >> 8) & 0xFF);
|
|
|
|
((uint8_t *) gate)[2] = (uint8_t) (selector & 0xFF);
|
|
|
|
((uint8_t *) gate)[3] = (uint8_t) ((selector >> 8) & 0xFF);
|
|
|
|
((uint8_t *) gate)[4] = (uint8_t) (attr & 0xFF);
|
|
|
|
((uint8_t *) gate)[5] = (uint8_t) ((attr >> 8) & 0xFF);
|
|
|
|
((uint8_t *) gate)[6] = (uint8_t) ((offset >> 16) & 0xFF);
|
|
|
|
((uint8_t *) gate)[7] = (uint8_t) ((offset >> 24) & 0xFF);
|
|
|
|
((uint8_t *) gate)[8] = (uint8_t) ((offset >> 32) & 0xFF);
|
|
|
|
((uint8_t *) gate)[9] = (uint8_t) ((offset >> 40) & 0xFF);
|
|
|
|
((uint8_t *) gate)[10] = (uint8_t) ((offset >> 48) & 0xFF);
|
|
|
|
((uint8_t *) gate)[11] = (uint8_t) ((offset >> 56) & 0xFF);
|
|
|
|
((uint8_t *) gate)[12] = 0;
|
|
|
|
((uint8_t *) gate)[13] = 0;
|
|
|
|
((uint8_t *) gate)[14] = 0;
|
|
|
|
((uint8_t *) gate)[15] = 0;
|
|
|
|
return;
|
2015-04-22 08:06:15 +00:00
|
|
|
}
|
|
|
|
|
2016-06-01 05:00:29 +00:00
|
|
|
void KAPI hal_set_interrupt_handler(uint64_t index,
|
2016-05-17 19:03:18 +00:00
|
|
|
void (*handler)(void))
|
2015-04-22 08:06:15 +00:00
|
|
|
{
|
2016-06-13 04:11:38 +00:00
|
|
|
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;
|
|
|
|
}
|
2015-11-14 22:53:30 +00:00
|
|
|
return;
|
2015-09-03 14:45:28 +00:00
|
|
|
}
|
|
|
|
|
2016-06-01 05:00:29 +00:00
|
|
|
void KAPI hal_assert(int64_t expression,
|
2016-05-17 19:03:18 +00:00
|
|
|
char *message)
|
2015-09-03 14:45:28 +00:00
|
|
|
{
|
2015-11-14 22:53:30 +00:00
|
|
|
if (!expression)
|
2015-09-03 14:45:28 +00:00
|
|
|
{
|
|
|
|
hal_printf("HAL: Assertion failed. Detail: %s", message == NULL ? "NULL" : message);
|
2015-09-04 01:49:37 +00:00
|
|
|
hal_halt_cpu();
|
2015-09-03 14:45:28 +00:00
|
|
|
}
|
2015-11-14 22:53:30 +00:00
|
|
|
return;
|
2016-05-22 01:54:29 +00:00
|
|
|
}
|
2016-06-04 09:41:56 +00:00
|
|
|
|
2016-06-13 04:11:38 +00:00
|
|
|
void KAPI hal_interrupt_dispatcher(uint64_t int_vec, hal_intr_context_t* context, uint64_t error_code)
|
2016-06-04 09:41:56 +00:00
|
|
|
{
|
2016-06-13 04:11:38 +00:00
|
|
|
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);
|
|
|
|
}
|
2016-06-04 09:41:56 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-06-13 04:11:38 +00:00
|
|
|
|
|
|
|
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_enable_interrupt();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|