blob: 815816e2c3defe7810949f96d546d5597433f749 [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 Pappireddy464f2462021-08-03 11:23:07 -050061 * Attributes encoding in the manifest:
62
63 * Field Bit(s)
64 * ---------------------------
65 * Priority 7:0
66 * Security_State 8
67 * Config(Edge/Level) 9
68 * Type(SPI/PPI/SGI) 11:10
69 * Reserved 31:12
70 *
71 * Implementation defined Encodings for various fields:
72 *
73 * Security_State:
74 * - Secure: 1
75 * - Non-secure: 0
76 *
77 * Configuration:
78 * - Edge triggered: 0
Madhukar Pappireddy1f9df612023-01-04 08:38:22 -060079 * - Level sensitive: 1
Madhukar Pappireddy464f2462021-08-03 11:23:07 -050080 * Type:
81 * - SPI: 0b10
82 * - PPI: 0b01
83 * - SGI: 0b00
84 *
85 */
86
87#define INT_DESC_TYPE_SPI 2
88#define INT_DESC_TYPE_PPI 1
89#define INT_DESC_TYPE_SGI 0
90
91/** Interrupt Descriptor field masks and shifts. */
92
93#define INT_DESC_PRIORITY_SHIFT 0
94#define INT_DESC_SEC_STATE_SHIFT 8
95#define INT_DESC_CONFIG_SHIFT 9
96#define INT_DESC_TYPE_SHIFT 10
97
98struct interrupt_descriptor {
99 uint32_t interrupt_id;
100
101 /**
102 * Bit fields Position
103 * ---------------------
104 * reserved: 7:4
105 * type: 3:2
106 * config: 1
107 * sec_state: 0
108 */
109 uint8_t type_config_sec_state;
110 uint8_t priority;
111 bool valid;
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -0700112 bool mpidr_valid;
113 uint64_t mpidr;
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500114};
115
116/**
117 * Helper APIs for accessing interrupt_descriptor member variables.
118 */
119static inline uint32_t interrupt_desc_get_id(
120 struct interrupt_descriptor int_desc)
121{
122 return int_desc.interrupt_id;
123}
124
125static inline uint8_t interrupt_desc_get_sec_state(
126 struct interrupt_descriptor int_desc)
127{
128 return ((int_desc.type_config_sec_state >> 0) & 1U);
129}
130
131static inline uint8_t interrupt_desc_get_config(
132 struct interrupt_descriptor int_desc)
133{
134 return ((int_desc.type_config_sec_state >> 1) & 1U);
135}
136
137static inline uint8_t interrupt_desc_get_type(
138 struct interrupt_descriptor int_desc)
139{
140 return ((int_desc.type_config_sec_state >> 2) & 3U);
141}
142
143static inline uint8_t interrupt_desc_get_priority(
144 struct interrupt_descriptor int_desc)
145{
146 return int_desc.priority;
147}
148
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -0700149static inline uint64_t interrupt_desc_get_mpidr(
150 struct interrupt_descriptor int_desc)
151{
152 return int_desc.mpidr;
153}
154
155static inline bool interrupt_desc_get_mpidr_valid(
156 struct interrupt_descriptor int_desc)
157{
158 return int_desc.mpidr_valid;
159}
160
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500161static inline bool interrupt_desc_get_valid(
162 struct interrupt_descriptor int_desc)
163{
164 return int_desc.valid;
165}
166
167static inline void interrupt_desc_set_id(struct interrupt_descriptor *int_desc,
168 uint32_t interrupt_id)
169{
170 int_desc->interrupt_id = interrupt_id;
171}
172
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -0700173static inline void interrupt_desc_set_mpidr(
174 struct interrupt_descriptor *int_desc, uint64_t mpidr)
175{
176 int_desc->mpidr_valid = true;
177 int_desc->mpidr = mpidr;
178}
179
180static inline void interrupt_desc_set_mpidr_invalid(
181 struct interrupt_descriptor *int_desc)
182{
183 int_desc->mpidr_valid = false;
184 int_desc->mpidr = 0;
185}
186
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500187static inline void interrupt_desc_set_type_config_sec_state(
188 struct interrupt_descriptor *int_desc, uint8_t value)
189{
190 int_desc->type_config_sec_state = value;
191}
192
Madhukar Pappireddy18c6eb72023-08-21 12:16:18 -0500193static inline void interrupt_desc_set_sec_state(
194 struct interrupt_descriptor *int_desc, uint8_t value)
195{
196 /*
197 * Note that the type_config_sec_state field is 8 bit wide. Modify only
198 * the bit[0] of the type_config_sec_state field as it represents the
199 * security state of the interrupt.
200 */
201 int_desc->type_config_sec_state =
202 (int_desc->type_config_sec_state & 0xFE) | (value & 0x1);
203}
204
Madhukar Pappireddy464f2462021-08-03 11:23:07 -0500205static inline void interrupt_desc_set_priority(
206 struct interrupt_descriptor *int_desc, uint8_t priority)
207{
208 int_desc->priority = priority;
209}
210
211static inline void interrupt_desc_set_valid(
212 struct interrupt_descriptor *int_desc, bool valid)
213{
214 int_desc->valid = valid;
215}