x86/sev: Register GHCB memory when SEV-SNP is active
[linux-2.6-block.git] / arch / x86 / include / asm / sev.h
CommitLineData
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
21enum 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
30struct es_fault_info {
31 unsigned long vector;
32 unsigned long error_code;
33 unsigned long cr2;
34};
35
36struct pt_regs;
37
38/* ES instruction emulation context */
39struct es_em_ctxt {
40 struct pt_regs *regs;
41 struct insn insn;
42 struct es_fault_info fi;
43};
44
29dcc60f
JR
45void do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code);
46
47static 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
54struct real_mode_header;
55enum stack_type;
007faec0 56struct ghcb;
8940ac9c 57
74d8d9d5
JR
58/* Early IDT entry points for #VC handler */
59extern void vc_no_ghcb(void);
1aa9aa8e
JR
60extern void vc_boot_ghcb(void);
61extern 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
70extern struct static_key_false sev_es_enable_key;
71extern void __sev_es_ist_enter(struct pt_regs *regs);
72extern void __sev_es_ist_exit(void);
73static __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}
78static __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 83extern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh);
4ca68e02
JR
84extern void __sev_es_nmi_complete(void);
85static __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 90extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
007faec0
TL
91extern 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
96static 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
108static 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 125void setup_ghcb(void);
315562c9
JR
126#else
127static inline void sev_es_ist_enter(struct pt_regs *regs) { }
128static inline void sev_es_ist_exit(void) { }
8940ac9c 129static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
4ca68e02 130static inline void sev_es_nmi_complete(void) { }
39336f4f 131static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
0bd6f1e5 132static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
81cc3df9 133static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
95d33bfa 134static inline void setup_ghcb(void) { }
315562c9
JR
135#endif
136
29dcc60f 137#endif