blob: 47f9ed6f922d89c60c1f16f83cc3ea4cf36a4a4e [file] [log] [blame]
Fuad Tabba5c738432019-12-02 11:02:42 +00001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * 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.
Fuad Tabba5c738432019-12-02 11:02:42 +00007 */
8
9#pragma once
10
11#include "hf/addr.h"
Daniel Boulby801f8ef2022-06-27 14:21:01 +010012#include "hf/interrupt_desc.h"
Fuad Tabba5c738432019-12-02 11:02:42 +000013#include "hf/spinlock.h"
14
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010015#include "vmapi/hf/ffa.h"
Fuad Tabba5c738432019-12-02 11:02:42 +000016
Fuad Tabba5c738432019-12-02 11:02:42 +000017enum vcpu_state {
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000018 /** The vCPU is switched off. */
Fuad Tabba5c738432019-12-02 11:02:42 +000019 VCPU_STATE_OFF,
20
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000021 /** The vCPU is currently running. */
Fuad Tabba5c738432019-12-02 11:02:42 +000022 VCPU_STATE_RUNNING,
23
Madhukar Pappireddyb11e0d12021-08-02 19:44:35 -050024 /** The vCPU is waiting to be allocated CPU cycles to do work. */
25 VCPU_STATE_WAITING,
26
27 /**
28 * The vCPU is blocked and waiting for some work to complete on
29 * its behalf.
30 */
31 VCPU_STATE_BLOCKED,
32
33 /** The vCPU has been preempted by an interrupt. */
34 VCPU_STATE_PREEMPTED,
Fuad Tabba5c738432019-12-02 11:02:42 +000035
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000036 /** The vCPU is waiting for an interrupt. */
Fuad Tabba5c738432019-12-02 11:02:42 +000037 VCPU_STATE_BLOCKED_INTERRUPT,
38
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000039 /** The vCPU has aborted. */
Fuad Tabba5c738432019-12-02 11:02:42 +000040 VCPU_STATE_ABORTED,
41};
42
43struct interrupts {
44 /** Bitfield keeping track of which interrupts are enabled. */
45 uint32_t interrupt_enabled[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
46 /** Bitfield keeping track of which interrupts are pending. */
47 uint32_t interrupt_pending[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
Manish Pandey35e452f2021-02-18 21:36:34 +000048 /** Bitfield recording the interrupt pin configuration. */
49 uint32_t interrupt_type[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
Fuad Tabba5c738432019-12-02 11:02:42 +000050 /**
51 * The number of interrupts which are currently both enabled and
Manish Pandey35e452f2021-02-18 21:36:34 +000052 * pending. Count independently virtual IRQ and FIQ interrupt types
53 * i.e. the sum of the two counters is the number of bits set in
54 * interrupt_enable & interrupt_pending.
Fuad Tabba5c738432019-12-02 11:02:42 +000055 */
Manish Pandey35e452f2021-02-18 21:36:34 +000056 uint32_t enabled_and_pending_irq_count;
57 uint32_t enabled_and_pending_fiq_count;
Fuad Tabba5c738432019-12-02 11:02:42 +000058};
59
60struct vcpu_fault_info {
61 ipaddr_t ipaddr;
62 vaddr_t vaddr;
63 vaddr_t pc;
64 uint32_t mode;
65};
66
67struct vcpu {
68 struct spinlock lock;
69
70 /*
71 * The state is only changed in the context of the vCPU being run. This
72 * ensures the scheduler can easily keep track of the vCPU state as
73 * transitions are indicated by the return code from the run call.
74 */
75 enum vcpu_state state;
76
Madhukar Pappireddyb11e0d12021-08-02 19:44:35 -050077 bool is_bootstrapped;
Fuad Tabba5c738432019-12-02 11:02:42 +000078 struct cpu *cpu;
79 struct vm *vm;
80 struct arch_regs regs;
81 struct interrupts interrupts;
82
83 /*
84 * Determine whether the 'regs' field is available for use. This is set
85 * to false when a vCPU is about to run on a physical CPU, and is set
Olivier Deprez3caed1c2021-02-05 12:07:36 +010086 * back to true when it is descheduled. This is not relevant for the
87 * primary VM vCPUs in the normal world (or the "other world VM" vCPUs
88 * in the secure world) as they are pinned to physical CPUs and there
89 * is no contention to take care of.
Fuad Tabba5c738432019-12-02 11:02:42 +000090 */
91 bool regs_available;
Olivier Deprezee9d6a92019-11-26 09:14:11 +000092
93 /*
94 * If the current vCPU is executing as a consequence of a
95 * FFA_MSG_SEND_DIRECT_REQ invocation, then this member holds the
96 * originating VM ID from which the call originated.
97 * The value HF_INVALID_VM_ID implies the vCPU is not executing as
98 * a result of a prior FFA_MSG_SEND_DIRECT_REQ invocation.
99 */
100 ffa_vm_id_t direct_request_origin_vm_id;
Manish Pandeya5f39fb2020-09-11 09:47:11 +0100101
Madhukar Pappireddyb11e0d12021-08-02 19:44:35 -0500102 /** Determine whether partition is currently handling managed exit. */
Manish Pandeya5f39fb2020-09-11 09:47:11 +0100103 bool processing_managed_exit;
Madhukar Pappireddyf675bb62021-08-03 12:57:10 -0500104
105 /**
106 * Determine whether vCPU is currently handling secure interrupt.
107 */
108 bool processing_secure_interrupt;
109 bool secure_interrupt_deactivated;
110
111 /**
112 * INTID of the current secure interrupt being processed by this vCPU.
113 */
114 uint32_t current_sec_interrupt_id;
115
116 /**
117 * Track current vCPU which got pre-empted when secure interrupt
118 * triggered.
119 */
120 struct vcpu *preempted_vcpu;
Madhukar Pappireddydd6fdfb2021-12-14 12:30:36 -0600121
122 /**
123 * Current value of the Priority Mask register which is saved/restored
124 * during secure interrupt handling.
125 */
126 uint8_t priority_mask;
Madhukar Pappireddy0aaadbb2021-12-16 20:58:10 -0600127
128 /**
129 * Per FF-A v1.1-Beta0 spec section 8.3, an SP can use multiple
130 * mechanisms to signal completion of secure interrupt handling. SP
131 * can invoke explicit FF-A ABIs, namely FFA_MSG_WAIT and FFA_RUN,
132 * when in WAITING/BLOCKED state respectively, but has to perform
133 * implicit signal completion mechanism by dropping the priority
134 * of the virtual secure interrupt when SPMC signaled the virtual
135 * interrupt in PREEMPTED state(The vCPU was preempted by a Self S-Int
136 * while running). This variable helps SPMC to keep a track of such
137 * mechanism and perform appropriate bookkeeping.
138 */
139 bool implicit_completion_signal;
Fuad Tabba5c738432019-12-02 11:02:42 +0000140};
141
142/** Encapsulates a vCPU whose lock is held. */
143struct vcpu_locked {
144 struct vcpu *vcpu;
145};
146
Olivier Deprez0b6f10a2020-08-05 18:21:33 +0200147/** Container for two vcpu_locked structures. */
148struct two_vcpu_locked {
149 struct vcpu_locked vcpu1;
150 struct vcpu_locked vcpu2;
151};
152
Fuad Tabba5c738432019-12-02 11:02:42 +0000153struct vcpu_locked vcpu_lock(struct vcpu *vcpu);
Olivier Deprez0b6f10a2020-08-05 18:21:33 +0200154struct two_vcpu_locked vcpu_lock_both(struct vcpu *vcpu1, struct vcpu *vcpu2);
Fuad Tabba5c738432019-12-02 11:02:42 +0000155void vcpu_unlock(struct vcpu_locked *locked);
156void vcpu_init(struct vcpu *vcpu, struct vm *vm);
157void vcpu_on(struct vcpu_locked vcpu, ipaddr_t entry, uintreg_t arg);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100158ffa_vcpu_index_t vcpu_index(const struct vcpu *vcpu);
Fuad Tabba5c738432019-12-02 11:02:42 +0000159bool vcpu_is_off(struct vcpu_locked vcpu);
Max Shvetsov40108e72020-08-27 12:39:50 +0100160bool vcpu_secondary_reset_and_start(struct vcpu_locked vcpu_locked,
161 ipaddr_t entry, uintreg_t arg);
Fuad Tabba5c738432019-12-02 11:02:42 +0000162
163bool vcpu_handle_page_fault(const struct vcpu *current,
164 struct vcpu_fault_info *f);
Olivier Deprez2ebae3a2020-06-11 16:34:30 +0200165
Olivier Depreze6f7b9d2021-02-01 11:55:48 +0100166void vcpu_reset(struct vcpu *vcpu);
Manish Pandey35e452f2021-02-18 21:36:34 +0000167
J-Alves7ac49052022-02-08 17:20:53 +0000168void vcpu_set_phys_core_idx(struct vcpu *vcpu);
169
Manish Pandey35e452f2021-02-18 21:36:34 +0000170static inline void vcpu_irq_count_increment(struct vcpu_locked vcpu_locked)
171{
172 vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count++;
173}
174
175static inline void vcpu_irq_count_decrement(struct vcpu_locked vcpu_locked)
176{
177 vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count--;
178}
179
180static inline void vcpu_fiq_count_increment(struct vcpu_locked vcpu_locked)
181{
182 vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count++;
183}
184
185static inline void vcpu_fiq_count_decrement(struct vcpu_locked vcpu_locked)
186{
187 vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count--;
188}
189
190static inline uint32_t vcpu_interrupt_irq_count_get(
191 struct vcpu_locked vcpu_locked)
192{
193 return vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count;
194}
195
196static inline uint32_t vcpu_interrupt_fiq_count_get(
197 struct vcpu_locked vcpu_locked)
198{
199 return vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count;
200}
201
202static inline uint32_t vcpu_interrupt_count_get(struct vcpu_locked vcpu_locked)
203{
204 return vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count +
205 vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count;
206}