diff --git a/src/kernel/interrupt_isrs.inc b/src/kernel/interrupt_isrs.inc index 785f0af..593b77d 100644 --- a/src/kernel/interrupt_isrs.inc +++ b/src/kernel/interrupt_isrs.inc @@ -117,4 +117,5 @@ ISR (0xe1, 0, isrLINT0) ISR (0xe2, 0, isrLINT1) ISR (0xe3, 0, isrAPICError) ISR (0xe4, 0, ipiSchedule) +ISR (0xe5, 0, ipiShootdown) diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index 3b5e034..80eac6c 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -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); diff --git a/src/kernel/task.s b/src/kernel/task.s index 704b242..dd62f5c 100644 --- a/src/kernel/task.s +++ b/src/kernel/task.s @@ -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: diff --git a/src/kernel/vm_space.cpp b/src/kernel/vm_space.cpp index a7bd282..bef7e8a 100644 --- a/src/kernel/vm_space.cpp +++ b/src/kernel/vm_space.cpp @@ -1,6 +1,7 @@ #include #include +#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); }