From 2dd868797489f76caa396fd00410dac0c74e0567 Mon Sep 17 00:00:00 2001 From: Balazs Gerofi Date: Sun, 4 Aug 2019 23:31:47 +0000 Subject: [PATCH] flush instruction cache at context switch time if necessary Change-Id: Ic09415ea772a9de6dca43a98168a8346ca86d3e7 --- arch/arm64/kernel/cpu.c | 5 +++++ arch/arm64/kernel/include/arch/cpu.h | 2 ++ arch/arm64/kernel/memory.c | 1 + arch/x86_64/kernel/cpu.c | 4 ++++ arch/x86_64/kernel/include/arch/cpu.h | 1 + kernel/include/cls.h | 1 + kernel/process.c | 18 ++++++++++++++++++ 7 files changed, 32 insertions(+) diff --git a/arch/arm64/kernel/cpu.c b/arch/arm64/kernel/cpu.c index 8f9fca3c..d7490247 100644 --- a/arch/arm64/kernel/cpu.c +++ b/arch/arm64/kernel/cpu.c @@ -1772,4 +1772,9 @@ int smp_call_func(cpu_set_t *__cpu_set, smp_func_t __func, void *__arg) return -1; } +void arch_flush_icache_all(void) +{ + asm("ic ialluis"); + dsb(ish); +} /*** end of file ***/ diff --git a/arch/arm64/kernel/include/arch/cpu.h b/arch/arm64/kernel/include/arch/cpu.h index 803d6ad7..f89e9d01 100644 --- a/arch/arm64/kernel/include/arch/cpu.h +++ b/arch/arm64/kernel/include/arch/cpu.h @@ -102,4 +102,6 @@ static inline void cpu_disable_nmi(void) #endif /* __ASSEMBLY__ */ +void arch_flush_icache_all(void); + #endif /* !__HEADER_ARM64_ARCH_CPU_H */ diff --git a/arch/arm64/kernel/memory.c b/arch/arm64/kernel/memory.c index e776818d..f5674f14 100644 --- a/arch/arm64/kernel/memory.c +++ b/arch/arm64/kernel/memory.c @@ -3199,6 +3199,7 @@ void load_page_table(struct page_table *pt) { if (pt == NULL) { // load page table for idle(EL1) process. + switch_mm(init_pt); return; } // load page table for user(EL0) thread. diff --git a/arch/x86_64/kernel/cpu.c b/arch/x86_64/kernel/cpu.c index 66ee5da7..2ba5bd36 100644 --- a/arch/x86_64/kernel/cpu.c +++ b/arch/x86_64/kernel/cpu.c @@ -1821,6 +1821,10 @@ ihk_mc_init_user_tlsbase(ihk_mc_user_context_t *ctx, do_arch_prctl(ARCH_SET_FS, tls_base_addr); } +void arch_flush_icache_all(void) +{ + return; +} /*@ @ assigns \nothing; diff --git a/arch/x86_64/kernel/include/arch/cpu.h b/arch/x86_64/kernel/include/arch/cpu.h index 8eec92a0..e7dd7a26 100644 --- a/arch/x86_64/kernel/include/arch/cpu.h +++ b/arch/x86_64/kernel/include/arch/cpu.h @@ -47,5 +47,6 @@ static inline unsigned long read_tsc(void) WRITE_ONCE(*p, v); \ }) +void arch_flush_icache_all(void); #endif /* ARCH_CPU_H */ diff --git a/kernel/include/cls.h b/kernel/include/cls.h index 554e33df..0a2139b6 100644 --- a/kernel/include/cls.h +++ b/kernel/include/cls.h @@ -73,6 +73,7 @@ struct cpu_local_var { ihk_spinlock_t runq_lock; unsigned long runq_irqstate; struct thread *current; + int prevpid; struct list_head runq; size_t runq_len; size_t runq_reserved; /* Number of threads which are about to be added to runq */ diff --git a/kernel/process.c b/kernel/process.c index b63dba69..e950b10e 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -3324,6 +3324,7 @@ void schedule(void) struct thread *next, *prev, *thread, *tmp = NULL; int switch_ctx = 0; struct thread *last; + int prevpid; if (cpu_local_var(no_preempt)) { kprintf("%s: WARNING can't schedule() while no preemption, cnt: %d\n", @@ -3337,6 +3338,7 @@ void schedule(void) next = NULL; prev = v->current; + prevpid = v->prevpid; v->flags &= ~CPU_FLAG_NEED_RESCHED; @@ -3381,6 +3383,8 @@ void schedule(void) if (prev != next) { switch_ctx = 1; + v->prevpid = v->current && v->current->proc ? + v->current->proc->pid : 0; v->current = next; reset_cputime(); } @@ -3420,6 +3424,18 @@ void schedule(void) next->vm->address_space->page_table) ihk_mc_load_page_table(next->vm->address_space->page_table); + /* + * Unless switching to a thread in the same process, + * to the idle thread, or to the same process that ran + * before the idle, clear the instruction cache. + */ + if ((prev && prev->proc != next->proc) && + next != &cpu_local_var(idle) && + (prevpid != next->proc->pid || + prev != &cpu_local_var(idle))) { + arch_flush_icache_all(); + } + last = arch_switch_context(prev, next); /* @@ -3433,6 +3449,8 @@ void schedule(void) cpu_local_var(runq_irqstate)); if ((last != NULL) && (last->status == PS_EXITED)) { + v->prevpid = 0; + arch_flush_icache_all(); release_thread(last); rusage_num_threads_dec(); #ifdef RUSAGE_DEBUG