[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>
This commit is contained in:
parent
1943f53c9c
commit
7f0bf656c6
@ -114,6 +114,8 @@ extern void pfault_fini(void);
|
|||||||
extern void cmma_init(void);
|
extern void cmma_init(void);
|
||||||
extern int memcpy_real(void *, void *, size_t);
|
extern int memcpy_real(void *, void *, size_t);
|
||||||
extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
|
extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
|
||||||
|
extern int copy_to_user_real(void __user *dest, void *src, size_t count);
|
||||||
|
extern int copy_from_user_real(void *dest, void __user *src, size_t count);
|
||||||
|
|
||||||
#define finish_arch_switch(prev) do { \
|
#define finish_arch_switch(prev) do { \
|
||||||
set_fs(current->thread.mm_segment); \
|
set_fs(current->thread.mm_segment); \
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
#include <linux/gfp.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -60,6 +61,9 @@ long probe_kernel_write(void *dst, const void *src, size_t size)
|
|||||||
return copied < 0 ? -EFAULT : 0;
|
return copied < 0 ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy memory in real mode (kernel to kernel)
|
||||||
|
*/
|
||||||
int memcpy_real(void *dest, void *src, size_t count)
|
int memcpy_real(void *dest, void *src, size_t count)
|
||||||
{
|
{
|
||||||
register unsigned long _dest asm("2") = (unsigned long) dest;
|
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)
|
|||||||
__ctl_load(cr0, 0, 0);
|
__ctl_load(cr0, 0, 0);
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy memory from kernel (real) to user (virtual)
|
||||||
|
*/
|
||||||
|
int copy_to_user_real(void __user *dest, void *src, size_t count)
|
||||||
|
{
|
||||||
|
int offs = 0, size, rc;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = (char *) __get_free_page(GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
rc = -EFAULT;
|
||||||
|
while (offs < count) {
|
||||||
|
size = min(PAGE_SIZE, count - offs);
|
||||||
|
if (memcpy_real(buf, src + offs, size))
|
||||||
|
goto out;
|
||||||
|
if (copy_to_user(dest + offs, buf, size))
|
||||||
|
goto out;
|
||||||
|
offs += size;
|
||||||
|
}
|
||||||
|
rc = 0;
|
||||||
|
out:
|
||||||
|
free_page((unsigned long) buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy memory from user (virtual) to kernel (real)
|
||||||
|
*/
|
||||||
|
int copy_from_user_real(void *dest, void __user *src, size_t count)
|
||||||
|
{
|
||||||
|
int offs = 0, size, rc;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = (char *) __get_free_page(GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
rc = -EFAULT;
|
||||||
|
while (offs < count) {
|
||||||
|
size = min(PAGE_SIZE, count - offs);
|
||||||
|
if (copy_from_user(buf, src + offs, size))
|
||||||
|
goto out;
|
||||||
|
if (memcpy_real(dest + offs, buf, size))
|
||||||
|
goto out;
|
||||||
|
offs += size;
|
||||||
|
}
|
||||||
|
rc = 0;
|
||||||
|
out:
|
||||||
|
free_page((unsigned long) buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
@ -142,22 +142,6 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
|
|||||||
return memcpy_hsa(dest, src, count, TO_KERNEL);
|
return memcpy_hsa(dest, src, count, TO_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
|
|
||||||
{
|
|
||||||
static char buf[4096];
|
|
||||||
int offs = 0, size;
|
|
||||||
|
|
||||||
while (offs < count) {
|
|
||||||
size = min(sizeof(buf), count - offs);
|
|
||||||
if (memcpy_real(buf, (void *) src + offs, size))
|
|
||||||
return -EFAULT;
|
|
||||||
if (copy_to_user(dest + offs, buf, size))
|
|
||||||
return -EFAULT;
|
|
||||||
offs += size;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init init_cpu_info(enum arch_id arch)
|
static int __init init_cpu_info(enum arch_id arch)
|
||||||
{
|
{
|
||||||
struct save_area *sa;
|
struct save_area *sa;
|
||||||
@ -346,8 +330,8 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
|
|||||||
|
|
||||||
/* Copy from real mem */
|
/* Copy from real mem */
|
||||||
size = count - mem_offs - hdr_count;
|
size = count - mem_offs - hdr_count;
|
||||||
rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,
|
rc = copy_to_user_real(buf + hdr_count + mem_offs,
|
||||||
size);
|
(void *) mem_start + mem_offs, size);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user