Commit | Line | Data |
---|---|---|
29dcc60f JR |
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> | |
597cfe48 | 12 | #include <asm/insn.h> |
b81fc74d | 13 | #include <asm/sev-common.h> |
29dcc60f | 14 | |
2ea29c5a | 15 | #define GHCB_PROTOCOL_MIN 1ULL |
cbd3d4f7 | 16 | #define GHCB_PROTOCOL_MAX 2ULL |
b81fc74d | 17 | #define GHCB_DEFAULT_USAGE 0ULL |
29dcc60f | 18 | |
29dcc60f JR |
19 | #define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); } |
20 | ||
597cfe48 JR |
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 | ||
29dcc60f JR |
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 | ||
8940ac9c TL |
54 | struct real_mode_header; |
55 | enum stack_type; | |
007faec0 | 56 | struct ghcb; |
8940ac9c | 57 | |
74d8d9d5 JR |
58 | /* Early IDT entry points for #VC handler */ |
59 | extern void vc_no_ghcb(void); | |
1aa9aa8e JR |
60 | extern void vc_boot_ghcb(void); |
61 | extern bool handle_vc_boot_ghcb(struct pt_regs *regs); | |
74d8d9d5 | 62 | |
0bd6f1e5 BS |
63 | /* Software defined (when rFlags.CF = 1) */ |
64 | #define PVALIDATE_FAIL_NOUPDATE 255 | |
65 | ||
81cc3df9 BS |
66 | /* RMP page size */ |
67 | #define RMP_PG_SIZE_4K 0 | |
68 | ||
315562c9 JR |
69 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
70 | extern struct static_key_false sev_es_enable_key; | |
71 | extern void __sev_es_ist_enter(struct pt_regs *regs); | |
72 | extern void __sev_es_ist_exit(void); | |
73 | static __always_inline void sev_es_ist_enter(struct pt_regs *regs) | |
74 | { | |
75 | if (static_branch_unlikely(&sev_es_enable_key)) | |
76 | __sev_es_ist_enter(regs); | |
77 | } | |
78 | static __always_inline void sev_es_ist_exit(void) | |
79 | { | |
80 | if (static_branch_unlikely(&sev_es_enable_key)) | |
81 | __sev_es_ist_exit(); | |
82 | } | |
8940ac9c | 83 | extern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh); |
4ca68e02 JR |
84 | extern void __sev_es_nmi_complete(void); |
85 | static __always_inline void sev_es_nmi_complete(void) | |
86 | { | |
87 | if (static_branch_unlikely(&sev_es_enable_key)) | |
88 | __sev_es_nmi_complete(); | |
89 | } | |
39336f4f | 90 | extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd); |
007faec0 TL |
91 | extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, |
92 | bool set_ghcb_msr, | |
93 | struct es_em_ctxt *ctxt, | |
94 | u64 exit_code, u64 exit_info_1, | |
95 | u64 exit_info_2); | |
81cc3df9 BS |
96 | static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) |
97 | { | |
98 | int rc; | |
99 | ||
100 | /* "rmpadjust" mnemonic support in binutils 2.36 and newer */ | |
101 | asm volatile(".byte 0xF3,0x0F,0x01,0xFE\n\t" | |
102 | : "=a"(rc) | |
103 | : "a"(vaddr), "c"(rmp_psize), "d"(attrs) | |
104 | : "memory", "cc"); | |
105 | ||
106 | return rc; | |
107 | } | |
0bd6f1e5 BS |
108 | static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) |
109 | { | |
110 | bool no_rmpupdate; | |
111 | int rc; | |
112 | ||
113 | /* "pvalidate" mnemonic support in binutils 2.36 and newer */ | |
114 | asm volatile(".byte 0xF2, 0x0F, 0x01, 0xFF\n\t" | |
115 | CC_SET(c) | |
116 | : CC_OUT(c) (no_rmpupdate), "=a"(rc) | |
117 | : "a"(vaddr), "c"(rmp_psize), "d"(validate) | |
118 | : "memory", "cc"); | |
119 | ||
120 | if (no_rmpupdate) | |
121 | return PVALIDATE_FAIL_NOUPDATE; | |
122 | ||
123 | return rc; | |
124 | } | |
95d33bfa | 125 | void setup_ghcb(void); |
315562c9 JR |
126 | #else |
127 | static inline void sev_es_ist_enter(struct pt_regs *regs) { } | |
128 | static inline void sev_es_ist_exit(void) { } | |
8940ac9c | 129 | static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; } |
4ca68e02 | 130 | static inline void sev_es_nmi_complete(void) { } |
39336f4f | 131 | static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; } |
0bd6f1e5 | 132 | static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; } |
81cc3df9 | 133 | static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; } |
95d33bfa | 134 | static inline void setup_ghcb(void) { } |
315562c9 JR |
135 | #endif |
136 | ||
29dcc60f | 137 | #endif |