| Olivier Deprez | f17eadc | 2021-01-25 15:33:38 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2021 The Hafnium Authors. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style |
| 5 | * license that can be found in the LICENSE file or at |
| 6 | * https://opensource.org/licenses/BSD-3-Clause. |
| 7 | */ |
| 8 | |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 9 | #include "hf/arch/plat/psci.h" |
| 10 | |
| 11 | #include "hf/api.h" |
| 12 | #include "hf/check.h" |
| Olivier Deprez | f17eadc | 2021-01-25 15:33:38 +0100 | [diff] [blame] | 13 | #include "hf/cpu.h" |
| Karl Meakin | 902af08 | 2024-11-28 14:58:38 +0000 | [diff] [blame] | 14 | #include "hf/ffa/notifications.h" |
| Olivier Deprez | 70f8a4a | 2022-09-26 09:17:56 +0200 | [diff] [blame] | 15 | #include "hf/vm.h" |
| Olivier Deprez | f17eadc | 2021-01-25 15:33:38 +0100 | [diff] [blame] | 16 | |
| 17 | #include "psci.h" |
| 18 | |
| Max Shvetsov | 9c0ebe4 | 2020-08-27 12:37:57 +0100 | [diff] [blame] | 19 | void cpu_entry(struct cpu *c); |
| 20 | |
| Olivier Deprez | f17eadc | 2021-01-25 15:33:38 +0100 | [diff] [blame] | 21 | /** |
| 22 | * Returns zero in context of the SPMC as it does not rely |
| 23 | * on the EL3 PSCI framework. |
| 24 | */ |
| 25 | uint32_t plat_psci_version_get(void) |
| 26 | { |
| 27 | return 0; |
| 28 | } |
| 29 | |
| 30 | /** |
| 31 | * Initialize the platform power managment module in context of |
| 32 | * running the SPMC. |
| 33 | */ |
| 34 | void plat_psci_init(void) |
| 35 | { |
| Max Shvetsov | 9c0ebe4 | 2020-08-27 12:37:57 +0100 | [diff] [blame] | 36 | struct ffa_value res; |
| 37 | |
| Olivier Deprez | d614d32 | 2021-06-18 15:21:00 +0200 | [diff] [blame] | 38 | /* |
| 39 | * DEN0077A FF-A v1.1 Beta0 section 18.3.2.1.1 |
| 40 | * Register the SPMC secondary cold boot entry point at the secure |
| 41 | * physical FF-A instance (to the SPMD). |
| 42 | */ |
| Olivier Deprez | e8015b42 | 2025-08-28 09:53:42 +0200 | [diff] [blame] | 43 | res = smc_ffa_call_ext( |
| Max Shvetsov | 9c0ebe4 | 2020-08-27 12:37:57 +0100 | [diff] [blame] | 44 | (struct ffa_value){.func = FFA_SECONDARY_EP_REGISTER_64, |
| 45 | .arg1 = (uintreg_t)&cpu_entry}); |
| 46 | |
| Olivier Deprez | ad5f3c1 | 2025-04-10 11:27:14 +0200 | [diff] [blame] | 47 | if (res.func != FFA_SUCCESS_32 && res.func != FFA_SUCCESS_64) { |
| Max Shvetsov | 9c0ebe4 | 2020-08-27 12:37:57 +0100 | [diff] [blame] | 48 | panic("FFA_SECONDARY_EP_REGISTER_64 failed"); |
| 49 | } |
| Olivier Deprez | f17eadc | 2021-01-25 15:33:38 +0100 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | void plat_psci_cpu_suspend(uint32_t power_state) |
| 53 | { |
| 54 | (void)power_state; |
| 55 | } |
| 56 | |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 57 | /** Switch to the normal world vCPU pinned on this physical CPU now. */ |
| 58 | static struct vcpu *plat_psci_switch_to_other_world(struct cpu *c) |
| 59 | { |
| 60 | struct vcpu_locked other_world_vcpu_locked; |
| 61 | struct vm *other_world_vm = vm_find(HF_OTHER_WORLD_ID); |
| 62 | struct vcpu *other_world_vcpu; |
| 63 | |
| 64 | CHECK(other_world_vm != NULL); |
| 65 | |
| 66 | other_world_vcpu = vm_get_vcpu(other_world_vm, cpu_index(c)); |
| 67 | |
| 68 | CHECK(other_world_vcpu != NULL); |
| 69 | |
| 70 | other_world_vcpu_locked = vcpu_lock(other_world_vcpu); |
| 71 | |
| 72 | /* |
| 73 | * Return FFA_MSG_WAIT_32 to indicate to SPMD that SPMC |
| 74 | * has successfully finished initialization on this |
| 75 | * CPU. |
| 76 | */ |
| 77 | arch_regs_set_retval(&other_world_vcpu->regs, |
| 78 | (struct ffa_value){.func = FFA_MSG_WAIT_32}); |
| 79 | |
| 80 | other_world_vcpu->state = VCPU_STATE_WAITING; |
| 81 | vcpu_unlock(&other_world_vcpu_locked); |
| 82 | |
| 83 | return other_world_vcpu; |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * Check if there is at least one SP whose execution context needs to be |
| 88 | * bootstrapped on this physical CPU. |
| 89 | */ |
| 90 | static struct vm *plat_psci_get_boot_vm(struct cpu *c) |
| 91 | { |
| 92 | struct vm *boot_vm; |
| 93 | |
| 94 | if (cpu_index(c) == PRIMARY_CPU_IDX) { |
| 95 | boot_vm = vm_get_boot_vm(); |
| 96 | |
| 97 | /* |
| 98 | * On the primary CPU, at least one SP will exist whose |
| 99 | * execution context shall be bootstrapped. |
| 100 | */ |
| 101 | CHECK(boot_vm != NULL); |
| 102 | } else { |
| 103 | boot_vm = vm_get_boot_vm_secondary_core(); |
| 104 | |
| 105 | /* |
| 106 | * It is possible that no SP might exist that needs its |
| 107 | * execution context to be bootstrapped on secondary CPU. This |
| 108 | * can happen if all the SPs in the system are UP partitions and |
| 109 | * hence, have no vCPUs pinned to secondary CPUs. |
| 110 | */ |
| 111 | if (boot_vm != NULL) { |
| 112 | assert(boot_vm->vcpu_count > 1); |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | return boot_vm; |
| 117 | } |
| 118 | |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 119 | struct vcpu *plat_psci_cpu_resume(struct cpu *c) |
| Olivier Deprez | f17eadc | 2021-01-25 15:33:38 +0100 | [diff] [blame] | 120 | { |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 121 | struct vcpu_locked vcpu_locked; |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 122 | struct vm *boot_vm; |
| 123 | struct vcpu *boot_vcpu; |
| Olivier Deprez | 70f8a4a | 2022-09-26 09:17:56 +0200 | [diff] [blame] | 124 | |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 125 | cpu_on(c); |
| 126 | |
| 127 | arch_cpu_init(c); |
| 128 | |
| 129 | /* Initialize SRI for running core. */ |
| Karl Meakin | 117c808 | 2024-12-04 16:03:28 +0000 | [diff] [blame] | 130 | ffa_notifications_sri_init(c); |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 131 | |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 132 | boot_vm = plat_psci_get_boot_vm(c); |
| Madhukar Pappireddy | a49ba16 | 2024-11-25 09:40:45 -0600 | [diff] [blame] | 133 | |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 134 | if (boot_vm == NULL) { |
| 135 | return plat_psci_switch_to_other_world(c); |
| Max Shvetsov | 9c0ebe4 | 2020-08-27 12:37:57 +0100 | [diff] [blame] | 136 | } |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 137 | |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 138 | /* Obtain the vCPU for the boot SP on this CPU. */ |
| 139 | boot_vcpu = vm_get_vcpu(boot_vm, cpu_index(c)); |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 140 | |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 141 | /* Lock the vCPU to update its fields. */ |
| 142 | vcpu_locked = vcpu_lock(boot_vcpu); |
| 143 | |
| 144 | /* Pin the vCPU to this CPU. */ |
| 145 | boot_vcpu->cpu = c; |
| 146 | |
| 147 | vcpu_secondary_reset_and_start(vcpu_locked, boot_vcpu->vm->secondary_ep, |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 148 | 0ULL); |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 149 | |
| Madhukar Pappireddy | d6c055d | 2025-05-08 15:35:46 -0500 | [diff] [blame] | 150 | /* Set the vCPU's state to STARTING. */ |
| 151 | boot_vcpu->state = VCPU_STATE_STARTING; |
| 152 | boot_vcpu->regs_available = false; |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 153 | |
| 154 | /* vCPU restarts in runtime model for SP initialization. */ |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 155 | boot_vcpu->rt_model = RTM_SP_INIT; |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 156 | |
| 157 | /* Set the designated GP register with the core linear id. */ |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 158 | vcpu_set_phys_core_idx(boot_vcpu); |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 159 | |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 160 | if (cpu_index(c) == PRIMARY_CPU_IDX) { |
| 161 | /* |
| 162 | * Boot information is passed by the SPMC to the SP's execution |
| 163 | * context only on the primary CPU. |
| 164 | */ |
| 165 | vcpu_set_boot_info_gp_reg(boot_vcpu); |
| 166 | } |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 167 | |
| Olivier Deprez | 148b560 | 2022-03-16 17:13:06 +0100 | [diff] [blame] | 168 | vcpu_unlock(&vcpu_locked); |
| 169 | |
| Madhukar Pappireddy | 44b85ff | 2024-11-25 10:29:22 -0600 | [diff] [blame] | 170 | return boot_vcpu; |
| Olivier Deprez | f17eadc | 2021-01-25 15:33:38 +0100 | [diff] [blame] | 171 | } |