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();
|
cpu_init();
|
||||||
|
|
||||||
|
__asm__("sti");
|
||||||
|
|
||||||
debug_info("Boot complete\n");
|
debug_info("Boot complete\n");
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
|
|||||||
start_scheduler();
|
start_scheduler();
|
||||||
|
|
||||||
PANIC("End of kernel function!");
|
PANIC("End of kernel function!");
|
||||||
|
|
||||||
debug_info("Broke out of panic");
|
debug_info("Broke out of panic");
|
||||||
for(;;);
|
for(;;);
|
||||||
}
|
}
|
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] = \
|
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};
|
{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()
|
void early_cpu_init()
|
||||||
{
|
{
|
||||||
interrupt_init();
|
interrupt_init();
|
||||||
@ -15,4 +35,7 @@ void early_cpu_init()
|
|||||||
void cpu_init()
|
void cpu_init()
|
||||||
{
|
{
|
||||||
acpi_parse();
|
acpi_parse();
|
||||||
|
pic_disable();
|
||||||
|
apic_init();
|
||||||
|
ioapic_init();
|
||||||
}
|
}
|
@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MSR_APIC_BASE 0x0000001B
|
||||||
|
|
||||||
#define MAX_CPUS 16
|
#define MAX_CPUS 16
|
||||||
#define MAX_IRQS 24
|
#define MAX_IRQS 24
|
||||||
|
#define IRQ_BASE 0x20
|
||||||
|
|
||||||
struct cpu {
|
struct cpu {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
@ -30,4 +33,8 @@ uint64_t read_msr(uint32_t);
|
|||||||
uint64_t write_msr(uint32_t msr, uint64_t value);
|
uint64_t write_msr(uint32_t msr, uint64_t value);
|
||||||
|
|
||||||
// cpu/acpi.c
|
// cpu/acpi.c
|
||||||
void acpi_parse();
|
void acpi_parse();
|
||||||
|
|
||||||
|
// cpu/apic.c
|
||||||
|
void apic_init();
|
||||||
|
void ioapic_init();
|
Loading…
x
Reference in New Issue
Block a user