[PATCH] arm: psci: Add psci-off functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nikita Venkatesh <nikita.venkatesh@xxxxxxx>

Add PSCI_CPU_OFF testscase to  arm/psci testsuite. The test uses the
following method.

The primary CPU brings up all the secondary CPUs, which are held in a wait
loop. Once the primary releases the CPUs, each of the secondary CPUs
proceed to issue PSCI_CPU_OFF. This is indicated by a cpumask and also
the status of the call is updated by the secondary CPU in cpu_off_done[].

The primary CPU waits for all the secondary CPUs to update the cpumask
and then proceeds to check for the status of the individual CPU CPU_OFF
request. There is a chance that some CPUs might fail at the CPU_OFF
request and come back and update the status once the primary CPU has
finished the scan. There is no fool proof method to handle this. As of
now, we add a 1sec delay between the cpumask check and the scan for the
status.

The test can be triggered by "cpu-off" command line argument.

Signed-off-by: Nikita Venkatesh <nikita.venkatesh@xxxxxxx>
---
 arm/psci.c        | 87 +++++++++++++++++++++++++++++++++++++++++------
 arm/unittests.cfg |  6 ++++
 2 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/arm/psci.c b/arm/psci.c
index efa0722..5485718 100644
--- a/arm/psci.c
+++ b/arm/psci.c
@@ -12,6 +12,9 @@
 #include <asm/processor.h>
 #include <asm/smp.h>
 #include <asm/psci.h>
+#include <asm/delay.h>
+
+#define CPU_OFF_TEST_WAIT_TIME 1000

 static bool invalid_function_exception;

@@ -69,8 +72,10 @@ static bool psci_affinity_info_off(void)
 }

 static int cpu_on_ret[NR_CPUS];
-static cpumask_t cpu_on_ready, cpu_on_done;
+static bool cpu_off_success[NR_CPUS];
+static cpumask_t cpu_on_ready, cpu_on_done, cpu_off_done;
 static volatile int cpu_on_start;
+static volatile int cpu_off_start;

 static void cpu_on_secondary_entry(void)
 {
@@ -83,6 +88,19 @@ static void cpu_on_secondary_entry(void)
        cpumask_set_cpu(cpu, &cpu_on_done);
 }

+static void cpu_off_secondary_test(void)
+{
+       int cpu = smp_processor_id();
+       while (!cpu_off_start)
+               cpu_relax();
+       /* On to the CPU off test */
+       cpu_off_success[cpu] = true;
+       cpumask_set_cpu(cpu, &cpu_off_done);
+       cpu_psci_cpu_die();
+       /* The CPU shouldn't execute the next steps. */
+       cpu_off_success[cpu] = false;
+}
+
 static bool psci_cpu_on_test(void)
 {
        bool failed = false;
@@ -130,7 +148,56 @@ static bool psci_cpu_on_test(void)
        return !failed;
 }

-int main(void)
+static bool psci_cpu_off_test(void)
+{
+       bool failed = false;
+       int cpu;
+
+       for_each_present_cpu(cpu) {
+               if (cpu < 1)
+                       continue;
+               smp_boot_secondary(cpu, cpu_off_secondary_test);
+       }
+
+       cpumask_set_cpu(0, &cpu_off_done);
+
+       report_info("PSCI OFF Test");
+
+       /* Release the CPUs */
+       cpu_off_start = 1;
+
+       /* Wait until all are done */
+       while (!cpumask_full(&cpu_off_done))
+               cpu_relax();
+
+       /* Allow all the other CPUs to complete the operation */
+       mdelay(CPU_OFF_TEST_WAIT_TIME);
+
+       for_each_present_cpu(cpu) {
+               if (cpu == 0)
+                       continue;
+
+               if (!cpu_off_success[cpu]) {
+                       report_info("CPU%d could not be turned off", cpu);
+                       failed = true;
+               }
+       }
+       return !failed;
+}
+
+static void run_default_psci_tests(void)
+{
+       report(psci_invalid_function(), "invalid-function");
+       report(psci_affinity_info_on(), "affinity-info-on");
+       report(psci_affinity_info_off(), "affinity-info-off");
+       if (ERRATA(6c7a5dce22b3)){
+               report(psci_cpu_on_test(), "cpu-on");
+       } else {
+               report_skip("Skipping unsafe cpu-on test. Set ERRATA_6c7a5dce22b3=y to enable.");
+       }
+}
+
+int main(int argc, char **argv)
 {
        int ver = psci_invoke(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);

@@ -143,15 +210,15 @@ int main(void)

        report_info("PSCI version %d.%d", PSCI_VERSION_MAJOR(ver),
                                          PSCI_VERSION_MINOR(ver));
-       report(psci_invalid_function(), "invalid-function");
-       report(psci_affinity_info_on(), "affinity-info-on");
-       report(psci_affinity_info_off(), "affinity-info-off");
-
-       if (ERRATA(6c7a5dce22b3))
-               report(psci_cpu_on_test(), "cpu-on");
-       else
-               report_skip("Skipping unsafe cpu-on test. Set ERRATA_6c7a5dce22b3=y to enable.");

+       if (argc < 2) {
+               run_default_psci_tests();
+       } else if (strcmp(argv[1], "cpu-off") == 0) {
+               report(psci_cpu_off_test(), "cpu-off");
+       } else {
+               printf("Unknown subtest\n");
+               abort();
+       }
 done:
 #if 0
        report_summary();
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index 5e67b55..02ffbcd 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -218,6 +218,12 @@ file = psci.flat
 smp = $MAX_SMP
 groups = psci

+[psci-cpu-off]
+file = psci.flat
+groups = psci
+smp = $MAX_SMP
+extra_params = -append 'cpu-off'
+
 # Timer tests
 [timer]
 file = timer.flat
--
2.17.1
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm



[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux