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