Skip to content

Commit d1dafd0

Browse files
xiaobo55xavpatel
authored andcommitted
KVM: arm64: selftests: Enable tuning of error margin in arch_timer test
There are intermittent failures occurred when stressing the arch-timer test in a Qemu VM: Guest assert failed, vcpu 0; stage; 4; iter: 3 ==== Test Assertion Failure ==== aarch64/arch_timer.c:196: config_iter + 1 == irq_iter pid=4048 tid=4049 errno=4 - Interrupted system call 1 0x000000000040253b: test_vcpu_run at arch_timer.c:248 2 0x0000ffffb60dd5c7: ?? ??:0 3 0x0000ffffb6145d1b: ?? ??:0 0x3 != 0x2 (config_iter + 1 != irq_iter)e Further test and debug show that the timeout for an interrupt to arrive do have random high fluctuation, espectially when testing in an virtual environment. To alleviate this issue, just expose the timeout value as user configurable and print some hint message to increase the value when hitting the failure.. Signed-off-by: Haibo Xu <[email protected]> Reviewed-by: Andrew Jones <[email protected]> Reviewed-by: Marc Zyngier <[email protected]> Signed-off-by: Anup Patel <[email protected]>
1 parent f0617e4 commit d1dafd0

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

tools/testing/selftests/kvm/aarch64/arch_timer.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
* CVAL and TVAL registers. This consitutes the four stages in the test.
77
* The guest's main thread configures the timer interrupt for a stage
88
* and waits for it to fire, with a timeout equal to the timer period.
9-
* It asserts that the timeout doesn't exceed the timer period.
9+
* It asserts that the timeout doesn't exceed the timer period plus
10+
* a user configurable error margin(default to 100us).
1011
*
1112
* On the other hand, upon receipt of an interrupt, the guest's interrupt
1213
* handler validates the interrupt by checking if the architectural state
1314
* is in compliance with the specifications.
1415
*
1516
* The test provides command-line options to configure the timer's
16-
* period (-p), number of vCPUs (-n), and iterations per stage (-i).
17-
* To stress-test the timer stack even more, an option to migrate the
18-
* vCPUs across pCPUs (-m), at a particular rate, is also provided.
17+
* period (-p), number of vCPUs (-n), iterations per stage (-i) and timer
18+
* interrupt arrival error margin (-e). To stress-test the timer stack
19+
* even more, an option to migrate the vCPUs across pCPUs (-m), at a
20+
* particular rate, is also provided.
1921
*
2022
* Copyright (c) 2021, Google LLC.
2123
*/
@@ -46,6 +48,7 @@ struct test_args {
4648
uint32_t nr_iter;
4749
uint32_t timer_period_ms;
4850
uint32_t migration_freq_ms;
51+
uint32_t timer_err_margin_us;
4952
struct kvm_arm_counter_offset offset;
5053
};
5154

@@ -54,6 +57,7 @@ static struct test_args test_args = {
5457
.nr_iter = NR_TEST_ITERS_DEF,
5558
.timer_period_ms = TIMER_TEST_PERIOD_MS_DEF,
5659
.migration_freq_ms = TIMER_TEST_MIGRATION_FREQ_MS,
60+
.timer_err_margin_us = TIMER_TEST_ERR_MARGIN_US,
5761
.offset = { .reserved = 1 },
5862
};
5963

@@ -190,10 +194,14 @@ static void guest_run_stage(struct test_vcpu_shared_data *shared_data,
190194

191195
/* Setup a timeout for the interrupt to arrive */
192196
udelay(msecs_to_usecs(test_args.timer_period_ms) +
193-
TIMER_TEST_ERR_MARGIN_US);
197+
test_args.timer_err_margin_us);
194198

195199
irq_iter = READ_ONCE(shared_data->nr_iter);
196-
GUEST_ASSERT_EQ(config_iter + 1, irq_iter);
200+
__GUEST_ASSERT(config_iter + 1 == irq_iter,
201+
"config_iter + 1 = 0x%lx, irq_iter = 0x%lx.\n"
202+
" Guest timer interrupt was not trigged within the specified\n"
203+
" interval, try to increase the error margin by [-e] option.\n",
204+
config_iter + 1, irq_iter);
197205
}
198206
}
199207

@@ -408,8 +416,9 @@ static void test_vm_cleanup(struct kvm_vm *vm)
408416

409417
static void test_print_help(char *name)
410418
{
411-
pr_info("Usage: %s [-h] [-n nr_vcpus] [-i iterations] [-p timer_period_ms]\n",
412-
name);
419+
pr_info("Usage: %s [-h] [-n nr_vcpus] [-i iterations] [-p timer_period_ms]\n"
420+
"\t\t [-m migration_freq_ms] [-o counter_offset]\n"
421+
"\t\t [-e timer_err_margin_us]\n", name);
413422
pr_info("\t-n: Number of vCPUs to configure (default: %u; max: %u)\n",
414423
NR_VCPUS_DEF, KVM_MAX_VCPUS);
415424
pr_info("\t-i: Number of iterations per stage (default: %u)\n",
@@ -419,14 +428,16 @@ static void test_print_help(char *name)
419428
pr_info("\t-m: Frequency (in ms) of vCPUs to migrate to different pCPU. 0 to turn off (default: %u)\n",
420429
TIMER_TEST_MIGRATION_FREQ_MS);
421430
pr_info("\t-o: Counter offset (in counter cycles, default: 0)\n");
431+
pr_info("\t-e: Interrupt arrival error margin (in us) of the guest timer (default: %u)\n",
432+
TIMER_TEST_ERR_MARGIN_US);
422433
pr_info("\t-h: print this help screen\n");
423434
}
424435

425436
static bool parse_args(int argc, char *argv[])
426437
{
427438
int opt;
428439

429-
while ((opt = getopt(argc, argv, "hn:i:p:m:o:")) != -1) {
440+
while ((opt = getopt(argc, argv, "hn:i:p:m:o:e:")) != -1) {
430441
switch (opt) {
431442
case 'n':
432443
test_args.nr_vcpus = atoi_positive("Number of vCPUs", optarg);
@@ -445,6 +456,9 @@ static bool parse_args(int argc, char *argv[])
445456
case 'm':
446457
test_args.migration_freq_ms = atoi_non_negative("Frequency", optarg);
447458
break;
459+
case 'e':
460+
test_args.timer_err_margin_us = atoi_non_negative("Error Margin", optarg);
461+
break;
448462
case 'o':
449463
test_args.offset.counter_offset = strtol(optarg, NULL, 0);
450464
test_args.offset.reserved = 0;

0 commit comments

Comments
 (0)