s390: Allow vmalloc target buffers for copy_from_oldmem()

Currently copy_from_oldmem() is not able to copy to virtual memory.
When using kexec pre-allocated ELF header, copy_from_oldmem()
is used to copy the ELF notes information to vmalloc buffers.

So fix this and use the new function copy_from_realmem() that allows
copying also to vmalloc memory.

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-09-27 15:41:43 +02:00 committed by Martin Schwidefsky
parent 22bfda6688
commit 4d3b0664a0

View File

@ -40,28 +40,26 @@ static inline void *load_real_addr(void *addr)
} }
/* /*
* Copy up to one page to vmalloc or real memory * Copy real to virtual or real memory
*/ */
static ssize_t copy_page_real(void *buf, void *src, size_t csize) static int copy_from_realmem(void *dest, void *src, size_t count)
{ {
size_t size; unsigned long size;
int rc;
if (is_vmalloc_addr(buf)) { if (!count)
BUG_ON(csize >= PAGE_SIZE); return 0;
/* If buf is not page aligned, copy first part */ if (!is_vmalloc_or_module_addr(dest))
size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize); return memcpy_real(dest, src, count);
if (size) { do {
if (memcpy_real(load_real_addr(buf), src, size)) size = min(count, PAGE_SIZE - (__pa(dest) & ~PAGE_MASK));
return -EFAULT; if (memcpy_real(load_real_addr(dest), src, size))
buf += size; return -EFAULT;
src += size; count -= size;
} dest += size;
/* Copy second part */ src += size;
size = csize - size; } while (count);
return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0; return 0;
} else {
return memcpy_real(buf, src, csize);
}
} }
/* /*
@ -114,7 +112,7 @@ static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize,
rc = copy_to_user_real((void __force __user *) buf, rc = copy_to_user_real((void __force __user *) buf,
(void *) src, csize); (void *) src, csize);
else else
rc = copy_page_real(buf, (void *) src, csize); rc = copy_from_realmem(buf, (void *) src, csize);
return (rc == 0) ? rc : csize; return (rc == 0) ? rc : csize;
} }
@ -210,7 +208,7 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
if (OLDMEM_BASE) { if (OLDMEM_BASE) {
if ((unsigned long) src < OLDMEM_SIZE) { if ((unsigned long) src < OLDMEM_SIZE) {
copied = min(count, OLDMEM_SIZE - (unsigned long) src); copied = min(count, OLDMEM_SIZE - (unsigned long) src);
rc = memcpy_real(dest, src + OLDMEM_BASE, copied); rc = copy_from_realmem(dest, src + OLDMEM_BASE, copied);
if (rc) if (rc)
return rc; return rc;
} }
@ -223,7 +221,7 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
return rc; return rc;
} }
} }
return memcpy_real(dest + copied, src + copied, count - copied); return copy_from_realmem(dest + copied, src + copied, count - copied);
} }
/* /*