diff options
author | Michal Simek <monstr@monstr.eu> | 2010-05-24 12:13:24 +0200 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-08-04 10:22:31 +0200 |
commit | 6847ba91a190fe41d21779d6b382b47b2f4c50f4 (patch) | |
tree | a7d628c0f938259003a35e1b7d2316924768900a | |
parent | e05816679b61e47e90d7455a8f6dc6126dc479e3 (diff) | |
download | op-kernel-dev-6847ba91a190fe41d21779d6b382b47b2f4c50f4.zip op-kernel-dev-6847ba91a190fe41d21779d6b382b47b2f4c50f4.tar.gz |
microblaze: Fix copy_to_user_page macro
copy_to_user_page macro is used in mm/memory.c:access_process_vm
function. This function is called from ptrace code (POKETEXT, POKEDATA)
which write data to memory. Microblaze handle physical address for
caches that's why there is virt_to_phys conversion.
There is potential one location which can caused the problem on WB system.
The important is take a look at write PTRACEs requests
(POKE/TEXT, DATA, USR).
Note:
Majority of Microblaze PTRACE code is moved to generic location
in newer kernel version that's why this solution should work on
the newest kernel version too.
linux/io.h is in cacheflush because of mm/nommu.c
Tested on a WB system - hello world debugging.
Signed-off-by: Michal Simek <monstr@monstr.eu>
-rw-r--r-- | arch/microblaze/include/asm/cacheflush.h | 4 | ||||
-rw-r--r-- | arch/microblaze/kernel/ptrace.c | 17 |
2 files changed, 19 insertions, 2 deletions
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h index e9bb567..7ebd955 100644 --- a/arch/microblaze/include/asm/cacheflush.h +++ b/arch/microblaze/include/asm/cacheflush.h @@ -103,8 +103,10 @@ do { \ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { \ + u32 addr = virt_to_phys(dst); \ + invalidate_icache_range((unsigned) (addr), (unsigned) (addr) + (len));\ memcpy((dst), (src), (len)); \ - flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ + flush_dcache_range((unsigned) (addr), (unsigned) (addr) + (len));\ } while (0) #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index a4a7770..dc03ffc 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -38,6 +38,8 @@ #include <asm/processor.h> #include <linux/uaccess.h> #include <asm/asm-offsets.h> +#include <asm/cacheflush.h> +#include <asm/io.h> /* Returns the address where the register at REG_OFFS in P is stashed away. */ static microblaze_reg_t *reg_save_addr(unsigned reg_offs, @@ -101,8 +103,21 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) microblaze_reg_t *reg_addr = reg_save_addr(addr, child); if (request == PTRACE_PEEKUSR) val = *reg_addr; - else + else { +#if 1 *reg_addr = data; +#else + /* MS potential problem on WB system + * Be aware that reg_addr is virtual address + * virt_to_phys conversion is necessary. + * This could be sensible solution. + */ + u32 paddr = virt_to_phys((u32)reg_addr); + invalidate_icache_range(paddr, paddr + 4); + *reg_addr = data; + flush_dcache_range(paddr, paddr + 4); +#endif + } } else rval = -EIO; |