x86/boot/compressed/64: Add stage1 #VC handler
[linux-2.6-microblaze.git] / arch / x86 / kernel / sev-es-shared.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * AMD Encrypted Register State Support
4  *
5  * Author: Joerg Roedel <jroedel@suse.de>
6  *
7  * This file is not compiled stand-alone. It contains code shared
8  * between the pre-decompression boot code and the running Linux kernel
9  * and is included directly into both code-bases.
10  */
11
12 /*
13  * Boot VC Handler - This is the first VC handler during boot, there is no GHCB
14  * page yet, so it only supports the MSR based communication with the
15  * hypervisor and only the CPUID exit-code.
16  */
17 void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
18 {
19         unsigned int fn = lower_bits(regs->ax, 32);
20         unsigned long val;
21
22         /* Only CPUID is supported via MSR protocol */
23         if (exit_code != SVM_EXIT_CPUID)
24                 goto fail;
25
26         sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_EAX));
27         VMGEXIT();
28         val = sev_es_rd_ghcb_msr();
29         if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP)
30                 goto fail;
31         regs->ax = val >> 32;
32
33         sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_EBX));
34         VMGEXIT();
35         val = sev_es_rd_ghcb_msr();
36         if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP)
37                 goto fail;
38         regs->bx = val >> 32;
39
40         sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_ECX));
41         VMGEXIT();
42         val = sev_es_rd_ghcb_msr();
43         if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP)
44                 goto fail;
45         regs->cx = val >> 32;
46
47         sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_EDX));
48         VMGEXIT();
49         val = sev_es_rd_ghcb_msr();
50         if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP)
51                 goto fail;
52         regs->dx = val >> 32;
53
54         /* Skip over the CPUID two-byte opcode */
55         regs->ip += 2;
56
57         return;
58
59 fail:
60         sev_es_wr_ghcb_msr(GHCB_SEV_TERMINATE);
61         VMGEXIT();
62
63         /* Shouldn't get here - if we do halt the machine */
64         while (true)
65                 asm volatile("hlt\n");
66 }