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

Commit 7f0bf656 authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky
Browse files

[S390] Add real memory access functions



Add access function for real memory needed by s390 kdump backend.

Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 1943f53c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -114,6 +114,8 @@ extern void pfault_fini(void);
extern void cmma_init(void);
extern int memcpy_real(void *, void *, size_t);
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 {					     \
	set_fs(current->thread.mm_segment);				     \
+56 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/gfp.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;
}

/*
 * Copy memory in real mode (kernel to kernel)
 */
int memcpy_real(void *dest, void *src, size_t count)
{
	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);
	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;
}
+2 −18
Original line number Diff line number Diff line
@@ -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);
}

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)
{
	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 */
	size = count - mem_offs - hdr_count;
	rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,
			      size);
	rc = copy_to_user_real(buf + hdr_count + mem_offs,
			       (void *) mem_start + mem_offs, size);
	if (rc)
		goto fail;