mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 18:24:14 +08:00
992b649a3f
In the kdump kernel, the memory of the first kernel needs to be dumped into the vmcore file. If SME is enabled in the first kernel, the old memory has to be remapped with the memory encryption mask in order to access it properly. Split copy_oldmem_page() functionality to handle encrypted memory properly. [ bp: Heavily massage everything. ] Signed-off-by: Lianbo Jiang <lijiang@redhat.com> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: kexec@lists.infradead.org Cc: tglx@linutronix.de Cc: mingo@redhat.com Cc: hpa@zytor.com Cc: akpm@linux-foundation.org Cc: dan.j.williams@intel.com Cc: bhelgaas@google.com Cc: baiyaowei@cmss.chinamobile.com Cc: tiwai@suse.de Cc: brijesh.singh@amd.com Cc: dyoung@redhat.com Cc: bhe@redhat.com Cc: jroedel@suse.de Link: https://lkml.kernel.org/r/be7b47f9-6be6-e0d1-2c2a-9125bc74b818@redhat.com
73 lines
2.1 KiB
C
73 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Memory preserving reboot related code.
|
|
*
|
|
* Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
|
|
* Copyright (C) IBM Corporation, 2004. All rights reserved
|
|
*/
|
|
|
|
#include <linux/errno.h>
|
|
#include <linux/crash_dump.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/io.h>
|
|
|
|
static ssize_t __copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
|
|
unsigned long offset, int userbuf,
|
|
bool encrypted)
|
|
{
|
|
void *vaddr;
|
|
|
|
if (!csize)
|
|
return 0;
|
|
|
|
if (encrypted)
|
|
vaddr = (__force void *)ioremap_encrypted(pfn << PAGE_SHIFT, PAGE_SIZE);
|
|
else
|
|
vaddr = (__force void *)ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
|
|
|
|
if (!vaddr)
|
|
return -ENOMEM;
|
|
|
|
if (userbuf) {
|
|
if (copy_to_user((void __user *)buf, vaddr + offset, csize)) {
|
|
iounmap((void __iomem *)vaddr);
|
|
return -EFAULT;
|
|
}
|
|
} else
|
|
memcpy(buf, vaddr + offset, csize);
|
|
|
|
set_iounmap_nonlazy();
|
|
iounmap((void __iomem *)vaddr);
|
|
return csize;
|
|
}
|
|
|
|
/**
|
|
* copy_oldmem_page - copy one page of memory
|
|
* @pfn: page frame number to be copied
|
|
* @buf: target memory address for the copy; this can be in kernel address
|
|
* space or user address space (see @userbuf)
|
|
* @csize: number of bytes to copy
|
|
* @offset: offset in bytes into the page (based on pfn) to begin the copy
|
|
* @userbuf: if set, @buf is in user address space, use copy_to_user(),
|
|
* otherwise @buf is in kernel address space, use memcpy().
|
|
*
|
|
* Copy a page from the old kernel's memory. For this page, there is no pte
|
|
* mapped in the current kernel. We stitch up a pte, similar to kmap_atomic.
|
|
*/
|
|
ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
|
|
unsigned long offset, int userbuf)
|
|
{
|
|
return __copy_oldmem_page(pfn, buf, csize, offset, userbuf, false);
|
|
}
|
|
|
|
/**
|
|
* copy_oldmem_page_encrypted - same as copy_oldmem_page() above but ioremap the
|
|
* memory with the encryption mask set to accomodate kdump on SME-enabled
|
|
* machines.
|
|
*/
|
|
ssize_t copy_oldmem_page_encrypted(unsigned long pfn, char *buf, size_t csize,
|
|
unsigned long offset, int userbuf)
|
|
{
|
|
return __copy_oldmem_page(pfn, buf, csize, offset, userbuf, true);
|
|
}
|