1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

add IPIs to shoot down the TLB on all cores

This commit is contained in:
Stefan Lankes 2015-05-31 07:44:24 +02:00
parent 047951bafd
commit a916196c3d
3 changed files with 75 additions and 0 deletions

View file

@ -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

View file

@ -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<MAX_CORES; i++)
{
if (i == core_id)
continue;
if (!online[i])
continue;
set_ipi_dest(i);
lapic_write(APIC_ICR1, APIC_INT_ASSERT|APIC_DM_FIXED|124);
j = 0;
while((lapic_read(APIC_ICR1) & APIC_ICR_BUSY) && (j < 1000))
j++; // wait for it to finish, give up eventualy tho
}
irq_nested_enable(flags);
return 0;
}
static void apic_tlb_handler(struct state *s)
{
uint32_t val = read_cr3();
if (val)
write_cr3(val);
//kputs("Flush TLB!\n");
}
#endif
static void apic_err_handler(struct state *s)
{
kprintf("Got APIC error 0x%x\n", lapic_read(APIC_ESR));
@ -612,7 +671,11 @@ int apic_init(void)
// set APIC error handler
irq_install_handler(126, apic_err_handler);
#if MAX_CORES > 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;
}

View file

@ -87,6 +87,7 @@ int smp_main(void)
create_kernel_task(NULL, foo, "foo2", NORMAL_PRIO);
flush_tlb();
while(1) {
HALT;
}