18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AMD Encrypted Register State Support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Joerg Roedel <jroedel@suse.de> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef __ASM_ENCRYPTED_STATE_H 98c2ecf20Sopenharmony_ci#define __ASM_ENCRYPTED_STATE_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/types.h> 128c2ecf20Sopenharmony_ci#include <asm/insn.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define GHCB_SEV_INFO 0x001UL 158c2ecf20Sopenharmony_ci#define GHCB_SEV_INFO_REQ 0x002UL 168c2ecf20Sopenharmony_ci#define GHCB_INFO(v) ((v) & 0xfffUL) 178c2ecf20Sopenharmony_ci#define GHCB_PROTO_MAX(v) (((v) >> 48) & 0xffffUL) 188c2ecf20Sopenharmony_ci#define GHCB_PROTO_MIN(v) (((v) >> 32) & 0xffffUL) 198c2ecf20Sopenharmony_ci#define GHCB_PROTO_OUR 0x0001UL 208c2ecf20Sopenharmony_ci#define GHCB_SEV_CPUID_REQ 0x004UL 218c2ecf20Sopenharmony_ci#define GHCB_CPUID_REQ_EAX 0 228c2ecf20Sopenharmony_ci#define GHCB_CPUID_REQ_EBX 1 238c2ecf20Sopenharmony_ci#define GHCB_CPUID_REQ_ECX 2 248c2ecf20Sopenharmony_ci#define GHCB_CPUID_REQ_EDX 3 258c2ecf20Sopenharmony_ci#define GHCB_CPUID_REQ(fn, reg) (GHCB_SEV_CPUID_REQ | \ 268c2ecf20Sopenharmony_ci (((unsigned long)reg & 3) << 30) | \ 278c2ecf20Sopenharmony_ci (((unsigned long)fn) << 32)) 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define GHCB_PROTOCOL_MAX 0x0001UL 308c2ecf20Sopenharmony_ci#define GHCB_DEFAULT_USAGE 0x0000UL 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define GHCB_SEV_CPUID_RESP 0x005UL 338c2ecf20Sopenharmony_ci#define GHCB_SEV_TERMINATE 0x100UL 348c2ecf20Sopenharmony_ci#define GHCB_SEV_TERMINATE_REASON(reason_set, reason_val) \ 358c2ecf20Sopenharmony_ci (((((u64)reason_set) & 0x7) << 12) | \ 368c2ecf20Sopenharmony_ci ((((u64)reason_val) & 0xff) << 16)) 378c2ecf20Sopenharmony_ci#define GHCB_SEV_ES_REASON_GENERAL_REQUEST 0 388c2ecf20Sopenharmony_ci#define GHCB_SEV_ES_REASON_PROTOCOL_UNSUPPORTED 1 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define GHCB_SEV_GHCB_RESP_CODE(v) ((v) & 0xfff) 418c2ecf20Sopenharmony_ci#define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); } 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cienum es_result { 448c2ecf20Sopenharmony_ci ES_OK, /* All good */ 458c2ecf20Sopenharmony_ci ES_UNSUPPORTED, /* Requested operation not supported */ 468c2ecf20Sopenharmony_ci ES_VMM_ERROR, /* Unexpected state from the VMM */ 478c2ecf20Sopenharmony_ci ES_DECODE_FAILED, /* Instruction decoding failed */ 488c2ecf20Sopenharmony_ci ES_EXCEPTION, /* Instruction caused exception */ 498c2ecf20Sopenharmony_ci ES_RETRY, /* Retry instruction emulation */ 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistruct es_fault_info { 538c2ecf20Sopenharmony_ci unsigned long vector; 548c2ecf20Sopenharmony_ci unsigned long error_code; 558c2ecf20Sopenharmony_ci unsigned long cr2; 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct pt_regs; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* ES instruction emulation context */ 618c2ecf20Sopenharmony_cistruct es_em_ctxt { 628c2ecf20Sopenharmony_ci struct pt_regs *regs; 638c2ecf20Sopenharmony_ci struct insn insn; 648c2ecf20Sopenharmony_ci struct es_fault_info fi; 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_civoid do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic inline u64 lower_bits(u64 val, unsigned int bits) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci u64 mask = (1ULL << bits) - 1; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return (val & mask); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct real_mode_header; 778c2ecf20Sopenharmony_cienum stack_type; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* Early IDT entry points for #VC handler */ 808c2ecf20Sopenharmony_ciextern void vc_no_ghcb(void); 818c2ecf20Sopenharmony_ciextern void vc_boot_ghcb(void); 828c2ecf20Sopenharmony_ciextern bool handle_vc_boot_ghcb(struct pt_regs *regs); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT 858c2ecf20Sopenharmony_ciextern struct static_key_false sev_es_enable_key; 868c2ecf20Sopenharmony_ciextern void __sev_es_ist_enter(struct pt_regs *regs); 878c2ecf20Sopenharmony_ciextern void __sev_es_ist_exit(void); 888c2ecf20Sopenharmony_cistatic __always_inline void sev_es_ist_enter(struct pt_regs *regs) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci if (static_branch_unlikely(&sev_es_enable_key)) 918c2ecf20Sopenharmony_ci __sev_es_ist_enter(regs); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_cistatic __always_inline void sev_es_ist_exit(void) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci if (static_branch_unlikely(&sev_es_enable_key)) 968c2ecf20Sopenharmony_ci __sev_es_ist_exit(); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ciextern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh); 998c2ecf20Sopenharmony_ciextern void __sev_es_nmi_complete(void); 1008c2ecf20Sopenharmony_cistatic __always_inline void sev_es_nmi_complete(void) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci if (static_branch_unlikely(&sev_es_enable_key)) 1038c2ecf20Sopenharmony_ci __sev_es_nmi_complete(); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ciextern int __init sev_es_efi_map_ghcbs(pgd_t *pgd); 1068c2ecf20Sopenharmony_ci#else 1078c2ecf20Sopenharmony_cistatic inline void sev_es_ist_enter(struct pt_regs *regs) { } 1088c2ecf20Sopenharmony_cistatic inline void sev_es_ist_exit(void) { } 1098c2ecf20Sopenharmony_cistatic inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; } 1108c2ecf20Sopenharmony_cistatic inline void sev_es_nmi_complete(void) { } 1118c2ecf20Sopenharmony_cistatic inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; } 1128c2ecf20Sopenharmony_ci#endif 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#endif 115