Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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