@@ -92,6 +92,47 @@ static bool has_v4_1(void)
92
92
return !!sgi_domain_ops ;
93
93
}
94
94
95
+ static int its_alloc_vcpu_sgis (struct its_vpe * vpe , int idx )
96
+ {
97
+ char * name ;
98
+ int sgi_base ;
99
+
100
+ if (!has_v4_1 ())
101
+ return 0 ;
102
+
103
+ name = kasprintf (GFP_KERNEL , "GICv4-sgi-%d" , task_pid_nr (current ));
104
+ if (!name )
105
+ goto err ;
106
+
107
+ vpe -> fwnode = irq_domain_alloc_named_id_fwnode (name , idx );
108
+ if (!vpe -> fwnode )
109
+ goto err ;
110
+
111
+ kfree (name );
112
+ name = NULL ;
113
+
114
+ vpe -> sgi_domain = irq_domain_create_linear (vpe -> fwnode , 16 ,
115
+ sgi_domain_ops , vpe );
116
+ if (!vpe -> sgi_domain )
117
+ goto err ;
118
+
119
+ sgi_base = __irq_domain_alloc_irqs (vpe -> sgi_domain , -1 , 16 ,
120
+ NUMA_NO_NODE , vpe ,
121
+ false, NULL );
122
+ if (sgi_base <= 0 )
123
+ goto err ;
124
+
125
+ return 0 ;
126
+
127
+ err :
128
+ if (vpe -> sgi_domain )
129
+ irq_domain_remove (vpe -> sgi_domain );
130
+ if (vpe -> fwnode )
131
+ irq_domain_free_fwnode (vpe -> fwnode );
132
+ kfree (name );
133
+ return - ENOMEM ;
134
+ }
135
+
95
136
int its_alloc_vcpu_irqs (struct its_vm * vm )
96
137
{
97
138
int vpe_base_irq , i ;
@@ -118,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
118
159
if (vpe_base_irq <= 0 )
119
160
goto err ;
120
161
121
- for (i = 0 ; i < vm -> nr_vpes ; i ++ )
162
+ for (i = 0 ; i < vm -> nr_vpes ; i ++ ) {
163
+ int ret ;
122
164
vm -> vpes [i ]-> irq = vpe_base_irq + i ;
165
+ ret = its_alloc_vcpu_sgis (vm -> vpes [i ], i );
166
+ if (ret )
167
+ goto err ;
168
+ }
123
169
124
170
return 0 ;
125
171
@@ -132,8 +178,28 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
132
178
return - ENOMEM ;
133
179
}
134
180
181
+ static void its_free_sgi_irqs (struct its_vm * vm )
182
+ {
183
+ int i ;
184
+
185
+ if (!has_v4_1 ())
186
+ return ;
187
+
188
+ for (i = 0 ; i < vm -> nr_vpes ; i ++ ) {
189
+ unsigned int irq = irq_find_mapping (vm -> vpes [i ]-> sgi_domain , 0 );
190
+
191
+ if (WARN_ON (!irq ))
192
+ continue ;
193
+
194
+ irq_domain_free_irqs (irq , 16 );
195
+ irq_domain_remove (vm -> vpes [i ]-> sgi_domain );
196
+ irq_domain_free_fwnode (vm -> vpes [i ]-> fwnode );
197
+ }
198
+ }
199
+
135
200
void its_free_vcpu_irqs (struct its_vm * vm )
136
201
{
202
+ its_free_sgi_irqs (vm );
137
203
irq_domain_free_irqs (vm -> vpes [0 ]-> irq , vm -> nr_vpes );
138
204
irq_domain_remove (vm -> domain );
139
205
irq_domain_free_fwnode (vm -> fwnode );
0 commit comments