7 #include <asm/kvm_asm.h>
8 #include <asm/kvm_hyp.h>
9 #include <asm/kvm_mmu.h>
10 #include <linux/arm-smccc.h>
11 #include <linux/kvm_host.h>
12 #include <uapi/linux/psci.h>
25 #define INVALID_CPU_ID UINT_MAX
33 #define PSCI_BOOT_ARGS_UNLOCKED 0
34 #define PSCI_BOOT_ARGS_LOCKED 1
36 #define PSCI_BOOT_ARGS_INIT \
37 ((struct psci_boot_args){ \
38 .lock = ATOMIC_INIT(PSCI_BOOT_ARGS_UNLOCKED), \
44 #define is_psci_0_1(what, func_id) \
45 (kvm_host_psci_config.psci_0_1_ ## what ## _implemented && \
46 (func_id) == kvm_host_psci_config.function_ids_0_1.what)
59 return (PSCI_0_2_FN(0) <= func_id && func_id <= PSCI_0_2_FN(31)) ||
60 (PSCI_0_2_FN64(0) <= func_id && func_id <= PSCI_0_2_FN64(31));
63 static unsigned long psci_call(
unsigned long fn,
unsigned long arg0,
64 unsigned long arg1,
unsigned long arg2)
66 struct arm_smccc_res res;
68 arm_smccc_1_1_smc(fn, arg0, arg1, arg2, &res);
72 static unsigned long psci_forward(
struct kvm_cpu_context *host_ctxt)
83 if (mpidr & ~MPIDR_HWID_BITMASK)
86 for (i = 0; i < NR_CPUS; i++) {
96 return atomic_cmpxchg_acquire(&args->
lock,
107 static int psci_cpu_on(u64 func_id,
struct kvm_cpu_context *host_ctxt)
115 struct kvm_nvhe_init_params *init_params;
127 return PSCI_RET_INVALID_PARAMS;
129 boot_args = per_cpu_ptr(&cpu_on_args, cpu_id);
130 init_params = per_cpu_ptr(&kvm_init_params, cpu_id);
134 return PSCI_RET_ALREADY_ON;
142 __hyp_pa(init_params));
145 if (ret != PSCI_RET_SUCCESS)
158 struct kvm_nvhe_init_params *init_params;
160 boot_args = this_cpu_ptr(&suspend_args);
161 init_params = this_cpu_ptr(&kvm_init_params);
176 __hyp_pa(init_params));
185 struct kvm_nvhe_init_params *init_params;
187 boot_args = this_cpu_ptr(&suspend_args);
188 init_params = this_cpu_ptr(&kvm_init_params);
200 __hyp_pa(init_params), 0);
206 struct kvm_cpu_context *host_ctxt;
208 host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
211 boot_args = this_cpu_ptr(&cpu_on_args);
213 boot_args = this_cpu_ptr(&suspend_args);
216 write_sysreg_el2(boot_args->
pc, SYS_ELR);
233 return PSCI_RET_NOT_SUPPORTED;
239 case PSCI_0_2_FN_PSCI_VERSION:
240 case PSCI_0_2_FN_CPU_OFF:
241 case PSCI_0_2_FN64_AFFINITY_INFO:
242 case PSCI_0_2_FN64_MIGRATE:
243 case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
244 case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
250 case PSCI_0_2_FN_SYSTEM_OFF:
251 case PSCI_0_2_FN_SYSTEM_RESET:
253 case PSCI_0_2_FN64_CPU_SUSPEND:
255 case PSCI_0_2_FN64_CPU_ON:
258 return PSCI_RET_NOT_SUPPORTED;
265 case PSCI_1_0_FN_PSCI_FEATURES:
266 case PSCI_1_0_FN_SET_SUSPEND_MODE:
267 case PSCI_1_1_FN64_SYSTEM_RESET2:
269 case PSCI_1_0_FN64_SYSTEM_SUSPEND:
281 case PSCI_VERSION(0, 1):
286 case PSCI_VERSION(0, 2):
u64 cpu_logical_map(unsigned int cpu)
static int psci_system_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt)
bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
static bool is_psci_0_2_call(u64 func_id)
#define PSCI_BOOT_ARGS_INIT
static unsigned long psci_forward(struct kvm_cpu_context *host_ctxt)
static __always_inline void release_boot_args(struct psci_boot_args *args)
static bool is_psci_0_1_call(u64 func_id)
#define is_psci_0_1(what, func_id)
static int psci_cpu_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt)
#define PSCI_BOOT_ARGS_UNLOCKED
void __noreturn __host_enter(struct kvm_cpu_context *host_ctxt)
#define PSCI_BOOT_ARGS_LOCKED
static int psci_cpu_on(u64 func_id, struct kvm_cpu_context *host_ctxt)
void kvm_hyp_cpu_resume(unsigned long r0)
static unsigned int find_cpu_id(u64 mpidr)
static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_ctxt)
static DEFINE_PER_CPU(struct psci_boot_args, cpu_on_args)
static unsigned long psci_call(unsigned long fn, unsigned long arg0, unsigned long arg1, unsigned long arg2)
static unsigned long psci_0_2_handler(u64 func_id, struct kvm_cpu_context *host_ctxt)
static unsigned long psci_0_1_handler(u64 func_id, struct kvm_cpu_context *host_ctxt)
static __always_inline bool try_acquire_boot_args(struct psci_boot_args *args)
asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on)
struct kvm_host_psci_config __ro_after_init kvm_host_psci_config
void kvm_hyp_cpu_entry(unsigned long r0)
#define DECLARE_REG(type, name, ctxt, reg)
struct vgic_global kvm_vgic_global_state __ro_after_init