1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * sbi_pmu_test.c - Tests the riscv64 SBI PMU functionality. 4 * 5 * Copyright (c) 2024, Rivos Inc. 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <sys/types.h> 13 #include "kvm_util.h" 14 #include "test_util.h" 15 #include "processor.h" 16 #include "sbi.h" 17 #include "arch_timer.h" 18 #include "ucall_common.h" 19 20 /* Maximum counters(firmware + hardware) */ 21 #define RISCV_MAX_PMU_COUNTERS 64 22 union sbi_pmu_ctr_info ctrinfo_arr[RISCV_MAX_PMU_COUNTERS]; 23 24 /* Snapshot shared memory data */ 25 #define PMU_SNAPSHOT_GPA_BASE BIT(30) 26 static void *snapshot_gva; 27 static vm_paddr_t snapshot_gpa; 28 29 static int vcpu_shared_irq_count; 30 static int counter_in_use; 31 32 /* Cache the available counters in a bitmask */ 33 static unsigned long counter_mask_available; 34 35 static bool illegal_handler_invoked; 36 37 #define SBI_PMU_TEST_BASIC BIT(0) 38 #define SBI_PMU_TEST_EVENTS BIT(1) 39 #define SBI_PMU_TEST_SNAPSHOT BIT(2) 40 #define SBI_PMU_TEST_OVERFLOW BIT(3) 41 42 #define SBI_PMU_OVERFLOW_IRQNUM_DEFAULT 5 43 struct test_args { 44 int disabled_tests; 45 int overflow_irqnum; 46 }; 47 48 static struct test_args targs; 49 50 unsigned long pmu_csr_read_num(int csr_num) 51 { 52 #define switchcase_csr_read(__csr_num, __val) {\ 53 case __csr_num: \ 54 __val = csr_read(__csr_num); \ 55 break; } 56 #define switchcase_csr_read_2(__csr_num, __val) {\ 57 switchcase_csr_read(__csr_num + 0, __val) \ 58 switchcase_csr_read(__csr_num + 1, __val)} 59 #define switchcase_csr_read_4(__csr_num, __val) {\ 60 switchcase_csr_read_2(__csr_num + 0, __val) \ 61 switchcase_csr_read_2(__csr_num + 2, __val)} 62 #define switchcase_csr_read_8(__csr_num, __val) {\ 63 switchcase_csr_read_4(__csr_num + 0, __val) \ 64 switchcase_csr_read_4(__csr_num + 4, __val)} 65 #define switchcase_csr_read_16(__csr_num, __val) {\ 66 switchcase_csr_read_8(__csr_num + 0, __val) \ 67 switchcase_csr_read_8(__csr_num + 8, __val)} 68 #define switchcase_csr_read_32(__csr_num, __val) {\ 69 switchcase_csr_read_16(__csr_num + 0, __val) \ 70 switchcase_csr_read_16(__csr_num + 16, __val)} 71 72 unsigned long ret = 0; 73 74 switch (csr_num) { 75 switchcase_csr_read_32(CSR_CYCLE, ret) 76 default : 77 break; 78 } 79 80 return ret; 81 #undef switchcase_csr_read_32 82 #undef switchcase_csr_read_16 83 #undef switchcase_csr_read_8 84 #undef switchcase_csr_read_4 85 #undef switchcase_csr_read_2 86 #undef switchcase_csr_read 87 } 88 89 static inline void dummy_func_loop(uint64_t iter) 90 { 91 int i = 0; 92 93 while (i < iter) { 94 asm volatile("nop"); 95 i++; 96 } 97 } 98 99 static void start_counter(unsigned long counter, unsigned long start_flags, 100 unsigned long ival) 101 { 102 struct sbiret ret; 103 104 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, counter, 1, start_flags, 105 ival, 0, 0); 106 __GUEST_ASSERT(ret.error == 0, "Unable to start counter %ld\n", counter); 107 } 108 109 /* This should be invoked only for reset counter use case */ 110 static void stop_reset_counter(unsigned long counter, unsigned long stop_flags) 111 { 112 struct sbiret ret; 113 114 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, counter, 1, 115 stop_flags | SBI_PMU_STOP_FLAG_RESET, 0, 0, 0); 116 __GUEST_ASSERT(ret.error == SBI_ERR_ALREADY_STOPPED, 117 "Unable to stop counter %ld\n", counter); 118 } 119 120 static void stop_counter(unsigned long counter, unsigned long stop_flags) 121 { 122 struct sbiret ret; 123 124 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, counter, 1, stop_flags, 125 0, 0, 0); 126 __GUEST_ASSERT(ret.error == 0 || ret.error == SBI_ERR_ALREADY_STOPPED, 127 "Unable to stop counter %ld error %ld\n", counter, ret.error); 128 } 129 130 static void guest_illegal_exception_handler(struct pt_regs *regs) 131 { 132 unsigned long insn; 133 int opcode, csr_num, funct3; 134 135 __GUEST_ASSERT(regs->cause == EXC_INST_ILLEGAL, 136 "Unexpected exception handler %lx\n", regs->cause); 137 138 insn = regs->badaddr; 139 opcode = (insn & INSN_OPCODE_MASK) >> INSN_OPCODE_SHIFT; 140 __GUEST_ASSERT(opcode == INSN_OPCODE_SYSTEM, 141 "Unexpected instruction with opcode 0x%x insn 0x%lx\n", opcode, insn); 142 143 csr_num = GET_CSR_NUM(insn); 144 funct3 = GET_RM(insn); 145 /* Validate if it is a CSR read/write operation */ 146 __GUEST_ASSERT(funct3 <= 7 && (funct3 != 0 && funct3 != 4), 147 "Unexpected system opcode with funct3 0x%x csr_num 0x%x\n", 148 funct3, csr_num); 149 150 /* Validate if it is a HPMCOUNTER CSR operation */ 151 __GUEST_ASSERT((csr_num >= CSR_CYCLE && csr_num <= CSR_HPMCOUNTER31), 152 "Unexpected csr_num 0x%x\n", csr_num); 153 154 illegal_handler_invoked = true; 155 /* skip the trapping instruction */ 156 regs->epc += 4; 157 } 158 159 static void guest_irq_handler(struct pt_regs *regs) 160 { 161 unsigned int irq_num = regs->cause & ~CAUSE_IRQ_FLAG; 162 struct riscv_pmu_snapshot_data *snapshot_data = snapshot_gva; 163 unsigned long overflown_mask; 164 165 /* Validate that we are in the correct irq handler */ 166 GUEST_ASSERT_EQ(irq_num, IRQ_PMU_OVF); 167 168 /* Stop all counters first to avoid further interrupts */ 169 stop_counter(counter_in_use, SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT); 170 171 csr_clear(CSR_SIP, BIT(IRQ_PMU_OVF)); 172 173 overflown_mask = READ_ONCE(snapshot_data->ctr_overflow_mask); 174 GUEST_ASSERT(overflown_mask & 0x01); 175 176 WRITE_ONCE(vcpu_shared_irq_count, vcpu_shared_irq_count+1); 177 } 178 179 static unsigned long get_counter_index(unsigned long cbase, unsigned long cmask, 180 unsigned long cflags, 181 unsigned long event) 182 { 183 struct sbiret ret; 184 185 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask, 186 cflags, event, 0, 0); 187 __GUEST_ASSERT(ret.error == 0, "config matching failed %ld\n", ret.error); 188 GUEST_ASSERT(ret.value < RISCV_MAX_PMU_COUNTERS); 189 GUEST_ASSERT(BIT(ret.value) & counter_mask_available); 190 191 return ret.value; 192 } 193 194 static unsigned long get_num_counters(void) 195 { 196 struct sbiret ret; 197 198 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_NUM_COUNTERS, 0, 0, 0, 0, 0, 0); 199 200 __GUEST_ASSERT(ret.error == 0, "Unable to retrieve number of counters from SBI PMU"); 201 __GUEST_ASSERT(ret.value < RISCV_MAX_PMU_COUNTERS, 202 "Invalid number of counters %ld\n", ret.value); 203 204 return ret.value; 205 } 206 207 static void update_counter_info(int num_counters) 208 { 209 int i = 0; 210 struct sbiret ret; 211 212 for (i = 0; i < num_counters; i++) { 213 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0); 214 215 /* There can be gaps in logical counter indicies*/ 216 if (ret.error) 217 continue; 218 GUEST_ASSERT_NE(ret.value, 0); 219 220 ctrinfo_arr[i].value = ret.value; 221 counter_mask_available |= BIT(i); 222 } 223 224 GUEST_ASSERT(counter_mask_available > 0); 225 } 226 227 static unsigned long read_fw_counter(int idx, union sbi_pmu_ctr_info ctrinfo) 228 { 229 struct sbiret ret; 230 231 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ, idx, 0, 0, 0, 0, 0); 232 GUEST_ASSERT(ret.error == 0); 233 return ret.value; 234 } 235 236 static unsigned long read_counter(int idx, union sbi_pmu_ctr_info ctrinfo) 237 { 238 unsigned long counter_val = 0; 239 240 __GUEST_ASSERT(ctrinfo.type < 2, "Invalid counter type %d", ctrinfo.type); 241 242 if (ctrinfo.type == SBI_PMU_CTR_TYPE_HW) 243 counter_val = pmu_csr_read_num(ctrinfo.csr); 244 else if (ctrinfo.type == SBI_PMU_CTR_TYPE_FW) 245 counter_val = read_fw_counter(idx, ctrinfo); 246 247 return counter_val; 248 } 249 250 static inline void verify_sbi_requirement_assert(void) 251 { 252 long out_val = 0; 253 bool probe; 254 255 probe = guest_sbi_probe_extension(SBI_EXT_PMU, &out_val); 256 GUEST_ASSERT(probe && out_val == 1); 257 258 if (get_host_sbi_spec_version() < sbi_mk_version(2, 0)) 259 __GUEST_ASSERT(0, "SBI implementation version doesn't support PMU Snapshot"); 260 } 261 262 static void snapshot_set_shmem(vm_paddr_t gpa, unsigned long flags) 263 { 264 unsigned long lo = (unsigned long)gpa; 265 #if __riscv_xlen == 32 266 unsigned long hi = (unsigned long)(gpa >> 32); 267 #else 268 unsigned long hi = gpa == -1 ? -1 : 0; 269 #endif 270 struct sbiret ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_SNAPSHOT_SET_SHMEM, 271 lo, hi, flags, 0, 0, 0); 272 273 GUEST_ASSERT(ret.value == 0 && ret.error == 0); 274 } 275 276 static void test_pmu_event(unsigned long event) 277 { 278 unsigned long counter; 279 unsigned long counter_value_pre, counter_value_post; 280 unsigned long counter_init_value = 100; 281 282 counter = get_counter_index(0, counter_mask_available, 0, event); 283 counter_value_pre = read_counter(counter, ctrinfo_arr[counter]); 284 285 /* Do not set the initial value */ 286 start_counter(counter, 0, 0); 287 dummy_func_loop(10000); 288 stop_counter(counter, 0); 289 290 counter_value_post = read_counter(counter, ctrinfo_arr[counter]); 291 __GUEST_ASSERT(counter_value_post > counter_value_pre, 292 "Event update verification failed: post [%lx] pre [%lx]\n", 293 counter_value_post, counter_value_pre); 294 295 /* 296 * We can't just update the counter without starting it. 297 * Do start/stop twice to simulate that by first initializing to a very 298 * high value and a low value after that. 299 */ 300 start_counter(counter, SBI_PMU_START_FLAG_SET_INIT_VALUE, ULONG_MAX/2); 301 stop_counter(counter, 0); 302 counter_value_pre = read_counter(counter, ctrinfo_arr[counter]); 303 304 start_counter(counter, SBI_PMU_START_FLAG_SET_INIT_VALUE, counter_init_value); 305 stop_counter(counter, 0); 306 counter_value_post = read_counter(counter, ctrinfo_arr[counter]); 307 __GUEST_ASSERT(counter_value_pre > counter_value_post, 308 "Counter reinitialization verification failed : post [%lx] pre [%lx]\n", 309 counter_value_post, counter_value_pre); 310 311 /* Now set the initial value and compare */ 312 start_counter(counter, SBI_PMU_START_FLAG_SET_INIT_VALUE, counter_init_value); 313 dummy_func_loop(10000); 314 stop_counter(counter, 0); 315 316 counter_value_post = read_counter(counter, ctrinfo_arr[counter]); 317 __GUEST_ASSERT(counter_value_post > counter_init_value, 318 "Event update verification failed: post [%lx] pre [%lx]\n", 319 counter_value_post, counter_init_value); 320 321 stop_reset_counter(counter, 0); 322 } 323 324 static void test_pmu_event_snapshot(unsigned long event) 325 { 326 unsigned long counter; 327 unsigned long counter_value_pre, counter_value_post; 328 unsigned long counter_init_value = 100; 329 struct riscv_pmu_snapshot_data *snapshot_data = snapshot_gva; 330 331 counter = get_counter_index(0, counter_mask_available, 0, event); 332 counter_value_pre = read_counter(counter, ctrinfo_arr[counter]); 333 334 /* Do not set the initial value */ 335 start_counter(counter, 0, 0); 336 dummy_func_loop(10000); 337 stop_counter(counter, SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT); 338 339 /* The counter value is updated w.r.t relative index of cbase */ 340 counter_value_post = READ_ONCE(snapshot_data->ctr_values[0]); 341 __GUEST_ASSERT(counter_value_post > counter_value_pre, 342 "Event update verification failed: post [%lx] pre [%lx]\n", 343 counter_value_post, counter_value_pre); 344 345 /* 346 * We can't just update the counter without starting it. 347 * Do start/stop twice to simulate that by first initializing to a very 348 * high value and a low value after that. 349 */ 350 WRITE_ONCE(snapshot_data->ctr_values[0], ULONG_MAX/2); 351 start_counter(counter, SBI_PMU_START_FLAG_INIT_SNAPSHOT, 0); 352 stop_counter(counter, SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT); 353 counter_value_pre = READ_ONCE(snapshot_data->ctr_values[0]); 354 355 WRITE_ONCE(snapshot_data->ctr_values[0], counter_init_value); 356 start_counter(counter, SBI_PMU_START_FLAG_INIT_SNAPSHOT, 0); 357 stop_counter(counter, SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT); 358 counter_value_post = READ_ONCE(snapshot_data->ctr_values[0]); 359 __GUEST_ASSERT(counter_value_pre > counter_value_post, 360 "Counter reinitialization verification failed : post [%lx] pre [%lx]\n", 361 counter_value_post, counter_value_pre); 362 363 /* Now set the initial value and compare */ 364 WRITE_ONCE(snapshot_data->ctr_values[0], counter_init_value); 365 start_counter(counter, SBI_PMU_START_FLAG_INIT_SNAPSHOT, 0); 366 dummy_func_loop(10000); 367 stop_counter(counter, SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT); 368 369 counter_value_post = READ_ONCE(snapshot_data->ctr_values[0]); 370 __GUEST_ASSERT(counter_value_post > counter_init_value, 371 "Event update verification failed: post [%lx] pre [%lx]\n", 372 counter_value_post, counter_init_value); 373 374 stop_reset_counter(counter, 0); 375 } 376 377 static void test_pmu_event_overflow(unsigned long event) 378 { 379 unsigned long counter; 380 unsigned long counter_value_post; 381 unsigned long counter_init_value = ULONG_MAX - 10000; 382 struct riscv_pmu_snapshot_data *snapshot_data = snapshot_gva; 383 384 counter = get_counter_index(0, counter_mask_available, 0, event); 385 counter_in_use = counter; 386 387 /* The counter value is updated w.r.t relative index of cbase passed to start/stop */ 388 WRITE_ONCE(snapshot_data->ctr_values[0], counter_init_value); 389 start_counter(counter, SBI_PMU_START_FLAG_INIT_SNAPSHOT, 0); 390 dummy_func_loop(10000); 391 udelay(msecs_to_usecs(2000)); 392 /* irq handler should have stopped the counter */ 393 stop_counter(counter, SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT); 394 395 counter_value_post = READ_ONCE(snapshot_data->ctr_values[0]); 396 /* The counter value after stopping should be less the init value due to overflow */ 397 __GUEST_ASSERT(counter_value_post < counter_init_value, 398 "counter_value_post %lx counter_init_value %lx for counter\n", 399 counter_value_post, counter_init_value); 400 401 stop_reset_counter(counter, 0); 402 } 403 404 static void test_invalid_event(void) 405 { 406 struct sbiret ret; 407 unsigned long event = 0x1234; /* A random event */ 408 409 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, 0, 410 counter_mask_available, 0, event, 0, 0); 411 GUEST_ASSERT_EQ(ret.error, SBI_ERR_NOT_SUPPORTED); 412 } 413 414 static void test_pmu_events(void) 415 { 416 int num_counters = 0; 417 418 /* Get the counter details */ 419 num_counters = get_num_counters(); 420 update_counter_info(num_counters); 421 422 /* Sanity testing for any random invalid event */ 423 test_invalid_event(); 424 425 /* Only these two events are guaranteed to be present */ 426 test_pmu_event(SBI_PMU_HW_CPU_CYCLES); 427 test_pmu_event(SBI_PMU_HW_INSTRUCTIONS); 428 429 GUEST_DONE(); 430 } 431 432 static void test_pmu_basic_sanity(void) 433 { 434 long out_val = 0; 435 bool probe; 436 struct sbiret ret; 437 int num_counters = 0, i; 438 union sbi_pmu_ctr_info ctrinfo; 439 440 probe = guest_sbi_probe_extension(SBI_EXT_PMU, &out_val); 441 GUEST_ASSERT(probe && out_val == 1); 442 443 num_counters = get_num_counters(); 444 445 for (i = 0; i < num_counters; i++) { 446 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 447 0, 0, 0, 0, 0); 448 449 /* There can be gaps in logical counter indicies*/ 450 if (ret.error) 451 continue; 452 GUEST_ASSERT_NE(ret.value, 0); 453 454 ctrinfo.value = ret.value; 455 456 /** 457 * Accessibility check of hardware and read capability of firmware counters. 458 * The spec doesn't mandate any initial value. No need to check any value. 459 */ 460 if (ctrinfo.type == SBI_PMU_CTR_TYPE_HW) { 461 pmu_csr_read_num(ctrinfo.csr); 462 GUEST_ASSERT(illegal_handler_invoked); 463 } else if (ctrinfo.type == SBI_PMU_CTR_TYPE_FW) { 464 read_fw_counter(i, ctrinfo); 465 } 466 } 467 468 GUEST_DONE(); 469 } 470 471 static void test_pmu_events_snaphost(void) 472 { 473 int num_counters = 0; 474 struct riscv_pmu_snapshot_data *snapshot_data = snapshot_gva; 475 int i; 476 477 /* Verify presence of SBI PMU and minimum requrired SBI version */ 478 verify_sbi_requirement_assert(); 479 480 snapshot_set_shmem(snapshot_gpa, 0); 481 482 /* Get the counter details */ 483 num_counters = get_num_counters(); 484 update_counter_info(num_counters); 485 486 /* Validate shared memory access */ 487 GUEST_ASSERT_EQ(READ_ONCE(snapshot_data->ctr_overflow_mask), 0); 488 for (i = 0; i < num_counters; i++) { 489 if (counter_mask_available & (BIT(i))) 490 GUEST_ASSERT_EQ(READ_ONCE(snapshot_data->ctr_values[i]), 0); 491 } 492 /* Only these two events are guranteed to be present */ 493 test_pmu_event_snapshot(SBI_PMU_HW_CPU_CYCLES); 494 test_pmu_event_snapshot(SBI_PMU_HW_INSTRUCTIONS); 495 496 GUEST_DONE(); 497 } 498 499 static void test_pmu_events_overflow(void) 500 { 501 int num_counters = 0, i = 0; 502 503 /* Verify presence of SBI PMU and minimum requrired SBI version */ 504 verify_sbi_requirement_assert(); 505 506 snapshot_set_shmem(snapshot_gpa, 0); 507 csr_set(CSR_IE, BIT(IRQ_PMU_OVF)); 508 local_irq_enable(); 509 510 /* Get the counter details */ 511 num_counters = get_num_counters(); 512 update_counter_info(num_counters); 513 514 /* 515 * Qemu supports overflow for cycle/instruction. 516 * This test may fail on any platform that do not support overflow for these two events. 517 */ 518 for (i = 0; i < targs.overflow_irqnum; i++) 519 test_pmu_event_overflow(SBI_PMU_HW_CPU_CYCLES); 520 GUEST_ASSERT_EQ(vcpu_shared_irq_count, targs.overflow_irqnum); 521 522 vcpu_shared_irq_count = 0; 523 524 for (i = 0; i < targs.overflow_irqnum; i++) 525 test_pmu_event_overflow(SBI_PMU_HW_INSTRUCTIONS); 526 GUEST_ASSERT_EQ(vcpu_shared_irq_count, targs.overflow_irqnum); 527 528 GUEST_DONE(); 529 } 530 531 static void run_vcpu(struct kvm_vcpu *vcpu) 532 { 533 struct ucall uc; 534 535 vcpu_run(vcpu); 536 switch (get_ucall(vcpu, &uc)) { 537 case UCALL_ABORT: 538 REPORT_GUEST_ASSERT(uc); 539 break; 540 case UCALL_DONE: 541 case UCALL_SYNC: 542 break; 543 default: 544 TEST_FAIL("Unknown ucall %lu", uc.cmd); 545 break; 546 } 547 } 548 549 void test_vm_destroy(struct kvm_vm *vm) 550 { 551 memset(ctrinfo_arr, 0, sizeof(union sbi_pmu_ctr_info) * RISCV_MAX_PMU_COUNTERS); 552 counter_mask_available = 0; 553 kvm_vm_free(vm); 554 } 555 556 static void test_vm_basic_test(void *guest_code) 557 { 558 struct kvm_vm *vm; 559 struct kvm_vcpu *vcpu; 560 561 vm = vm_create_with_one_vcpu(&vcpu, guest_code); 562 __TEST_REQUIRE(__vcpu_has_sbi_ext(vcpu, KVM_RISCV_SBI_EXT_PMU), 563 "SBI PMU not available, skipping test"); 564 vm_init_vector_tables(vm); 565 /* Illegal instruction handler is required to verify read access without configuration */ 566 vm_install_exception_handler(vm, EXC_INST_ILLEGAL, guest_illegal_exception_handler); 567 568 vcpu_init_vector_tables(vcpu); 569 run_vcpu(vcpu); 570 571 test_vm_destroy(vm); 572 } 573 574 static void test_vm_events_test(void *guest_code) 575 { 576 struct kvm_vm *vm = NULL; 577 struct kvm_vcpu *vcpu = NULL; 578 579 vm = vm_create_with_one_vcpu(&vcpu, guest_code); 580 __TEST_REQUIRE(__vcpu_has_sbi_ext(vcpu, KVM_RISCV_SBI_EXT_PMU), 581 "SBI PMU not available, skipping test"); 582 run_vcpu(vcpu); 583 584 test_vm_destroy(vm); 585 } 586 587 static void test_vm_setup_snapshot_mem(struct kvm_vm *vm, struct kvm_vcpu *vcpu) 588 { 589 /* PMU Snapshot requires single page only */ 590 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, PMU_SNAPSHOT_GPA_BASE, 1, 1, 0); 591 /* PMU_SNAPSHOT_GPA_BASE is identity mapped */ 592 virt_map(vm, PMU_SNAPSHOT_GPA_BASE, PMU_SNAPSHOT_GPA_BASE, 1); 593 594 snapshot_gva = (void *)(PMU_SNAPSHOT_GPA_BASE); 595 snapshot_gpa = addr_gva2gpa(vcpu->vm, (vm_vaddr_t)snapshot_gva); 596 sync_global_to_guest(vcpu->vm, snapshot_gva); 597 sync_global_to_guest(vcpu->vm, snapshot_gpa); 598 } 599 600 static void test_vm_events_snapshot_test(void *guest_code) 601 { 602 struct kvm_vm *vm = NULL; 603 struct kvm_vcpu *vcpu; 604 605 vm = vm_create_with_one_vcpu(&vcpu, guest_code); 606 __TEST_REQUIRE(__vcpu_has_sbi_ext(vcpu, KVM_RISCV_SBI_EXT_PMU), 607 "SBI PMU not available, skipping test"); 608 609 test_vm_setup_snapshot_mem(vm, vcpu); 610 611 run_vcpu(vcpu); 612 613 test_vm_destroy(vm); 614 } 615 616 static void test_vm_events_overflow(void *guest_code) 617 { 618 struct kvm_vm *vm = NULL; 619 struct kvm_vcpu *vcpu; 620 621 vm = vm_create_with_one_vcpu(&vcpu, guest_code); 622 __TEST_REQUIRE(__vcpu_has_sbi_ext(vcpu, KVM_RISCV_SBI_EXT_PMU), 623 "SBI PMU not available, skipping test"); 624 625 __TEST_REQUIRE(__vcpu_has_isa_ext(vcpu, KVM_RISCV_ISA_EXT_SSCOFPMF), 626 "Sscofpmf is not available, skipping overflow test"); 627 628 test_vm_setup_snapshot_mem(vm, vcpu); 629 vm_init_vector_tables(vm); 630 vm_install_interrupt_handler(vm, guest_irq_handler); 631 632 vcpu_init_vector_tables(vcpu); 633 /* Initialize guest timer frequency. */ 634 timer_freq = vcpu_get_reg(vcpu, RISCV_TIMER_REG(frequency)); 635 636 /* Export the shared variables to the guest */ 637 sync_global_to_guest(vm, timer_freq); 638 sync_global_to_guest(vm, vcpu_shared_irq_count); 639 sync_global_to_guest(vm, targs); 640 641 run_vcpu(vcpu); 642 643 test_vm_destroy(vm); 644 } 645 646 static void test_print_help(char *name) 647 { 648 pr_info("Usage: %s [-h] [-t <test name>] [-n <number of LCOFI interrupt for overflow test>]\n", 649 name); 650 pr_info("\t-t: Test to run (default all). Available tests are 'basic', 'events', 'snapshot', 'overflow'\n"); 651 pr_info("\t-n: Number of LCOFI interrupt to trigger for each event in overflow test (default: %d)\n", 652 SBI_PMU_OVERFLOW_IRQNUM_DEFAULT); 653 pr_info("\t-h: print this help screen\n"); 654 } 655 656 static bool parse_args(int argc, char *argv[]) 657 { 658 int opt; 659 int temp_disabled_tests = SBI_PMU_TEST_BASIC | SBI_PMU_TEST_EVENTS | SBI_PMU_TEST_SNAPSHOT | 660 SBI_PMU_TEST_OVERFLOW; 661 int overflow_interrupts = 0; 662 663 while ((opt = getopt(argc, argv, "ht:n:")) != -1) { 664 switch (opt) { 665 case 't': 666 if (!strncmp("basic", optarg, 5)) 667 temp_disabled_tests &= ~SBI_PMU_TEST_BASIC; 668 else if (!strncmp("events", optarg, 6)) 669 temp_disabled_tests &= ~SBI_PMU_TEST_EVENTS; 670 else if (!strncmp("snapshot", optarg, 8)) 671 temp_disabled_tests &= ~SBI_PMU_TEST_SNAPSHOT; 672 else if (!strncmp("overflow", optarg, 8)) 673 temp_disabled_tests &= ~SBI_PMU_TEST_OVERFLOW; 674 else 675 goto done; 676 targs.disabled_tests = temp_disabled_tests; 677 break; 678 case 'n': 679 overflow_interrupts = atoi_positive("Number of LCOFI", optarg); 680 break; 681 case 'h': 682 default: 683 goto done; 684 } 685 } 686 687 if (overflow_interrupts > 0) { 688 if (targs.disabled_tests & SBI_PMU_TEST_OVERFLOW) { 689 pr_info("-n option is only available for overflow test\n"); 690 goto done; 691 } else { 692 targs.overflow_irqnum = overflow_interrupts; 693 } 694 } 695 696 return true; 697 done: 698 test_print_help(argv[0]); 699 return false; 700 } 701 702 int main(int argc, char *argv[]) 703 { 704 targs.disabled_tests = 0; 705 targs.overflow_irqnum = SBI_PMU_OVERFLOW_IRQNUM_DEFAULT; 706 707 if (!parse_args(argc, argv)) 708 exit(KSFT_SKIP); 709 710 if (!(targs.disabled_tests & SBI_PMU_TEST_BASIC)) { 711 test_vm_basic_test(test_pmu_basic_sanity); 712 pr_info("SBI PMU basic test : PASS\n"); 713 } 714 715 if (!(targs.disabled_tests & SBI_PMU_TEST_EVENTS)) { 716 test_vm_events_test(test_pmu_events); 717 pr_info("SBI PMU event verification test : PASS\n"); 718 } 719 720 if (!(targs.disabled_tests & SBI_PMU_TEST_SNAPSHOT)) { 721 test_vm_events_snapshot_test(test_pmu_events_snaphost); 722 pr_info("SBI PMU event verification with snapshot test : PASS\n"); 723 } 724 725 if (!(targs.disabled_tests & SBI_PMU_TEST_OVERFLOW)) { 726 test_vm_events_overflow(test_pmu_events_overflow); 727 pr_info("SBI PMU event verification with overflow test : PASS\n"); 728 } 729 730 return 0; 731 } 732