Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

The kdump mmap patch series (git commit 83086978c63afd7c73e1c) 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>

authored by

Michael Holzheu and committed by
Martin Schwidefsky
191a2fa0 5a74953f

+47 -4
+47 -4
arch/s390/kernel/crash_dump.c
··· 21 21 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) 22 22 #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y)))) 23 23 24 + 25 + /* 26 + * Return physical address for virtual address 27 + */ 28 + static inline void *load_real_addr(void *addr) 29 + { 30 + unsigned long real_addr; 31 + 32 + asm volatile( 33 + " lra %0,0(%1)\n" 34 + " jz 0f\n" 35 + " la %0,0\n" 36 + "0:" 37 + : "=a" (real_addr) : "a" (addr) : "cc"); 38 + return (void *)real_addr; 39 + } 40 + 41 + /* 42 + * Copy up to one page to vmalloc or real memory 43 + */ 44 + static ssize_t copy_page_real(void *buf, void *src, size_t csize) 45 + { 46 + size_t size; 47 + 48 + if (is_vmalloc_addr(buf)) { 49 + BUG_ON(csize >= PAGE_SIZE); 50 + /* If buf is not page aligned, copy first part */ 51 + size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize); 52 + if (size) { 53 + if (memcpy_real(load_real_addr(buf), src, size)) 54 + return -EFAULT; 55 + buf += size; 56 + src += size; 57 + } 58 + /* Copy second part */ 59 + size = csize - size; 60 + return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0; 61 + } else { 62 + return memcpy_real(buf, src, csize); 63 + } 64 + } 65 + 24 66 /* 25 67 * Copy one page from "oldmem" 26 68 * ··· 74 32 size_t csize, unsigned long offset, int userbuf) 75 33 { 76 34 unsigned long src; 35 + int rc; 77 36 78 37 if (!csize) 79 38 return 0; ··· 86 43 src < OLDMEM_BASE + OLDMEM_SIZE) 87 44 src -= OLDMEM_BASE; 88 45 if (userbuf) 89 - copy_to_user_real((void __force __user *) buf, (void *) src, 90 - csize); 46 + rc = copy_to_user_real((void __force __user *) buf, 47 + (void *) src, csize); 91 48 else 92 - memcpy_real(buf, (void *) src, csize); 93 - return csize; 49 + rc = copy_page_real(buf, (void *) src, csize); 50 + return (rc == 0) ? csize : rc; 94 51 } 95 52 96 53 /*