> + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STOPPED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_START_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) { > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + continue; > + } else if (ret.value != SBI_EXT_HSM_STARTED) { > + report_info("hart %ld status is not 'started' (ret.value=%ld)", hartid, ret.value); > + continue; > + } else { > + cpumask_set_cpu(cpu, &hsm_start); ...to here can be factored into a function that returns the count and shared with the hsm_stop test since hsm_start doesn't need to be a cpumask either. The function just needs to take the three states as parameters. > + } > + > + sbi_hsm_timer_fired = false; > + timer_start(hsm_timer_duration); > + > + while (!(READ_ONCE(sbi_hsm_hart_start_checks[cpu]) & SBI_HSM_TEST_DONE) && !sbi_hsm_timer_fired) > + cpu_relax(); > + > + timer_stop(); > + > + if (sbi_hsm_timer_fired) { > + report_info("hsm timer fired before hart %ld is done with start checks", hartid); > + continue; > + } > + > + if (!(sbi_hsm_hart_start_checks[cpu] & SBI_HSM_TEST_SATP)) > + report_info("satp is not zero for test hart %ld", hartid); > + else if (!(sbi_hsm_hart_start_checks[cpu] & SBI_HSM_TEST_SIE)) > + report_info("sstatus.SIE is not zero for test hart %ld", hartid); > + else if (!(sbi_hsm_hart_start_checks[cpu] & SBI_HSM_TEST_HARTID_A1)) > + report_info("either a0 or a1 is not hartid for test hart %ld", hartid); > + else > + cpumask_set_cpu(cpu, &hsm_check); > + } > + > + report(cpumask_weight(&hsm_start) == max_cpus - 1, "all secondary harts started"); > + report(cpumask_weight(&hsm_check) == max_cpus - 1, > + "all secondary harts have expected register values after hart start"); hsm_check can also just be a counter. > + > + report_prefix_pop(); > + > + report_prefix_push("hart_stop"); > + > + memset(sbi_hsm_stop_hart, 1, sizeof(sbi_hsm_stop_hart)); > + > + cpumask_clear(&hsm_stop); > + > + for_each_cpu(cpu, &secondary_cpus_mask) { > + hartid = cpus[cpu].hartid; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STARTED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STOP_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_STOPPED) > + report_info("hart %ld status is not 'stopped' (ret.value=%ld)", hartid, ret.value); > + else > + cpumask_set_cpu(cpu, &hsm_stop); > + } > + > + report(cpumask_weight(&hsm_stop) == max_cpus - 1, "all secondary harts stopped"); > + > + /* Reset the stop flags so that we can reuse them after suspension tests */ > + memset(sbi_hsm_stop_hart, 0, sizeof(sbi_hsm_stop_hart)); > + > + report_prefix_pop(); > + > + report_prefix_push("hart_start"); > + > + /* Select just one secondary cpu to run the invalid hartid test */ > + on_cpu(cpumask_next(-1, &secondary_cpus_mask), hart_start_invalid_hartid, NULL); > + > + report(sbi_hsm_invalid_hartid_check, "secondary hart refuse to start with invalid hartid"); > + > + on_cpumask_async(&secondary_cpus_mask, hart_execute, NULL); > + > + cpumask_clear(&hsm_start); > + > + for_each_cpu(cpu, &secondary_cpus_mask) { > + hartid = cpus[cpu].hartid; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STOPPED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_START_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_STARTED) > + report_info("hart %ld status is not 'started' (ret.value=%ld)", hartid, ret.value); > + else > + cpumask_set_cpu(cpu, &hsm_start); > + } > + > + report(cpumask_weight(&hsm_start) == max_cpus - 1, "all secondary harts started"); > + Can factor from here... > + sbi_hsm_timer_fired = false; > + timer_start(hsm_timer_duration); > + > + while (cpumask_weight(&cpu_idle_mask) != max_cpus - 1 && !sbi_hsm_timer_fired) > + cpu_relax(); > + > + timer_stop(); > + > + if (sbi_hsm_timer_fired) > + report_info("hsm timer fired before all secondary harts started"); ...to here into a helper function. > + > + report(cpumask_weight(&cpu_idle_mask) == max_cpus - 1, > + "all secondary harts successfully executed code after start"); > + report(cpumask_weight(&cpu_online_mask) == max_cpus, "all secondary harts online"); > + report(cpumask_weight(&sbi_hsm_started_hart_checks) == max_cpus - 1, > + "all secondary harts are already started"); > + > + report_prefix_pop(); > + > + report_prefix_push("hart_suspend"); > + > + if (!sbi_probe(SBI_EXT_IPI)) { > + report_skip("skipping suspension tests since ipi extension is unavailable"); > + report_prefix_pop(); > + ipi_unavailable = true; > + goto sbi_hsm_hart_stop_tests; > + } > + > + on_cpumask_async(&secondary_cpus_mask, hart_retentive_suspend, NULL); > + > + cpumask_clear(&hsm_suspend); > + > + for_each_cpu(cpu, &secondary_cpus_mask) { > + hartid = cpus[cpu].hartid; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STARTED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPEND_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_SUSPENDED) > + report_info("hart %ld status is not 'suspended' (ret.value=%ld)", hartid, ret.value); > + else > + cpumask_set_cpu(cpu, &hsm_suspend); > + } > + > + report(cpumask_weight(&hsm_suspend) == max_cpus - 1, "all secondary harts retentive suspended"); hsm_suspend can be a counter. > + > + /* Ignore the return value since we check the status of each hart anyway */ > + sbi_send_ipi_cpumask(&secondary_cpus_mask); > + > + cpumask_clear(&hsm_resume); > + > + for_each_cpu(cpu, &secondary_cpus_mask) { > + hartid = cpus[cpu].hartid; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPENDED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_RESUME_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_STARTED) > + report_info("hart %ld status is not 'started' (ret.value=%ld)", hartid, ret.value); > + else > + cpumask_set_cpu(cpu, &hsm_resume); > + } > + > + report(cpumask_weight(&hsm_resume) == max_cpus - 1, "all secondary harts retentive resumed"); hsm_resume can be a counter. > + > + sbi_hsm_timer_fired = false; > + timer_start(hsm_timer_duration); > + > + while (cpumask_weight(&cpu_idle_mask) != max_cpus - 1 && !sbi_hsm_timer_fired) > + cpu_relax(); > + > + timer_stop(); > + > + if (sbi_hsm_timer_fired) > + report_info("hsm timer fired before all secondary harts retentive resumed"); > + > + report(cpumask_weight(&cpu_idle_mask) == max_cpus - 1, > + "all secondary harts successfully executed code after retentive suspend"); > + report(cpumask_weight(&cpu_online_mask) == max_cpus, > + "all secondary harts online"); > + > + on_cpumask_async(&secondary_cpus_mask, hart_non_retentive_suspend, NULL); > + > + cpumask_clear(&hsm_suspend); > + > + for_each_cpu(cpu, &secondary_cpus_mask) { > + hartid = cpus[cpu].hartid; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STARTED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPEND_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_SUSPENDED) > + report_info("hart %ld status is not 'suspended' (ret.value=%ld)", hartid, ret.value); > + else > + cpumask_set_cpu(cpu, &hsm_suspend); > + } > + > + report(cpumask_weight(&hsm_suspend) == max_cpus - 1, "all secondary harts non-retentive suspended"); > + > + /* Ignore the return value since we check the status of each hart anyway */ > + sbi_send_ipi_cpumask(&secondary_cpus_mask); > + > + cpumask_clear(&hsm_resume); > + cpumask_clear(&hsm_check); > + > + for_each_cpu(cpu, &secondary_cpus_mask) { > + hartid = cpus[cpu].hartid; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPENDED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_RESUME_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) { > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + continue; > + } else if (ret.value != SBI_EXT_HSM_STARTED) { > + report_info("hart %ld status is not 'started' (ret.value=%ld)", hartid, ret.value); > + continue; > + } else { > + cpumask_set_cpu(cpu, &hsm_resume); > + } > + > + sbi_hsm_timer_fired = false; > + timer_start(hsm_timer_duration); > + > + while (!((READ_ONCE(sbi_hsm_non_retentive_hart_suspend_checks[cpu])) & SBI_HSM_TEST_DONE) > + && !sbi_hsm_timer_fired) > + cpu_relax(); > + > + timer_stop(); > + > + if (sbi_hsm_timer_fired) { > + report_info("hsm timer fired before hart %ld is done with non-retentive resume checks", > + hartid); > + continue; > + } > + > + if (!(sbi_hsm_non_retentive_hart_suspend_checks[cpu] & SBI_HSM_TEST_SATP)) > + report_info("satp is not zero for test hart %ld", hartid); > + else if (!(sbi_hsm_non_retentive_hart_suspend_checks[cpu] & SBI_HSM_TEST_SIE)) > + report_info("sstatus.SIE is not zero for test hart %ld", hartid); > + else if (!(sbi_hsm_non_retentive_hart_suspend_checks[cpu] & SBI_HSM_TEST_HARTID_A1)) > + report_info("either a0 or a1 is not hartid for test hart %ld", hartid); > + else > + cpumask_set_cpu(cpu, &hsm_check); > + } > + > + report(cpumask_weight(&hsm_resume) == max_cpus - 1, "all secondary harts non-retentive resumed"); > + report(cpumask_weight(&hsm_check) == max_cpus - 1, > + "all secondary harts have expected register values after non-retentive resume"); > + > + report_prefix_pop(); > + > +sbi_hsm_hart_stop_tests: > + report_prefix_push("hart_stop"); > + > + if (ipi_unavailable) > + on_cpumask_async(&secondary_cpus_mask, hart_stop, NULL); > + else > + memset(sbi_hsm_stop_hart, 1, sizeof(sbi_hsm_stop_hart)); > + > + cpumask_clear(&hsm_stop); > + > + for_each_cpu(cpu, &secondary_cpus_mask) { > + hartid = cpus[cpu].hartid; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STARTED, hsm_timer_duration)) > + continue; > + if (hart_wait_on_status(hartid, SBI_EXT_HSM_STOP_PENDING, hsm_timer_duration)) > + continue; > + > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_STOPPED) > + report_info("hart %ld status is not 'stopped' (ret.value=%ld)", hartid, ret.value); > + else > + cpumask_set_cpu(cpu, &hsm_stop); > + } > + > + report(cpumask_weight(&hsm_stop) == max_cpus - 1, "all secondary harts stopped"); > + > + if (__riscv_xlen == 32 || ipi_unavailable) { > + hsm_timer_teardown(); > + report_prefix_popn(2); > + return; > + } > + > + report_prefix_pop(); This pop should go above the if 32-bit check and the pop inside that if's body should be changed to a single pop. > + > + report_prefix_push("hart_suspend"); > + > + /* Select just one secondary cpu to run suspension tests with MSB of suspend type being set */ > + cpu = cpumask_next(-1, &secondary_cpus_mask); > + hartid = cpus[cpu].hartid; > + > + /* Boot up the secondary cpu and let it proceed to the idle loop */ > + on_cpu(cpu, hart_empty_fn, NULL); > + > + on_cpu_async(cpu, hart_retentive_suspend_with_msb_set, NULL); > + > + if (!hart_wait_on_status(hartid, SBI_EXT_HSM_STARTED, hsm_timer_duration) && > + !hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPEND_PENDING, hsm_timer_duration)) { > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_SUSPENDED) > + report_info("hart %ld status is not 'suspended' (ret.value=%ld)", hartid, ret.value); > + else > + suspend_with_msb = true; > + } > + > + report(suspend_with_msb, "secondary hart retentive suspended with MSB set"); > + > + /* Ignore the return value since we manually validate the status of the hart anyway */ > + sbi_send_ipi_cpu(cpu); > + > + if (!hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPENDED, hsm_timer_duration) && > + !hart_wait_on_status(hartid, SBI_EXT_HSM_RESUME_PENDING, hsm_timer_duration)) { > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_STARTED) > + report_info("hart %ld status is not 'started' (ret.value=%ld)", hartid, ret.value); > + else > + resume_with_msb = true; > + } > + > + report(resume_with_msb, "secondary hart retentive resumed with MSB set"); > + > + /* Reset these flags so that we can reuse them for the non-retentive suspension test */ > + suspend_with_msb = false; > + resume_with_msb = false; > + sbi_hsm_stop_hart[cpu] = 0; > + sbi_hsm_non_retentive_hart_suspend_checks[cpu] = 0; > + > + on_cpu_async(cpu, hart_non_retentive_suspend_with_msb_set, NULL); > + > + if (!hart_wait_on_status(hartid, SBI_EXT_HSM_STARTED, hsm_timer_duration) && > + !hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPEND_PENDING, hsm_timer_duration)) { > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_SUSPENDED) > + report_info("hart %ld status is not 'suspended' (ret.value=%ld)", hartid, ret.value); > + else > + suspend_with_msb = true; > + } > + > + report(suspend_with_msb, "secondary hart non-retentive suspended with MSB set"); > + > + /* Ignore the return value since we manually validate the status of the hart anyway */ > + sbi_send_ipi_cpu(cpu); > + > + if (!hart_wait_on_status(hartid, SBI_EXT_HSM_SUSPENDED, hsm_timer_duration) && > + !hart_wait_on_status(hartid, SBI_EXT_HSM_RESUME_PENDING, hsm_timer_duration)) { > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_STARTED) > + report_info("hart %ld status is not 'started' (ret.value=%ld)", hartid, ret.value); > + else > + resume_with_msb = true; > + > + sbi_hsm_timer_fired = false; > + timer_start(hsm_timer_duration); > + > + while (!((READ_ONCE(sbi_hsm_non_retentive_hart_suspend_checks[cpu])) & SBI_HSM_TEST_DONE) > + && !sbi_hsm_timer_fired) > + cpu_relax(); > + > + timer_stop(); > + > + if (sbi_hsm_timer_fired) { > + report_info("hsm timer fired before hart %ld is done with non-retentive resume checks", > + hartid); > + } else { > + if (!(sbi_hsm_non_retentive_hart_suspend_checks[cpu] & SBI_HSM_TEST_SATP)) > + report_info("satp is not zero for test hart %ld", hartid); > + else if (!(sbi_hsm_non_retentive_hart_suspend_checks[cpu] & SBI_HSM_TEST_SIE)) > + report_info("sstatus.SIE is not zero for test hart %ld", hartid); > + else if (!(sbi_hsm_non_retentive_hart_suspend_checks[cpu] & SBI_HSM_TEST_HARTID_A1)) > + report_info("either a0 or a1 is not hartid for test hart %ld", hartid); > + else > + check_with_msb = true; > + } > + } > + > + report(resume_with_msb, "secondary hart non-retentive resumed with MSB set"); > + report(check_with_msb, > + "secondary hart has expected register values after non-retentive resume with MSB set"); > + > + report_prefix_pop(); > + > + report_prefix_push("hart_stop"); > + > + sbi_hsm_stop_hart[cpu] = 1; > + > + if (!hart_wait_on_status(hartid, SBI_EXT_HSM_STARTED, hsm_timer_duration) && > + !hart_wait_on_status(hartid, SBI_EXT_HSM_STOP_PENDING, hsm_timer_duration)) { > + ret = sbi_hart_get_status(hartid); > + if (ret.error) > + report_info("hart %ld get status failed (error=%ld)", hartid, ret.error); > + else if (ret.value != SBI_EXT_HSM_STOPPED) > + report_info("hart %ld status is not 'stopped' (ret.value=%ld)", hartid, ret.value); > + else > + stop_with_msb = true; > + } > + > + report(stop_with_msb, "secondary hart stopped after suspension tests with MSB set"); > + > + hsm_timer_teardown(); > + report_prefix_popn(2); > +} > + > int main(int argc, char **argv) > { > if (argc > 1 && !strcmp(argv[1], "-h")) { > @@ -844,6 +1506,7 @@ int main(int argc, char **argv) > check_base(); > check_time(); > check_ipi(); > + check_hsm(); > check_dbcn(); > check_susp(); > > -- > 2.43.0 > Thanks, drew