aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2011-10-30 10:16:39 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-10-30 10:16:42 -0400
commit7f0bf656c66e4292e965c95fd9de55c72b6578bb (patch)
tree5940a3c7ce75d64deb03a0a4f2199f64c497c1bf
parent1943f53c9ca182fa233e5a17e89ef8e421d7819e (diff)
[S390] Add real memory access functions
Add access function for real memory needed by s390 kdump backend. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/system.h2
-rw-r--r--arch/s390/mm/maccess.c56
-rw-r--r--drivers/s390/char/zcore.c20
3 files changed, 60 insertions, 18 deletions
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
index 6582f69f2389..afb849e4bf4b 100644
--- a/arch/s390/include/asm/system.h
+++ b/arch/s390/include/asm/system.h
@@ -114,6 +114,8 @@ extern void pfault_fini(void);
114extern void cmma_init(void); 114extern void cmma_init(void);
115extern int memcpy_real(void *, void *, size_t); 115extern int memcpy_real(void *, void *, size_t);
116extern void copy_to_absolute_zero(void *dest, void *src, size_t count); 116extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
117extern int copy_to_user_real(void __user *dest, void *src, size_t count);
118extern int copy_from_user_real(void *dest, void __user *src, size_t count);
117 119
118#define finish_arch_switch(prev) do { \ 120#define finish_arch_switch(prev) do { \
119 set_fs(current->thread.mm_segment); \ 121 set_fs(current->thread.mm_segment); \
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index 5dbbaa6e594c..1cb8427bedfb 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -11,6 +11,7 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/types.h> 12#include <linux/types.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/gfp.h>
14#include <asm/system.h> 15#include <asm/system.h>
15 16
16/* 17/*
@@ -60,6 +61,9 @@ long probe_kernel_write(void *dst, const void *src, size_t size)
60 return copied < 0 ? -EFAULT : 0; 61 return copied < 0 ? -EFAULT : 0;
61} 62}
62 63
64/*
65 * Copy memory in real mode (kernel to kernel)
66 */
63int memcpy_real(void *dest, void *src, size_t count) 67int memcpy_real(void *dest, void *src, size_t count)
64{ 68{
65 register unsigned long _dest asm("2") = (unsigned long) dest; 69 register unsigned long _dest asm("2") = (unsigned long) dest;
@@ -101,3 +105,55 @@ void copy_to_absolute_zero(void *dest, void *src, size_t count)
101 __ctl_load(cr0, 0, 0); 105 __ctl_load(cr0, 0, 0);
102 preempt_enable(); 106 preempt_enable();
103} 107}
108
109/*
110 * Copy memory from kernel (real) to user (virtual)
111 */
112int copy_to_user_real(void __user *dest, void *src, size_t count)
113{
114 int offs = 0, size, rc;
115 char *buf;
116
117 buf = (char *) __get_free_page(GFP_KERNEL);
118 if (!buf)
119 return -ENOMEM;
120 rc = -EFAULT;
121 while (offs < count) {
122 size = min(PAGE_SIZE, count - offs);
123 if (memcpy_real(buf, src + offs, size))
124 goto out;
125 if (copy_to_user(dest + offs, buf, size))
126 goto out;
127 offs += size;
128 }
129 rc = 0;
130out:
131 free_page((unsigned long) buf);
132 return rc;
133}
134
135/*
136 * Copy memory from user (virtual) to kernel (real)
137 */
138int copy_from_user_real(void *dest, void __user *src, size_t count)
139{
140 int offs = 0, size, rc;
141 char *buf;
142
143 buf = (char *) __get_free_page(GFP_KERNEL);
144 if (!buf)
145 return -ENOMEM;
146 rc = -EFAULT;
147 while (offs < count) {
148 size = min(PAGE_SIZE, count - offs);
149 if (copy_from_user(buf, src + offs, size))
150 goto out;
151 if (memcpy_real(dest + offs, buf, size))
152 goto out;
153 offs += size;
154 }
155 rc = 0;
156out:
157 free_page((unsigned long) buf);
158 return rc;
159}
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 3b94044027c2..f4f1da213e28 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -142,22 +142,6 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
142 return memcpy_hsa(dest, src, count, TO_KERNEL); 142 return memcpy_hsa(dest, src, count, TO_KERNEL);
143} 143}
144 144
145static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
146{
147 static char buf[4096];
148 int offs = 0, size;
149
150 while (offs < count) {
151 size = min(sizeof(buf), count - offs);
152 if (memcpy_real(buf, (void *) src + offs, size))
153 return -EFAULT;
154 if (copy_to_user(dest + offs, buf, size))
155 return -EFAULT;
156 offs += size;
157 }
158 return 0;
159}
160
161static int __init init_cpu_info(enum arch_id arch) 145static int __init init_cpu_info(enum arch_id arch)
162{ 146{
163 struct save_area *sa; 147 struct save_area *sa;
@@ -346,8 +330,8 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
346 330
347 /* Copy from real mem */ 331 /* Copy from real mem */
348 size = count - mem_offs - hdr_count; 332 size = count - mem_offs - hdr_count;
349 rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs, 333 rc = copy_to_user_real(buf + hdr_count + mem_offs,
350 size); 334 (void *) mem_start + mem_offs, size);
351 if (rc) 335 if (rc)
352 goto fail; 336 goto fail;
353 337