forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/arch/x86/mm/mem_encrypt_identity.c
....@@ -1,13 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * AMD Memory Encryption Support
34 *
45 * Copyright (C) 2016 Advanced Micro Devices, Inc.
56 *
67 * Author: Tom Lendacky <thomas.lendacky@amd.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License version 2 as
10
- * published by the Free Software Foundation.
118 */
129
1310 #define DISABLE_BRANCH_PROFILING
....@@ -27,6 +24,7 @@
2724 * be extended when new paravirt and debugging variants are added.)
2825 */
2926 #undef CONFIG_PARAVIRT
27
+#undef CONFIG_PARAVIRT_XXL
3028 #undef CONFIG_PARAVIRT_SPINLOCKS
3129
3230 /*
....@@ -80,6 +78,19 @@
8078 unsigned long vaddr;
8179 unsigned long vaddr_end;
8280 };
81
+
82
+/*
83
+ * This work area lives in the .init.scratch section, which lives outside of
84
+ * the kernel proper. It is sized to hold the intermediate copy buffer and
85
+ * more than enough pagetable pages.
86
+ *
87
+ * By using this section, the kernel can be encrypted in place and it
88
+ * avoids any possibility of boot parameters or initramfs images being
89
+ * placed such that the in-place encryption logic overwrites them. This
90
+ * section is 2MB aligned to allow for simple pagetable setup using only
91
+ * PMD entries (see vmlinux.lds.S).
92
+ */
93
+static char sme_workarea[2 * PMD_PAGE_SIZE] __section(".init.scratch");
8394
8495 static char sme_cmdline_arg[] __initdata = "mem_encrypt";
8596 static char sme_cmdline_on[] __initdata = "on";
....@@ -322,8 +333,13 @@
322333 }
323334 #endif
324335
325
- /* Set the encryption workarea to be immediately after the kernel */
326
- workarea_start = kernel_end;
336
+ /*
337
+ * We're running identity mapped, so we must obtain the address to the
338
+ * SME encryption workarea using rip-relative addressing.
339
+ */
340
+ asm ("lea sme_workarea(%%rip), %0"
341
+ : "=r" (workarea_start)
342
+ : "p" (sme_workarea));
327343
328344 /*
329345 * Calculate required number of workarea bytes needed:
....@@ -496,14 +512,6 @@
496512
497513 #define AMD_SME_BIT BIT(0)
498514 #define AMD_SEV_BIT BIT(1)
499
- /*
500
- * Set the feature mask (SME or SEV) based on whether we are
501
- * running under a hypervisor.
502
- */
503
- eax = 1;
504
- ecx = 0;
505
- native_cpuid(&eax, &ebx, &ecx, &edx);
506
- feature_mask = (ecx & BIT(31)) ? AMD_SEV_BIT : AMD_SME_BIT;
507515
508516 /*
509517 * Check for the SME/SEV feature:
....@@ -516,23 +524,38 @@
516524 eax = 0x8000001f;
517525 ecx = 0;
518526 native_cpuid(&eax, &ebx, &ecx, &edx);
519
- if (!(eax & feature_mask))
527
+ /* Check whether SEV or SME is supported */
528
+ if (!(eax & (AMD_SEV_BIT | AMD_SME_BIT)))
520529 return;
521530
522531 me_mask = 1UL << (ebx & 0x3f);
523532
533
+ /* Check the SEV MSR whether SEV or SME is enabled */
534
+ sev_status = __rdmsr(MSR_AMD64_SEV);
535
+ feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
536
+
524537 /* Check if memory encryption is enabled */
525538 if (feature_mask == AMD_SME_BIT) {
539
+ /*
540
+ * No SME if Hypervisor bit is set. This check is here to
541
+ * prevent a guest from trying to enable SME. For running as a
542
+ * KVM guest the MSR_K8_SYSCFG will be sufficient, but there
543
+ * might be other hypervisors which emulate that MSR as non-zero
544
+ * or even pass it through to the guest.
545
+ * A malicious hypervisor can still trick a guest into this
546
+ * path, but there is no way to protect against that.
547
+ */
548
+ eax = 1;
549
+ ecx = 0;
550
+ native_cpuid(&eax, &ebx, &ecx, &edx);
551
+ if (ecx & BIT(31))
552
+ return;
553
+
526554 /* For SME, check the SYSCFG MSR */
527555 msr = __rdmsr(MSR_K8_SYSCFG);
528556 if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
529557 return;
530558 } else {
531
- /* For SEV, check the SEV MSR */
532
- msr = __rdmsr(MSR_AMD64_SEV);
533
- if (!(msr & MSR_AMD64_SEV_ENABLED))
534
- return;
535
-
536559 /* SEV state cannot be controlled by a command line option */
537560 sme_me_mask = me_mask;
538561 sev_enabled = true;
....@@ -563,7 +586,8 @@
563586 cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
564587 ((u64)bp->ext_cmd_line_ptr << 32));
565588
566
- cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer));
589
+ if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0)
590
+ return;
567591
568592 if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
569593 sme_me_mask = me_mask;