
modified: README.md modified: src/.gdb_history modified: src/bootloader/enter_kernel.asm modified: src/bootloader/gdt.asm modified: src/debug/gdbinit.gdb modified: src/include/int.h modified: src/include/paging.h modified: src/include/smp.h modified: src/include/smp_sync.h modified: src/indigo_os modified: src/kernel/int.c modified: src/kernel/kernel.c modified: src/kernel/klog.c modified: src/kernel/madt.c modified: src/kernel/page.c modified: src/kernel/panic.c modified: src/kernel/printf.c modified: src/kernel/smp.c modified: src/kernel/smp_trampoline.asm modified: .gitignore deleted: src/.gdb_history modified: .gitignore modified: README.md deleted: src/.gdb_history modified: src/bootloader/enter_kernel.asm modified: src/bootloader/gdt.asm modified: src/debug/gdbinit.gdb modified: src/include/int.h modified: src/include/paging.h modified: src/include/smp.h modified: src/include/smp_sync.h modified: src/indigo_os modified: src/kernel/int.c modified: src/kernel/kernel.c modified: src/kernel/klog.c modified: src/kernel/madt.c modified: src/kernel/page.c modified: src/kernel/panic.c modified: src/kernel/printf.c modified: src/kernel/smp.c modified: src/kernel/smp_trampoline.asm modified: README.md
248 lines
6.5 KiB
C
248 lines
6.5 KiB
C
#include <int.h>
|
|
#include <acpi.h>
|
|
#include <io.h>
|
|
#include <paging.h>
|
|
#include <printf.h>
|
|
#include <isv.h>
|
|
#include <addr.h>
|
|
#include <libc.h>
|
|
#include <madt.h>
|
|
#include <timer.h>
|
|
#include <panic.h>
|
|
|
|
#define SEGMENT_GDT 0
|
|
#define SEGMENT_LDT 1
|
|
|
|
|
|
|
|
//io commands
|
|
#define ICW1_ICW4 0x01
|
|
#define ICW1_INIT 0x10
|
|
|
|
#define ICW4_8086 0x01
|
|
|
|
|
|
// PIC
|
|
#define PICM_COMMAND 0x20
|
|
#define PICM_DATA 0x21
|
|
|
|
#define PICS_COMMAND 0xa0
|
|
#define PICS_DATA 0xa1
|
|
|
|
#define KERNEL_IDT_DESC_GATE(addr) \
|
|
((struct idt_descriptor) { \
|
|
.offset_1 = (uint16_t)((uint64_t)addr & 0xffff), \
|
|
.offset_2 = (uint16_t)((uint64_t)addr >> 16), \
|
|
.offset_3 = (uint32_t)((uint64_t)addr >> 32), \
|
|
.segment = 0x8, \
|
|
.ist = 0, \
|
|
.type = INT_GATE_64, \
|
|
.priv = 0, \
|
|
.reserved = 0, \
|
|
.reserved_1 = 0, \
|
|
.reserved_2 = 0, \
|
|
.present = 1 \
|
|
})
|
|
|
|
|
|
#define IOAPICR_VER 1
|
|
|
|
struct idt_descriptor {
|
|
uint16_t offset_1;
|
|
uint16_t segment;
|
|
unsigned int ist:3; //interupt stack table offset
|
|
unsigned int reserved:5;
|
|
unsigned int type:4;
|
|
unsigned int reserved_1:1;
|
|
unsigned int priv:2;
|
|
unsigned int present:1;
|
|
uint16_t offset_2;
|
|
uint32_t offset_3;
|
|
uint32_t reserved_2;
|
|
} __attribute__((packed));
|
|
|
|
|
|
struct segment_descriptor {
|
|
unsigned int priv:2;
|
|
unsigned int type:1;
|
|
unsigned int index:13;
|
|
} __attribute__((packed));
|
|
|
|
struct idt_reg {
|
|
uint16_t size;
|
|
uint64_t offset;
|
|
} __attribute__((packed));
|
|
|
|
struct idt_descriptor *idt;
|
|
|
|
static struct idt_reg idtr;
|
|
|
|
|
|
|
|
lapic_t lapic; //would make this static but it's needed by timer.c
|
|
static struct ioapic_fixedlen ioapic;
|
|
static uint64_t isr_bitmap[4]; //first 32 is for exceptions;
|
|
|
|
|
|
void disable_pic() {
|
|
//remapping PIC
|
|
outb_wait(PICM_COMMAND, ICW1_INIT | ICW1_ICW4); //initilizing
|
|
outb_wait(PICS_COMMAND, ICW1_INIT | ICW1_ICW4);
|
|
|
|
outb_wait(PICM_DATA, 32); //IRQ offsets
|
|
outb_wait(PICS_DATA, 40);
|
|
|
|
outb_wait(PICM_DATA, 4); //notify master of slave
|
|
outb_wait(PICS_DATA, 2); //nofity slave of mediocore social ethical standards
|
|
|
|
outb_wait(PICM_DATA, ICW4_8086);
|
|
outb_wait(PICS_DATA, ICW4_8086);
|
|
|
|
|
|
//masking.
|
|
outb_wait(PICS_DATA, 0xff);
|
|
outb_wait(PICM_DATA, 0xff);
|
|
}
|
|
|
|
void write_ioapic(void *ioapic_addr, uint32_t reg, uint32_t value) {
|
|
uint32_t *ioapic_r = ioapic_addr;
|
|
ioapic_r[0] = reg & 0xff;
|
|
ioapic_r[4] = value;
|
|
}
|
|
|
|
uint32_t read_ioapic(void *ioapic_addr, uint32_t reg) {
|
|
uint32_t *ioapic_r = ioapic_addr;
|
|
ioapic_r[0] = reg & 0xff;
|
|
return ioapic_r[4];
|
|
}
|
|
|
|
void create_fixed_interrupt(unsigned int irq, struct apic_vt *redirect) {
|
|
irq = irq_to_gsi(irq); //make sure there's no redirection entries.
|
|
|
|
struct ioapic_t *ioapic_smi = (void *)0;
|
|
for(unsigned int i = 0; i < ioapic.count; i++) {
|
|
if((irq >= ioapic.ioapic[i].gsi_base) &&
|
|
(irq < (ioapic.ioapic[i].gsi_base + ioapic.ioapic[i].gsi_count))) {
|
|
ioapic_smi = ioapic.ioapic[i].address;
|
|
break;
|
|
}
|
|
}
|
|
if(!ioapic_smi) PANIC(KERNEL_PANIC_INVALID_IOAPIC_VEC);
|
|
|
|
|
|
write_ioapic(ioapic_smi, (0x10 + (irq * 2)), *(uint32_t *)redirect);
|
|
write_ioapic(ioapic_smi, ((0x10 + (irq * 2)) + 1), *(uint64_t *)redirect >> 32);
|
|
}
|
|
|
|
unsigned int alloc_idt(struct idt_entry *entry) {
|
|
unsigned int b, i;
|
|
for(b = 0; b < (sizeof(isr_bitmap) / 8); b++) {
|
|
for(i = 0; i < 64; i++) {
|
|
if(!((isr_bitmap[b] >> i) & 1)) {
|
|
isr_bitmap[b] |= (uint64_t)1 << i;
|
|
idt[(b * 64) + i] = (struct idt_descriptor) {
|
|
.offset_1 = (uint16_t)((uint64_t)entry->addr & 0xffff),
|
|
.offset_2 = (uint16_t)((uint64_t)entry->addr >> 16),
|
|
.offset_3 = (uint32_t)((uint64_t)entry->addr >> 32),
|
|
.segment = 0x8,
|
|
.ist = entry->ist,
|
|
.type = entry->type,
|
|
.priv = entry->priv,
|
|
.reserved = 0,
|
|
.reserved_1 = 0,
|
|
.reserved_2 = 0,
|
|
.present = 1
|
|
};
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void modify_idt(struct idt_entry *entry, unsigned int vector) {
|
|
idt[vector] = (struct idt_descriptor) {
|
|
.offset_1 = (uint16_t)((uint64_t)entry->addr & 0xffff),
|
|
.offset_2 = (uint16_t)((uint64_t)entry->addr >> 16),
|
|
.offset_3 = (uint32_t)((uint64_t)entry->addr >> 32),
|
|
.segment = 0x8,
|
|
.ist = entry->ist,
|
|
.type = entry->type,
|
|
.priv = entry->priv,
|
|
.reserved = 0,
|
|
.reserved_1 = 0,
|
|
.reserved_2 = 0,
|
|
.present = 1
|
|
};
|
|
}
|
|
|
|
void free_idt(unsigned int entry) {
|
|
isr_bitmap[entry / 64] ^= ((uint64_t)1 << (entry & 63));
|
|
idt[entry].present = 0;
|
|
}
|
|
|
|
inline void clear_int() {
|
|
lapic[44] = 0;
|
|
}
|
|
|
|
|
|
void init_exceptions() {
|
|
//for idt index explainations, see include/panic.h
|
|
//TODO maybe utalize add_idt_entry?
|
|
unsigned int e;
|
|
idt[0] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
|
|
idt[8] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
|
|
idt[16] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
|
|
idt[17] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
|
|
idt[30] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
|
|
for(e = 5; e < 8; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
|
|
for(e = 10; e < 15; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
|
|
for(e = 18; e < 21; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
|
|
}
|
|
|
|
void smp_load_idt() {
|
|
asm("lidt [%0]\n"::"m"(idtr));
|
|
}
|
|
|
|
void init_interrupts_bsp() {
|
|
init_madt();
|
|
debug_madt();
|
|
lapic = get_lapic();
|
|
|
|
get_ioapic(&ioapic);
|
|
for(unsigned int i = 0; i < ioapic.count; i++) {
|
|
ioapic.ioapic[i].gsi_count = ((read_ioapic(ioapic.ioapic[i].address, IOAPICR_VER) >> 16) & 0xff);
|
|
printf("Found ioapic %i at addr %p, gsi %i to %i\n", i, ioapic.ioapic[i].address,
|
|
ioapic.ioapic[0].gsi_base, ioapic.ioapic[0].gsi_base + ioapic.ioapic[0].gsi_count);
|
|
}
|
|
|
|
disable_pic();
|
|
|
|
idt = palloc(0x1000);
|
|
idtr.size = 0x1000;
|
|
idtr.offset = (uint64_t)idt;
|
|
|
|
bzero(&isr_bitmap, sizeof(isr_bitmap));
|
|
isr_bitmap[0] = (((uint64_t)1 << 32) - 1);
|
|
|
|
asm("lidt [%0]\n"::"m"(idtr));
|
|
|
|
|
|
//Spurrious Interrupt (permanent, required for APIC)
|
|
idt[SPURRIOUS_VECTOR] = KERNEL_IDT_DESC_GATE(spurrious_int);
|
|
|
|
//Spurrious interrupt on IDT
|
|
lapic[60] = 0x1ff; //page 395
|
|
|
|
//initlize exceptions
|
|
init_exceptions();
|
|
|
|
|
|
//initilize the timers
|
|
init_timer();
|
|
asm("sti\n");
|
|
}
|
|
|
|
void smp_init_interrupts() {
|
|
}
|