kernel: Add invalidation utility routines to VMTranslationMap.

These allow us to move a lot of the basic logic out of the
TranslationMaps. In the process, it extends the fix applied
to x86 in the previous commit to all the other maps.
This commit is contained in:
Augustin Cavalier
2026-03-17 13:30:11 -04:00
parent b4546a49f0
commit cf2179fa35
7 changed files with 59 additions and 122 deletions
@@ -89,6 +89,10 @@ protected:
void UnaccessedPageUnmapped(VMArea* area,
page_num_t pageNumber);
static void InvalidateUserTLB(CPUSet cpus, intptr_t context);
static void InvalidateTLBList(CPUSet cpus, intptr_t context,
addr_t* invalidPages, int32 count);
protected:
recursive_lock fLock;
int32 fMapCount;
@@ -107,18 +107,7 @@ ARMVMTranslationMap::Flush()
smp_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
NULL, SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
} else {
cpu_status state = disable_interrupts();
arch_cpu_user_tlb_invalidate(0);
restore_interrupts(state);
}
InvalidateUserTLB(PagingStructures()->active_on_cpus, x86_read_cr3());
}
} else {
TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
@@ -129,17 +118,8 @@ ARMVMTranslationMap::Flush()
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
arch_cpu_invalidate_tlb_list(0, fInvalidPages, fInvalidPagesCount);
}
InvalidateTLBList(PagingStructures()->active_on_cpus, x86_read_cr3(),
fInvalidPages, fInvalidPagesCount);
}
}
fInvalidPagesCount = 0;
@@ -107,18 +107,7 @@ M68KVMTranslationMap::Flush()
smp_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
NULL, SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
} else {
cpu_status state = disable_interrupts();
arch_cpu_user_tlb_invalidate(0);
restore_interrupts(state);
}
InvalidateUserTLB(PagingStructures()->active_on_cpus, x86_read_cr3());
}
} else {
TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
@@ -129,17 +118,8 @@ M68KVMTranslationMap::Flush()
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
arch_cpu_invalidate_tlb_list(0, fInvalidPages, fInvalidPagesCount);
}
InvalidateTLBList(PagingStructures()->active_on_cpus, x86_read_cr3(),
fInvalidPages, fInvalidPagesCount);
}
}
fInvalidPagesCount = 0;
@@ -107,18 +107,7 @@ PPCVMTranslationMap::Flush()
smp_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
NULL, SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
} else {
cpu_status state = disable_interrupts();
arch_cpu_user_tlb_invalidate(0);
restore_interrupts(state);
}
InvalidateUserTLB(PagingStructures()->active_on_cpus, x86_read_cr3());
}
} else {
TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
@@ -129,17 +118,8 @@ PPCVMTranslationMap::Flush()
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
arch_cpu_invalidate_tlb_list(0, fInvalidPages, fInvalidPagesCount);
}
InvalidateTLBList(PagingStructures()->active_on_cpus, x86_read_cr3(),
fInvalidPages, fInvalidPagesCount);
}
}
fInvalidPagesCount = 0;
@@ -623,9 +623,6 @@ RISCV64VMTranslationMap::ClearAccessedAndModified(VMArea* area, addr_t address,
void
RISCV64VMTranslationMap::Flush()
{
// copy of X86VMTranslationMap::Flush
// TODO: move to common VMTranslationMap class
if (fInvalidPagesCount <= 0)
return;
@@ -640,18 +637,7 @@ RISCV64VMTranslationMap::Flush()
smp_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
NULL, SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = fActiveOnCpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
} else {
cpu_status state = disable_interrupts();
arch_cpu_user_tlb_invalidate(0);
restore_interrupts(state);
}
InvalidateUserTLB(fActiveOnCpus, x86_read_cr3());
}
} else {
TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
@@ -662,17 +648,8 @@ RISCV64VMTranslationMap::Flush()
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = fActiveOnCpus;
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
arch_cpu_invalidate_tlb_list(0, fInvalidPages, fInvalidPagesCount);
}
InvalidateTLBList(fActiveOnCpus, x86_read_cr3(),
fInvalidPages, fInvalidPagesCount);
}
}
fInvalidPagesCount = 0;
@@ -107,20 +107,7 @@ X86VMTranslationMap::Flush()
smp_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
NULL, SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
const bool current = cpuMask.GetBit(cpu);
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
if (current)
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
x86_read_cr3(), 0, 0, NULL, SMP_MSG_FLAG_SYNC);
} else if (current) {
cpu_status state = disable_interrupts();
arch_cpu_user_tlb_invalidate(0);
restore_interrupts(state);
}
InvalidateUserTLB(PagingStructures()->active_on_cpus, x86_read_cr3());
}
} else {
TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
@@ -131,19 +118,8 @@ X86VMTranslationMap::Flush()
0, (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else {
int32 cpu = smp_get_current_cpu();
CPUSet cpuMask = PagingStructures()->active_on_cpus;
const bool current = cpuMask.GetBit(cpu);
cpuMask.ClearBit(cpu);
if (!cpuMask.IsEmpty()) {
if (current)
cpuMask.SetBit(cpu);
smp_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
x86_read_cr3(), (addr_t)fInvalidPages, fInvalidPagesCount, NULL,
SMP_MSG_FLAG_SYNC);
} else if (current) {
arch_cpu_invalidate_tlb_list(0, fInvalidPages, fInvalidPagesCount);
}
InvalidateTLBList(PagingStructures()->active_on_cpus, x86_read_cr3(),
fInvalidPages, fInvalidPagesCount);
}
}
fInvalidPagesCount = 0;
+40
View File
@@ -334,6 +334,46 @@ VMTranslationMap::UnaccessedPageUnmapped(VMArea* area, page_num_t pageNumber)
}
/*! Invokes arch_cpu_user_tlb_invalidate() on the specified CPUs. */
void
VMTranslationMap::InvalidateUserTLB(CPUSet cpus, intptr_t context)
{
int32 cpu = smp_get_current_cpu();
const bool current = cpus.GetBit(cpu);
cpus.ClearBit(cpu);
if (!cpus.IsEmpty()) {
if (current)
cpus.SetBit(cpu);
smp_multicast_ici(cpus, SMP_MSG_USER_INVALIDATE_PAGES,
context, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
} else if (current) {
cpu_status state = disable_interrupts();
arch_cpu_user_tlb_invalidate(context);
restore_interrupts(state);
}
}
/*! Invokes arch_cpu_invalidate_tlb_list() on the specified CPUs. */
void
VMTranslationMap::InvalidateTLBList(CPUSet cpus, intptr_t context,
addr_t* invalidPages, int32 count)
{
int32 cpu = smp_get_current_cpu();
const bool current = cpus.GetBit(cpu);
cpus.ClearBit(cpu);
if (!cpus.IsEmpty()) {
if (current)
cpus.SetBit(cpu);
smp_multicast_ici(cpus, SMP_MSG_INVALIDATE_PAGE_LIST,
context, (addr_t)invalidPages, count, NULL,
SMP_MSG_FLAG_SYNC);
} else if (current) {
arch_cpu_invalidate_tlb_list(context, invalidPages, count);
}
}
// #pragma mark - ReverseMappingInfoCallback