diff --git a/hermit/arch/x86/include/asm/processor.h b/hermit/arch/x86/include/asm/processor.h index 7cbd90aa5..8d498064f 100644 --- a/hermit/arch/x86/include/asm/processor.h +++ b/hermit/arch/x86/include/asm/processor.h @@ -352,6 +352,9 @@ inline static void invalidate_cache(void) { asm volatile ("invd" ::: "memory"); } +/// Send IPIs to the other core, which flush the TLB on the other cores. +int ipi_tlb_flush(void); + /** @brief Flush Translation Lookaside Buffer * * Just reads cr3 and writes the same value back into it. @@ -362,6 +365,10 @@ static inline void flush_tlb(void) if (val) write_cr3(val); + +#if MAX_CORES > 1 + ipi_tlb_flush(); +#endif } /** @brief Flush a specific page entry in TLB @@ -370,6 +377,10 @@ static inline void flush_tlb(void) static inline void tlb_flush_one_page(size_t addr) { asm volatile("invlpg (%0)" : : "r"(addr) : "memory"); + +#if MAX_CORES > 1 + ipi_tlb_flush(); +#endif } /** @brief Invalidate cache diff --git a/hermit/arch/x86/kernel/apic.c b/hermit/arch/x86/kernel/apic.c index 83a70ab6b..729fde9a0 100644 --- a/hermit/arch/x86/kernel/apic.c +++ b/hermit/arch/x86/kernel/apic.c @@ -70,11 +70,15 @@ static uint32_t icr = 0; static uint32_t ncores = 1; static uint8_t irq_redirect[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}; static uint8_t initialized = 0; +static uint8_t online[MAX_CORES] = {[0 ... MAX_CORES-1] = 0}; + spinlock_t bootlock = SPINLOCK_INIT; // forward declaration static int lapic_reset(void); +extern atomic_int32_t cpu_online; + static uint32_t lapic_read_default(uint32_t addr) { return *((const volatile uint32_t*) (lapic+addr)); @@ -586,6 +590,7 @@ int smp_start(void) cpu_detection(); //kprintf("CR0 of core %u: 0x%x\n", apic_cpu_id(), read_cr0()); + online[apic_cpu_id()] = 1; set_idle_task(); @@ -594,6 +599,60 @@ int smp_start(void) return smp_main(); } +#if MAX_CORES > 1 +static inline void set_ipi_dest(uint32_t cpu_id) { + uint32_t tmp; + + tmp = lapic_read(APIC_ICR2); + tmp &= 0x00FFFFFF; + tmp |= (cpu_id << 24); + lapic_write(APIC_ICR2, tmp); +} + +int ipi_tlb_flush(void) +{ + uint32_t core_id = CORE_ID; + uint32_t flags; + uint32_t i, j; + + if (atomic_int32_read(&cpu_online) == 1) + return 0; + + if (lapic_read(APIC_ICR1) & APIC_ICR_BUSY) { + kputs("ERROR: previous send not complete"); + return -EIO; + } + + flags = irq_nested_disable(); + for(i=0; i 1 + irq_install_handler(124, apic_tlb_handler); +#endif kprintf("Boot processor %u (ID %u)\n", boot_processor, apic_processors[boot_processor]->id); + online[boot_processor] = 1; return 0; } diff --git a/hermit/kernel/main.c b/hermit/kernel/main.c index 400d8ba33..61a1b9177 100644 --- a/hermit/kernel/main.c +++ b/hermit/kernel/main.c @@ -87,6 +87,7 @@ int smp_main(void) create_kernel_task(NULL, foo, "foo2", NORMAL_PRIO); + flush_tlb(); while(1) { HALT; }