mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
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:
parent
5a74953ff5
commit
191a2fa0a8
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user