@@ -148,6 +148,7 @@ static struct irq_domain *its_parent;
148
148
#define ITS_LIST_MAX 16
149
149
150
150
static unsigned long its_list_map ;
151
+ static DEFINE_IDA (its_vpeid_ida );
151
152
152
153
#define gic_data_rdist () (raw_cpu_ptr(gic_rdists->rdist))
153
154
#define gic_data_rdist_rd_base () (gic_data_rdist()->rd_base)
@@ -1255,6 +1256,11 @@ static struct page *its_allocate_prop_table(gfp_t gfp_flags)
1255
1256
return prop_page ;
1256
1257
}
1257
1258
1259
+ static void its_free_prop_table (struct page * prop_page )
1260
+ {
1261
+ free_pages ((unsigned long )page_address (prop_page ),
1262
+ get_order (LPI_PROPBASE_SZ ));
1263
+ }
1258
1264
1259
1265
static int __init its_alloc_lpi_tables (void )
1260
1266
{
@@ -1557,6 +1563,12 @@ static struct page *its_allocate_pending_table(gfp_t gfp_flags)
1557
1563
return pend_page ;
1558
1564
}
1559
1565
1566
+ static void its_free_pending_table (struct page * pt )
1567
+ {
1568
+ free_pages ((unsigned long )page_address (pt ),
1569
+ get_order (max_t (u32 , LPI_PENDBASE_SZ , SZ_64K )));
1570
+ }
1571
+
1560
1572
static void its_cpu_init_lpis (void )
1561
1573
{
1562
1574
void __iomem * rbase = gic_data_rdist_rd_base ();
@@ -1779,6 +1791,34 @@ static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
1779
1791
return its_alloc_table_entry (baser , dev_id );
1780
1792
}
1781
1793
1794
+ static bool its_alloc_vpe_table (u32 vpe_id )
1795
+ {
1796
+ struct its_node * its ;
1797
+
1798
+ /*
1799
+ * Make sure the L2 tables are allocated on *all* v4 ITSs. We
1800
+ * could try and only do it on ITSs corresponding to devices
1801
+ * that have interrupts targeted at this VPE, but the
1802
+ * complexity becomes crazy (and you have tons of memory
1803
+ * anyway, right?).
1804
+ */
1805
+ list_for_each_entry (its , & its_nodes , entry ) {
1806
+ struct its_baser * baser ;
1807
+
1808
+ if (!its -> is_v4 )
1809
+ continue ;
1810
+
1811
+ baser = its_get_baser (its , GITS_BASER_TYPE_VCPU );
1812
+ if (!baser )
1813
+ return false;
1814
+
1815
+ if (!its_alloc_table_entry (baser , vpe_id ))
1816
+ return false;
1817
+ }
1818
+
1819
+ return true;
1820
+ }
1821
+
1782
1822
static struct its_device * its_create_device (struct its_node * its , u32 dev_id ,
1783
1823
int nvecs )
1784
1824
{
@@ -2036,7 +2076,136 @@ static struct irq_chip its_vpe_irq_chip = {
2036
2076
.name = "GICv4-vpe" ,
2037
2077
};
2038
2078
2079
+ static int its_vpe_id_alloc (void )
2080
+ {
2081
+ return ida_simple_get (& its_vpeid_ida , 0 , 1 << 16 , GFP_KERNEL );
2082
+ }
2083
+
2084
+ static void its_vpe_id_free (u16 id )
2085
+ {
2086
+ ida_simple_remove (& its_vpeid_ida , id );
2087
+ }
2088
+
2089
+ static int its_vpe_init (struct its_vpe * vpe )
2090
+ {
2091
+ struct page * vpt_page ;
2092
+ int vpe_id ;
2093
+
2094
+ /* Allocate vpe_id */
2095
+ vpe_id = its_vpe_id_alloc ();
2096
+ if (vpe_id < 0 )
2097
+ return vpe_id ;
2098
+
2099
+ /* Allocate VPT */
2100
+ vpt_page = its_allocate_pending_table (GFP_KERNEL );
2101
+ if (!vpt_page ) {
2102
+ its_vpe_id_free (vpe_id );
2103
+ return - ENOMEM ;
2104
+ }
2105
+
2106
+ if (!its_alloc_vpe_table (vpe_id )) {
2107
+ its_vpe_id_free (vpe_id );
2108
+ its_free_pending_table (vpe -> vpt_page );
2109
+ return - ENOMEM ;
2110
+ }
2111
+
2112
+ vpe -> vpe_id = vpe_id ;
2113
+ vpe -> vpt_page = vpt_page ;
2114
+
2115
+ return 0 ;
2116
+ }
2117
+
2118
+ static void its_vpe_teardown (struct its_vpe * vpe )
2119
+ {
2120
+ its_vpe_id_free (vpe -> vpe_id );
2121
+ its_free_pending_table (vpe -> vpt_page );
2122
+ }
2123
+
2124
+ static void its_vpe_irq_domain_free (struct irq_domain * domain ,
2125
+ unsigned int virq ,
2126
+ unsigned int nr_irqs )
2127
+ {
2128
+ struct its_vm * vm = domain -> host_data ;
2129
+ int i ;
2130
+
2131
+ irq_domain_free_irqs_parent (domain , virq , nr_irqs );
2132
+
2133
+ for (i = 0 ; i < nr_irqs ; i ++ ) {
2134
+ struct irq_data * data = irq_domain_get_irq_data (domain ,
2135
+ virq + i );
2136
+ struct its_vpe * vpe = irq_data_get_irq_chip_data (data );
2137
+
2138
+ BUG_ON (vm != vpe -> its_vm );
2139
+
2140
+ clear_bit (data -> hwirq , vm -> db_bitmap );
2141
+ its_vpe_teardown (vpe );
2142
+ irq_domain_reset_irq_data (data );
2143
+ }
2144
+
2145
+ if (bitmap_empty (vm -> db_bitmap , vm -> nr_db_lpis )) {
2146
+ its_lpi_free_chunks (vm -> db_bitmap , vm -> db_lpi_base , vm -> nr_db_lpis );
2147
+ its_free_prop_table (vm -> vprop_page );
2148
+ }
2149
+ }
2150
+
2151
+ static int its_vpe_irq_domain_alloc (struct irq_domain * domain , unsigned int virq ,
2152
+ unsigned int nr_irqs , void * args )
2153
+ {
2154
+ struct its_vm * vm = args ;
2155
+ unsigned long * bitmap ;
2156
+ struct page * vprop_page ;
2157
+ int base , nr_ids , i , err = 0 ;
2158
+
2159
+ BUG_ON (!vm );
2160
+
2161
+ bitmap = its_lpi_alloc_chunks (nr_irqs , & base , & nr_ids );
2162
+ if (!bitmap )
2163
+ return - ENOMEM ;
2164
+
2165
+ if (nr_ids < nr_irqs ) {
2166
+ its_lpi_free_chunks (bitmap , base , nr_ids );
2167
+ return - ENOMEM ;
2168
+ }
2169
+
2170
+ vprop_page = its_allocate_prop_table (GFP_KERNEL );
2171
+ if (!vprop_page ) {
2172
+ its_lpi_free_chunks (bitmap , base , nr_ids );
2173
+ return - ENOMEM ;
2174
+ }
2175
+
2176
+ vm -> db_bitmap = bitmap ;
2177
+ vm -> db_lpi_base = base ;
2178
+ vm -> nr_db_lpis = nr_ids ;
2179
+ vm -> vprop_page = vprop_page ;
2180
+
2181
+ for (i = 0 ; i < nr_irqs ; i ++ ) {
2182
+ vm -> vpes [i ]-> vpe_db_lpi = base + i ;
2183
+ err = its_vpe_init (vm -> vpes [i ]);
2184
+ if (err )
2185
+ break ;
2186
+ err = its_irq_gic_domain_alloc (domain , virq + i ,
2187
+ vm -> vpes [i ]-> vpe_db_lpi );
2188
+ if (err )
2189
+ break ;
2190
+ irq_domain_set_hwirq_and_chip (domain , virq + i , i ,
2191
+ & its_vpe_irq_chip , vm -> vpes [i ]);
2192
+ set_bit (i , bitmap );
2193
+ }
2194
+
2195
+ if (err ) {
2196
+ if (i > 0 )
2197
+ its_vpe_irq_domain_free (domain , virq , i - 1 );
2198
+
2199
+ its_lpi_free_chunks (bitmap , base , nr_ids );
2200
+ its_free_prop_table (vprop_page );
2201
+ }
2202
+
2203
+ return err ;
2204
+ }
2205
+
2039
2206
static const struct irq_domain_ops its_vpe_domain_ops = {
2207
+ .alloc = its_vpe_irq_domain_alloc ,
2208
+ .free = its_vpe_irq_domain_free ,
2040
2209
};
2041
2210
2042
2211
static int its_force_quiescent (void __iomem * base )
0 commit comments