From dd5b8336f5867831f71f4ae9069205a914801432 Mon Sep 17 00:00:00 2001 From: Alejandro Vallejo Date: Wed, 21 Jan 2026 15:28:54 +0100 Subject: [PATCH] x86/svm: Intercept Bus Locks for HVM guests Configure the Bus Lock intercept when supported by hardware (Zen5 and later). The VMCB counter is initialised to zero so it fires upon the first instruction that locks the bus. On the #VMEXIT handler that counter is set to 1 because it has fault behaviour and the offending instruction needs to re-execute. Signed-off-by: Alejandro Vallejo Reviewed-by: Andrew Cooper --- CHANGELOG.md | 4 ++++ xen/arch/x86/hvm/svm/svm.c | 11 +++++++++++ xen/arch/x86/hvm/svm/vmcb.c | 7 +++++++ 3 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53d92a2597..18f3d10f20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Changed ### Added + - On x86: + - Support for Bus Lock Threshold on AMD Zen5 and later CPUs, used by Xen to + mitigate (by rate-limiting) the system wide impact of an HVM guest + misusing atomic instructions. ### Removed - On x86: diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 5d23603fc1..18ba837738 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -2524,6 +2524,7 @@ const struct hvm_function_table * __init start_svm(void) P(cpu_has_tsc_ratio, "TSC Rate MSR"); P(cpu_has_svm_sss, "NPT Supervisor Shadow Stack"); P(cpu_has_svm_spec_ctrl, "MSR_SPEC_CTRL virtualisation"); + P(cpu_has_svm_bus_lock, "Bus Lock Filter"); #undef P if ( !printed ) @@ -3087,6 +3088,16 @@ void asmlinkage svm_vmexit_handler(void) break; } + case VMEXIT_BUS_LOCK: + /* + * This is a fault and blocked the Bus Lock inducing action. We're + * only interested in rate limiting the guest, so credit it one "lock" + * in order to re-execute the instruction. + */ + perfc_incr(buslock); + vmcb->bus_lock_count = 1; + break; + default: unexpected_exit_type: gprintk(XENLOG_ERR, "Unexpected vmexit: reason %#"PRIx64", " diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 8734fd2bca..e583ef8548 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -66,6 +66,13 @@ static int construct_vmcb(struct vcpu *v) GENERAL2_INTERCEPT_XSETBV | GENERAL2_INTERCEPT_ICEBP | GENERAL2_INTERCEPT_RDPRU; + /* + * Well behaved logic shouldn't ever Bus Lock, but we care about rate + * limiting buggy/malicious cases. + */ + if ( cpu_has_svm_bus_lock ) + vmcb->_general3_intercepts |= GENERAL3_INTERCEPT_BUS_LOCK; + /* Intercept all debug-register writes. */ vmcb->_dr_intercepts = ~0u;