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;