1 // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 // 3 // SPDX-License-Identifier: BSD-3-Clause 4 5 #include <assert.h> 6 #include <hyptypes.h> 7 8 #include <cpulocal.h> 9 #include <power.h> 10 #include <scheduler.h> 11 #include <thread.h> 12 13 #if defined(INTERFACE_VCPU_RUN) 14 #include <vcpu.h> 15 #include <vcpu_run.h> 16 #endif 17 18 #include "event_handlers.h" 19 20 error_t vcpu_power_handle_vcpu_poweron(thread_t * vcpu)21vcpu_power_handle_vcpu_poweron(thread_t *vcpu) 22 { 23 assert((vcpu != NULL) && !vcpu->vcpu_power_should_vote); 24 vcpu->vcpu_power_should_vote = true; 25 26 cpu_index_t cpu = scheduler_get_affinity(vcpu); 27 bool can_vote = cpulocal_index_valid(cpu); 28 29 #if defined(INTERFACE_VCPU_RUN) 30 if (vcpu_run_is_enabled(vcpu)) { 31 can_vote = false; 32 } 33 #endif 34 35 error_t ret; 36 if (can_vote) { 37 ret = power_vote_cpu_on(cpu); 38 } else { 39 ret = OK; 40 } 41 42 return ret; 43 } 44 45 error_t vcpu_power_handle_vcpu_poweroff(thread_t * vcpu)46vcpu_power_handle_vcpu_poweroff(thread_t *vcpu) 47 { 48 assert((vcpu != NULL) && vcpu->vcpu_power_should_vote); 49 vcpu->vcpu_power_should_vote = false; 50 51 cpu_index_t cpu = scheduler_get_affinity(vcpu); 52 bool can_vote = cpulocal_index_valid(cpu); 53 #if defined(INTERFACE_VCPU_RUN) 54 if (vcpu_run_is_enabled(vcpu)) { 55 can_vote = false; 56 } 57 #endif 58 59 if (can_vote) { 60 power_vote_cpu_off(cpu); 61 } 62 63 return OK; 64 } 65 66 void vcpu_power_handle_vcpu_stopped(void)67vcpu_power_handle_vcpu_stopped(void) 68 { 69 thread_t *vcpu = thread_get_self(); 70 assert((vcpu != NULL) && (vcpu->kind == THREAD_KIND_VCPU)); 71 72 scheduler_lock_nopreempt(vcpu); 73 74 if (vcpu->vcpu_power_should_vote) { 75 vcpu->vcpu_power_should_vote = false; 76 77 cpu_index_t cpu = scheduler_get_affinity(vcpu); 78 bool can_vote = cpulocal_index_valid(cpu); 79 #if defined(INTERFACE_VCPU_RUN) 80 if (vcpu_run_is_enabled(vcpu)) { 81 can_vote = false; 82 } 83 #endif 84 85 if (can_vote) { 86 power_vote_cpu_off(cpu); 87 } 88 } 89 90 scheduler_unlock_nopreempt(vcpu); 91 } 92 93 #if defined(INTERFACE_VCPU_RUN) 94 void vcpu_power_handle_vcpu_run_enabled(thread_t * vcpu)95vcpu_power_handle_vcpu_run_enabled(thread_t *vcpu) 96 { 97 cpu_index_t cpu = scheduler_get_affinity(vcpu); 98 bool can_vote = cpulocal_index_valid(cpu); 99 100 if (can_vote && vcpu->vcpu_power_should_vote) { 101 power_vote_cpu_off(cpu); 102 } 103 } 104 #endif 105 106 error_t vcpu_power_handle_scheduler_set_affinity_prepare(thread_t * vcpu,cpu_index_t prev_cpu,cpu_index_t next_cpu)107vcpu_power_handle_scheduler_set_affinity_prepare(thread_t *vcpu, 108 cpu_index_t prev_cpu, 109 cpu_index_t next_cpu) 110 { 111 error_t ret = OK; 112 assert(prev_cpu != next_cpu); 113 114 if (vcpu->kind != THREAD_KIND_VCPU) { 115 goto out; 116 } 117 118 #if defined(INTERFACE_VCPU_RUN) 119 if (vcpu_run_is_enabled(vcpu)) { 120 goto out; 121 } 122 #endif 123 124 if (vcpu->vcpu_power_should_vote) { 125 if (cpulocal_index_valid(next_cpu)) { 126 ret = power_vote_cpu_on(next_cpu); 127 } 128 if ((ret == OK) && cpulocal_index_valid(prev_cpu)) { 129 power_vote_cpu_off(prev_cpu); 130 } 131 } 132 133 out: 134 return ret; 135 } 136