powerpc/pseries/svm: Unshare all pages before kexecing a new kernel
authorRam Pai <linuxram@us.ibm.com>
Tue, 20 Aug 2019 02:13:20 +0000 (23:13 -0300)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 29 Aug 2019 23:55:40 +0000 (09:55 +1000)
A new kernel deserves a clean slate. Any pages shared with the hypervisor
is unshared before invoking the new kernel. However there are exceptions.
If the new kernel is invoked to dump the current kernel, or if there is a
explicit request to preserve the state of the current kernel, unsharing
of pages is skipped.

NOTE: While testing crashkernel, make sure at least 256M is reserved for
crashkernel. Otherwise SWIOTLB allocation will fail and crash kernel will
fail to boot.

Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190820021326.6884-11-bauerman@linux.ibm.com
arch/powerpc/include/asm/ultravisor-api.h
arch/powerpc/include/asm/ultravisor.h
arch/powerpc/kernel/machine_kexec_64.c

index 0f5b2d7..4fcda1d 100644 (file)
@@ -28,5 +28,6 @@
 #define UV_ESM                         0xF110
 #define UV_SHARE_PAGE                  0xF130
 #define UV_UNSHARE_PAGE                        0xF134
+#define UV_UNSHARE_ALL_PAGES           0xF140
 
 #endif /* _ASM_POWERPC_ULTRAVISOR_API_H */
index e5c8413..b1bc2e0 100644 (file)
@@ -41,4 +41,9 @@ static inline int uv_unshare_page(u64 pfn, u64 npages)
        return ucall_norets(UV_UNSHARE_PAGE, pfn, npages);
 }
 
+static inline int uv_unshare_all_pages(void)
+{
+       return ucall_norets(UV_UNSHARE_ALL_PAGES);
+}
+
 #endif /* _ASM_POWERPC_ULTRAVISOR_H */
index 18481b0..04a7cba 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/smp.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/asm-prototypes.h>
+#include <asm/svm.h>
+#include <asm/ultravisor.h>
 
 int default_machine_kexec_prepare(struct kimage *image)
 {
@@ -327,6 +329,13 @@ void default_machine_kexec(struct kimage *image)
 #ifdef CONFIG_PPC_PSERIES
        kexec_paca.lppaca_ptr = NULL;
 #endif
+
+       if (is_secure_guest() && !(image->preserve_context ||
+                                  image->type == KEXEC_TYPE_CRASH)) {
+               uv_unshare_all_pages();
+               printk("kexec: Unshared all shared pages.\n");
+       }
+
        paca_ptrs[kexec_paca.paca_index] = &kexec_paca;
 
        setup_paca(&kexec_paca);