diff options
author | Michal Simek <monstr@monstr.eu> | 2010-05-24 06:13:24 -0400 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-08-04 04:22:31 -0400 |
commit | 6847ba91a190fe41d21779d6b382b47b2f4c50f4 (patch) | |
tree | a7d628c0f938259003a35e1b7d2316924768900a /arch/microblaze/kernel/ptrace.c | |
parent | e05816679b61e47e90d7455a8f6dc6126dc479e3 (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/microblaze/kernel/ptrace.c')
-rw-r--r-- | arch/microblaze/kernel/ptrace.c | 17 |
1 files changed, 16 insertions, 1 deletions
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. */ |
43 | static microblaze_reg_t *reg_save_addr(unsigned reg_offs, | 45 | 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) | |||
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 | ||