From: Joerg Roedel <jroe...@suse.de>

Check whether the hypervisor supports GHCB version 2 and use it if
available.

Signed-off-by: Joerg Roedel <jroe...@suse.de>
---
 arch/x86/boot/compressed/sev.c | 10 ++++++++--
 arch/x86/include/asm/sev.h     |  4 ++--
 arch/x86/kernel/sev-shared.c   | 17 ++++++++++++++---
 3 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 101e08c67296..7f8416f76be7 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -119,16 +119,22 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
 /* Include code for early handlers */
 #include "../../kernel/sev-shared.c"
 
+static unsigned int ghcb_protocol;
+
 static u64 sev_get_ghcb_proto_ver(void)
 {
-       return GHCB_PROTOCOL_MAX;
+       return ghcb_protocol;
 }
 
 static bool early_setup_sev_es(void)
 {
-       if (!sev_es_negotiate_protocol(NULL))
+       struct sev_ghcb_protocol_info info;
+
+       if (!sev_es_negotiate_protocol(&info))
                sev_es_terminate(GHCB_SEV_ES_REASON_PROTOCOL_UNSUPPORTED);
 
+       ghcb_protocol = info.vm_proto;
+
        if (set_page_decrypted((unsigned long)&boot_ghcb_page))
                return false;
 
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index fa5cd05d3b5b..134a7c9d91b6 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -12,8 +12,8 @@
 #include <asm/insn.h>
 #include <asm/sev-common.h>
 
-#define GHCB_PROTO_OUR         0x0001UL
-#define GHCB_PROTOCOL_MAX      1ULL
+#define GHCB_PROTOCOL_MIN      1ULL
+#define GHCB_PROTOCOL_MAX      2ULL
 #define GHCB_DEFAULT_USAGE     0ULL
 
 #define        VMGEXIT()                       { asm volatile("rep; 
vmmcall\n\r"); }
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index 36eaac2773ed..40a1ca81bdb8 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -61,6 +61,7 @@ static void __noreturn sev_es_terminate(unsigned int reason)
 
 static bool sev_es_negotiate_protocol(struct sev_ghcb_protocol_info *info)
 {
+       unsigned int protocol;
        u64 val;
 
        /* Do the GHCB protocol version negotiation */
@@ -71,14 +72,24 @@ static bool sev_es_negotiate_protocol(struct 
sev_ghcb_protocol_info *info)
        if (GHCB_MSR_INFO(val) != GHCB_MSR_SEV_INFO_RESP)
                return false;
 
-       if (GHCB_MSR_PROTO_MAX(val) < GHCB_PROTO_OUR ||
-           GHCB_MSR_PROTO_MIN(val) > GHCB_PROTO_OUR)
+       /* Sanity check untrusted input */
+       if (GHCB_MSR_PROTO_MIN(val) > GHCB_MSR_PROTO_MAX(val))
+               return false;
+
+       /* Use maximum supported protocol version */
+       protocol = min_t(unsigned int, GHCB_MSR_PROTO_MAX(val), 
GHCB_PROTOCOL_MAX);
+
+       /*
+        * Hypervisor does not support any protocol version required for this
+        * kernel.
+        */
+       if (protocol < GHCB_MSR_PROTO_MIN(val))
                return false;
 
        if (info) {
                info->hv_proto_min = GHCB_MSR_PROTO_MIN(val);
                info->hv_proto_max = GHCB_MSR_PROTO_MAX(val);
-               info->vm_proto     = GHCB_PROTO_OUR;
+               info->vm_proto     = protocol;
        }
 
        return true;
-- 
2.31.1

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

Reply via email to