xref: /linux/arch/x86/include/asm/sev.h (revision c9933d494c54f72290831191c09bb8488bfd5905)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * AMD Encrypted Register State Support
4  *
5  * Author: Joerg Roedel <jroedel@suse.de>
6  */
7 
8 #ifndef __ASM_ENCRYPTED_STATE_H
9 #define __ASM_ENCRYPTED_STATE_H
10 
11 #include <linux/types.h>
12 #include <asm/insn.h>
13 #include <asm/sev-common.h>
14 
15 #define GHCB_PROTO_OUR		0x0001UL
16 #define GHCB_PROTOCOL_MAX	1ULL
17 #define GHCB_DEFAULT_USAGE	0ULL
18 
19 #define	VMGEXIT()			{ asm volatile("rep; vmmcall\n\r"); }
20 
21 enum es_result {
22 	ES_OK,			/* All good */
23 	ES_UNSUPPORTED,		/* Requested operation not supported */
24 	ES_VMM_ERROR,		/* Unexpected state from the VMM */
25 	ES_DECODE_FAILED,	/* Instruction decoding failed */
26 	ES_EXCEPTION,		/* Instruction caused exception */
27 	ES_RETRY,		/* Retry instruction emulation */
28 };
29 
30 struct es_fault_info {
31 	unsigned long vector;
32 	unsigned long error_code;
33 	unsigned long cr2;
34 };
35 
36 struct pt_regs;
37 
38 /* ES instruction emulation context */
39 struct es_em_ctxt {
40 	struct pt_regs *regs;
41 	struct insn insn;
42 	struct es_fault_info fi;
43 };
44 
45 void do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code);
46 
47 static inline u64 lower_bits(u64 val, unsigned int bits)
48 {
49 	u64 mask = (1ULL << bits) - 1;
50 
51 	return (val & mask);
52 }
53 
54 struct real_mode_header;
55 enum stack_type;
56 struct ghcb;
57 
58 /* Early IDT entry points for #VC handler */
59 extern void vc_no_ghcb(void);
60 extern void vc_boot_ghcb(void);
61 extern bool handle_vc_boot_ghcb(struct pt_regs *regs);
62 
63 #ifdef CONFIG_AMD_MEM_ENCRYPT
64 extern struct static_key_false sev_es_enable_key;
65 extern void __sev_es_ist_enter(struct pt_regs *regs);
66 extern void __sev_es_ist_exit(void);
67 static __always_inline void sev_es_ist_enter(struct pt_regs *regs)
68 {
69 	if (static_branch_unlikely(&sev_es_enable_key))
70 		__sev_es_ist_enter(regs);
71 }
72 static __always_inline void sev_es_ist_exit(void)
73 {
74 	if (static_branch_unlikely(&sev_es_enable_key))
75 		__sev_es_ist_exit();
76 }
77 extern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh);
78 extern void __sev_es_nmi_complete(void);
79 static __always_inline void sev_es_nmi_complete(void)
80 {
81 	if (static_branch_unlikely(&sev_es_enable_key))
82 		__sev_es_nmi_complete();
83 }
84 extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
85 extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
86 					  bool set_ghcb_msr,
87 					  struct es_em_ctxt *ctxt,
88 					  u64 exit_code, u64 exit_info_1,
89 					  u64 exit_info_2);
90 #else
91 static inline void sev_es_ist_enter(struct pt_regs *regs) { }
92 static inline void sev_es_ist_exit(void) { }
93 static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
94 static inline void sev_es_nmi_complete(void) { }
95 static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
96 #endif
97 
98 #endif
99