mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[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:
@@ -117,4 +117,5 @@ ISR (0xe1, 0, isrLINT0)
|
||||
ISR (0xe2, 0, isrLINT1)
|
||||
ISR (0xe3, 0, isrAPICError)
|
||||
ISR (0xe4, 0, ipiSchedule)
|
||||
ISR (0xe5, 0, ipiShootdown)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user