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

The kdump mmap patch series (git commit 83086978c6) 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: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Michael Holzheu 2013-07-18 12:18:27 +02:00 committed by Martin Schwidefsky
parent 5a74953ff5
commit 191a2fa0a8

View File

@ -21,6 +21,48 @@
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
#define PTR_DIFF(x, y) ((unsigned long)(((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" * 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) size_t csize, unsigned long offset, int userbuf)
{ {
unsigned long src; unsigned long src;
int rc;
if (!csize) if (!csize)
return 0; return 0;
@ -43,11 +86,11 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
src < OLDMEM_BASE + OLDMEM_SIZE) src < OLDMEM_BASE + OLDMEM_SIZE)
src -= OLDMEM_BASE; src -= OLDMEM_BASE;
if (userbuf) if (userbuf)
copy_to_user_real((void __force __user *) buf, (void *) src, rc = copy_to_user_real((void __force __user *) buf,
csize); (void *) src, csize);
else else
memcpy_real(buf, (void *) src, csize); rc = copy_page_real(buf, (void *) src, csize);
return csize; return (rc == 0) ? csize : rc;
} }
/* /*