@@ -10,6 +10,7 @@
*/
#include <asm/debugreg.h>
+#include "atomic.h"
#include "libcflat.h"
#include "processor.h"
#include "desc.h"
@@ -81,6 +82,12 @@ static void handle_ud(struct ex_regs *regs)
got_ud = 1;
}
+static bool got_ac;
+static void handle_ac(struct ex_regs *regs)
+{
+ got_ac = true;
+}
+
typedef unsigned long (*db_test_fn)(void);
typedef void (*db_report_fn)(unsigned long, const char *);
@@ -409,6 +416,41 @@ static noinline unsigned long singlestep_with_sti_hlt(void)
return start_rip;
}
+static noinline uint64_t bus_lock(uint64_t magic)
+{
+ uint8_t buffer[128] __attribute__((aligned(64))) = { };
+ atomic64_t *val = (atomic64_t *)&buffer[60];
+
+ atomic64_cmpxchg(val, 0, magic);
+ return READ_ONCE(*(uint64_t *)val);
+}
+
+static void bus_lock_test(void)
+{
+ const uint64_t magic = 0xdeadbeefdeadbeefull;
+ bool bus_lock_db = false;
+ uint64_t val;
+
+ /*
+ * Generate a bus lock (via a locked access that splits cache lines)
+ * in CPL0 and again in CPL3 (Bus Lock Detect only affects CPL3), and
+ * verify that no #AC or #DB is generated (the relevant features are
+ * not enabled).
+ */
+ val = bus_lock(magic);
+ report(!got_ac && !n && val == magic,
+ "CPL0 Split Lock #AC = %u (#DB = %u), val = %lx (wanted %lx)",
+ got_ac, n, val, magic);
+
+ val = run_in_user((usermode_func)bus_lock, DB_VECTOR, magic, 0, 0, 0, &bus_lock_db);
+ report(!bus_lock_db && val == magic,
+ "CPL3 Bus Lock #DB = %u, val = %lx (wanted %lx)",
+ bus_lock_db, val, magic);
+
+ n = 0;
+ got_ac = false;
+}
+
int main(int ac, char **av)
{
unsigned long cr4;
@@ -416,6 +458,9 @@ int main(int ac, char **av)
handle_exception(DB_VECTOR, handle_db);
handle_exception(BP_VECTOR, handle_bp);
handle_exception(UD_VECTOR, handle_ud);
+ handle_exception(AC_VECTOR, handle_ac);
+
+ bus_lock_test();
/*
* DR4 is an alias for DR6 (and DR5 aliases DR7) if CR4.DE is NOT set,
Add a testcase to the debug test to verify that a split-lock in the guest does NOT result in an #AC or #DB (and that the test isn't killed). While KVM may run the guest with split-lock #AC enabled, KVM should never inject an #AC into the guest. And Bus Lock Detect/Trap should flat out never be enabled while KVM is running the guest. Link: https://bugzilla.kernel.org/show_bug.cgi?id=219787 Link: https://lore.kernel.org/all/bug-219787-28872@https.bugzilla.kernel.org%2F Signed-off-by: Sean Christopherson <seanjc@google.com> --- x86/debug.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)