[MODERN FEATURES] Enable APIC

This commit is contained in:
Thomas Lovén 2017-01-24 22:19:23 +01:00
parent 56d5fea388
commit 8bd9b0ef16
4 changed files with 82 additions and 0 deletions

View File

@ -8,6 +8,7 @@
#include <process.h>
#include <cpuid.h>
#include <acpi.h>
#include <apic.h>
void thread_function()
{
@ -33,6 +34,7 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
scheduler_init();
pic_init();
acpi_init();
apic_init();
process_t *p1 = process_spawn(0);

11
kernel/include/apic.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <stdint.h>
void apic_init();
void apic_interrupt(uint8_t destination, uint8_t level, uint8_t type, uint8_t vector);
void apic_ack();
#define APIC_INT_LEVEL_ASSERT 0x1
#define APIC_INT_LEVEL_DEASSERT 0x0
#define APIC_INT_TYPE_FIXED 0x0
#define APIC_INT_TYPE_INIT 0x5
#define APIC_INT_TYPE_STARTUP 0x6

View File

@ -58,6 +58,14 @@
#define INT_IRQ22 0x36
#define INT_IRQ23 0x37
#define INT_APIC_TIMER 0x40
#define INT_APIC_THERMAL 0x41
#define INT_APIC_PERF 0x42
#define INT_APIC_LINT0 0x43
#define INT_APIC_LINT1 0x44
#define INT_APIC_ERROR 0x45
#define INT_APIC_SPUR 0xFF
#ifndef __ASSEMBLER__
#include <stdint.h>

61
kernel/interrupts/apic.c Normal file
View File

@ -0,0 +1,61 @@
#include <apic.h>
#include <int.h>
#include <msr.h>
#include <debug.h>
#include <mem.h>
#define APIC_MSR_ENABLE 0x800
#define APIC_BASE 0xFEE00000
#define R_ID 0x020
#define R_VERSION 0x030
#define R_EOI 0x0B0
#define R_LDR 0x0D0
#define R_SPURIOUS 0x0F0
#define R_INT_CMD_LO 0x300
#define R_INT_CMD_HI 0x310
#define R_TIMER_LVT 0x320
#define R_THERMAL_LVT 0x330
#define R_PERF_LVT 0x340
#define R_LINT0_LVT 0x350
#define R_LINT1_LVT 0x360
#define R_ERROR_LVT 0x370
#define LVT_MASKED 0x10000
#define SPURIOUS_LVT_ENABLED 0x100
#define APIC(reg) apic[reg/4]
uint32_t volatile *apic = P2V(APIC_BASE);
void apic_interrupt(uint8_t destination, uint8_t level, uint8_t type, uint8_t vector)
{
uint64_t data = ((level & 0x1)<<14) | ((type & 0x7)<<8) | vector;
APIC(R_INT_CMD_HI) = destination << 24;
APIC(R_INT_CMD_LO) = data;
}
void apic_ack()
{
APIC(R_EOI) = 0;
}
void apic_init()
{
debug_info("APIC - APIC_BASE MSR: %x\n", msr_read(MSR_APIC_BASE));
// Enable APIC by setting the enable bit in the APIC MSR
msr_write(MSR_APIC_BASE, msr_read(MSR_APIC_BASE) | APIC_MSR_ENABLE);
// Make sure the APIC base addres is mapped in kernel memory
vmm_set_page(0, (uintptr_t)P2V(APIC_BASE), APIC_BASE, PAGE_PRESENT | PAGE_WRITE);
debug_info("APIC - ID: %x\n", APIC(R_ID));
debug_info("APIC - Version: %x\n", APIC(R_VERSION));
uint8_t id = APIC(R_ID) >> 24;
if(id <= 0)
APIC(R_LDR) = 1 << (24 + id);
APIC(R_SPURIOUS) = SPURIOUS_LVT_ENABLED | INT_APIC_SPUR;
APIC(R_EOI) = 0;
}