apic ipis, scheduler stub, crappy and slow tlb shootdown

This commit is contained in:
Matheus
2022-08-09 23:53:39 -03:00
parent b2d8e5a166
commit c565bc006f
19 changed files with 242 additions and 54 deletions
+53 -2
View File
@@ -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
View File
@@ -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();
}
+2
View File
@@ -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);
+3
View File
@@ -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;
+4
View File
@@ -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;
+8 -5
View File
@@ -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
-12
View File
@@ -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
+6
View File
@@ -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);
+11
View File
@@ -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
+16
View File
@@ -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){
}
+1 -3
View File
@@ -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
View File
@@ -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");
+6 -1
View File
@@ -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",
-23
View File
@@ -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);
}
+7 -4
View File
@@ -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 = {
+33
View File
@@ -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
View File
@@ -1,5 +1,5 @@
objects := $(patsubst %.c,%.o,$(wildcard *.c))
subdirs := mm
subdirs := mm sched
OBJPATH=$(OBJDIR)
export
+12
View File
@@ -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)/$@
+49
View File
@@ -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();
}