From cd62c27097720adf1c7bb099a011ebd079a88aa5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Jun 2009 10:26:42 +0200 Subject: [PATCH] --- yaml --- r: 148775 b: refs/heads/master c: 88df125fd6127e409793fd84a574566651450320 h: refs/heads/master i: 148773: 34f0fc51420b9f23befb33830c2817610ab4d2a1 148771: f74662f4284fb15b4ff62f68c64a20d281107683 148767: 7fafd312aa0aa7ba1f1644e574d3a21dd4622b7b v: v3 --- [refs] | 2 +- trunk/arch/s390/mm/Makefile | 2 +- trunk/arch/s390/mm/maccess.c | 61 ++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 trunk/arch/s390/mm/maccess.c diff --git a/[refs] b/[refs] index 33613f38df5b..d17502131d9f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d93f82b6e0c12a4373f2d04b1f92fcb2d175b62c +refs/heads/master: 88df125fd6127e409793fd84a574566651450320 diff --git a/trunk/arch/s390/mm/Makefile b/trunk/arch/s390/mm/Makefile index 2a7458134544..db05661ac895 100644 --- a/trunk/arch/s390/mm/Makefile +++ b/trunk/arch/s390/mm/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux s390-specific parts of the memory manager. # -obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o +obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_PAGE_STATES) += page-states.o diff --git a/trunk/arch/s390/mm/maccess.c b/trunk/arch/s390/mm/maccess.c new file mode 100644 index 000000000000..81756271dc44 --- /dev/null +++ b/trunk/arch/s390/mm/maccess.c @@ -0,0 +1,61 @@ +/* + * Access kernel memory without faulting -- s390 specific implementation. + * + * Copyright IBM Corp. 2009 + * + * Author(s): Heiko Carstens , + * + */ + +#include +#include +#include +#include +#include + +/* + * This function writes to kernel memory bypassing DAT and possible + * write protection. It copies one to four bytes from src to dst + * using the stura instruction. + * Returns the number of bytes copied or -EFAULT. + */ +static long probe_kernel_write_odd(void *dst, void *src, size_t size) +{ + unsigned long count, aligned; + int offset, mask; + int rc = -EFAULT; + + aligned = (unsigned long) dst & ~3UL; + offset = (unsigned long) dst & 3; + count = min_t(unsigned long, 4 - offset, size); + mask = (0xf << (4 - count)) & 0xf; + mask >>= offset; + asm volatile( + " bras 1,0f\n" + " icm 0,0,0(%3)\n" + "0: l 0,0(%1)\n" + " lra %1,0(%1)\n" + "1: ex %2,0(1)\n" + "2: stura 0,%1\n" + " la %0,0\n" + "3:\n" + EX_TABLE(0b,3b) EX_TABLE(1b,3b) EX_TABLE(2b,3b) + : "+d" (rc), "+a" (aligned) + : "a" (mask), "a" (src) : "cc", "memory", "0", "1"); + return rc ? rc : count; +} + +long probe_kernel_write(void *dst, void *src, size_t size) +{ + long copied = 0; + + while (size) { + copied = probe_kernel_write_odd(dst, src, size); + if (copied < 0) + break; + dst += copied; + src += copied; + size -= copied; + } + return copied < 0 ? -EFAULT : 0; +}