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

Commit 191a2fa0 authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky
Browse files

s390/kdump: Allow copy_oldmem_page() copy to virtual memory



The kdump mmap patch series (git commit 83086978) changed the
requirements for copy_oldmem_page(). Now this function is used for copying
to virtual memory.

So implement vmalloc support for the s390 version of copy_oldmem_page().

Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 5a74953f
Loading
Loading
Loading
Loading
+47 −4
Original line number Diff line number Diff line
@@ -21,6 +21,48 @@
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))


/*
 * Return physical address for virtual address
 */
static inline void *load_real_addr(void *addr)
{
	unsigned long real_addr;

	asm volatile(
		   "	lra     %0,0(%1)\n"
		   "	jz	0f\n"
		   "	la	%0,0\n"
		   "0:"
		   : "=a" (real_addr) : "a" (addr) : "cc");
	return (void *)real_addr;
}

/*
 * Copy up to one page to vmalloc or real memory
 */
static ssize_t copy_page_real(void *buf, void *src, size_t csize)
{
	size_t size;

	if (is_vmalloc_addr(buf)) {
		BUG_ON(csize >= PAGE_SIZE);
		/* If buf is not page aligned, copy first part */
		size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize);
		if (size) {
			if (memcpy_real(load_real_addr(buf), src, size))
				return -EFAULT;
			buf += size;
			src += size;
		}
		/* Copy second part */
		size = csize - size;
		return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0;
	} else {
		return memcpy_real(buf, src, csize);
	}
}

/*
 * Copy one page from "oldmem"
 *
@@ -32,6 +74,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
			 size_t csize, unsigned long offset, int userbuf)
{
	unsigned long src;
	int rc;

	if (!csize)
		return 0;
@@ -43,11 +86,11 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
		 src < OLDMEM_BASE + OLDMEM_SIZE)
		src -= OLDMEM_BASE;
	if (userbuf)
		copy_to_user_real((void __force __user *) buf, (void *) src,
				  csize);
		rc = copy_to_user_real((void __force __user *) buf,
				       (void *) src, csize);
	else
		memcpy_real(buf, (void *) src, csize);
	return csize;
		rc = copy_page_real(buf, (void *) src, csize);
	return (rc == 0) ? csize : rc;
}

/*