]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
microblaze: Fix copy_to_user_page macro
authorMichal Simek <monstr@monstr.eu>
Mon, 24 May 2010 10:13:24 +0000 (12:13 +0200)
committerMichal Simek <monstr@monstr.eu>
Wed, 4 Aug 2010 08:22:31 +0000 (10:22 +0200)
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>
arch/microblaze/include/asm/cacheflush.h
arch/microblaze/kernel/ptrace.c

index e9bb567e1b0ea749d7a0660778a7413fb5b14d41..7ebd955460d9bbac40b4327c56d5a4d36e8a759b 100644 (file)
@@ -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)           \
index a4a7770c61402b17a8b488c35eb0f2c889ac1eee..dc03ffc8174a9ee632c892105a1331c93c02dcd8 100644 (file)
@@ -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;