mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:17:44 +00:00
Kernel/aarch64: Flush entire TLB cache when changing TTBR0_EL1
Setting the page table base register (ttbr0_el1) is not enough, and will not flush the TLB caches, in contrary with x86_64 where setting the CR3 register will actually flush the caches. This commit adds the necessary code to properly flush the TLB caches when context switching. This commit also changes Processor::flush_tlb_local to use the vmalle1 variant, as previously we would be flushing the tlb's of all the cores in the inner-shareable domain.
This commit is contained in:
parent
188a52db01
commit
6a8581855d
3 changed files with 16 additions and 2 deletions
|
@ -49,12 +49,14 @@ LockRefPtr<PageDirectory> PageDirectory::find_current()
|
||||||
void activate_kernel_page_directory(PageDirectory const& page_directory)
|
void activate_kernel_page_directory(PageDirectory const& page_directory)
|
||||||
{
|
{
|
||||||
Aarch64::Asm::set_ttbr0_el1(page_directory.ttbr0());
|
Aarch64::Asm::set_ttbr0_el1(page_directory.ttbr0());
|
||||||
|
Processor::flush_entire_tlb_local();
|
||||||
}
|
}
|
||||||
|
|
||||||
void activate_page_directory(PageDirectory const& page_directory, Thread* current_thread)
|
void activate_page_directory(PageDirectory const& page_directory, Thread* current_thread)
|
||||||
{
|
{
|
||||||
current_thread->regs().ttbr0_el1 = page_directory.ttbr0();
|
current_thread->regs().ttbr0_el1 = page_directory.ttbr0();
|
||||||
Aarch64::Asm::set_ttbr0_el1(page_directory.ttbr0());
|
Aarch64::Asm::set_ttbr0_el1(page_directory.ttbr0());
|
||||||
|
Processor::flush_entire_tlb_local();
|
||||||
}
|
}
|
||||||
|
|
||||||
UNMAP_AFTER_INIT NonnullLockRefPtr<PageDirectory> PageDirectory::must_create_kernel_page_directory()
|
UNMAP_AFTER_INIT NonnullLockRefPtr<PageDirectory> PageDirectory::must_create_kernel_page_directory()
|
||||||
|
|
|
@ -113,7 +113,15 @@ void Processor::flush_tlb_local(VirtualAddress, size_t)
|
||||||
{
|
{
|
||||||
// FIXME: Figure out how to flush a single page
|
// FIXME: Figure out how to flush a single page
|
||||||
asm volatile("dsb ishst");
|
asm volatile("dsb ishst");
|
||||||
asm volatile("tlbi vmalle1is");
|
asm volatile("tlbi vmalle1");
|
||||||
|
asm volatile("dsb ish");
|
||||||
|
asm volatile("isb");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Processor::flush_entire_tlb_local()
|
||||||
|
{
|
||||||
|
asm volatile("dsb ishst");
|
||||||
|
asm volatile("tlbi vmalle1");
|
||||||
asm volatile("dsb ish");
|
asm volatile("dsb ish");
|
||||||
asm volatile("isb");
|
asm volatile("isb");
|
||||||
}
|
}
|
||||||
|
@ -529,8 +537,10 @@ extern "C" void enter_thread_context(Thread* from_thread, Thread* to_thread)
|
||||||
|
|
||||||
auto& from_regs = from_thread->regs();
|
auto& from_regs = from_thread->regs();
|
||||||
auto& to_regs = to_thread->regs();
|
auto& to_regs = to_thread->regs();
|
||||||
if (from_regs.ttbr0_el1 != to_regs.ttbr0_el1)
|
if (from_regs.ttbr0_el1 != to_regs.ttbr0_el1) {
|
||||||
Aarch64::Asm::set_ttbr0_el1(to_regs.ttbr0_el1);
|
Aarch64::Asm::set_ttbr0_el1(to_regs.ttbr0_el1);
|
||||||
|
Processor::flush_entire_tlb_local();
|
||||||
|
}
|
||||||
|
|
||||||
to_thread->set_cpu(Processor::current().id());
|
to_thread->set_cpu(Processor::current().id());
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,8 @@ public:
|
||||||
|
|
||||||
static void set_thread_specific_data(VirtualAddress thread_specific_data);
|
static void set_thread_specific_data(VirtualAddress thread_specific_data);
|
||||||
|
|
||||||
|
static void flush_entire_tlb_local();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Processor(Processor const&) = delete;
|
Processor(Processor const&) = delete;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue