For AMD SEV determine C-bit position and guest mode in locore0.
authorbluhm <bluhm@openbsd.org>
Sun, 21 Jul 2024 19:41:31 +0000 (19:41 +0000)
committerbluhm <bluhm@openbsd.org>
Sun, 21 Jul 2024 19:41:31 +0000 (19:41 +0000)
Actually determine the C-bit position if we are running as a guest
with SEV enabled.  Configure pg_crypt, pg_frame and pg_lgframe
accordingly, using the physical address bit reduction provided by
cpuid.

from hshoexer@; OK mlarkin@

sys/arch/amd64/amd64/cpu.c
sys/arch/amd64/amd64/locore0.S
sys/arch/amd64/amd64/pmap.c
sys/arch/amd64/include/cpu.h
sys/arch/amd64/include/specialreg.h

index 8df6de0..898c230 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.190 2024/06/07 16:53:35 kettenis Exp $      */
+/*     $OpenBSD: cpu.c,v 1.191 2024/07/21 19:41:31 bluhm Exp $ */
 /* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
 
 /*-
@@ -157,6 +157,7 @@ int cpu_ebxfeature = 0;             /* cpuid(1).ebx */
 int cpu_ecxfeature = 0;                /* INTERSECTION(cpuid(1).ecx) */
 int cpu_feature = 0;           /* cpuid(1).edx */
 int ecpu_ecxfeature = 0;       /* cpuid(0x80000001).ecx */
+int cpu_sev_guestmode = 0;
 int cpu_meltdown = 0;
 int cpu_use_xsaves = 0;
 int need_retpoline = 1;                /* most systems need retpoline */
index bbfed3a..bc45eee 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: locore0.S,v 1.24 2024/07/10 12:36:13 bluhm Exp $      */
+/*     $OpenBSD: locore0.S,v 1.25 2024/07/21 19:41:31 bluhm Exp $      */
 /*     $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $     */
 
 /*
@@ -268,6 +268,78 @@ bi_size_ok:
 cont:
        orl     %edx, RELOC(cpu_feature)
 
+       /*
+        * Determine AMD SME and SEV capabilities.
+        */
+       movl    $RELOC(cpu_vendor),%ebp
+       cmpl $0x68747541, (%ebp)        /* "Auth" */
+       jne     .Lno_smesev
+       cmpl $0x69746e65, 4(%ebp)       /* "enti" */
+       jne     .Lno_smesev
+       cmpl $0x444d4163, 8(%ebp)       /* "cAMD" */
+       jne     .Lno_smesev
+
+       /* AMD CPU, check for SME and SEV. */
+       movl    $0x8000001f, %eax
+       cpuid
+       pushl   %eax
+       andl    $CPUIDEAX_SME, %eax     /* SME */
+       popl    %eax
+       jz      .Lno_smesev
+       andl    $CPUIDEAX_SEV, %eax     /* SEV */
+       jz      .Lno_smesev
+
+       /* Are we in guest mode with SEV enabled? */
+       movl    $MSR_SEV_STATUS, %ecx
+       rdmsr
+       andl    $SEV_STAT_ENABLED, %eax
+       jz      .Lno_smesev
+
+       /* Determine C bit position */
+       movl    %ebx, %ecx      /* %ebx from previous cpuid */
+       andl    $0x3f, %ecx
+       cmpl    $0x20, %ecx     /* must be at least bit 32 (counting from 0) */
+       jl      .Lno_smesev
+       xorl    %eax, %eax
+       movl    %eax, RELOC(pg_crypt)
+       subl    $0x20, %ecx
+       movl    $0x1, %eax
+       shll    %cl, %eax
+       movl    %eax, RELOC((pg_crypt + 4))
+
+       /*
+        * Determine physical address reduction. Adjust page frame masks.
+        *
+        * The top 12 bits of a physical address are reserved and
+        * supposed to be 0. Thus PG_FRAME masks of the top 12 bits
+        * and low 10 bits (offset into page).  PG_LGFRAME is defined
+        * similarly.
+        *
+        * According to the number of reduction bits we shrink the
+        * page frame masks beginning at bit 51.
+        *
+        * E.g. with a 5 bit reduction PG_FRAME will be reduced from
+        * 0x000ffffffffff000 to 0x00007ffffffff000.
+        *
+        * One of the now freed bits will be used as the C bit, e.g.
+        * bit 51.
+        */
+       movl    %ebx, %ecx                      /* %ebx from previous cpuid */
+       andl    $0xfc0, %ecx
+       shrl    $6, %ecx                        /* number of bits to reduce */
+
+       movl    $1, %eax                        /* calculate mask */
+       shll    $20, %eax
+       shrl    %cl, %eax
+       decl    %eax
+
+       andl    %eax, RELOC(pg_frame + 4)       /* apply mask */
+       andl    %eax, RELOC(pg_lgframe + 4)
+
+       movl    $0x1, RELOC(cpu_sev_guestmode)  /* we are a SEV guest */
+
+.Lno_smesev:
+
        /*
         * Finished with old stack; load new %esp now instead of later so we
         * can trace this code without having to worry about the trace trap
index 0c3fe07..f8c4ace 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.169 2024/07/09 19:11:06 bluhm Exp $        */
+/*     $OpenBSD: pmap.c,v 1.170 2024/07/21 19:41:31 bluhm Exp $        */
 /*     $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
 
 /*
@@ -660,6 +660,8 @@ pmap_bootstrap(paddr_t first_avail, paddr_t max_pa)
        vaddr_t kva, kva_end;
        pt_entry_t *pml3, *pml2;
 
+       KASSERT(((0x1000ULL | pg_crypt) & pg_frame) == 0x1000ULL);
+
        /*
         * define the boundaries of the managed kernel virtual address
         * space.
index 8bc757c..f5aada4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.h,v 1.174 2024/06/24 21:22:14 bluhm Exp $ */
+/*     $OpenBSD: cpu.h,v 1.175 2024/07/21 19:41:31 bluhm Exp $ */
 /*     $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $     */
 
 /*-
@@ -398,6 +398,7 @@ extern int cpu_feature;
 extern int cpu_ebxfeature;
 extern int cpu_ecxfeature;
 extern int ecpu_ecxfeature;
+extern int cpu_sev_guestmode;
 extern int cpu_id;
 extern char cpu_vendor[];
 extern int cpuid_level;
index 7d1a080..a8a7e49 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: specialreg.h,v 1.114 2024/07/14 07:57:42 dv Exp $     */
+/*     $OpenBSD: specialreg.h,v 1.115 2024/07/21 19:41:31 bluhm Exp $  */
 /*     $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $      */
 /*     $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $  */
 
 #define                NB_CFG_DISIOREQLOCK     0x0000000000000004ULL
 #define                NB_CFG_DISDATMSK        0x0000001000000000ULL
 
+#define MSR_SEV_STATUS 0xc0010131
+#define                SEV_STAT_ENABLED        0x00000001
+
 #define        MSR_LS_CFG      0xc0011020
 #define                LS_CFG_DIS_LS2_SQUISH   0x02000000