1 /*
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 /**
18 * 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
23 struct interrupt_bitmap {
24 uint32_t bitmap[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
25 };
26
interrupt_bitmap_get_value(struct interrupt_bitmap * bitmap,uint32_t intid)27 static 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
interrupt_bitmap_set_value(struct interrupt_bitmap * bitmap,uint32_t intid)36 static 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
interrupt_bitmap_clear_value(struct interrupt_bitmap * bitmap,uint32_t intid)45 static 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 }
53 /**
54 * Attributes encoding in the manifest:
55
56 * Field Bit(s)
57 * ---------------------------
58 * Priority 7:0
59 * Security_State 8
60 * Config(Edge/Level) 9
61 * Type(SPI/PPI/SGI) 11:10
62 * Reserved 31:12
63 *
64 * Implementation defined Encodings for various fields:
65 *
66 * Security_State:
67 * - Secure: 1
68 * - Non-secure: 0
69 *
70 * Configuration:
71 * - Edge triggered: 0
72 * - Level triggered: 1
73 * Type:
74 * - SPI: 0b10
75 * - PPI: 0b01
76 * - SGI: 0b00
77 *
78 */
79
80 #define INT_DESC_TYPE_SPI 2
81 #define INT_DESC_TYPE_PPI 1
82 #define INT_DESC_TYPE_SGI 0
83
84 /** Interrupt Descriptor field masks and shifts. */
85
86 #define INT_DESC_PRIORITY_SHIFT 0
87 #define INT_DESC_SEC_STATE_SHIFT 8
88 #define INT_DESC_CONFIG_SHIFT 9
89 #define INT_DESC_TYPE_SHIFT 10
90
91 struct interrupt_descriptor {
92 uint32_t interrupt_id;
93
94 /**
95 * Bit fields Position
96 * ---------------------
97 * reserved: 7:4
98 * type: 3:2
99 * config: 1
100 * sec_state: 0
101 */
102 uint8_t type_config_sec_state;
103 uint8_t priority;
104 bool valid;
105 };
106
107 /**
108 * Helper APIs for accessing interrupt_descriptor member variables.
109 */
interrupt_desc_get_id(struct interrupt_descriptor int_desc)110 static inline uint32_t interrupt_desc_get_id(
111 struct interrupt_descriptor int_desc)
112 {
113 return int_desc.interrupt_id;
114 }
115
interrupt_desc_get_sec_state(struct interrupt_descriptor int_desc)116 static inline uint8_t interrupt_desc_get_sec_state(
117 struct interrupt_descriptor int_desc)
118 {
119 return ((int_desc.type_config_sec_state >> 0) & 1U);
120 }
121
interrupt_desc_get_config(struct interrupt_descriptor int_desc)122 static inline uint8_t interrupt_desc_get_config(
123 struct interrupt_descriptor int_desc)
124 {
125 return ((int_desc.type_config_sec_state >> 1) & 1U);
126 }
127
interrupt_desc_get_type(struct interrupt_descriptor int_desc)128 static inline uint8_t interrupt_desc_get_type(
129 struct interrupt_descriptor int_desc)
130 {
131 return ((int_desc.type_config_sec_state >> 2) & 3U);
132 }
133
interrupt_desc_get_priority(struct interrupt_descriptor int_desc)134 static inline uint8_t interrupt_desc_get_priority(
135 struct interrupt_descriptor int_desc)
136 {
137 return int_desc.priority;
138 }
139
interrupt_desc_get_valid(struct interrupt_descriptor int_desc)140 static inline bool interrupt_desc_get_valid(
141 struct interrupt_descriptor int_desc)
142 {
143 return int_desc.valid;
144 }
145
interrupt_desc_set_id(struct interrupt_descriptor * int_desc,uint32_t interrupt_id)146 static inline void interrupt_desc_set_id(struct interrupt_descriptor *int_desc,
147 uint32_t interrupt_id)
148 {
149 int_desc->interrupt_id = interrupt_id;
150 }
151
interrupt_desc_set_type_config_sec_state(struct interrupt_descriptor * int_desc,uint8_t value)152 static inline void interrupt_desc_set_type_config_sec_state(
153 struct interrupt_descriptor *int_desc, uint8_t value)
154 {
155 int_desc->type_config_sec_state = value;
156 }
157
interrupt_desc_set_priority(struct interrupt_descriptor * int_desc,uint8_t priority)158 static inline void interrupt_desc_set_priority(
159 struct interrupt_descriptor *int_desc, uint8_t priority)
160 {
161 int_desc->priority = priority;
162 }
163
interrupt_desc_set_valid(struct interrupt_descriptor * int_desc,bool valid)164 static inline void interrupt_desc_set_valid(
165 struct interrupt_descriptor *int_desc, bool valid)
166 {
167 int_desc->valid = valid;
168 }
169