mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-31 14:38:21 +00:00
mmu: make shootdown data per cpu
This commit is contained in:
@@ -203,11 +203,6 @@ pagetableptr_t arch_mmu_newtable() {
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *shootdown_page;
|
|
||||||
static size_t shootdown_size;
|
|
||||||
static spinlock_t shootdown_lock;
|
|
||||||
static int shootdown_remaining = 0;
|
|
||||||
|
|
||||||
static inline void do_invalidate(void *page, size_t size) {
|
static inline void do_invalidate(void *page, size_t size) {
|
||||||
// if a full reload was requested or we are doing a big release on
|
// if a full reload was requested or we are doing a big release on
|
||||||
if (page == NULL || size >= 32 * PAGE_SIZE) {
|
if (page == NULL || size >= 32 * PAGE_SIZE) {
|
||||||
@@ -222,8 +217,10 @@ static inline void do_invalidate(void *page, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void arch_mmu_tlbipi(isr_t *isr, context_t *context) {
|
void arch_mmu_tlbipi(isr_t *isr, context_t *context) {
|
||||||
do_invalidate(shootdown_page, shootdown_size);
|
do_invalidate(current_cpu()->shootdown_page, current_cpu()->shootdown_size);
|
||||||
__atomic_sub_fetch(&shootdown_remaining, 1, __ATOMIC_SEQ_CST);
|
__assert(current_cpu()->shootdown_lock);
|
||||||
|
__atomic_add_fetch(current_cpu()->shootdown_done, 1, __ATOMIC_SEQ_CST);
|
||||||
|
spinlock_release(¤t_cpu()->shootdown_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if page == NULL, this will do a userspace shootdown that flushes the whole tlb
|
// if page == NULL, this will do a userspace shootdown that flushes the whole tlb
|
||||||
@@ -238,30 +235,33 @@ void arch_mmu_invalidate_range(void *page, size_t size) {
|
|||||||
|| ((page == NULL || (page >= USERSPACE_START && page < USERSPACE_END)) // or in userspace...
|
|| ((page == NULL || (page >= USERSPACE_START && page < USERSPACE_END)) // or in userspace...
|
||||||
&& thread->proc && thread->proc->runningthreadcount > 1)); // in a process which has multiple threads running
|
&& thread->proc && thread->proc->runningthreadcount > 1)); // in a process which has multiple threads running
|
||||||
|
|
||||||
|
int shootdown_done = 0;
|
||||||
|
int shootdown_total = 0;
|
||||||
int old_ipl;
|
int old_ipl;
|
||||||
if (do_shootdown) {
|
if (do_shootdown) {
|
||||||
old_ipl = interrupt_raiseipl(IPL_DPC);
|
old_ipl = interrupt_raiseipl(IPL_DPC);
|
||||||
spinlock_acquire(&shootdown_lock);
|
|
||||||
|
|
||||||
shootdown_page = page;
|
|
||||||
shootdown_size = size;
|
|
||||||
shootdown_remaining = arch_smp_cpusawake - 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < arch_smp_cpusawake; ++i) {
|
for (int i = 0; i < arch_smp_cpusawake; ++i) {
|
||||||
if (smp_cpus[i] == current_cpu())
|
if (smp_cpus[i] == current_cpu())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
spinlock_acquire(&smp_cpus[i]->shootdown_lock);
|
||||||
|
smp_cpus[i]->shootdown_page = page;
|
||||||
|
smp_cpus[i]->shootdown_size = size;
|
||||||
|
smp_cpus[i]->shootdown_done = &shootdown_done;
|
||||||
|
|
||||||
|
++shootdown_total;
|
||||||
arch_smp_send_ipi(smp_cpus[i], &smp_cpus[i]->isr[0xfe], ARCH_SMP_IPI_TARGET, false);
|
arch_smp_send_ipi(smp_cpus[i], &smp_cpus[i]->isr[0xfe], ARCH_SMP_IPI_TARGET, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we can lower ipl while waiting for the other cpus to shoot down because the spinlocks are now owned by the other cpus
|
||||||
|
interrupt_loweripl(old_ipl);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_invalidate(page, size);
|
do_invalidate(page, size);
|
||||||
|
|
||||||
if (do_shootdown) {
|
if (do_shootdown) {
|
||||||
while (__atomic_load_n(&shootdown_remaining, __ATOMIC_SEQ_CST)) CPU_PAUSE();
|
while (__atomic_load_n(&shootdown_done, __ATOMIC_SEQ_CST) != shootdown_total) CPU_PAUSE();
|
||||||
|
|
||||||
spinlock_release(&shootdown_lock);
|
|
||||||
interrupt_loweripl(old_ipl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ typedef struct cpu_t {
|
|||||||
|
|
||||||
void *topology_node;
|
void *topology_node;
|
||||||
|
|
||||||
|
void *shootdown_page;
|
||||||
|
size_t shootdown_size;
|
||||||
|
spinlock_t shootdown_lock;
|
||||||
|
int *shootdown_done;
|
||||||
|
|
||||||
// architecture specific, does not need to be exposed
|
// architecture specific, does not need to be exposed
|
||||||
|
|
||||||
uint64_t gdt[7];
|
uint64_t gdt[7];
|
||||||
|
|||||||
Reference in New Issue
Block a user