blob: 7a2bdf35fcbca6ffbc9086b1d0866c1af0662eb6 [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"
12#include "hf/spinlock.h"
13
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010014#include "vmapi/hf/ffa.h"
Fuad Tabba5c738432019-12-02 11:02:42 +000015
16/** The number of bits in each element of the interrupt bitfields. */
17#define INTERRUPT_REGISTER_BITS 32
18
19enum vcpu_state {
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000020 /** The vCPU is switched off. */
Fuad Tabba5c738432019-12-02 11:02:42 +000021 VCPU_STATE_OFF,
22
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000023 /** The vCPU is ready to be run. */
Fuad Tabba5c738432019-12-02 11:02:42 +000024 VCPU_STATE_READY,
25
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000026 /** The vCPU is currently running. */
Fuad Tabba5c738432019-12-02 11:02:42 +000027 VCPU_STATE_RUNNING,
28
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000029 /** The vCPU is waiting for a message. */
Fuad Tabba5c738432019-12-02 11:02:42 +000030 VCPU_STATE_BLOCKED_MAILBOX,
31
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000032 /** The vCPU is waiting for an interrupt. */
Fuad Tabba5c738432019-12-02 11:02:42 +000033 VCPU_STATE_BLOCKED_INTERRUPT,
34
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000035 /** The vCPU has aborted. */
Fuad Tabba5c738432019-12-02 11:02:42 +000036 VCPU_STATE_ABORTED,
37};
38
39struct interrupts {
40 /** Bitfield keeping track of which interrupts are enabled. */
41 uint32_t interrupt_enabled[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
42 /** Bitfield keeping track of which interrupts are pending. */
43 uint32_t interrupt_pending[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
Manish Pandey35e452f2021-02-18 21:36:34 +000044 /** Bitfield recording the interrupt pin configuration. */
45 uint32_t interrupt_type[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
Fuad Tabba5c738432019-12-02 11:02:42 +000046 /**
47 * The number of interrupts which are currently both enabled and
Manish Pandey35e452f2021-02-18 21:36:34 +000048 * pending. Count independently virtual IRQ and FIQ interrupt types
49 * i.e. the sum of the two counters is the number of bits set in
50 * interrupt_enable & interrupt_pending.
Fuad Tabba5c738432019-12-02 11:02:42 +000051 */
Manish Pandey35e452f2021-02-18 21:36:34 +000052 uint32_t enabled_and_pending_irq_count;
53 uint32_t enabled_and_pending_fiq_count;
Fuad Tabba5c738432019-12-02 11:02:42 +000054};
55
56struct vcpu_fault_info {
57 ipaddr_t ipaddr;
58 vaddr_t vaddr;
59 vaddr_t pc;
60 uint32_t mode;
61};
62
63struct vcpu {
64 struct spinlock lock;
65
66 /*
67 * The state is only changed in the context of the vCPU being run. This
68 * ensures the scheduler can easily keep track of the vCPU state as
69 * transitions are indicated by the return code from the run call.
70 */
71 enum vcpu_state state;
72
73 struct cpu *cpu;
74 struct vm *vm;
75 struct arch_regs regs;
76 struct interrupts interrupts;
77
78 /*
79 * Determine whether the 'regs' field is available for use. This is set
80 * to false when a vCPU is about to run on a physical CPU, and is set
Olivier Deprez3caed1c2021-02-05 12:07:36 +010081 * back to true when it is descheduled. This is not relevant for the
82 * primary VM vCPUs in the normal world (or the "other world VM" vCPUs
83 * in the secure world) as they are pinned to physical CPUs and there
84 * is no contention to take care of.
Fuad Tabba5c738432019-12-02 11:02:42 +000085 */
86 bool regs_available;
Olivier Deprezee9d6a92019-11-26 09:14:11 +000087
88 /*
89 * If the current vCPU is executing as a consequence of a
90 * FFA_MSG_SEND_DIRECT_REQ invocation, then this member holds the
91 * originating VM ID from which the call originated.
92 * The value HF_INVALID_VM_ID implies the vCPU is not executing as
93 * a result of a prior FFA_MSG_SEND_DIRECT_REQ invocation.
94 */
95 ffa_vm_id_t direct_request_origin_vm_id;
Fuad Tabba5c738432019-12-02 11:02:42 +000096};
97
98/** Encapsulates a vCPU whose lock is held. */
99struct vcpu_locked {
100 struct vcpu *vcpu;
101};
102
Olivier Deprez0b6f10a2020-08-05 18:21:33 +0200103/** Container for two vcpu_locked structures. */
104struct two_vcpu_locked {
105 struct vcpu_locked vcpu1;
106 struct vcpu_locked vcpu2;
107};
108
Fuad Tabba5c738432019-12-02 11:02:42 +0000109struct vcpu_locked vcpu_lock(struct vcpu *vcpu);
Olivier Deprez0b6f10a2020-08-05 18:21:33 +0200110struct two_vcpu_locked vcpu_lock_both(struct vcpu *vcpu1, struct vcpu *vcpu2);
Fuad Tabba5c738432019-12-02 11:02:42 +0000111void vcpu_unlock(struct vcpu_locked *locked);
112void vcpu_init(struct vcpu *vcpu, struct vm *vm);
113void vcpu_on(struct vcpu_locked vcpu, ipaddr_t entry, uintreg_t arg);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100114ffa_vcpu_index_t vcpu_index(const struct vcpu *vcpu);
Fuad Tabba5c738432019-12-02 11:02:42 +0000115bool vcpu_is_off(struct vcpu_locked vcpu);
Max Shvetsov40108e72020-08-27 12:39:50 +0100116bool vcpu_secondary_reset_and_start(struct vcpu_locked vcpu_locked,
117 ipaddr_t entry, uintreg_t arg);
Fuad Tabba5c738432019-12-02 11:02:42 +0000118
119bool vcpu_handle_page_fault(const struct vcpu *current,
120 struct vcpu_fault_info *f);
Olivier Deprez2ebae3a2020-06-11 16:34:30 +0200121
Olivier Depreze6f7b9d2021-02-01 11:55:48 +0100122void vcpu_reset(struct vcpu *vcpu);
Manish Pandey35e452f2021-02-18 21:36:34 +0000123
124static inline void vcpu_irq_count_increment(struct vcpu_locked vcpu_locked)
125{
126 vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count++;
127}
128
129static inline void vcpu_irq_count_decrement(struct vcpu_locked vcpu_locked)
130{
131 vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count--;
132}
133
134static inline void vcpu_fiq_count_increment(struct vcpu_locked vcpu_locked)
135{
136 vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count++;
137}
138
139static inline void vcpu_fiq_count_decrement(struct vcpu_locked vcpu_locked)
140{
141 vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count--;
142}
143
144static inline uint32_t vcpu_interrupt_irq_count_get(
145 struct vcpu_locked vcpu_locked)
146{
147 return vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count;
148}
149
150static inline uint32_t vcpu_interrupt_fiq_count_get(
151 struct vcpu_locked vcpu_locked)
152{
153 return vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count;
154}
155
156static inline uint32_t vcpu_interrupt_count_get(struct vcpu_locked vcpu_locked)
157{
158 return vcpu_locked.vcpu->interrupts.enabled_and_pending_irq_count +
159 vcpu_locked.vcpu->interrupts.enabled_and_pending_fiq_count;
160}