Enable apic and ioapic
This commit is contained in:
parent
95108d1c0a
commit
1d15768efb
@ -30,6 +30,8 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
|
||||
|
||||
cpu_init();
|
||||
|
||||
__asm__("sti");
|
||||
|
||||
debug_info("Boot complete\n");
|
||||
|
||||
|
||||
|
86
src/kernel/cpu/apic.c
Normal file
86
src/kernel/cpu/apic.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include <cpu.h>
|
||||
#include <memory.h>
|
||||
#include <debug.h>
|
||||
#include <ports.h>
|
||||
|
||||
#define APIC_BASE 0xFEE00000
|
||||
|
||||
#define APIC_MSR_ENABLE (1<<11)
|
||||
|
||||
#define APIC_REG(r) (((uint32_t *)P2V(APIC_BASE + (r)))[0])
|
||||
|
||||
union ioapic_redirection{
|
||||
uint64_t val;
|
||||
struct {
|
||||
uint32_t l;
|
||||
uint32_t h;
|
||||
}__attribute__((packed));
|
||||
struct {
|
||||
uint8_t vector;
|
||||
uint8_t flags;
|
||||
uint8_t mask;
|
||||
uint32_t reserved;
|
||||
uint8_t target;
|
||||
}__attribute__((packed));
|
||||
};
|
||||
|
||||
static uint32_t ioapic_read(int reg)
|
||||
{
|
||||
uint32_t volatile *ioregsel = P2V(ioapic.addr);
|
||||
uint32_t volatile *iowin = P2V(ioapic.addr + 0x10);
|
||||
*ioregsel = reg;
|
||||
return *iowin;
|
||||
}
|
||||
static void ioapic_write(int reg, uint32_t value)
|
||||
{
|
||||
uint32_t volatile *ioregsel = P2V(ioapic.addr);
|
||||
uint32_t volatile *iowin = P2V(ioapic.addr + 0x10);
|
||||
*ioregsel = reg;
|
||||
*iowin = value;
|
||||
}
|
||||
|
||||
static uint64_t ioapic_read_redirection(int irq)
|
||||
{
|
||||
union ioapic_redirection retval;
|
||||
retval.l = ioapic_read(0x10 + 2*irq);
|
||||
retval.h = ioapic_read(0x11 + 2*irq);
|
||||
return retval.val;
|
||||
}
|
||||
static void ioapic_write_redirection(int irq, uint64_t val)
|
||||
{
|
||||
union ioapic_redirection value;
|
||||
value.val = val;
|
||||
ioapic_write(0x10 + 2*irq, value.l);
|
||||
ioapic_write(0x11 + 2*irq, value.h);
|
||||
}
|
||||
|
||||
void ioapic_init()
|
||||
{
|
||||
vmm_set_page(kernel_P4, (uintptr_t)P2V(ioapic.addr), ioapic.addr, PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL);
|
||||
|
||||
union ioapic_redirection red;
|
||||
for(int i = 0; i < 24; i++)
|
||||
{
|
||||
red.val = ioapic_read_redirection(i);
|
||||
red.vector = IRQ_BASE+i;
|
||||
red.flags = 0x0;
|
||||
if(i == 1) // Mask the timer interrupt
|
||||
red.mask &= ~0x1;
|
||||
else // but unmask all others for testing
|
||||
red.mask |= 0x1;
|
||||
red.target = 0x0;
|
||||
ioapic_write_redirection(i, red.val);
|
||||
}
|
||||
}
|
||||
|
||||
void apic_init()
|
||||
{
|
||||
// Enable local APIC
|
||||
write_msr(MSR_APIC_BASE, read_msr(MSR_APIC_BASE) | APIC_MSR_ENABLE);
|
||||
|
||||
// Map apic offset into kernel memory
|
||||
vmm_set_page(kernel_P4, (uintptr_t)P2V(APIC_BASE), APIC_BASE, PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL);
|
||||
|
||||
APIC_REG(0xF0) = APIC_REG(0xF0) | (1<<8);
|
||||
APIC_REG(0xB0) = 0;
|
||||
}
|
@ -7,6 +7,26 @@ struct ioapic ioapic = {0,0,0};
|
||||
uint8_t irq_redirects[MAX_IRQS] = \
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
|
||||
|
||||
#define PIC1_ADDR 0x20
|
||||
#define PIC2_ADDR 0xA0
|
||||
#define PIC_INITIALIZE 0x10
|
||||
#define PIC_SINGLE 0x02
|
||||
static void pic_disable()
|
||||
{
|
||||
// Absolute minimum work to initialize and disable legacy PIC.
|
||||
// Both the primary and secondary PIC will think they are alone
|
||||
// in a MCS-80 arch computer but that doesn't matter since all
|
||||
// interrupts will be masked anyway :)
|
||||
// Ref: Intel 8259A Datasheet
|
||||
outb(PIC1_ADDR, PIC_INITIALIZE | PIC_SINGLE);
|
||||
outb(PIC2_ADDR, PIC_INITIALIZE | PIC_SINGLE);
|
||||
outb(PIC1_ADDR | 1, 0);
|
||||
outb(PIC2_ADDR | 1, 0);
|
||||
// Mask all interrupts
|
||||
outb(PIC1_ADDR | 1, 0xFF);
|
||||
outb(PIC2_ADDR | 1, 0xFF);
|
||||
}
|
||||
|
||||
void early_cpu_init()
|
||||
{
|
||||
interrupt_init();
|
||||
@ -15,4 +35,7 @@ void early_cpu_init()
|
||||
void cpu_init()
|
||||
{
|
||||
acpi_parse();
|
||||
pic_disable();
|
||||
apic_init();
|
||||
ioapic_init();
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#define MSR_APIC_BASE 0x0000001B
|
||||
|
||||
#define MAX_CPUS 16
|
||||
#define MAX_IRQS 24
|
||||
#define IRQ_BASE 0x20
|
||||
|
||||
struct cpu {
|
||||
uint8_t id;
|
||||
@ -31,3 +34,7 @@ uint64_t write_msr(uint32_t msr, uint64_t value);
|
||||
|
||||
// cpu/acpi.c
|
||||
void acpi_parse();
|
||||
|
||||
// cpu/apic.c
|
||||
void apic_init();
|
||||
void ioapic_init();
|
Loading…
x
Reference in New Issue
Block a user