[kernel] Add a _very_ basic TLB shootdown mechanism

This TLB shootdown implementation is pretty janky: When the kernel
unmaps a mapping, it sends an IPI to all other cores and doesn't even
wait to ensure they've finished handling it. Upon getting one of these
IPIs, the core just re-writes cr3 to flush all TLBs.
This commit is contained in:
Justin C. Miller
2024-08-13 19:02:40 -07:00
parent d3c1d6cc34
commit 4649d5f77b
4 changed files with 28 additions and 10 deletions

View File

@@ -117,4 +117,5 @@ ISR (0xe1, 0, isrLINT0)
ISR (0xe2, 0, isrLINT1)
ISR (0xe3, 0, isrAPICError)
ISR (0xe4, 0, ipiSchedule)
ISR (0xe5, 0, ipiShootdown)

View File

@@ -21,6 +21,7 @@ constexpr uintptr_t apic_eoi_addr = 0xfee000b0 + mem::linear_offset;
extern "C" {
void isr_handler(cpu_state*);
void irq_handler(cpu_state*);
void _reload_cr3();
}
uint8_t
@@ -187,6 +188,11 @@ isr_handler(cpu_state *regs)
scheduler::get().schedule();
break;
case isr::ipiShootdown:
// TODO: Real shootdown algorithm
_reload_cr3();
break;
default:
util::format({message, sizeof(message)}, "Unknown interrupt 0x%lx", regs->interrupt);
kassert(false, message, regs);

View File

@@ -91,3 +91,10 @@ _current_gsbase:
mov rax, [gs:CPU_DATA.self]
ret
.end:
global _reload_cr3: function hidden (_reload_cr3.end - _reload_cr3)
_reload_cr3:
mov rax, cr3
mov cr3, rax
ret
.end:

View File

@@ -1,6 +1,7 @@
#include <j6/memutils.h>
#include <arch/memory.h>
#include "apic.h"
#include "kassert.h"
#include "frame_allocator.h"
#include "logger.h"
@@ -81,7 +82,7 @@ vm_space::kernel_space()
}
uintptr_t
vm_space::add(uintptr_t base, obj::vm_area *area, util::bitset32 flags)
vm_space::add(uintptr_t base, obj::vm_area *new_area, util::bitset32 flags)
{
if (!base)
base = min_auto_address;
@@ -89,23 +90,23 @@ vm_space::add(uintptr_t base, obj::vm_area *area, util::bitset32 flags)
//TODO: optimize find/insert
bool exact = flags.get(vm_flags::exact);
for (size_t i = 0; i < m_areas.count(); ++i) {
const vm_space::area &a = m_areas[i];
uintptr_t aend = a.base + a.area->size();
if (base >= aend)
const vm_space::area &cur = m_areas[i];
uintptr_t cur_end = cur.base + cur.area->size();
if (base >= cur_end)
continue;
uintptr_t end = base + area->size();
if (end <= a.base)
uintptr_t end = base + new_area->size();
if (end <= cur.base)
break;
else if (exact)
return 0;
else
base = aend;
base = cur_end;
}
m_areas.sorted_insert({base, area});
area->add_to(this);
area->handle_retain();
m_areas.sorted_insert({base, new_area});
new_area->add_to(this);
new_area->handle_retain();
return base;
}
@@ -267,6 +268,9 @@ vm_space::clear(const obj::vm_area &vma, uintptr_t offset, size_t count, bool fr
++it;
}
current_cpu().apic->send_ipi_broadcast(
lapic::ipi_fixed, false, isr::ipiShootdown);
if (free && free_count)
fa.free(free_start, free_count);
}