46
46
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
47
47
#define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1)
48
48
49
+ #define RD_LOCAL_LPI_ENABLED BIT(0)
50
+ #define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
51
+ #define RD_LOCAL_MEMRESERVE_DONE BIT(2)
52
+
49
53
static u32 lpi_id_bits ;
50
54
51
55
/*
@@ -3044,7 +3048,7 @@ static void its_cpu_init_lpis(void)
3044
3048
phys_addr_t paddr ;
3045
3049
u64 val , tmp ;
3046
3050
3047
- if (gic_data_rdist ()-> lpi_enabled )
3051
+ if (gic_data_rdist ()-> flags & RD_LOCAL_LPI_ENABLED )
3048
3052
return ;
3049
3053
3050
3054
val = readl_relaxed (rbase + GICR_CTLR );
@@ -3063,15 +3067,13 @@ static void its_cpu_init_lpis(void)
3063
3067
paddr &= GENMASK_ULL (51 , 16 );
3064
3068
3065
3069
WARN_ON (!gic_check_reserved_range (paddr , LPI_PENDBASE_SZ ));
3066
- its_free_pending_table (gic_data_rdist ()-> pend_page );
3067
- gic_data_rdist ()-> pend_page = NULL ;
3070
+ gic_data_rdist ()-> flags |= RD_LOCAL_PENDTABLE_PREALLOCATED ;
3068
3071
3069
3072
goto out ;
3070
3073
}
3071
3074
3072
3075
pend_page = gic_data_rdist ()-> pend_page ;
3073
3076
paddr = page_to_phys (pend_page );
3074
- WARN_ON (gic_reserve_range (paddr , LPI_PENDBASE_SZ ));
3075
3077
3076
3078
/* set PROPBASE */
3077
3079
val = (gic_rdists -> prop_table_pa |
@@ -3158,10 +3160,11 @@ static void its_cpu_init_lpis(void)
3158
3160
/* Make sure the GIC has seen the above */
3159
3161
dsb (sy );
3160
3162
out :
3161
- gic_data_rdist ()-> lpi_enabled = true ;
3163
+ gic_data_rdist ()-> flags |= RD_LOCAL_LPI_ENABLED ;
3162
3164
pr_info ("GICv3: CPU%d: using %s LPI pending table @%pa\n" ,
3163
3165
smp_processor_id (),
3164
- gic_data_rdist ()-> pend_page ? "allocated" : "reserved" ,
3166
+ gic_data_rdist ()-> flags & RD_LOCAL_PENDTABLE_PREALLOCATED ?
3167
+ "reserved" : "allocated" ,
3165
3168
& paddr );
3166
3169
}
3167
3170
@@ -5138,7 +5141,7 @@ static int redist_disable_lpis(void)
5138
5141
*
5139
5142
* If running with preallocated tables, there is nothing to do.
5140
5143
*/
5141
- if (gic_data_rdist ()-> lpi_enabled ||
5144
+ if (( gic_data_rdist ()-> flags & RD_LOCAL_LPI_ENABLED ) ||
5142
5145
(gic_rdists -> flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED ))
5143
5146
return 0 ;
5144
5147
@@ -5200,6 +5203,51 @@ int its_cpu_init(void)
5200
5203
return 0 ;
5201
5204
}
5202
5205
5206
+ static void rdist_memreserve_cpuhp_cleanup_workfn (struct work_struct * work )
5207
+ {
5208
+ cpuhp_remove_state_nocalls (gic_rdists -> cpuhp_memreserve_state );
5209
+ gic_rdists -> cpuhp_memreserve_state = CPUHP_INVALID ;
5210
+ }
5211
+
5212
+ static DECLARE_WORK (rdist_memreserve_cpuhp_cleanup_work ,
5213
+ rdist_memreserve_cpuhp_cleanup_workfn ) ;
5214
+
5215
+ static int its_cpu_memreserve_lpi (unsigned int cpu )
5216
+ {
5217
+ struct page * pend_page ;
5218
+ int ret = 0 ;
5219
+
5220
+ /* This gets to run exactly once per CPU */
5221
+ if (gic_data_rdist ()-> flags & RD_LOCAL_MEMRESERVE_DONE )
5222
+ return 0 ;
5223
+
5224
+ pend_page = gic_data_rdist ()-> pend_page ;
5225
+ if (WARN_ON (!pend_page )) {
5226
+ ret = - ENOMEM ;
5227
+ goto out ;
5228
+ }
5229
+ /*
5230
+ * If the pending table was pre-programmed, free the memory we
5231
+ * preemptively allocated. Otherwise, reserve that memory for
5232
+ * later kexecs.
5233
+ */
5234
+ if (gic_data_rdist ()-> flags & RD_LOCAL_PENDTABLE_PREALLOCATED ) {
5235
+ its_free_pending_table (pend_page );
5236
+ gic_data_rdist ()-> pend_page = NULL ;
5237
+ } else {
5238
+ phys_addr_t paddr = page_to_phys (pend_page );
5239
+ WARN_ON (gic_reserve_range (paddr , LPI_PENDBASE_SZ ));
5240
+ }
5241
+
5242
+ out :
5243
+ /* Last CPU being brought up gets to issue the cleanup */
5244
+ if (cpumask_equal (& cpus_booted_once_mask , cpu_possible_mask ))
5245
+ schedule_work (& rdist_memreserve_cpuhp_cleanup_work );
5246
+
5247
+ gic_data_rdist ()-> flags |= RD_LOCAL_MEMRESERVE_DONE ;
5248
+ return ret ;
5249
+ }
5250
+
5203
5251
static const struct of_device_id its_device_id [] = {
5204
5252
{ .compatible = "arm,gic-v3-its" , },
5205
5253
{},
@@ -5383,6 +5431,26 @@ static void __init its_acpi_probe(void)
5383
5431
static void __init its_acpi_probe (void ) { }
5384
5432
#endif
5385
5433
5434
+ int __init its_lpi_memreserve_init (void )
5435
+ {
5436
+ int state ;
5437
+
5438
+ if (!efi_enabled (EFI_CONFIG_TABLES ))
5439
+ return 0 ;
5440
+
5441
+ gic_rdists -> cpuhp_memreserve_state = CPUHP_INVALID ;
5442
+ state = cpuhp_setup_state (CPUHP_AP_ONLINE_DYN ,
5443
+ "irqchip/arm/gicv3/memreserve:online" ,
5444
+ its_cpu_memreserve_lpi ,
5445
+ NULL );
5446
+ if (state < 0 )
5447
+ return state ;
5448
+
5449
+ gic_rdists -> cpuhp_memreserve_state = state ;
5450
+
5451
+ return 0 ;
5452
+ }
5453
+
5386
5454
int __init its_init (struct fwnode_handle * handle , struct rdists * rdists ,
5387
5455
struct irq_domain * parent_domain )
5388
5456
{
0 commit comments