mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Conflicts: arch/x86/boot/startup/sme.c arch/x86/coco/sev/core.c arch/x86/kernel/fpu/core.c arch/x86/kernel/fpu/xstate.c Semantic conflict: arch/x86/include/asm/sev-internal.h Signed-off-by: Ingo Molnar <mingo@kernel.org>
105 lines
2.9 KiB
C
105 lines
2.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#define DR7_RESET_VALUE 0x400
|
|
|
|
extern struct ghcb boot_ghcb_page;
|
|
extern u64 sev_hv_features;
|
|
extern u64 sev_secrets_pa;
|
|
|
|
/* #VC handler runtime per-CPU data */
|
|
struct sev_es_runtime_data {
|
|
struct ghcb ghcb_page;
|
|
|
|
/*
|
|
* Reserve one page per CPU as backup storage for the unencrypted GHCB.
|
|
* It is needed when an NMI happens while the #VC handler uses the real
|
|
* GHCB, and the NMI handler itself is causing another #VC exception. In
|
|
* that case the GHCB content of the first handler needs to be backed up
|
|
* and restored.
|
|
*/
|
|
struct ghcb backup_ghcb;
|
|
|
|
/*
|
|
* Mark the per-cpu GHCBs as in-use to detect nested #VC exceptions.
|
|
* There is no need for it to be atomic, because nothing is written to
|
|
* the GHCB between the read and the write of ghcb_active. So it is safe
|
|
* to use it when a nested #VC exception happens before the write.
|
|
*
|
|
* This is necessary for example in the #VC->NMI->#VC case when the NMI
|
|
* happens while the first #VC handler uses the GHCB. When the NMI code
|
|
* raises a second #VC handler it might overwrite the contents of the
|
|
* GHCB written by the first handler. To avoid this the content of the
|
|
* GHCB is saved and restored when the GHCB is detected to be in use
|
|
* already.
|
|
*/
|
|
bool ghcb_active;
|
|
bool backup_ghcb_active;
|
|
|
|
/*
|
|
* Cached DR7 value - write it on DR7 writes and return it on reads.
|
|
* That value will never make it to the real hardware DR7 as debugging
|
|
* is currently unsupported in SEV-ES guests.
|
|
*/
|
|
unsigned long dr7;
|
|
};
|
|
|
|
struct ghcb_state {
|
|
struct ghcb *ghcb;
|
|
};
|
|
|
|
extern struct svsm_ca boot_svsm_ca_page;
|
|
|
|
struct ghcb *__sev_get_ghcb(struct ghcb_state *state);
|
|
void __sev_put_ghcb(struct ghcb_state *state);
|
|
|
|
DECLARE_PER_CPU(struct sev_es_runtime_data*, runtime_data);
|
|
DECLARE_PER_CPU(struct sev_es_save_area *, sev_vmsa);
|
|
|
|
void early_set_pages_state(unsigned long vaddr, unsigned long paddr,
|
|
unsigned long npages, enum psc_op op);
|
|
|
|
DECLARE_PER_CPU(struct svsm_ca *, svsm_caa);
|
|
DECLARE_PER_CPU(u64, svsm_caa_pa);
|
|
|
|
extern struct svsm_ca *boot_svsm_caa;
|
|
extern u64 boot_svsm_caa_pa;
|
|
|
|
static __always_inline struct svsm_ca *svsm_get_caa(void)
|
|
{
|
|
if (sev_cfg.use_cas)
|
|
return this_cpu_read(svsm_caa);
|
|
else
|
|
return boot_svsm_caa;
|
|
}
|
|
|
|
static __always_inline u64 svsm_get_caa_pa(void)
|
|
{
|
|
if (sev_cfg.use_cas)
|
|
return this_cpu_read(svsm_caa_pa);
|
|
else
|
|
return boot_svsm_caa_pa;
|
|
}
|
|
|
|
int svsm_perform_call_protocol(struct svsm_call *call);
|
|
|
|
static inline u64 sev_es_rd_ghcb_msr(void)
|
|
{
|
|
return native_rdmsrq(MSR_AMD64_SEV_ES_GHCB);
|
|
}
|
|
|
|
static __always_inline void sev_es_wr_ghcb_msr(u64 val)
|
|
{
|
|
u32 low, high;
|
|
|
|
low = (u32)(val);
|
|
high = (u32)(val >> 32);
|
|
|
|
native_wrmsr(MSR_AMD64_SEV_ES_GHCB, low, high);
|
|
}
|
|
|
|
void snp_register_ghcb_early(unsigned long paddr);
|
|
bool sev_es_negotiate_protocol(void);
|
|
bool sev_es_check_cpu_features(void);
|
|
u64 get_hv_features(void);
|
|
|
|
const struct snp_cpuid_table *snp_cpuid_get_table(void);
|