mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
apic ipis, scheduler stub, crappy and slow tlb shootdown
This commit is contained in:
+53
-2
@@ -5,15 +5,26 @@
|
||||
#include <arch/panic.h>
|
||||
#include <stdio.h>
|
||||
#include <arch/cls.h>
|
||||
#include <arch/hpet.h>
|
||||
|
||||
#define APIC_REGISTER_ID 0x20
|
||||
#define APIC_REGISTER_EOI 0xB0
|
||||
#define APIC_REGISTER_SPURIOUS 0xF0
|
||||
#define APIC_REGISTER_ICR_LO 0x300
|
||||
#define APIC_REGISTER_ICR_HI 0x310
|
||||
#define APIC_TIMER_LVT 0x320
|
||||
#define APIC_THERMAL_LVT 0x330
|
||||
#define APIC_PERFORMANCE_LVT 0x340
|
||||
#define APIC_LINT0_LVT 0x350
|
||||
#define APIC_LINT1_LVT 0x360
|
||||
#define APIC_ERROR_LVT 0x370
|
||||
#define APIC_TIMER_INITIALCOUNT 0x380
|
||||
#define APIC_TIMER_COUNT 0x390
|
||||
#define APIC_TIMER_DIVIDE 0x3E0
|
||||
|
||||
#define LVT_DELIVERY_NMI (0b100 << 8)
|
||||
#define LVT_MASK (1 << 16)
|
||||
|
||||
#define TYPE_LAPIC 0
|
||||
#define TYPE_IOAPIC 1
|
||||
#define TYPE_OVERRIDE 2
|
||||
@@ -95,6 +106,7 @@ static size_t localnmi_count = 0;
|
||||
static size_t x2apic_count = 0;
|
||||
|
||||
void* lapicaddr;
|
||||
bool done = false;
|
||||
ioapic_descriptor* ioapics;
|
||||
|
||||
void* tablestart;
|
||||
@@ -158,6 +170,18 @@ static inline void lapic_writereg(size_t reg, uint32_t data){
|
||||
*(uint32_t volatile*)(lapicaddr + reg) = data;
|
||||
}
|
||||
|
||||
void apic_sendipi(uint8_t cpu, uint8_t vec, uint8_t dest, uint8_t mode, uint8_t level){
|
||||
|
||||
if(!done) return; // this function will be called before the apic initialization code is run so we need this safeguard
|
||||
|
||||
lapic_writereg(APIC_REGISTER_ICR_HI, (uint32_t)cpu << 24);
|
||||
lapic_writereg(APIC_REGISTER_ICR_LO, vec | (level << 14) | (mode << 15) | (dest << 18));
|
||||
}
|
||||
|
||||
void apic_eoi(){
|
||||
lapic_writereg(APIC_REGISTER_EOI, 0);
|
||||
}
|
||||
|
||||
void apic_timerstart(size_t ticks){
|
||||
lapic_writereg(APIC_TIMER_INITIALCOUNT, ticks);
|
||||
}
|
||||
@@ -187,13 +211,40 @@ size_t apic_timercalibrate(size_t ms){
|
||||
|
||||
void apic_lapicinit(){
|
||||
|
||||
// mask everything off besides the timer
|
||||
|
||||
lapic_writereg(APIC_THERMAL_LVT, LVT_MASK);
|
||||
lapic_writereg(APIC_PERFORMANCE_LVT, LVT_MASK);
|
||||
lapic_writereg(APIC_LINT0_LVT, LVT_MASK);
|
||||
lapic_writereg(APIC_LINT1_LVT, LVT_MASK);
|
||||
lapic_writereg(APIC_ERROR_LVT, LVT_MASK);
|
||||
|
||||
|
||||
arch_getcls()->lapicid = (lapic_readreg(APIC_REGISTER_ID));
|
||||
arch_getcls()->lapicid >>= 24;
|
||||
|
||||
lapic_entry* current;
|
||||
// get the acpi id for the local nmi sources
|
||||
|
||||
for(size_t i = 0; i < lapic_count; ++i){
|
||||
current = findstructure(TYPE_LAPIC, i);
|
||||
if(arch_getcls()->lapicid == current->apicid)
|
||||
break;
|
||||
}
|
||||
|
||||
arch_getcls()->acpi_id = current->acpi_id;
|
||||
|
||||
lapic_writereg(APIC_REGISTER_SPURIOUS, 0x1FF);
|
||||
lapic_writereg(APIC_TIMER_LVT, 1 << 16); // mask timer interrupt off
|
||||
|
||||
|
||||
for(size_t i = 0; i < localnmi_count; ++i){
|
||||
lapicnmi_entry* e = findstructure(TYPE_LAPICNMI, i);
|
||||
if(e->acpi_id == current->acpi_id || e->acpi_id == 0xFF){
|
||||
lapic_writereg(APIC_LINT0_LVT + 0x10*e->lint, 0x30 | LVT_DELIVERY_NMI | (e->flags << 12));
|
||||
}
|
||||
}
|
||||
|
||||
asm("sti");
|
||||
|
||||
}
|
||||
|
||||
@@ -275,6 +326,6 @@ void apic_init(){
|
||||
ioapic_writeiored(&ioapics[i], j, 0, 0, 0, 0, 0, 0, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
done = true;
|
||||
|
||||
}
|
||||
|
||||
+16
-2
@@ -2,7 +2,15 @@
|
||||
#include <arch/isr.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <arch/schedtimer.h>
|
||||
|
||||
// the IDT should look like this:
|
||||
//
|
||||
// 0-0x19 -> exceptions
|
||||
// 0x20 -> panic ipi
|
||||
// 0x21 -> lapic nmi
|
||||
// 0x22 -> mmu invalidate page ipi
|
||||
// ...
|
||||
// 0x80 -> timer
|
||||
|
||||
idtentry_t idt[256];
|
||||
|
||||
@@ -37,8 +45,14 @@ void idt_bspinit(){
|
||||
|
||||
idt_setentry(&idt[VECTOR_PF], asmisr_pagefault, 0x28, FLAGS_PRESENT | FLAGS_TYPE_TRAP, 0);
|
||||
|
||||
idt_setentry(&idt[SCHEDTIMER_VECTOR], asmisr_schedtimer, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0);
|
||||
idt_setentry(&idt[VECTOR_PANIC], asmisr_panic, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0);
|
||||
|
||||
idt_setentry(&idt[VECTOR_MMUINVAL], asmisr_mmuinval, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0);
|
||||
|
||||
idt_setentry(&idt[VECTOR_LAPICNMI], asmisr_lapicnmi, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0);
|
||||
|
||||
idt_setentry(&idt[VECTOR_TIMER], asmisr_timer, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0);
|
||||
|
||||
idt_reload();
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void apic_sendipi(uint8_t cpu, uint8_t vec, uint8_t dest, uint8_t mode, uint8_t level);
|
||||
void apic_eoi();
|
||||
void apic_timerstop();
|
||||
void apic_timerstart(size_t ticks);
|
||||
void apic_timerinterruptset(uint8_t vector);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <arch/ist.h>
|
||||
#include <arch/regs.h>
|
||||
#include <kernel/vmm.h>
|
||||
#include <kernel/sched.h>
|
||||
|
||||
// cpu level storage
|
||||
// this will be pointed to by GS and will contain per cpu info
|
||||
@@ -14,8 +15,10 @@ typedef struct{
|
||||
gdt_t gdt;
|
||||
ist_t ist;
|
||||
int lapicid;
|
||||
int acpi_id;
|
||||
arch_regs *laststate;
|
||||
vmm_context *context;
|
||||
thread_t* thread;
|
||||
size_t schedtimerticksperms;
|
||||
} cls_t;
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
#define VECTOR_GPF 13
|
||||
#define VECTOR_PF 14
|
||||
|
||||
#define VECTOR_PANIC 0x20
|
||||
#define VECTOR_LAPICNMI 0x21
|
||||
#define VECTOR_MMUINVAL 0x22
|
||||
#define VECTOR_TIMER 0x80
|
||||
|
||||
typedef struct{
|
||||
uint16_t size;
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
|
||||
#include <arch/regs.h>
|
||||
|
||||
extern void asmisr_schedtimer(arch_regs*);
|
||||
extern void asmisr_general(arch_regs*);
|
||||
extern void asmisr_except(arch_regs*);
|
||||
extern void asmisr_pagefault(arch_regs*);
|
||||
|
||||
extern void asmisr_timer();
|
||||
extern void asmisr_general();
|
||||
extern void asmisr_except();
|
||||
extern void asmisr_pagefault();
|
||||
extern void asmisr_panic();
|
||||
extern void asmisr_lapicnmi();
|
||||
extern void asmisr_mmuinval();
|
||||
extern void asmisr_timer();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef _SCHEDTIMER_H_INCLUDE
|
||||
#define _SCHEDTIMER_H_INCLUDE
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define SCHEDTIMER_VECTOR 0x50
|
||||
|
||||
void arch_schedtimer_run(size_t ms);
|
||||
void arch_schedtimer_stop();
|
||||
void arch_schedtimer_calibrate();
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,12 @@
|
||||
|
||||
void smp_init();
|
||||
|
||||
#define IPI_CPU_ALLBUTSELF 3
|
||||
#define IPI_CPU_ALL 2
|
||||
#define IPI_CPU_SELF 1
|
||||
#define IPI_CPU_TARGET 0
|
||||
|
||||
void arch_smp_sendipi(int cpu, int vector, int mode);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -126,7 +126,18 @@ section .text
|
||||
iretq
|
||||
%endmacro
|
||||
|
||||
extern asmisr_panic
|
||||
asmisr_panic:
|
||||
|
||||
cli
|
||||
.hlt:
|
||||
hlt
|
||||
jmp .hlt ; NMI stuff
|
||||
|
||||
except asmisr_pagefault, isr_pagefault
|
||||
isr asmisr_general, isr_general
|
||||
except asmisr_except, isr_except
|
||||
isr asmisr_schedtimer, isr_schedtimer
|
||||
isr asmisr_lapicnmi, isr_lapicnmi
|
||||
isr asmisr_mmuinval, isr_mmuinval
|
||||
isr asmisr_timer, isr_timer
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#include <arch/isr.h>
|
||||
#include <arch/panic.h>
|
||||
#include <kernel/vmm.h>
|
||||
#include <arch/apic.h>
|
||||
|
||||
void isr_schedtimer(arch_regs *reg){
|
||||
printf("schedtimer irq\n");
|
||||
|
||||
apic_eoi();
|
||||
|
||||
}
|
||||
|
||||
void isr_general(arch_regs *reg){
|
||||
@@ -22,3 +26,15 @@ void isr_pagefault(arch_regs *reg){
|
||||
_panic("Page fault!", reg);
|
||||
|
||||
}
|
||||
|
||||
void isr_lapicnmi(){
|
||||
_panic("Local apic NMI", 0);
|
||||
}
|
||||
|
||||
void isr_mmuinval(){
|
||||
arch_mmu_invalidateipi();
|
||||
}
|
||||
|
||||
void isr_timer(arch_regs* reg){
|
||||
|
||||
}
|
||||
|
||||
@@ -61,8 +61,6 @@ void kmain(){
|
||||
apic_lapicinit();
|
||||
|
||||
hpet_init();
|
||||
|
||||
arch_schedtimer_calibrate();
|
||||
|
||||
vfs_init();
|
||||
|
||||
@@ -78,7 +76,7 @@ void kmain(){
|
||||
pci_enumerate();
|
||||
|
||||
smp_init();
|
||||
|
||||
|
||||
_panic("End of kmain()", 0);
|
||||
|
||||
}
|
||||
|
||||
+14
-1
@@ -8,6 +8,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <arch/cls.h>
|
||||
#include <arch/idt.h>
|
||||
#include <arch/smp.h>
|
||||
|
||||
volatile struct limine_kernel_address_request kaddrreq = {
|
||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||
@@ -27,8 +29,20 @@ static void switchcontext(arch_mmu_tableptr context){
|
||||
asm("mov %%rax, %%cr3" : : "a"(context));
|
||||
}
|
||||
|
||||
// FIXME add a semaphore here
|
||||
|
||||
// XXX only do this on an unmap or other specific situations
|
||||
|
||||
void* inv = NULL;
|
||||
|
||||
void arch_mmu_invalidateipi(){
|
||||
asm("invlpg (%%rax)" : : "a"(inv));
|
||||
}
|
||||
|
||||
static void invalidate(void* addr){
|
||||
asm("invlpg (%%rax)" : : "a"(addr));
|
||||
inv = addr;
|
||||
arch_smp_sendipi(0, VECTOR_MMUINVAL, IPI_CPU_ALLBUTSELF);
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +250,6 @@ void arch_mmu_init(){
|
||||
|
||||
|
||||
switchcontext(context);
|
||||
|
||||
arch_getcls()->context->context = context;
|
||||
|
||||
printf("In bootstrap context\n");
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <arch/panic.h>
|
||||
#include <arch/idt.h>
|
||||
#include <arch/regs.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <arch/smp.h>
|
||||
|
||||
#define TRACE_MAXDEPTH 10
|
||||
|
||||
@@ -19,8 +21,11 @@ static void tracestack(uint64_t** addr){
|
||||
}
|
||||
|
||||
__attribute((noreturn)) void _panic(char* reason, arch_regs *reg){
|
||||
|
||||
|
||||
printf("PANIC: %s\n", reason);
|
||||
|
||||
// XXX maybe this should be an NMI?
|
||||
arch_smp_sendipi(0, VECTOR_PANIC, IPI_CPU_ALLBUTSELF);
|
||||
|
||||
if(reg){
|
||||
printf("Register dump:\nRAX: %p RBX: %p RCX: %p RDX: %p R8: %p R9: %p R10: %p R11: %p R12: %p R13: %p R14: %p R15: %p RDI: %p RSP: %p RBP: %p DS: %p ES: %p FS: %p GS: %p CR2: %p ERR: %p RIP: %p CS: %p RFLAGS: %p SS: %p\n",
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#include <arch/schedtimer.h>
|
||||
#include <arch/cls.h>
|
||||
#include <arch/apic.h>
|
||||
|
||||
void arch_schedtimer_waitms(size_t ms){
|
||||
|
||||
apic_timerstart(cls->schedtimerticksperms * ms);
|
||||
|
||||
}
|
||||
|
||||
void arch_schedtimer_stop(){
|
||||
|
||||
apic_timerstop();
|
||||
|
||||
}
|
||||
|
||||
void arch_schedtimer_calibrate(){
|
||||
|
||||
cls->schedtimerticksperms = apic_timercalibrate(1);
|
||||
|
||||
apic_timerinterruptset(SCHEDTIMER_VECTOR);
|
||||
|
||||
}
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
cls_t* apcls;
|
||||
|
||||
|
||||
size_t oncpucount = 1;
|
||||
static int lock = 0;
|
||||
static size_t cpucount = 1;
|
||||
|
||||
@@ -27,14 +29,15 @@ static void apstartup(struct limine_smp_info *info){
|
||||
arch_mmu_apinit();
|
||||
|
||||
apic_lapicinit();
|
||||
|
||||
arch_schedtimer_calibrate();
|
||||
|
||||
printf("CPU %lu ready!\n", info->lapic_id);
|
||||
|
||||
for(;;) asm("hlt");
|
||||
|
||||
}
|
||||
|
||||
asm("cli;hlt");
|
||||
|
||||
void arch_smp_sendipi(int processor, int vector, int mode){
|
||||
apic_sendipi(processor, vector, mode, 0, 1);
|
||||
}
|
||||
|
||||
static volatile struct limine_smp_request smpreq = {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef _SCHED_H_INCLUDE
|
||||
#define _SCHED_H_INCLUDE
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <arch/regs.h>
|
||||
#include <kernel/vfs.h>
|
||||
|
||||
#define THREAD_STATE_WAITING 0
|
||||
#define THREAD_STATE_RUNNING 1
|
||||
#define THREAD_STATE_BLOCKED 2
|
||||
|
||||
struct _proc_t;
|
||||
|
||||
typedef struct _thread_t{
|
||||
struct _thread_t* next;
|
||||
struct _proc_t* proc;
|
||||
arch_regs* regs;
|
||||
size_t state;
|
||||
void* kernelstack;
|
||||
} thread_t;
|
||||
|
||||
typedef struct _proc_t{
|
||||
struct _proc_t* parent;
|
||||
struct _proc_t* sibling;
|
||||
struct _proc_t* child;
|
||||
pid_t pid;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
dirnode_t* root;
|
||||
dirnode_t* cwd;
|
||||
} proc_t;
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
objects := $(patsubst %.c,%.o,$(wildcard *.c))
|
||||
subdirs := mm
|
||||
subdirs := mm sched
|
||||
OBJPATH=$(OBJDIR)
|
||||
export
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
objects := $(patsubst %.c,%.o,$(wildcard *.c))
|
||||
subdirs :=
|
||||
OBJPATH=$(OBJDIR)
|
||||
export
|
||||
|
||||
all: $(subdirs) $(objects)
|
||||
for subdir in $(subdirs) ; do $(MAKE) -C $${subdir} ; done
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
mkdir -p $(OBJPATH)
|
||||
cp $@ $(OBJPATH)/$@
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <kernel/sched.h>
|
||||
#include <arch/cls.h>
|
||||
|
||||
thread_t* queue;
|
||||
thread_t* blocked;
|
||||
|
||||
static thread_t* next_thread(){
|
||||
|
||||
thread_t* thread = queue;
|
||||
|
||||
while(1){
|
||||
|
||||
while(thread != NULL && thread->state != THREAD_STATE_WAITING)
|
||||
thread = thread->next;
|
||||
|
||||
if(!thread)
|
||||
asm("hlt"); // wait until something happens that would allow a thread to be scheduled
|
||||
|
||||
}
|
||||
|
||||
return thread;
|
||||
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) static void sched_switch(thread_t* thread){
|
||||
|
||||
thread_t* current = arch_getcls()->thread;
|
||||
|
||||
if(current->proc != thread->proc){
|
||||
|
||||
// change address spaces and all
|
||||
|
||||
}
|
||||
|
||||
arch_switchcontext(thread->regs);
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void sched_timerhook(arch_regs* c){
|
||||
|
||||
thread_t* current = arch_getcls()->thread;
|
||||
|
||||
memcpy(current->regs, c, sizeof(arch_regs));
|
||||
|
||||
;
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
Reference in New Issue
Block a user