diff options
| author | Neeraj Upadhyay <Neeraj.Upadhyay@amd.com> | 2025-08-28 16:39:26 +0530 |
|---|---|---|
| committer | Borislav Petkov (AMD) <bp@alien8.de> | 2025-09-01 12:47:07 +0200 |
| commit | ea7d792e11e10f502933c39f3836cb73d35dac36 (patch) | |
| tree | b0f3eadd902590e8a601eb5064cb283fe6026acc /arch/x86/coco/sev/core.c | |
| parent | 2c6978ea1a85603fe7d401f7bb3a1fbcab21fde2 (diff) | |
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
Diffstat (limited to 'arch/x86/coco/sev/core.c')
| -rw-r--r-- | arch/x86/coco/sev/core.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index bb33fc2265db..da9fa9d7254b 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -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); |