2020-09-07 21:15:20 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
/*
|
|
|
|
* AMD Encrypted Register State Support
|
|
|
|
*
|
|
|
|
* Author: Joerg Roedel <jroedel@suse.de>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __ASM_ENCRYPTED_STATE_H
|
|
|
|
#define __ASM_ENCRYPTED_STATE_H
|
|
|
|
|
|
|
|
#include <linux/types.h>
|
2020-09-07 21:15:24 +08:00
|
|
|
#include <asm/insn.h>
|
2020-09-07 21:15:20 +08:00
|
|
|
|
2020-09-07 21:15:24 +08:00
|
|
|
#define GHCB_SEV_INFO 0x001UL
|
|
|
|
#define GHCB_SEV_INFO_REQ 0x002UL
|
|
|
|
#define GHCB_INFO(v) ((v) & 0xfffUL)
|
|
|
|
#define GHCB_PROTO_MAX(v) (((v) >> 48) & 0xffffUL)
|
|
|
|
#define GHCB_PROTO_MIN(v) (((v) >> 32) & 0xffffUL)
|
|
|
|
#define GHCB_PROTO_OUR 0x0001UL
|
2020-09-07 21:15:20 +08:00
|
|
|
#define GHCB_SEV_CPUID_REQ 0x004UL
|
|
|
|
#define GHCB_CPUID_REQ_EAX 0
|
|
|
|
#define GHCB_CPUID_REQ_EBX 1
|
|
|
|
#define GHCB_CPUID_REQ_ECX 2
|
|
|
|
#define GHCB_CPUID_REQ_EDX 3
|
|
|
|
#define GHCB_CPUID_REQ(fn, reg) (GHCB_SEV_CPUID_REQ | \
|
|
|
|
(((unsigned long)reg & 3) << 30) | \
|
|
|
|
(((unsigned long)fn) << 32))
|
|
|
|
|
2020-09-07 21:15:24 +08:00
|
|
|
#define GHCB_PROTOCOL_MAX 0x0001UL
|
|
|
|
#define GHCB_DEFAULT_USAGE 0x0000UL
|
|
|
|
|
2020-09-07 21:15:20 +08:00
|
|
|
#define GHCB_SEV_CPUID_RESP 0x005UL
|
|
|
|
#define GHCB_SEV_TERMINATE 0x100UL
|
2020-09-07 21:15:24 +08:00
|
|
|
#define GHCB_SEV_TERMINATE_REASON(reason_set, reason_val) \
|
|
|
|
(((((u64)reason_set) & 0x7) << 12) | \
|
|
|
|
((((u64)reason_val) & 0xff) << 16))
|
|
|
|
#define GHCB_SEV_ES_REASON_GENERAL_REQUEST 0
|
|
|
|
#define GHCB_SEV_ES_REASON_PROTOCOL_UNSUPPORTED 1
|
2020-09-07 21:15:20 +08:00
|
|
|
|
|
|
|
#define GHCB_SEV_GHCB_RESP_CODE(v) ((v) & 0xfff)
|
|
|
|
#define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); }
|
|
|
|
|
2020-09-07 21:15:24 +08:00
|
|
|
enum es_result {
|
|
|
|
ES_OK, /* All good */
|
|
|
|
ES_UNSUPPORTED, /* Requested operation not supported */
|
|
|
|
ES_VMM_ERROR, /* Unexpected state from the VMM */
|
|
|
|
ES_DECODE_FAILED, /* Instruction decoding failed */
|
|
|
|
ES_EXCEPTION, /* Instruction caused exception */
|
|
|
|
ES_RETRY, /* Retry instruction emulation */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct es_fault_info {
|
|
|
|
unsigned long vector;
|
|
|
|
unsigned long error_code;
|
|
|
|
unsigned long cr2;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct pt_regs;
|
|
|
|
|
|
|
|
/* ES instruction emulation context */
|
|
|
|
struct es_em_ctxt {
|
|
|
|
struct pt_regs *regs;
|
|
|
|
struct insn insn;
|
|
|
|
struct es_fault_info fi;
|
|
|
|
};
|
|
|
|
|
2020-09-07 21:15:20 +08:00
|
|
|
void do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code);
|
|
|
|
|
|
|
|
static inline u64 lower_bits(u64 val, unsigned int bits)
|
|
|
|
{
|
|
|
|
u64 mask = (1ULL << bits) - 1;
|
|
|
|
|
|
|
|
return (val & mask);
|
|
|
|
}
|
|
|
|
|
2020-09-07 21:16:07 +08:00
|
|
|
struct real_mode_header;
|
|
|
|
enum stack_type;
|
|
|
|
|
2020-09-08 20:35:17 +08:00
|
|
|
/* Early IDT entry points for #VC handler */
|
|
|
|
extern void vc_no_ghcb(void);
|
2020-09-08 20:38:16 +08:00
|
|
|
extern void vc_boot_ghcb(void);
|
|
|
|
extern bool handle_vc_boot_ghcb(struct pt_regs *regs);
|
2020-09-08 20:35:17 +08:00
|
|
|
|
2020-09-07 21:15:44 +08:00
|
|
|
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
|
|
|
extern struct static_key_false sev_es_enable_key;
|
|
|
|
extern void __sev_es_ist_enter(struct pt_regs *regs);
|
|
|
|
extern void __sev_es_ist_exit(void);
|
|
|
|
static __always_inline void sev_es_ist_enter(struct pt_regs *regs)
|
|
|
|
{
|
|
|
|
if (static_branch_unlikely(&sev_es_enable_key))
|
|
|
|
__sev_es_ist_enter(regs);
|
|
|
|
}
|
|
|
|
static __always_inline void sev_es_ist_exit(void)
|
|
|
|
{
|
|
|
|
if (static_branch_unlikely(&sev_es_enable_key))
|
|
|
|
__sev_es_ist_exit();
|
|
|
|
}
|
2020-09-07 21:16:07 +08:00
|
|
|
extern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh);
|
2020-09-07 21:16:11 +08:00
|
|
|
extern void __sev_es_nmi_complete(void);
|
|
|
|
static __always_inline void sev_es_nmi_complete(void)
|
|
|
|
{
|
|
|
|
if (static_branch_unlikely(&sev_es_enable_key))
|
|
|
|
__sev_es_nmi_complete();
|
|
|
|
}
|
2020-09-07 21:15:44 +08:00
|
|
|
#else
|
|
|
|
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
|
|
|
|
static inline void sev_es_ist_exit(void) { }
|
2020-09-07 21:16:07 +08:00
|
|
|
static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
|
2020-09-07 21:16:11 +08:00
|
|
|
static inline void sev_es_nmi_complete(void) { }
|
2020-09-07 21:15:44 +08:00
|
|
|
#endif
|
|
|
|
|
2020-09-07 21:15:20 +08:00
|
|
|
#endif
|