Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6847ba91 authored by Michal Simek's avatar Michal Simek
Browse files

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: default avatarMichal Simek <monstr@monstr.eu>
parent e0581667
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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)		\
+16 −1
Original line number Diff line number Diff line
@@ -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;