mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
x86/apic: Support LAPIC timer for Secure AVIC
Secure AVIC requires the LAPIC timer to be emulated by the hypervisor. KVM already supports emulating the LAPIC timer using hrtimers. In order to emulate it, APIC_LVTT, APIC_TMICT and APIC_TDCR register values need to be propagated to the hypervisor for arming the timer. APIC_TMCCT register value has to be read from the hypervisor, which is required for calibrating the APIC timer. So, read/write all APIC timer registers from/to the hypervisor. Co-developed-by: Kishon Vijay Abraham I <kvijayab@amd.com> Signed-off-by: Kishon Vijay Abraham I <kvijayab@amd.com> Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Tianyu Lan <tiala@microsoft.com> Link: https://lore.kernel.org/20250828110926.208866-1-Neeraj.Upadhyay@amd.com
This commit is contained in:
parent
2c6978ea1a
commit
ea7d792e11
|
|
@ -1108,6 +1108,32 @@ int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u64 savic_ghcb_msr_read(u32 reg)
|
||||
{
|
||||
u64 msr = APIC_BASE_MSR + (reg >> 4);
|
||||
struct pt_regs regs = { .cx = msr };
|
||||
struct es_em_ctxt ctxt = { .regs = ®s };
|
||||
struct ghcb_state state;
|
||||
enum es_result res;
|
||||
struct ghcb *ghcb;
|
||||
|
||||
guard(irqsave)();
|
||||
|
||||
ghcb = __sev_get_ghcb(&state);
|
||||
vc_ghcb_invalidate(ghcb);
|
||||
|
||||
res = sev_es_ghcb_handle_msr(ghcb, &ctxt, false);
|
||||
if (res != ES_OK) {
|
||||
pr_err("Secure AVIC MSR (0x%llx) read returned error (%d)\n", msr, res);
|
||||
/* MSR read failures are treated as fatal errors */
|
||||
snp_abort();
|
||||
}
|
||||
|
||||
__sev_put_ghcb(&state);
|
||||
|
||||
return regs.ax | regs.dx << 32;
|
||||
}
|
||||
|
||||
void savic_ghcb_msr_write(u32 reg, u64 value)
|
||||
{
|
||||
u64 msr = APIC_BASE_MSR + (reg >> 4);
|
||||
|
|
|
|||
|
|
@ -534,6 +534,7 @@ int snp_svsm_vtpm_send_command(u8 *buffer);
|
|||
void __init snp_secure_tsc_prepare(void);
|
||||
void __init snp_secure_tsc_init(void);
|
||||
enum es_result savic_register_gpa(u64 gpa);
|
||||
u64 savic_ghcb_msr_read(u32 reg);
|
||||
void savic_ghcb_msr_write(u32 reg, u64 value);
|
||||
|
||||
static __always_inline void vc_ghcb_invalidate(struct ghcb *ghcb)
|
||||
|
|
@ -609,6 +610,7 @@ static inline void __init snp_secure_tsc_prepare(void) { }
|
|||
static inline void __init snp_secure_tsc_init(void) { }
|
||||
static inline enum es_result savic_register_gpa(u64 gpa) { return ES_UNSUPPORTED; }
|
||||
static inline void savic_ghcb_msr_write(u32 reg, u64 value) { }
|
||||
static inline u64 savic_ghcb_msr_read(u32 reg) { return 0; }
|
||||
|
||||
#endif /* CONFIG_AMD_MEM_ENCRYPT */
|
||||
|
||||
|
|
|
|||
|
|
@ -592,6 +592,8 @@ static void setup_APIC_timer(void)
|
|||
0xF, ~0UL);
|
||||
} else
|
||||
clockevents_register_device(levt);
|
||||
|
||||
apic_update_vector(smp_processor_id(), LOCAL_TIMER_VECTOR, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ static u32 savic_read(u32 reg)
|
|||
case APIC_TMICT:
|
||||
case APIC_TMCCT:
|
||||
case APIC_TDCR:
|
||||
return savic_ghcb_msr_read(reg);
|
||||
case APIC_ID:
|
||||
case APIC_LVR:
|
||||
case APIC_TASKPRI:
|
||||
|
|
@ -194,10 +195,12 @@ static void savic_write(u32 reg, u32 data)
|
|||
|
||||
switch (reg) {
|
||||
case APIC_LVTT:
|
||||
case APIC_LVT0:
|
||||
case APIC_LVT1:
|
||||
case APIC_TMICT:
|
||||
case APIC_TDCR:
|
||||
savic_ghcb_msr_write(reg, data);
|
||||
break;
|
||||
case APIC_LVT0:
|
||||
case APIC_LVT1:
|
||||
case APIC_TASKPRI:
|
||||
case APIC_EOI:
|
||||
case APIC_SPIV:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user