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
14#define GHCB_SEV_INFO		0x001UL
15#define GHCB_SEV_INFO_REQ	0x002UL
16#define		GHCB_INFO(v)		((v) & 0xfffUL)
17#define		GHCB_PROTO_MAX(v)	(((v) >> 48) & 0xffffUL)
18#define		GHCB_PROTO_MIN(v)	(((v) >> 32) & 0xffffUL)
19#define		GHCB_PROTO_OUR		0x0001UL
20#define GHCB_SEV_CPUID_REQ	0x004UL
21#define		GHCB_CPUID_REQ_EAX	0
22#define		GHCB_CPUID_REQ_EBX	1
23#define		GHCB_CPUID_REQ_ECX	2
24#define		GHCB_CPUID_REQ_EDX	3
25#define		GHCB_CPUID_REQ(fn, reg) (GHCB_SEV_CPUID_REQ | \
26					(((unsigned long)reg & 3) << 30) | \
27					(((unsigned long)fn) << 32))
28
29#define	GHCB_PROTOCOL_MAX	0x0001UL
30#define GHCB_DEFAULT_USAGE	0x0000UL
31
32#define GHCB_SEV_CPUID_RESP	0x005UL
33#define GHCB_SEV_TERMINATE	0x100UL
34#define		GHCB_SEV_TERMINATE_REASON(reason_set, reason_val)	\
35			(((((u64)reason_set) &  0x7) << 12) |		\
36			 ((((u64)reason_val) & 0xff) << 16))
37#define		GHCB_SEV_ES_REASON_GENERAL_REQUEST	0
38#define		GHCB_SEV_ES_REASON_PROTOCOL_UNSUPPORTED	1
39
40#define	GHCB_SEV_GHCB_RESP_CODE(v)	((v) & 0xfff)
41#define	VMGEXIT()			{ asm volatile("rep; vmmcall\n\r"); }
42
43enum es_result {
44	ES_OK,			/* All good */
45	ES_UNSUPPORTED,		/* Requested operation not supported */
46	ES_VMM_ERROR,		/* Unexpected state from the VMM */
47	ES_DECODE_FAILED,	/* Instruction decoding failed */
48	ES_EXCEPTION,		/* Instruction caused exception */
49	ES_RETRY,		/* Retry instruction emulation */
50};
51
52struct es_fault_info {
53	unsigned long vector;
54	unsigned long error_code;
55	unsigned long cr2;
56};
57
58struct pt_regs;
59
60/* ES instruction emulation context */
61struct es_em_ctxt {
62	struct pt_regs *regs;
63	struct insn insn;
64	struct es_fault_info fi;
65};
66
67void do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code);
68
69static inline u64 lower_bits(u64 val, unsigned int bits)
70{
71	u64 mask = (1ULL << bits) - 1;
72
73	return (val & mask);
74}
75
76struct real_mode_header;
77enum stack_type;
78
79/* Early IDT entry points for #VC handler */
80extern void vc_no_ghcb(void);
81extern void vc_boot_ghcb(void);
82extern bool handle_vc_boot_ghcb(struct pt_regs *regs);
83
84#ifdef CONFIG_AMD_MEM_ENCRYPT
85extern struct static_key_false sev_es_enable_key;
86extern void __sev_es_ist_enter(struct pt_regs *regs);
87extern void __sev_es_ist_exit(void);
88static __always_inline void sev_es_ist_enter(struct pt_regs *regs)
89{
90	if (static_branch_unlikely(&sev_es_enable_key))
91		__sev_es_ist_enter(regs);
92}
93static __always_inline void sev_es_ist_exit(void)
94{
95	if (static_branch_unlikely(&sev_es_enable_key))
96		__sev_es_ist_exit();
97}
98extern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh);
99extern void __sev_es_nmi_complete(void);
100static __always_inline void sev_es_nmi_complete(void)
101{
102	if (static_branch_unlikely(&sev_es_enable_key))
103		__sev_es_nmi_complete();
104}
105extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
106#else
107static inline void sev_es_ist_enter(struct pt_regs *regs) { }
108static inline void sev_es_ist_exit(void) { }
109static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
110static inline void sev_es_nmi_complete(void) { }
111static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
112#endif
113
114#endif
115