diff --git a/src/arch/x86_64/include/arch/smp.h b/src/arch/x86_64/include/arch/smp.h index ddad282d..628b0021 100644 --- a/src/arch/x86_64/include/arch/smp.h +++ b/src/arch/x86_64/include/arch/smp.h @@ -1,6 +1,8 @@ #ifndef _SMP_H_INCLUDE #define _SMP_H_INCLUDE +#include + void smp_init(); #define IPI_CPU_ALLBUTSELF 3 @@ -9,7 +11,7 @@ void smp_init(); #define IPI_CPU_TARGET 0 void arch_smp_sendipi(int cpu, int vector, int mode); - +size_t arch_smp_cpucount(); #endif diff --git a/src/arch/x86_64/isr.asm b/src/arch/x86_64/isr.asm index b07ddac3..78d92e7d 100644 --- a/src/arch/x86_64/isr.asm +++ b/src/arch/x86_64/isr.asm @@ -137,7 +137,6 @@ asmisr_panic: 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 diff --git a/src/arch/x86_64/isr.c b/src/arch/x86_64/isr.c index 3ba20afb..63daeb90 100644 --- a/src/arch/x86_64/isr.c +++ b/src/arch/x86_64/isr.c @@ -3,13 +3,6 @@ #include #include -void isr_schedtimer(arch_regs *reg){ - printf("schedtimer irq\n"); - - apic_eoi(); - -} - void isr_general(arch_regs *reg){ _panic("Unhandled interrupt", reg); asm("hlt"); @@ -33,8 +26,9 @@ void isr_lapicnmi(){ void isr_mmuinval(){ arch_mmu_invalidateipi(); + apic_eoi(); } void isr_timer(arch_regs* reg){ - + apic_eoi(); } diff --git a/src/arch/x86_64/mmu.c b/src/arch/x86_64/mmu.c index 1dc20d3c..d6cdb781 100644 --- a/src/arch/x86_64/mmu.c +++ b/src/arch/x86_64/mmu.c @@ -10,6 +10,7 @@ #include #include #include +#include volatile struct limine_kernel_address_request kaddrreq = { .id = LIMINE_KERNEL_ADDRESS_REQUEST, @@ -29,20 +30,23 @@ 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; +semaphore_t sem; + void arch_mmu_invalidateipi(){ asm("invlpg (%%rax)" : : "a"(inv)); + sem_signal(&sem); } static void invalidate(void* addr){ asm("invlpg (%%rax)" : : "a"(addr)); + sem.count = -arch_smp_cpucount(); + if(!sem.count) return; + sem.count += 2; inv = addr; arch_smp_sendipi(0, VECTOR_MMUINVAL, IPI_CPU_ALLBUTSELF); + while(!sem_tryacquire(&sem)); } @@ -145,8 +149,6 @@ int arch_mmu_map(arch_mmu_tableptr context, void* paddr, void* vaddr, size_t fla int ret = setpage(context, vaddr, entry); - if(ret) invalidate(vaddr); - return ret; } @@ -156,6 +158,7 @@ void arch_mmu_unmap(arch_mmu_tableptr context, void* vaddr){ if(!getmapping(context, vaddr)) return; arch_mmu_map(context, 0, vaddr, 0); + invalidate(vaddr); } diff --git a/src/arch/x86_64/smp.c b/src/arch/x86_64/smp.c index b3e0ab0a..62468f58 100644 --- a/src/arch/x86_64/smp.c +++ b/src/arch/x86_64/smp.c @@ -10,13 +10,12 @@ #include #include #include +#include -cls_t* apcls; +static cls_t* apcls; +static semaphore_t* sem; - -size_t oncpucount = 1; -static int lock = 0; -static size_t cpucount = 1; +static size_t cpucount = 0; static void apstartup(struct limine_smp_info *info){ @@ -31,11 +30,17 @@ static void apstartup(struct limine_smp_info *info){ apic_lapicinit(); printf("CPU %lu ready!\n", info->lapic_id); + + sem_signal(sem); for(;;) asm("hlt"); } +size_t arch_smp_cpucount(){ + return cpucount; +} + void arch_smp_sendipi(int processor, int vector, int mode){ apic_sendipi(processor, vector, mode, 0, 1); } @@ -59,6 +64,8 @@ void smp_init(){ printf("System has %lu CPUs\n", cpucount); + sem = sem_init(-cpucount + 2, 0); + for(size_t i = 0; i < cpucount; ++i){ if(cpus[i]->lapic_id == r->bsp_lapic_id) continue; printf("Dispatching CPU %lu\n", i); @@ -69,4 +76,7 @@ void smp_init(){ : "b"(&cpus[i]->goto_address), "a"(apstartup)); } + while(!sem_tryacquire(sem)) asm volatile("pause"); + + printf("All processors ready!\n"); } diff --git a/src/include/kernel/semaphore.h b/src/include/kernel/semaphore.h new file mode 100644 index 00000000..62472c20 --- /dev/null +++ b/src/include/kernel/semaphore.h @@ -0,0 +1,83 @@ +#ifndef _SEMAPHORE_H_INCLUDE +#define _SEMAPHORE_H_INCLUDE + +#include +#include +#include +#include +#include + +typedef struct{ + thread_t** waitingthreads; + int lock, count, threadcount; +} semaphore_t; + + +// a thread count of 0 will be a blockless semaphore + +static semaphore_t* sem_init(size_t count, size_t threadptrcount){ + + semaphore_t* semaphore = alloc(sizeof(semaphore_t)); + if(!semaphore) return NULL; + + if(threadptrcount){ + semaphore->waitingthreads = alloc(sizeof(thread_t*) * threadptrcount); + semaphore->threadcount = threadptrcount; + } + + semaphore->count = count; + + return semaphore; +} + +static bool sem_tryacquire(semaphore_t* sem){ + + spinlock_acquire(&sem->lock); + + bool res = (sem->count > 0); + + if(res) + --sem->count; + + + spinlock_release(&sem->lock); + + return res; + +} + +static void sem_wait(semaphore_t* sem){ + + + spinlock_acquire(&sem->lock); + + --sem->count; + + if(sem->count < 0 && sem->threadcount > 0){ + // TODO block + } + else if(sem->threadcount == 0){ + _panic("sem_wait with threadcount 0", 0); + } + + spinlock_release(&sem->lock); + +} + + +static void sem_signal(semaphore_t* sem){ + + + spinlock_acquire(&sem->lock); + + ++sem->count; + + if(sem->count <= 0 && sem->threadcount > 0){ + //TODO run a thread + } + + spinlock_release(&sem->lock); + +} + +#endif