8585
8686static struct irq_domain * gic_domain ;
8787static const struct irq_domain_ops * vpe_domain_ops ;
88+ static const struct irq_domain_ops * sgi_domain_ops ;
89+
90+ static bool has_v4_1 (void )
91+ {
92+ return !!sgi_domain_ops ;
93+ }
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+ }
88135
89136int its_alloc_vcpu_irqs (struct its_vm * vm )
90137{
@@ -112,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
112159 if (vpe_base_irq <= 0 )
113160 goto err ;
114161
115- for (i = 0 ; i < vm -> nr_vpes ; i ++ )
162+ for (i = 0 ; i < vm -> nr_vpes ; i ++ ) {
163+ int ret ;
116164 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+ }
117169
118170 return 0 ;
119171
@@ -126,8 +178,28 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
126178 return - ENOMEM ;
127179}
128180
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+
129200void its_free_vcpu_irqs (struct its_vm * vm )
130201{
202+ its_free_sgi_irqs (vm );
131203 irq_domain_free_irqs (vm -> vpes [0 ]-> irq , vm -> nr_vpes );
132204 irq_domain_remove (vm -> domain );
133205 irq_domain_free_fwnode (vm -> fwnode );
@@ -138,18 +210,50 @@ static int its_send_vpe_cmd(struct its_vpe *vpe, struct its_cmd_info *info)
138210 return irq_set_vcpu_affinity (vpe -> irq , info );
139211}
140212
141- int its_schedule_vpe (struct its_vpe * vpe , bool on )
213+ int its_make_vpe_non_resident (struct its_vpe * vpe , bool db )
214+ {
215+ struct irq_desc * desc = irq_to_desc (vpe -> irq );
216+ struct its_cmd_info info = { };
217+ int ret ;
218+
219+ WARN_ON (preemptible ());
220+
221+ info .cmd_type = DESCHEDULE_VPE ;
222+ if (has_v4_1 ()) {
223+ /* GICv4.1 can directly deal with doorbells */
224+ info .req_db = db ;
225+ } else {
226+ /* Undo the nested disable_irq() calls... */
227+ while (db && irqd_irq_disabled (& desc -> irq_data ))
228+ enable_irq (vpe -> irq );
229+ }
230+
231+ ret = its_send_vpe_cmd (vpe , & info );
232+ if (!ret )
233+ vpe -> resident = false;
234+
235+ return ret ;
236+ }
237+
238+ int its_make_vpe_resident (struct its_vpe * vpe , bool g0en , bool g1en )
142239{
143- struct its_cmd_info info ;
240+ struct its_cmd_info info = { } ;
144241 int ret ;
145242
146243 WARN_ON (preemptible ());
147244
148- info .cmd_type = on ? SCHEDULE_VPE : DESCHEDULE_VPE ;
245+ info .cmd_type = SCHEDULE_VPE ;
246+ if (has_v4_1 ()) {
247+ info .g0en = g0en ;
248+ info .g1en = g1en ;
249+ } else {
250+ /* Disabled the doorbell, as we're about to enter the guest */
251+ disable_irq_nosync (vpe -> irq );
252+ }
149253
150254 ret = its_send_vpe_cmd (vpe , & info );
151255 if (!ret )
152- vpe -> resident = on ;
256+ vpe -> resident = true ;
153257
154258 return ret ;
155259}
@@ -216,12 +320,28 @@ int its_prop_update_vlpi(int irq, u8 config, bool inv)
216320 return irq_set_vcpu_affinity (irq , & info );
217321}
218322
219- int its_init_v4 (struct irq_domain * domain , const struct irq_domain_ops * ops )
323+ int its_prop_update_vsgi (int irq , u8 priority , bool group )
324+ {
325+ struct its_cmd_info info = {
326+ .cmd_type = PROP_UPDATE_VSGI ,
327+ {
328+ .priority = priority ,
329+ .group = group ,
330+ },
331+ };
332+
333+ return irq_set_vcpu_affinity (irq , & info );
334+ }
335+
336+ int its_init_v4 (struct irq_domain * domain ,
337+ const struct irq_domain_ops * vpe_ops ,
338+ const struct irq_domain_ops * sgi_ops )
220339{
221340 if (domain ) {
222341 pr_info ("ITS: Enabling GICv4 support\n" );
223342 gic_domain = domain ;
224- vpe_domain_ops = ops ;
343+ vpe_domain_ops = vpe_ops ;
344+ sgi_domain_ops = sgi_ops ;
225345 return 0 ;
226346 }
227347
0 commit comments