hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/arch/mips/kernel/crash_dump.c
....@@ -5,6 +5,8 @@
55 #include <linux/uaccess.h>
66 #include <linux/slab.h>
77
8
+static void *kdump_buf_page;
9
+
810 /**
911 * copy_oldmem_page - copy one page from "oldmem"
1012 * @pfn: page frame number to be copied
....@@ -15,25 +17,51 @@
1517 * @userbuf: if set, @buf is in user address space, use copy_to_user(),
1618 * otherwise @buf is in kernel address space, use memcpy().
1719 *
18
- * Copy a page from "oldmem". For this page, there might be no pte mapped
20
+ * Copy a page from "oldmem". For this page, there is no pte mapped
1921 * in the current kernel.
22
+ *
23
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
24
+ * copying the data to a pre-allocated kernel page and then copying to user
25
+ * space in non-atomic context.
2026 */
21
-ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
22
- unsigned long offset, int userbuf)
27
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
28
+ size_t csize, unsigned long offset, int userbuf)
2329 {
2430 void *vaddr;
2531
2632 if (!csize)
2733 return 0;
2834
29
- vaddr = kmap_local_pfn(pfn);
35
+ vaddr = kmap_atomic_pfn(pfn);
3036
3137 if (!userbuf) {
32
- memcpy(buf, vaddr + offset, csize);
38
+ memcpy(buf, (vaddr + offset), csize);
39
+ kunmap_atomic(vaddr);
3340 } else {
34
- if (copy_to_user(buf, vaddr + offset, csize))
35
- csize = -EFAULT;
41
+ if (!kdump_buf_page) {
42
+ pr_warn("Kdump: Kdump buffer page not allocated\n");
43
+
44
+ return -EFAULT;
45
+ }
46
+ copy_page(kdump_buf_page, vaddr);
47
+ kunmap_atomic(vaddr);
48
+ if (copy_to_user(buf, (kdump_buf_page + offset), csize))
49
+ return -EFAULT;
3650 }
3751
3852 return csize;
3953 }
54
+
55
+static int __init kdump_buf_page_init(void)
56
+{
57
+ int ret = 0;
58
+
59
+ kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
60
+ if (!kdump_buf_page) {
61
+ pr_warn("Kdump: Failed to allocate kdump buffer page\n");
62
+ ret = -ENOMEM;
63
+ }
64
+
65
+ return ret;
66
+}
67
+arch_initcall(kdump_buf_page_init);