diff options
author | Michael Holzheu <holzheu@linux.vnet.ibm.com> | 2011-10-30 10:16:39 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2011-10-30 10:16:42 -0400 |
commit | 7f0bf656c66e4292e965c95fd9de55c72b6578bb (patch) | |
tree | 5940a3c7ce75d64deb03a0a4f2199f64c497c1bf | |
parent | 1943f53c9ca182fa233e5a17e89ef8e421d7819e (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.h | 2 | ||||
-rw-r--r-- | arch/s390/mm/maccess.c | 56 | ||||
-rw-r--r-- | drivers/s390/char/zcore.c | 20 |
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); | |||
114 | extern void cmma_init(void); | 114 | extern void cmma_init(void); |
115 | extern int memcpy_real(void *, void *, size_t); | 115 | extern int memcpy_real(void *, void *, size_t); |
116 | extern void copy_to_absolute_zero(void *dest, void *src, size_t count); | 116 | extern void copy_to_absolute_zero(void *dest, void *src, size_t count); |
117 | extern int copy_to_user_real(void __user *dest, void *src, size_t count); | ||
118 | extern 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 | */ | ||
63 | int memcpy_real(void *dest, void *src, size_t count) | 67 | int 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 | */ | ||
112 | int 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; | ||
130 | out: | ||
131 | free_page((unsigned long) buf); | ||
132 | return rc; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * Copy memory from user (virtual) to kernel (real) | ||
137 | */ | ||
138 | int 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; | ||
156 | out: | ||
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 | ||
145 | static 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 | |||
161 | static int __init init_cpu_info(enum arch_id arch) | 145 | static 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 | ||