Skip to content

Commit 55c8fd7

Browse files
mdouchametan-ucw
authored andcommitted
KVM: Add async communication helper functions
Some KVM tests need to communicate with VM controller program without stopping guest execution. Add guest helper functions for sending asynchronous guest signal to host and waiting for host to acknowledge the signal. Add host helper functions for waiting for guest signal and acknowledging it. Test programs using these functions must have at least two host threads. Signed-off-by: Martin Doucha <mdoucha@suse.cz> Reviewed-by: Petr Vorel <pvorel@suse.cz> Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
1 parent c747293 commit 55c8fd7

File tree

5 files changed

+85
-0
lines changed

5 files changed

+85
-0
lines changed

testcases/kernel/kvm/include/kvm_common.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010

1111
#define KVM_TNONE -1 /* "No result" status value */
1212

13+
/*
14+
* Result value for asynchronous notifications between guest and host.
15+
* Do not use this value directly. Call tst_signal_host() or tst_wait_host()
16+
* in guest code. The notification must be handled by another host thread
17+
* and then the result value must be reset to KVM_TNONE.
18+
*/
19+
#define KVM_TSYNC 0xfe
20+
1321
/*
1422
* Result value indicating end of test. If the test program exits using
1523
* the HLT instruction with any valid result value other than KVM_TEXIT or

testcases/kernel/kvm/include/kvm_guest.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ void tst_brk_(const char *file, const int lineno, int result,
6464
const char *message) __attribute__((noreturn));
6565
#define tst_brk(result, msg) tst_brk_(__FILE__, __LINE__, (result), (msg))
6666

67+
/*
68+
* Send asynchronous notification to host without stopping VM execution and
69+
* return immediately. The notification must be handled by another host thread.
70+
* The data argument will be passed to host in test_result->file_addr and
71+
* can be used to send additional data both ways.
72+
*/
73+
void tst_signal_host(void *data);
74+
75+
/*
76+
* Call tst_signal_host(data) and wait for host to call
77+
* tst_kvm_clear_guest_signal().
78+
*/
79+
void tst_wait_host(void *data);
80+
6781
void *tst_heap_alloc_aligned(size_t size, size_t align);
6882
void *tst_heap_alloc(size_t size);
6983

testcases/kernel/kvm/include/kvm_host.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,18 @@ int tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno);
136136
*/
137137
void tst_kvm_destroy_instance(struct tst_kvm_instance *inst);
138138

139+
/*
140+
* Wait for given VM to call tst_signal_host() or tst_wait_host(). Timeout
141+
* value is in milliseconds. Zero means no wait, negative value means wait
142+
* forever. Returns 0 if signal was received, KVM_TEXIT if the VM exited
143+
* without sending a signal, or -1 if timeout was reached.
144+
*/
145+
int tst_kvm_wait_guest(struct tst_kvm_instance *inst, int timeout_ms);
146+
147+
/*
148+
* Clear VM signal sent by tst_signal_host(). If the VM is waiting
149+
* in tst_wait_host(), this function will signal the VM to resume execution.
150+
*/
151+
void tst_kvm_clear_guest_signal(struct tst_kvm_instance *inst);
152+
139153
#endif /* KVM_HOST_H_ */

testcases/kernel/kvm/lib_guest.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,22 @@ void tst_brk_(const char *file, const int lineno, int result,
155155
kvm_exit();
156156
}
157157

158+
void tst_signal_host(void *data)
159+
{
160+
test_result->file_addr = (uintptr_t)data;
161+
test_result->result = KVM_TSYNC;
162+
}
163+
164+
void tst_wait_host(void *data)
165+
{
166+
volatile int32_t *vres = &test_result->result;
167+
168+
tst_signal_host(data);
169+
170+
while (*vres != KVM_TNONE)
171+
;
172+
}
173+
158174
void tst_handle_interrupt(struct kvm_interrupt_frame *ifrm, long vector,
159175
unsigned long errcode)
160176
{

testcases/kernel/kvm/lib_host.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#define TST_NO_DEFAULT_MAIN
1212
#include "tst_test.h"
13+
#include "tst_clocks.h"
14+
#include "tst_timer.h"
1315
#include "kvm_host.h"
1416

1517
static struct tst_kvm_instance test_vm = { .vm_fd = -1 };
@@ -288,6 +290,37 @@ void tst_kvm_destroy_instance(struct tst_kvm_instance *inst)
288290
memset(inst->ram, 0, sizeof(inst->ram));
289291
}
290292

293+
int tst_kvm_wait_guest(struct tst_kvm_instance *inst, int timeout_ms)
294+
{
295+
volatile struct tst_kvm_result *result = inst->result;
296+
int32_t res;
297+
struct timespec start, now;
298+
299+
if (timeout_ms >= 0)
300+
tst_clock_gettime(CLOCK_MONOTONIC, &start);
301+
302+
while ((res = result->result) != KVM_TSYNC) {
303+
if (res == KVM_TEXIT)
304+
return res;
305+
306+
if (timeout_ms >= 0) {
307+
tst_clock_gettime(CLOCK_MONOTONIC, &now);
308+
309+
if (tst_timespec_diff_ms(now, start) >= timeout_ms)
310+
return -1;
311+
}
312+
313+
usleep(1000);
314+
}
315+
316+
return 0;
317+
}
318+
319+
void tst_kvm_clear_guest_signal(struct tst_kvm_instance *inst)
320+
{
321+
inst->result->result = KVM_TNONE;
322+
}
323+
291324
void tst_kvm_setup(void)
292325
{
293326

0 commit comments

Comments
 (0)