Skip to content

Commit ef16b2d

Browse files
sean-jcbonzini
authored andcommitted
KVM: arm64: selftests: Enable single-step without a "full" ucall()
Add a new ucall hook, GUEST_UCALL_NONE(), to allow tests to make ucalls without allocating a ucall struct, and use it to enable single-step in ARM's debug-exceptions test. Like the disable single-step path, the enabling path also needs to ensure that no exclusive access sequences are attempted after enabling single-step, as the exclusive monitor is cleared on ERET from the debug exception taken to EL2. The test currently "works" because clear_bit() isn't actually an atomic operation... yet. Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent ef40757 commit ef16b2d

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

tools/testing/selftests/kvm/aarch64/debug-exceptions.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,6 @@ static void guest_svc_handler(struct ex_regs *regs)
239239
svc_addr = regs->pc;
240240
}
241241

242-
enum single_step_op {
243-
SINGLE_STEP_ENABLE = 0,
244-
};
245-
246242
static void guest_code_ss(int test_cnt)
247243
{
248244
uint64_t i;
@@ -253,8 +249,16 @@ static void guest_code_ss(int test_cnt)
253249
w_bvr = i << 2;
254250
w_wvr = i << 2;
255251

256-
/* Enable Single Step execution */
257-
GUEST_SYNC(SINGLE_STEP_ENABLE);
252+
/*
253+
* Enable Single Step execution. Note! This _must_ be a bare
254+
* ucall as the ucall() path uses atomic operations to manage
255+
* the ucall structures, and the built-in "atomics" are usually
256+
* implemented via exclusive access instructions. The exlusive
257+
* monitor is cleared on ERET, and so taking debug exceptions
258+
* during a LDREX=>STREX sequence will prevent forward progress
259+
* and hang the guest/test.
260+
*/
261+
GUEST_UCALL_NONE();
258262

259263
/*
260264
* The userspace will verify that the pc is as expected during
@@ -356,12 +360,9 @@ void test_single_step_from_userspace(int test_cnt)
356360
break;
357361
}
358362

359-
TEST_ASSERT(cmd == UCALL_SYNC,
363+
TEST_ASSERT(cmd == UCALL_NONE,
360364
"Unexpected ucall cmd 0x%lx", cmd);
361365

362-
TEST_ASSERT(uc.args[1] == SINGLE_STEP_ENABLE,
363-
"Unexpected ucall action 0x%lx", uc.args[1]);
364-
365366
debug.control = KVM_GUESTDBG_ENABLE |
366367
KVM_GUESTDBG_SINGLESTEP;
367368
ss_enable = true;

tools/testing/selftests/kvm/include/ucall_common.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ void ucall(uint64_t cmd, int nargs, ...);
3535
uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc);
3636
void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa);
3737

38+
/*
39+
* Perform userspace call without any associated data. This bare call avoids
40+
* allocating a ucall struct, which can be useful if the atomic operations in
41+
* the full ucall() are problematic and/or unwanted. Note, this will come out
42+
* as UCALL_NONE on the backend.
43+
*/
44+
#define GUEST_UCALL_NONE() ucall_arch_do_ucall((vm_vaddr_t)NULL)
45+
3846
#define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \
3947
ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4)
4048
#define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage)

0 commit comments

Comments
 (0)