1 /* SPDX-License-Identifier: GPL-2.0 */
3 * AMD Encrypted Register State Support
5 * Author: Joerg Roedel <jroedel@suse.de>
8 #ifndef __ASM_ENCRYPTED_STATE_H
9 #define __ASM_ENCRYPTED_STATE_H
11 #include <linux/types.h>
12 #include <linux/sev-guest.h>
15 #include <asm/sev-common.h>
16 #include <asm/bootparam.h>
18 #define GHCB_PROTOCOL_MIN 1ULL
19 #define GHCB_PROTOCOL_MAX 2ULL
20 #define GHCB_DEFAULT_USAGE 0ULL
22 #define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); }
26 ES_UNSUPPORTED, /* Requested operation not supported */
27 ES_VMM_ERROR, /* Unexpected state from the VMM */
28 ES_DECODE_FAILED, /* Instruction decoding failed */
29 ES_EXCEPTION, /* Instruction caused exception */
30 ES_RETRY, /* Retry instruction emulation */
33 struct es_fault_info {
35 unsigned long error_code;
41 /* ES instruction emulation context */
45 struct es_fault_info fi;
49 * AMD SEV Confidential computing blob structure. The structure is
50 * defined in OVMF UEFI firmware header:
51 * https://github.com/tianocore/edk2/blob/master/OvmfPkg/Include/Guid/ConfidentialComputingSevSnpBlob.h
53 #define CC_BLOB_SEV_HDR_MAGIC 0x45444d41
54 struct cc_blob_sev_info {
66 void do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code);
68 static inline u64 lower_bits(u64 val, unsigned int bits)
70 u64 mask = (1ULL << bits) - 1;
75 struct real_mode_header;
78 /* Early IDT entry points for #VC handler */
79 extern void vc_no_ghcb(void);
80 extern void vc_boot_ghcb(void);
81 extern bool handle_vc_boot_ghcb(struct pt_regs *regs);
83 /* Software defined (when rFlags.CF = 1) */
84 #define PVALIDATE_FAIL_NOUPDATE 255
87 #define RMP_PG_SIZE_4K 0
89 #define RMPADJUST_VMSA_PAGE_BIT BIT(16)
91 /* SNP Guest message request */
93 unsigned long req_gpa;
94 unsigned long resp_gpa;
95 unsigned long data_gpa;
96 unsigned int data_npages;
99 struct sev_guest_platform_data {
104 * The secrets page contains 96-bytes of reserved field that can be used by
105 * the guest OS. The guest OS uses the area to save the message sequence
106 * number for each VMPCK.
108 * See the GHCB spec section Secret page layout for the format for this area.
110 struct secrets_os_area {
115 u64 ap_jump_table_pa;
120 #define VMPCK_KEY_LEN 32
122 /* See the SNP spec version 0.9 for secrets page format */
123 struct snp_secrets_page_layout {
130 u8 vmpck0[VMPCK_KEY_LEN];
131 u8 vmpck1[VMPCK_KEY_LEN];
132 u8 vmpck2[VMPCK_KEY_LEN];
133 u8 vmpck3[VMPCK_KEY_LEN];
134 struct secrets_os_area os_area;
138 #ifdef CONFIG_AMD_MEM_ENCRYPT
139 extern struct static_key_false sev_es_enable_key;
140 extern void __sev_es_ist_enter(struct pt_regs *regs);
141 extern void __sev_es_ist_exit(void);
142 static __always_inline void sev_es_ist_enter(struct pt_regs *regs)
144 if (static_branch_unlikely(&sev_es_enable_key))
145 __sev_es_ist_enter(regs);
147 static __always_inline void sev_es_ist_exit(void)
149 if (static_branch_unlikely(&sev_es_enable_key))
152 extern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh);
153 extern void __sev_es_nmi_complete(void);
154 static __always_inline void sev_es_nmi_complete(void)
156 if (static_branch_unlikely(&sev_es_enable_key))
157 __sev_es_nmi_complete();
159 extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
160 extern void sev_enable(struct boot_params *bp);
162 static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs)
166 /* "rmpadjust" mnemonic support in binutils 2.36 and newer */
167 asm volatile(".byte 0xF3,0x0F,0x01,0xFE\n\t"
169 : "a"(vaddr), "c"(rmp_psize), "d"(attrs)
174 static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
179 /* "pvalidate" mnemonic support in binutils 2.36 and newer */
180 asm volatile(".byte 0xF2, 0x0F, 0x01, 0xFF\n\t"
182 : CC_OUT(c) (no_rmpupdate), "=a"(rc)
183 : "a"(vaddr), "c"(rmp_psize), "d"(validate)
187 return PVALIDATE_FAIL_NOUPDATE;
192 struct snp_guest_request_ioctl;
194 void setup_ghcb(void);
195 void early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
196 unsigned long npages);
197 void early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
198 unsigned long npages);
199 void snp_set_memory_shared(unsigned long vaddr, unsigned long npages);
200 void snp_set_memory_private(unsigned long vaddr, unsigned long npages);
201 void snp_set_wakeup_secondary_cpu(void);
202 bool snp_init(struct boot_params *bp);
203 void __noreturn snp_abort(void);
204 void snp_dmi_setup(void);
205 int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
206 u64 snp_get_unsupported_features(u64 status);
207 u64 sev_get_status(void);
209 static inline void sev_es_ist_enter(struct pt_regs *regs) { }
210 static inline void sev_es_ist_exit(void) { }
211 static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
212 static inline void sev_es_nmi_complete(void) { }
213 static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
214 static inline void sev_enable(struct boot_params *bp) { }
215 static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
216 static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
217 static inline void setup_ghcb(void) { }
218 static inline void __init
219 early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
220 static inline void __init
221 early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
222 static inline void snp_set_memory_shared(unsigned long vaddr, unsigned long npages) { }
223 static inline void snp_set_memory_private(unsigned long vaddr, unsigned long npages) { }
224 static inline void snp_set_wakeup_secondary_cpu(void) { }
225 static inline bool snp_init(struct boot_params *bp) { return false; }
226 static inline void snp_abort(void) { }
227 static inline void snp_dmi_setup(void) { }
228 static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
233 static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
234 static inline u64 sev_get_status(void) { return 0; }