blob: b97bfb00bb3d7e094aaf561a88ad3015fd82f667 [file] [log] [blame]
Madhukar Pappireddy464f2462021-08-03 11:23:07 -05001/*
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
9#pragma once
10
11#include <stdatomic.h>
12
13#include "hf/arch/types.h"
14
15#include "vmapi/hf/ffa.h"
16
17/**
Daniel Boulby801f8ef2022-06-27 14:21:01 +010018 * Macros for accessing the bitmap tracking interrupts.
19 */
20/* The number of bits in each element of the interrupt bitfields. */
21#define INTERRUPT_REGISTER_BITS 32
22
Daniel Boulby4ca50f02022-07-29 18:29:34 +010023struct interrupt_bitmap {
24 uint32_t bitmap[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
25};
Daniel Boulby801f8ef2022-06-27 14:21:01 +010026
Daniel Boulby4ca50f02022-07-29 18:29:34 +010027static inline uint32_t interrupt_bitmap_get_value(
28 struct interrupt_bitmap *bitmap, uint32_t intid)
29{
30 uint32_t index = intid / INTERRUPT_REGISTER_BITS;
31 uint32_t shift = intid % INTERRUPT_REGISTER_BITS;
32
33 return (bitmap->bitmap[index] >> shift) & 1U;
34}
35
36static inline void interrupt_bitmap_set_value(struct interrupt_bitmap *bitmap,
37 uint32_t intid)
38{
39 uint32_t index = intid / INTERRUPT_REGISTER_BITS;
40 uint32_t shift = intid % INTERRUPT_REGISTER_BITS;
41
42 bitmap->bitmap[index] |= 1U << shift;
43}
44
45static inline void interrupt_bitmap_clear_value(struct interrupt_bitmap *bitmap,
46 uint32_t intid)
47{
48 uint32_t index = intid / INTERRUPT_REGISTER_BITS;
49 uint32_t shift = intid % INTERRUPT_REGISTER_BITS;
50
51 bitmap->bitmap[index] &= ~(1U << shift);
52}
Madhukar Pappireddy3221a442023-07-24 16:10:55 -050053
54/**
55 * Legal values to change the security state of an interrupt.
56 */
57#define INT_SEC_STATE_NS 0
58#define INT_SEC_STATE_S 1
59
Daniel Boulby801f8ef2022-06-27 14:21:01 +010060/**
Madhukar Pappireddy938faaf2023-07-31 17:56:55 -050061 * Legal values to enable or disable an interrupt through the
62 * `INT_RECONFIGURE_ENABLE` command using the `HF_INTERRUPT_RECONFIGURE`
63 * paravirtualized interface.
64 */
65#define INT_DISABLE 0
66#define INT_ENABLE 1
67
68/**
Madhukar Pappireddy464f2462021-08-03 11:23:07 -050069 * Attributes encoding in the manifest:
70
71 * Field Bit(s)
72 * ---------------------------
73 * Priority 7:0
74 * Security_State 8
75 * Config(Edge/Level) 9
76 * Type(SPI/PPI/SGI) 11:10
77 * Reserved 31:12
78 *
79 * Implementation defined Encodings for various fields:
80 *
81 * Security_State:
82 * - Secure: 1
83 * - Non-secure: 0
84 *
85 * Configuration:
86 * - Edge triggered: 0
Madhukar Pappireddy1f9df612023-01-04 08:38:22 -060087 * - Level sensitive: 1
Madhukar Pappireddy464f2462021-08-03 11:23:07 -050088 * Type:
89 * - SPI: 0b10
90 * - PPI: 0b01
91 * - SGI: 0b00
92 *
93 */
94
95#define INT_DESC_TYPE_SPI 2
96#define INT_DESC_TYPE_PPI 1
97#define INT_DESC_TYPE_SGI 0
98
99/** Interrupt Descriptor field masks and shifts. */
100
101#define INT_DESC_PRIORITY_SHIFT 0
102#define INT_DESC_SEC_STATE_SHIFT 8
103#define INT_DESC_CONFIG_SHIFT 9
104#define INT_DESC_TYPE_SHIFT 10
105
106struct interrupt_descriptor {
107 uint32_t interrupt_id;
108
109 /**
110 * Bit fields Position
111 * ---------------------
112 * reserved: 7:4
113 * type: 3:2
114 * config: 1
115 * sec_state: 0
116 */
117 uint8_t type_config_sec_state;
118 uint8_t priority;
119 bool valid;
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -0700120 bool mpidr_valid;
121 uint64_t mpidr;
Madhukar Pappireddy938faaf2023-07-31 17:56:55 -0500122 bool enabled;
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500123};
124
125/**
126 * Helper APIs for accessing interrupt_descriptor member variables.
127 */
128static inline uint32_t interrupt_desc_get_id(
129 struct interrupt_descriptor int_desc)
130{
131 return int_desc.interrupt_id;
132}
133
134static inline uint8_t interrupt_desc_get_sec_state(
135 struct interrupt_descriptor int_desc)
136{
137 return ((int_desc.type_config_sec_state >> 0) & 1U);
138}
139
140static inline uint8_t interrupt_desc_get_config(
141 struct interrupt_descriptor int_desc)
142{
143 return ((int_desc.type_config_sec_state >> 1) & 1U);
144}
145
146static inline uint8_t interrupt_desc_get_type(
147 struct interrupt_descriptor int_desc)
148{
149 return ((int_desc.type_config_sec_state >> 2) & 3U);
150}
151
152static inline uint8_t interrupt_desc_get_priority(
153 struct interrupt_descriptor int_desc)
154{
155 return int_desc.priority;
156}
157
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -0700158static inline uint64_t interrupt_desc_get_mpidr(
159 struct interrupt_descriptor int_desc)
160{
161 return int_desc.mpidr;
162}
163
164static inline bool interrupt_desc_get_mpidr_valid(
165 struct interrupt_descriptor int_desc)
166{
167 return int_desc.mpidr_valid;
168}
169
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500170static inline bool interrupt_desc_get_valid(
171 struct interrupt_descriptor int_desc)
172{
173 return int_desc.valid;
174}
175
176static inline void interrupt_desc_set_id(struct interrupt_descriptor *int_desc,
177 uint32_t interrupt_id)
178{
179 int_desc->interrupt_id = interrupt_id;
180}
181
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -0700182static inline void interrupt_desc_set_mpidr(
183 struct interrupt_descriptor *int_desc, uint64_t mpidr)
184{
185 int_desc->mpidr_valid = true;
186 int_desc->mpidr = mpidr;
187}
188
189static inline void interrupt_desc_set_mpidr_invalid(
190 struct interrupt_descriptor *int_desc)
191{
192 int_desc->mpidr_valid = false;
193 int_desc->mpidr = 0;
194}
195
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500196static inline void interrupt_desc_set_type_config_sec_state(
197 struct interrupt_descriptor *int_desc, uint8_t value)
198{
199 int_desc->type_config_sec_state = value;
200}
201
Madhukar Pappireddy18c6eb72023-08-21 12:16:18 -0500202static inline void interrupt_desc_set_sec_state(
203 struct interrupt_descriptor *int_desc, uint8_t value)
204{
205 /*
206 * Note that the type_config_sec_state field is 8 bit wide. Modify only
207 * the bit[0] of the type_config_sec_state field as it represents the
208 * security state of the interrupt.
209 */
210 int_desc->type_config_sec_state =
211 (int_desc->type_config_sec_state & 0xFE) | (value & 0x1);
212}
213
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500214static inline void interrupt_desc_set_priority(
215 struct interrupt_descriptor *int_desc, uint8_t priority)
216{
217 int_desc->priority = priority;
218}
219
220static inline void interrupt_desc_set_valid(
221 struct interrupt_descriptor *int_desc, bool valid)
222{
223 int_desc->valid = valid;
224}
Madhukar Pappireddy938faaf2023-07-31 17:56:55 -0500225
226static inline void interrupt_desc_set_enabled(
227 struct interrupt_descriptor *int_desc, bool enable)
228{
229 int_desc->enabled = enable;
230}