mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
mmu: arch_mmu_invalidate() -> arch_mmu_invalidate_range()
This commit is contained in:
@@ -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, ¤t_cpu()->isr[0xfe], ARCH_SMP_IPI_OTHERCPUS, false);
|
arch_smp_sendipi(NULL, ¤t_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user