mmu: arch_mmu_invalidate() -> arch_mmu_invalidate_range()

This commit is contained in:
Matheus
2024-09-16 17:34:05 -03:00
parent a30f8ce5d9
commit 0a49ca75b5
3 changed files with 41 additions and 30 deletions
+40 -27
View File
@@ -136,17 +136,12 @@ bool arch_mmu_map(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t fla
return add_page(table, vaddr, entry, 0); return add_page(table, vaddr, entry, 0);
} }
void arch_mmu_invalidate(void *vaddr) {
arch_mmu_tlbshootdown(vaddr);
asm volatile ("invlpg (%%rax)" : : "a"(vaddr));
}
void arch_mmu_unmap(pagetableptr_t table, void *vaddr) { void arch_mmu_unmap(pagetableptr_t table, void *vaddr) {
uint64_t *entry = get_page(table, vaddr); uint64_t *entry = get_page(table, vaddr);
if (entry == NULL) if (entry == NULL)
return; return;
*entry = 0; *entry = 0;
arch_mmu_invalidate(vaddr); arch_mmu_invalidate_range(vaddr, PAGE_SIZE);
} }
void arch_mmu_remap(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t flags) { void arch_mmu_remap(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t flags) {
@@ -155,7 +150,7 @@ void arch_mmu_remap(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t f
return; return;
uintptr_t addr = paddr == NULL ? (*entryptr & ADDRMASK) : ((uintptr_t)paddr & ADDRMASK); uintptr_t addr = paddr == NULL ? (*entryptr & ADDRMASK) : ((uintptr_t)paddr & ADDRMASK);
*entryptr = addr | flags; *entryptr = addr | flags;
arch_mmu_invalidate(vaddr); arch_mmu_invalidate_range(vaddr, PAGE_SIZE);
} }
void *arch_mmu_getphysical(pagetableptr_t table, void *vaddr) { void *arch_mmu_getphysical(pagetableptr_t table, void *vaddr) {
@@ -209,35 +204,53 @@ pagetableptr_t arch_mmu_newtable() {
return table; return table;
} }
static void *mmupage = NULL; static void *shootdown_page;
static spinlock_t shootdownlock; static size_t shootdown_size;
static int remaining = 0; static spinlock_t shootdown_lock;
static int shootdown_remaining = 0;
void arch_mmu_tlbipi(isr_t *isr, context_t *context) { static inline void do_invalidate(void *page, size_t size) {
asm volatile ("invlpg (%%rax)" : : "a"(mmupage)); for (uintptr_t i = 0; i < size; i += PAGE_SIZE) {
__atomic_sub_fetch(&remaining, 1, __ATOMIC_SEQ_CST); uintptr_t ptr = (uintptr_t)page + i;
asm volatile ("invlpg (%%rax)" : : "a"(ptr) : "memory");
}
} }
void arch_mmu_tlbshootdown(void *page) { void arch_mmu_tlbipi(isr_t *isr, context_t *context) {
// scheduler not up yet, or there are no other cpus, nothing to do do_invalidate(shootdown_page, shootdown_size);
if (current_thread() == NULL || arch_smp_cpusawake == 1) __atomic_sub_fetch(&shootdown_remaining, 1, __ATOMIC_SEQ_CST);
return; }
if (page >= KERNELSPACE_START || void arch_mmu_invalidate_range(void *page, size_t size) {
(current_thread()->proc->runningthreadcount > 1 && page >= USERSPACE_START && page < USERSPACE_END)) { __assert(((uintptr_t)page % PAGE_SIZE) == 0);
// shoot down if page is in the kernel space or in a multithreaded userland application thread_t *thread = current_thread();
int oldipl = interrupt_raiseipl(IPL_DPC);
spinlock_acquire(&shootdownlock);
mmupage = page; bool do_shootdown = // do shootdown if
remaining = arch_smp_cpusawake - 1; current_thread() // scheduler is up
&& arch_smp_cpusawake >= 2 // and there are multiple cpus in the system
&& (page >= KERNELSPACE_START // and its either in the kernel
|| (page >= USERSPACE_START && page < USERSPACE_END // or in an userspace...
&& thread->proc && thread->proc->runningthreadcount > 1)); // in a process which has multiple threads running
int old_ipl;
if (do_shootdown) {
old_ipl = interrupt_raiseipl(IPL_DPC);
spinlock_acquire(&shootdown_lock);
shootdown_page = page;
shootdown_size = size;
shootdown_remaining = arch_smp_cpusawake - 1;
arch_smp_sendipi(NULL, &current_cpu()->isr[0xfe], ARCH_SMP_IPI_OTHERCPUS, false); arch_smp_sendipi(NULL, &current_cpu()->isr[0xfe], ARCH_SMP_IPI_OTHERCPUS, false);
}
while (__atomic_load_n(&remaining, __ATOMIC_SEQ_CST)) CPU_PAUSE(); do_invalidate(page, size);
spinlock_release(&shootdownlock); if (do_shootdown) {
interrupt_loweripl(oldipl); while (__atomic_load_n(&shootdown_remaining, __ATOMIC_SEQ_CST)) CPU_PAUSE();
spinlock_release(&shootdown_lock);
interrupt_loweripl(old_ipl);
} }
} }
+1 -2
View File
@@ -27,7 +27,6 @@ typedef uint64_t * pagetableptr_t; // physical address
void arch_mmu_destroytable(pagetableptr_t table); void arch_mmu_destroytable(pagetableptr_t table);
bool arch_mmu_map(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t flags); bool arch_mmu_map(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t flags);
void arch_mmu_invalidate(void *vaddr);
void arch_mmu_unmap(pagetableptr_t table, void *vaddr); void arch_mmu_unmap(pagetableptr_t table, void *vaddr);
void arch_mmu_remap(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t flags); void arch_mmu_remap(pagetableptr_t table, void *paddr, void *vaddr, mmuflags_t flags);
void arch_mmu_switch(pagetableptr_t table); void arch_mmu_switch(pagetableptr_t table);
@@ -38,7 +37,7 @@ bool arch_mmu_isdirty(pagetableptr_t table, void *vaddr);
pagetableptr_t arch_mmu_newtable(); pagetableptr_t arch_mmu_newtable();
void arch_mmu_init(); void arch_mmu_init();
void arch_mmu_apswitch(); void arch_mmu_apswitch();
void arch_mmu_tlbshootdown(void *page); void arch_mmu_invalidate_range(void *page, size_t size);
bool arch_mmu_getflags(pagetableptr_t table, void *vaddr, mmuflags_t *mmuflagsp); bool arch_mmu_getflags(pagetableptr_t table, void *vaddr, mmuflags_t *mmuflagsp);
#endif #endif
-1
View File
@@ -292,7 +292,6 @@ static void changemmurange(vmmrange_t *range, void *base, size_t size, mmuflags_
// we will only change the mapping if the permissions decreased // we will only change the mapping if the permissions decreased
if (mask) { if (mask) {
arch_mmu_remap(current_vmm_context()->pagetable, physical, address, currentflags & ~mask); arch_mmu_remap(current_vmm_context()->pagetable, physical, address, currentflags & ~mask);
arch_mmu_invalidate(address);
} }
} }
} }