aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2010-05-24 06:13:24 -0400
committerMichal Simek <monstr@monstr.eu>2010-08-04 04:22:31 -0400
commit6847ba91a190fe41d21779d6b382b47b2f4c50f4 (patch)
treea7d628c0f938259003a35e1b7d2316924768900a /arch
parente05816679b61e47e90d7455a8f6dc6126dc479e3 (diff)
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/microblaze/include/asm/cacheflush.h4
-rw-r--r--arch/microblaze/kernel/ptrace.c17
2 files changed, 19 insertions, 2 deletions
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h
index e9bb567e1b0e..7ebd955460d9 100644
--- a/arch/microblaze/include/asm/cacheflush.h
+++ b/arch/microblaze/include/asm/cacheflush.h
@@ -103,8 +103,10 @@ do { \
103 103
104#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ 104#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
105do { \ 105do { \
106 u32 addr = virt_to_phys(dst); \
107 invalidate_icache_range((unsigned) (addr), (unsigned) (addr) + (len));\
106 memcpy((dst), (src), (len)); \ 108 memcpy((dst), (src), (len)); \
107 flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ 109 flush_dcache_range((unsigned) (addr), (unsigned) (addr) + (len));\
108} while (0) 110} while (0)
109 111
110#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ 112#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 a4a7770c6140..dc03ffc8174a 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -38,6 +38,8 @@
38#include <asm/processor.h> 38#include <asm/processor.h>
39#include <linux/uaccess.h> 39#include <linux/uaccess.h>
40#include <asm/asm-offsets.h> 40#include <asm/asm-offsets.h>
41#include <asm/cacheflush.h>
42#include <asm/io.h>
41 43
42/* Returns the address where the register at REG_OFFS in P is stashed away. */ 44/* Returns the address where the register at REG_OFFS in P is stashed away. */
43static microblaze_reg_t *reg_save_addr(unsigned reg_offs, 45static 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)
101 microblaze_reg_t *reg_addr = reg_save_addr(addr, child); 103 microblaze_reg_t *reg_addr = reg_save_addr(addr, child);
102 if (request == PTRACE_PEEKUSR) 104 if (request == PTRACE_PEEKUSR)
103 val = *reg_addr; 105 val = *reg_addr;
104 else 106 else {
107#if 1
105 *reg_addr = data; 108 *reg_addr = data;
109#else
110 /* MS potential problem on WB system
111 * Be aware that reg_addr is virtual address
112 * virt_to_phys conversion is necessary.
113 * This could be sensible solution.
114 */
115 u32 paddr = virt_to_phys((u32)reg_addr);
116 invalidate_icache_range(paddr, paddr + 4);
117 *reg_addr = data;
118 flush_dcache_range(paddr, paddr + 4);
119#endif
120 }
106 } else 121 } else
107 rval = -EIO; 122 rval = -EIO;
108 123