Brett Weiland 175f5d3a00 SMP fixed for CPUs with defective cores
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
2021-09-12 13:08:34 -05:00

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() {
}