blob: af54f19abdfe40ce26dbc1b5238fa4cdddc212e6 [file] [log] [blame]
Karl Meakin5a365d32024-11-08 23:55:03 +00001/*
2 * Copyright 2024 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
9#include "hf/arch/other_world.h"
Karl Meakin5a365d32024-11-08 23:55:03 +000010
11#include "hf/api.h"
Karl Meakin902af082024-11-28 14:58:38 +000012#include "hf/ffa/indirect_messaging.h"
Karl Meakin5a365d32024-11-08 23:55:03 +000013#include "hf/vcpu.h"
14
Karl Meakin117c8082024-12-04 16:03:28 +000015bool ffa_cpu_cycles_run_forward(ffa_id_t vm_id, ffa_vcpu_index_t vcpu_idx,
16 struct ffa_value *ret)
Karl Meakin5a365d32024-11-08 23:55:03 +000017{
18 /*
19 * VM's requests should be forwarded to the SPMC, if target is an SP.
20 */
21 if (!vm_id_is_current_world(vm_id)) {
22 *ret = arch_other_world_call_ext((struct ffa_value){
23 .func = FFA_RUN_32, ffa_vm_vcpu(vm_id, vcpu_idx)});
24 return true;
25 }
26
27 return false;
28}
29
30/**
31 * Check if current VM can resume target VM/SP using FFA_RUN ABI.
32 */
Karl Meakin117c8082024-12-04 16:03:28 +000033bool ffa_cpu_cycles_run_checks(struct vcpu_locked current_locked,
34 ffa_id_t target_vm_id, ffa_vcpu_index_t vcpu_idx,
35 struct ffa_value *run_ret, struct vcpu **next)
Karl Meakin5a365d32024-11-08 23:55:03 +000036{
37 (void)next;
38 (void)vcpu_idx;
39
40 /* Only the primary VM can switch vCPUs. */
41 if (!vm_is_primary(current_locked.vcpu->vm)) {
42 run_ret->arg2 = FFA_DENIED;
43 return false;
44 }
45
46 /* Only secondary VM vCPUs can be run. */
47 if (target_vm_id == HF_PRIMARY_VM_ID) {
48 return false;
49 }
50
51 return true;
52}
53
54/**
55 * The invocation of FFA_MSG_WAIT at non-secure virtual FF-A instance is made
56 * to be compliant with version v1.0 of the FF-A specification. It serves as
57 * a blocking call.
58 */
Karl Meakin117c8082024-12-04 16:03:28 +000059struct ffa_value ffa_cpu_cycles_msg_wait_prepare(
60 struct vcpu_locked current_locked, struct vcpu **next)
Karl Meakin5a365d32024-11-08 23:55:03 +000061{
Karl Meakin117c8082024-12-04 16:03:28 +000062 return ffa_indirect_msg_recv(true, current_locked, next);
Karl Meakin5a365d32024-11-08 23:55:03 +000063}
64
Karl Meakin117c8082024-12-04 16:03:28 +000065bool ffa_cpu_cycles_check_runtime_state_transition(
66 struct vcpu_locked current_locked, ffa_id_t vm_id,
67 ffa_id_t receiver_vm_id, struct vcpu_locked receiver_locked,
68 uint32_t func, enum vcpu_state *next_state)
Karl Meakin5a365d32024-11-08 23:55:03 +000069{
70 (void)current_locked;
71 (void)vm_id;
72 (void)receiver_vm_id;
73 (void)receiver_locked;
74
75 switch (func) {
76 case FFA_YIELD_32:
77 /* Fall through. */
78 case FFA_MSG_SEND_DIRECT_REQ_64:
79 case FFA_MSG_SEND_DIRECT_REQ_32:
80 case FFA_MSG_SEND_DIRECT_REQ2_64:
81 case FFA_RUN_32:
82 *next_state = VCPU_STATE_BLOCKED;
83 return true;
84 case FFA_MSG_WAIT_32:
85 /* Fall through. */
86 case FFA_MSG_SEND_DIRECT_RESP_64:
87 case FFA_MSG_SEND_DIRECT_RESP_32:
88 case FFA_MSG_SEND_DIRECT_RESP2_64:
89 *next_state = VCPU_STATE_WAITING;
90 return true;
91 default:
92 return false;
93 }
94}
95
Karl Meakin117c8082024-12-04 16:03:28 +000096void ffa_cpu_cycles_init_schedule_mode_ffa_runeld_prepare(
97 struct vcpu_locked current_locked, struct vcpu_locked target_locked)
Karl Meakin5a365d32024-11-08 23:55:03 +000098{
99 /* Scheduling mode not supported in the Hypervisor/VMs. */
100 (void)current_locked;
101 (void)target_locked;
102}
103
104/*
105 * Prepare to yield execution back to the VM that allocated cpu cycles and move
106 * to BLOCKED state.
107 */
Karl Meakin117c8082024-12-04 16:03:28 +0000108struct ffa_value ffa_cpu_cycles_yield_prepare(struct vcpu_locked current_locked,
109 struct vcpu **next,
110 uint32_t timeout_low,
111 uint32_t timeout_high)
Karl Meakin5a365d32024-11-08 23:55:03 +0000112{
113 struct vcpu *current = current_locked.vcpu;
114 struct ffa_value ret = {
115 .func = FFA_YIELD_32,
116 .arg1 = ffa_vm_vcpu(current->vm->id, vcpu_index(current)),
117 .arg2 = timeout_low,
118 .arg3 = timeout_high,
119 };
120
121 /*
122 * Return execution to primary VM.
123 */
124 *next = api_switch_to_primary(current_locked, ret, VCPU_STATE_BLOCKED);
125
126 return (struct ffa_value){.func = FFA_SUCCESS_32};
127}