Microblaze invalidates the instruction cache via WIC opcode which, unlike WDC for data cache, requires the virtual address of the target location when MMU is used. The current code always uses the physical address, preventing the instruction cache to be properly invalidated and exposing the risk of user space applications to crash with signal 4 (illegal instruction) when executing the trampoline code in return from a signal handler. Same issue when the code is modified via copy_to_user_page. This patch fixes the calls to instruction cache invalidation using the correct addresses.
Signed-off-by: Romeo Cane <[email protected]> --- arch/microblaze/include/asm/cacheflush.h | 6 +++--- arch/microblaze/kernel/signal.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h index ffea82a..c978e64 100644 --- a/arch/microblaze/include/asm/cacheflush.h +++ b/arch/microblaze/include/asm/cacheflush.h @@ -106,11 +106,11 @@ static inline void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, void *src, int len) { - u32 addr = virt_to_phys(dst); + u32 paddr = virt_to_phys(dst); memcpy(dst, src, len); if (vma->vm_flags & VM_EXEC) { - invalidate_icache_range(addr, addr + PAGE_SIZE); - flush_dcache_range(addr, addr + PAGE_SIZE); + invalidate_icache_range(vaddr, vaddr + PAGE_SIZE); + flush_dcache_range(paddr, paddr + PAGE_SIZE); } } diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 9700152..757dd40 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -200,6 +200,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, address), address); preempt_disable(); + invalidate_icache_range(address, address + 8); ptep = pte_offset_map(pmdp, address); if (pte_present(*ptep)) { address = (unsigned long) page_address(pte_page(*ptep)); @@ -207,7 +208,6 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, address += ((unsigned long)frame->tramp) & ~PAGE_MASK; /* MS address is virtual */ address = __virt_to_phys(address); - invalidate_icache_range(address, address + 8); flush_dcache_range(address, address + 8); } pte_unmap(ptep); -- 1.9.1

