xref: /kvm-unit-tests/lib/arm/psci.c (revision b40a6180ed0ce59a19c4be059f4227bf6c2dee2e)
1 /*
2  * PSCI API
3  * From arch/arm[64]/kernel/psci.c
4  *
5  * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com>
6  *
7  * This work is licensed under the terms of the GNU LGPL, version 2.
8  */
9 #include <asm/psci.h>
10 #include <asm/setup.h>
11 #include <asm/page.h>
12 #include <asm/smp.h>
13 
14 __attribute__((noinline))
15 int psci_invoke(unsigned long function_id, unsigned long arg0,
16 		unsigned long arg1, unsigned long arg2)
17 {
18 	asm volatile(
19 		"hvc #0"
20 	: "+r" (function_id)
21 	: "r" (arg0), "r" (arg1), "r" (arg2));
22 	return function_id;
23 }
24 
25 int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
26 {
27 #ifdef __arm__
28 	return psci_invoke(PSCI_0_2_FN_CPU_ON, cpuid, entry_point, 0);
29 #else
30 	return psci_invoke(PSCI_0_2_FN64_CPU_ON, cpuid, entry_point, 0);
31 #endif
32 }
33 
34 extern void secondary_entry(void);
35 int cpu_psci_cpu_boot(unsigned int cpu)
36 {
37 	int err = psci_cpu_on(cpus[cpu], __pa(secondary_entry));
38 	if (err)
39 		printf("failed to boot CPU%d (%d)\n", cpu, err);
40 	return err;
41 }
42 
43 void cpu_psci_cpu_die(void)
44 {
45 	int err = psci_invoke(PSCI_0_2_FN_CPU_OFF, 0, 0, 0);
46 	printf("CPU%d unable to power off (error = %d)\n", smp_processor_id(), err);
47 }
48 
49 void psci_system_reset(void)
50 {
51 	psci_invoke(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
52 }
53 
54 void psci_system_off(void)
55 {
56 	int err = psci_invoke(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
57 	printf("CPU%d unable to do system off (error = %d)\n", smp_processor_id(), err);
58 }
59