@@ -39,7 +39,13 @@ static bool illegal_handler_invoked;
3939#define SBI_PMU_TEST_SNAPSHOT BIT(2)
4040#define SBI_PMU_TEST_OVERFLOW BIT(3)
4141
42- static int disabled_tests ;
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 ;
4349
4450unsigned long pmu_csr_read_num (int csr_num )
4551{
@@ -118,8 +124,8 @@ static void stop_counter(unsigned long counter, unsigned long stop_flags)
118124
119125 ret = sbi_ecall (SBI_EXT_PMU , SBI_EXT_PMU_COUNTER_STOP , counter , 1 , stop_flags ,
120126 0 , 0 , 0 );
121- __GUEST_ASSERT (ret .error == 0 , "Unable to stop counter %ld error %ld\n" ,
122- counter , ret .error );
127+ __GUEST_ASSERT (ret .error == 0 || ret . error == SBI_ERR_ALREADY_STOPPED ,
128+ "Unable to stop counter %ld error %ld\n" , counter , ret .error );
123129}
124130
125131static void guest_illegal_exception_handler (struct ex_regs * regs )
@@ -137,7 +143,6 @@ static void guest_irq_handler(struct ex_regs *regs)
137143 unsigned int irq_num = regs -> cause & ~CAUSE_IRQ_FLAG ;
138144 struct riscv_pmu_snapshot_data * snapshot_data = snapshot_gva ;
139145 unsigned long overflown_mask ;
140- unsigned long counter_val = 0 ;
141146
142147 /* Validate that we are in the correct irq handler */
143148 GUEST_ASSERT_EQ (irq_num , IRQ_PMU_OVF );
@@ -151,10 +156,6 @@ static void guest_irq_handler(struct ex_regs *regs)
151156 GUEST_ASSERT (overflown_mask & 0x01 );
152157
153158 WRITE_ONCE (vcpu_shared_irq_count , vcpu_shared_irq_count + 1 );
154-
155- counter_val = READ_ONCE (snapshot_data -> ctr_values [0 ]);
156- /* Now start the counter to mimick the real driver behavior */
157- start_counter (counter_in_use , SBI_PMU_START_FLAG_SET_INIT_VALUE , counter_val );
158159}
159160
160161static unsigned long get_counter_index (unsigned long cbase , unsigned long cmask ,
@@ -479,7 +480,7 @@ static void test_pmu_events_snaphost(void)
479480
480481static void test_pmu_events_overflow (void )
481482{
482- int num_counters = 0 ;
483+ int num_counters = 0 , i = 0 ;
483484
484485 /* Verify presence of SBI PMU and minimum requrired SBI version */
485486 verify_sbi_requirement_assert ();
@@ -496,11 +497,15 @@ static void test_pmu_events_overflow(void)
496497 * Qemu supports overflow for cycle/instruction.
497498 * This test may fail on any platform that do not support overflow for these two events.
498499 */
499- test_pmu_event_overflow (SBI_PMU_HW_CPU_CYCLES );
500- GUEST_ASSERT_EQ (vcpu_shared_irq_count , 1 );
500+ for (i = 0 ; i < targs .overflow_irqnum ; i ++ )
501+ test_pmu_event_overflow (SBI_PMU_HW_CPU_CYCLES );
502+ GUEST_ASSERT_EQ (vcpu_shared_irq_count , targs .overflow_irqnum );
503+
504+ vcpu_shared_irq_count = 0 ;
501505
502- test_pmu_event_overflow (SBI_PMU_HW_INSTRUCTIONS );
503- GUEST_ASSERT_EQ (vcpu_shared_irq_count , 2 );
506+ for (i = 0 ; i < targs .overflow_irqnum ; i ++ )
507+ test_pmu_event_overflow (SBI_PMU_HW_INSTRUCTIONS );
508+ GUEST_ASSERT_EQ (vcpu_shared_irq_count , targs .overflow_irqnum );
504509
505510 GUEST_DONE ();
506511}
@@ -609,7 +614,11 @@ static void test_vm_events_overflow(void *guest_code)
609614 vcpu_init_vector_tables (vcpu );
610615 /* Initialize guest timer frequency. */
611616 timer_freq = vcpu_get_reg (vcpu , RISCV_TIMER_REG (frequency ));
617+
618+ /* Export the shared variables to the guest */
612619 sync_global_to_guest (vm , timer_freq );
620+ sync_global_to_guest (vm , vcpu_shared_irq_count );
621+ sync_global_to_guest (vm , targs );
613622
614623 run_vcpu (vcpu );
615624
@@ -618,35 +627,54 @@ static void test_vm_events_overflow(void *guest_code)
618627
619628static void test_print_help (char * name )
620629{
621- pr_info ("Usage: %s [-h] [-d <test name>]\n" , name );
622- pr_info ("\t-d: Test to disable. Available tests are 'basic', 'events', 'snapshot', 'overflow'\n" );
630+ pr_info ("Usage: %s [-h] [-t <test name>] [-n <number of LCOFI interrupt for overflow test>]\n" ,
631+ name );
632+ pr_info ("\t-t: Test to run (default all). Available tests are 'basic', 'events', 'snapshot', 'overflow'\n" );
633+ pr_info ("\t-n: Number of LCOFI interrupt to trigger for each event in overflow test (default: %d)\n" ,
634+ SBI_PMU_OVERFLOW_IRQNUM_DEFAULT );
623635 pr_info ("\t-h: print this help screen\n" );
624636}
625637
626638static bool parse_args (int argc , char * argv [])
627639{
628640 int opt ;
641+ int temp_disabled_tests = SBI_PMU_TEST_BASIC | SBI_PMU_TEST_EVENTS | SBI_PMU_TEST_SNAPSHOT |
642+ SBI_PMU_TEST_OVERFLOW ;
643+ int overflow_interrupts = 0 ;
629644
630- while ((opt = getopt (argc , argv , "hd :" )) != -1 ) {
645+ while ((opt = getopt (argc , argv , "ht:n :" )) != -1 ) {
631646 switch (opt ) {
632- case 'd ' :
647+ case 't ' :
633648 if (!strncmp ("basic" , optarg , 5 ))
634- disabled_tests |= SBI_PMU_TEST_BASIC ;
649+ temp_disabled_tests &= ~ SBI_PMU_TEST_BASIC ;
635650 else if (!strncmp ("events" , optarg , 6 ))
636- disabled_tests |= SBI_PMU_TEST_EVENTS ;
651+ temp_disabled_tests &= ~ SBI_PMU_TEST_EVENTS ;
637652 else if (!strncmp ("snapshot" , optarg , 8 ))
638- disabled_tests |= SBI_PMU_TEST_SNAPSHOT ;
653+ temp_disabled_tests &= ~ SBI_PMU_TEST_SNAPSHOT ;
639654 else if (!strncmp ("overflow" , optarg , 8 ))
640- disabled_tests |= SBI_PMU_TEST_OVERFLOW ;
655+ temp_disabled_tests &= ~ SBI_PMU_TEST_OVERFLOW ;
641656 else
642657 goto done ;
658+ targs .disabled_tests = temp_disabled_tests ;
659+ break ;
660+ case 'n' :
661+ overflow_interrupts = atoi_positive ("Number of LCOFI" , optarg );
643662 break ;
644663 case 'h' :
645664 default :
646665 goto done ;
647666 }
648667 }
649668
669+ if (overflow_interrupts > 0 ) {
670+ if (targs .disabled_tests & SBI_PMU_TEST_OVERFLOW ) {
671+ pr_info ("-n option is only available for overflow test\n" );
672+ goto done ;
673+ } else {
674+ targs .overflow_irqnum = overflow_interrupts ;
675+ }
676+ }
677+
650678 return true;
651679done :
652680 test_print_help (argv [0 ]);
@@ -655,25 +683,28 @@ static bool parse_args(int argc, char *argv[])
655683
656684int main (int argc , char * argv [])
657685{
686+ targs .disabled_tests = 0 ;
687+ targs .overflow_irqnum = SBI_PMU_OVERFLOW_IRQNUM_DEFAULT ;
688+
658689 if (!parse_args (argc , argv ))
659690 exit (KSFT_SKIP );
660691
661- if (!(disabled_tests & SBI_PMU_TEST_BASIC )) {
692+ if (!(targs . disabled_tests & SBI_PMU_TEST_BASIC )) {
662693 test_vm_basic_test (test_pmu_basic_sanity );
663694 pr_info ("SBI PMU basic test : PASS\n" );
664695 }
665696
666- if (!(disabled_tests & SBI_PMU_TEST_EVENTS )) {
697+ if (!(targs . disabled_tests & SBI_PMU_TEST_EVENTS )) {
667698 test_vm_events_test (test_pmu_events );
668699 pr_info ("SBI PMU event verification test : PASS\n" );
669700 }
670701
671- if (!(disabled_tests & SBI_PMU_TEST_SNAPSHOT )) {
702+ if (!(targs . disabled_tests & SBI_PMU_TEST_SNAPSHOT )) {
672703 test_vm_events_snapshot_test (test_pmu_events_snaphost );
673704 pr_info ("SBI PMU event verification with snapshot test : PASS\n" );
674705 }
675706
676- if (!(disabled_tests & SBI_PMU_TEST_OVERFLOW )) {
707+ if (!(targs . disabled_tests & SBI_PMU_TEST_OVERFLOW )) {
677708 test_vm_events_overflow (test_pmu_events_overflow );
678709 pr_info ("SBI PMU event verification with overflow test : PASS\n" );
679710 }
0 commit comments