@@ -72,51 +72,55 @@ bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned i
72
72
}
73
73
EXPORT_SYMBOL_GPL (__riscv_isa_extension_available );
74
74
75
- static bool riscv_isa_extension_check (int id )
75
+ static int riscv_ext_zicbom_validate (const struct riscv_isa_ext_data * data ,
76
+ const unsigned long * isa_bitmap )
76
77
{
77
- switch (id ) {
78
- case RISCV_ISA_EXT_ZICBOM :
79
- if (!riscv_cbom_block_size ) {
80
- pr_err ("Zicbom detected in ISA string, disabling as no cbom-block-size found\n" );
81
- return false;
82
- } else if (!is_power_of_2 (riscv_cbom_block_size )) {
83
- pr_err ("Zicbom disabled as cbom-block-size present, but is not a power-of-2\n" );
84
- return false;
85
- }
86
- return true;
87
- case RISCV_ISA_EXT_ZICBOZ :
88
- if (!riscv_cboz_block_size ) {
89
- pr_err ("Zicboz detected in ISA string, disabling as no cboz-block-size found\n" );
90
- return false;
91
- } else if (!is_power_of_2 (riscv_cboz_block_size )) {
92
- pr_err ("Zicboz disabled as cboz-block-size present, but is not a power-of-2\n" );
93
- return false;
94
- }
95
- return true;
96
- case RISCV_ISA_EXT_INVALID :
97
- return false;
78
+ if (!riscv_cbom_block_size ) {
79
+ pr_err ("Zicbom detected in ISA string, disabling as no cbom-block-size found\n" );
80
+ return - EINVAL ;
98
81
}
82
+ if (!is_power_of_2 (riscv_cbom_block_size )) {
83
+ pr_err ("Zicbom disabled as cbom-block-size present, but is not a power-of-2\n" );
84
+ return - EINVAL ;
85
+ }
86
+ return 0 ;
87
+ }
99
88
100
- return true;
89
+ static int riscv_ext_zicboz_validate (const struct riscv_isa_ext_data * data ,
90
+ const unsigned long * isa_bitmap )
91
+ {
92
+ if (!riscv_cboz_block_size ) {
93
+ pr_err ("Zicboz detected in ISA string, disabling as no cboz-block-size found\n" );
94
+ return - EINVAL ;
95
+ }
96
+ if (!is_power_of_2 (riscv_cboz_block_size )) {
97
+ pr_err ("Zicboz disabled as cboz-block-size present, but is not a power-of-2\n" );
98
+ return - EINVAL ;
99
+ }
100
+ return 0 ;
101
101
}
102
102
103
- #define _RISCV_ISA_EXT_DATA (_name , _id , _subset_exts , _subset_exts_size ) { \
104
- .name = #_name, \
105
- .property = #_name, \
106
- .id = _id, \
107
- .subset_ext_ids = _subset_exts, \
108
- .subset_ext_size = _subset_exts_size \
103
+ #define _RISCV_ISA_EXT_DATA (_name , _id , _subset_exts , _subset_exts_size , _validate ) { \
104
+ .name = #_name, \
105
+ .property = #_name, \
106
+ .id = _id, \
107
+ .subset_ext_ids = _subset_exts, \
108
+ .subset_ext_size = _subset_exts_size, \
109
+ .validate = _validate \
109
110
}
110
111
111
- #define __RISCV_ISA_EXT_DATA (_name , _id ) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0)
112
+ #define __RISCV_ISA_EXT_DATA (_name , _id ) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, NULL )
112
113
113
114
/* Used to declare pure "lasso" extension (Zk for instance) */
114
115
#define __RISCV_ISA_EXT_BUNDLE (_name , _bundled_exts ) \
115
- _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, ARRAY_SIZE(_bundled_exts))
116
+ _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \
117
+ ARRAY_SIZE(_bundled_exts), NULL)
116
118
117
119
/* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */
118
120
#define __RISCV_ISA_EXT_SUPERSET (_name , _id , _sub_exts ) \
119
- _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts))
121
+ _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), NULL)
122
+ #define __RISCV_ISA_EXT_SUPERSET_VALIDATE (_name , _id , _sub_exts , _validate ) \
123
+ _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
120
124
121
125
static const unsigned int riscv_zk_bundled_exts [] = {
122
126
RISCV_ISA_EXT_ZBKB ,
@@ -281,8 +285,10 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
281
285
__RISCV_ISA_EXT_DATA (c , RISCV_ISA_EXT_c ),
282
286
__RISCV_ISA_EXT_SUPERSET (v , RISCV_ISA_EXT_v , riscv_v_exts ),
283
287
__RISCV_ISA_EXT_DATA (h , RISCV_ISA_EXT_h ),
284
- __RISCV_ISA_EXT_SUPERSET (zicbom , RISCV_ISA_EXT_ZICBOM , riscv_xlinuxenvcfg_exts ),
285
- __RISCV_ISA_EXT_SUPERSET (zicboz , RISCV_ISA_EXT_ZICBOZ , riscv_xlinuxenvcfg_exts ),
288
+ __RISCV_ISA_EXT_SUPERSET_VALIDATE (zicbom , RISCV_ISA_EXT_ZICBOM , riscv_xlinuxenvcfg_exts ,
289
+ riscv_ext_zicbom_validate ),
290
+ __RISCV_ISA_EXT_SUPERSET_VALIDATE (zicboz , RISCV_ISA_EXT_ZICBOZ , riscv_xlinuxenvcfg_exts ,
291
+ riscv_ext_zicboz_validate ),
286
292
__RISCV_ISA_EXT_DATA (zicntr , RISCV_ISA_EXT_ZICNTR ),
287
293
__RISCV_ISA_EXT_DATA (zicond , RISCV_ISA_EXT_ZICOND ),
288
294
__RISCV_ISA_EXT_DATA (zicsr , RISCV_ISA_EXT_ZICSR ),
@@ -349,33 +355,93 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
349
355
350
356
const size_t riscv_isa_ext_count = ARRAY_SIZE (riscv_isa_ext );
351
357
352
- static void __init match_isa_ext (const struct riscv_isa_ext_data * ext , const char * name ,
353
- const char * name_end , struct riscv_isainfo * isainfo )
358
+ static void riscv_isa_set_ext (const struct riscv_isa_ext_data * ext , unsigned long * bitmap )
354
359
{
355
- if ((name_end - name == strlen (ext -> name )) &&
356
- !strncasecmp (name , ext -> name , name_end - name )) {
357
- /*
358
- * If this is a bundle, enable all the ISA extensions that
359
- * comprise the bundle.
360
- */
361
- if (ext -> subset_ext_size ) {
362
- for (int i = 0 ; i < ext -> subset_ext_size ; i ++ ) {
363
- if (riscv_isa_extension_check (ext -> subset_ext_ids [i ]))
364
- set_bit (ext -> subset_ext_ids [i ], isainfo -> isa );
360
+ if (ext -> id != RISCV_ISA_EXT_INVALID )
361
+ set_bit (ext -> id , bitmap );
362
+
363
+ for (int i = 0 ; i < ext -> subset_ext_size ; i ++ ) {
364
+ if (ext -> subset_ext_ids [i ] != RISCV_ISA_EXT_INVALID )
365
+ set_bit (ext -> subset_ext_ids [i ], bitmap );
366
+ }
367
+ }
368
+
369
+ static const struct riscv_isa_ext_data * riscv_get_isa_ext_data (unsigned int ext_id )
370
+ {
371
+ for (int i = 0 ; i < riscv_isa_ext_count ; i ++ ) {
372
+ if (riscv_isa_ext [i ].id == ext_id )
373
+ return & riscv_isa_ext [i ];
374
+ }
375
+
376
+ return NULL ;
377
+ }
378
+
379
+ /*
380
+ * "Resolve" a source ISA bitmap into one that matches kernel configuration as
381
+ * well as correct extension dependencies. Some extensions depends on specific
382
+ * kernel configuration to be usable (V needs CONFIG_RISCV_ISA_V for instance)
383
+ * and this function will actually validate all the extensions provided in
384
+ * source_isa into the resolved_isa based on extensions validate() callbacks.
385
+ */
386
+ static void __init riscv_resolve_isa (unsigned long * source_isa ,
387
+ unsigned long * resolved_isa , unsigned long * this_hwcap ,
388
+ unsigned long * isa2hwcap )
389
+ {
390
+ bool loop ;
391
+ const struct riscv_isa_ext_data * ext ;
392
+ DECLARE_BITMAP (prev_resolved_isa , RISCV_ISA_EXT_MAX );
393
+ int max_loop_count = riscv_isa_ext_count , ret ;
394
+ unsigned int bit ;
395
+
396
+ do {
397
+ loop = false;
398
+ if (max_loop_count -- < 0 ) {
399
+ pr_err ("Failed to reach a stable ISA state\n" );
400
+ return ;
401
+ }
402
+ bitmap_copy (prev_resolved_isa , resolved_isa , RISCV_ISA_EXT_MAX );
403
+ for_each_set_bit (bit , source_isa , RISCV_ISA_EXT_MAX ) {
404
+ ext = riscv_get_isa_ext_data (bit );
405
+ if (!ext )
406
+ continue ;
407
+
408
+ if (ext -> validate ) {
409
+ ret = ext -> validate (ext , resolved_isa );
410
+ if (ret == - EPROBE_DEFER ) {
411
+ loop = true;
412
+ continue ;
413
+ } else if (ret ) {
414
+ /* Disable the extension entirely */
415
+ clear_bit (ext -> id , source_isa );
416
+ continue ;
417
+ }
365
418
}
419
+
420
+ set_bit (ext -> id , resolved_isa );
421
+ /* No need to keep it in source isa now that it is enabled */
422
+ clear_bit (ext -> id , source_isa );
423
+
424
+ /* Single letter extensions get set in hwcap */
425
+ if (ext -> id < RISCV_ISA_EXT_BASE )
426
+ * this_hwcap |= isa2hwcap [ext -> id ];
366
427
}
428
+ } while (loop && memcmp (prev_resolved_isa , resolved_isa , sizeof (prev_resolved_isa )));
429
+ }
367
430
368
- /*
369
- * This is valid even for bundle extensions which uses the RISCV_ISA_EXT_INVALID id
370
- * (rejected by riscv_isa_extension_check()).
371
- */
372
- if (riscv_isa_extension_check (ext -> id ))
373
- set_bit (ext -> id , isainfo -> isa );
431
+ static void __init match_isa_ext (const char * name , const char * name_end , unsigned long * bitmap )
432
+ {
433
+ for (int i = 0 ; i < riscv_isa_ext_count ; i ++ ) {
434
+ const struct riscv_isa_ext_data * ext = & riscv_isa_ext [i ];
435
+
436
+ if ((name_end - name == strlen (ext -> name )) &&
437
+ !strncasecmp (name , ext -> name , name_end - name )) {
438
+ riscv_isa_set_ext (ext , bitmap );
439
+ break ;
440
+ }
374
441
}
375
442
}
376
443
377
- static void __init riscv_parse_isa_string (unsigned long * this_hwcap , struct riscv_isainfo * isainfo ,
378
- unsigned long * isa2hwcap , const char * isa )
444
+ static void __init riscv_parse_isa_string (const char * isa , unsigned long * bitmap )
379
445
{
380
446
/*
381
447
* For all possible cpus, we have already validated in
@@ -388,7 +454,7 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
388
454
while (* isa ) {
389
455
const char * ext = isa ++ ;
390
456
const char * ext_end = isa ;
391
- bool ext_long = false, ext_err = false;
457
+ bool ext_err = false;
392
458
393
459
switch (* ext ) {
394
460
case 's' :
@@ -428,7 +494,6 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
428
494
* character itself while eliminating the extensions version number.
429
495
* A simple re-increment solves this problem.
430
496
*/
431
- ext_long = true;
432
497
for (; * isa && * isa != '_' ; ++ isa )
433
498
if (unlikely (!isalnum (* isa )))
434
499
ext_err = true;
@@ -509,15 +574,7 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
509
574
if (unlikely (ext_err ))
510
575
continue ;
511
576
512
- for (int i = 0 ; i < riscv_isa_ext_count ; i ++ )
513
- match_isa_ext (& riscv_isa_ext [i ], ext , ext_end , isainfo );
514
-
515
- if (!ext_long ) {
516
- int nr = tolower (* ext ) - 'a' ;
517
-
518
- if (riscv_isa_extension_check (nr ))
519
- * this_hwcap |= isa2hwcap [nr ];
520
- }
577
+ match_isa_ext (ext , ext_end , bitmap );
521
578
}
522
579
}
523
580
@@ -544,6 +601,7 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
544
601
for_each_possible_cpu (cpu ) {
545
602
struct riscv_isainfo * isainfo = & hart_isa [cpu ];
546
603
unsigned long this_hwcap = 0 ;
604
+ DECLARE_BITMAP (source_isa , RISCV_ISA_EXT_MAX ) = { 0 };
547
605
548
606
if (acpi_disabled ) {
549
607
node = of_cpu_device_node_get (cpu );
@@ -566,18 +624,18 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
566
624
}
567
625
}
568
626
569
- riscv_parse_isa_string (& this_hwcap , isainfo , isa2hwcap , isa );
627
+ riscv_parse_isa_string (isa , source_isa );
570
628
571
629
/*
572
630
* These ones were as they were part of the base ISA when the
573
631
* port & dt-bindings were upstreamed, and so can be set
574
632
* unconditionally where `i` is in riscv,isa on DT systems.
575
633
*/
576
634
if (acpi_disabled ) {
577
- set_bit (RISCV_ISA_EXT_ZICSR , isainfo -> isa );
578
- set_bit (RISCV_ISA_EXT_ZIFENCEI , isainfo -> isa );
579
- set_bit (RISCV_ISA_EXT_ZICNTR , isainfo -> isa );
580
- set_bit (RISCV_ISA_EXT_ZIHPM , isainfo -> isa );
635
+ set_bit (RISCV_ISA_EXT_ZICSR , source_isa );
636
+ set_bit (RISCV_ISA_EXT_ZIFENCEI , source_isa );
637
+ set_bit (RISCV_ISA_EXT_ZICNTR , source_isa );
638
+ set_bit (RISCV_ISA_EXT_ZIHPM , source_isa );
581
639
}
582
640
583
641
/*
@@ -590,9 +648,11 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
590
648
*/
591
649
if (acpi_disabled && boot_vendorid == THEAD_VENDOR_ID && boot_archid == 0x0 ) {
592
650
this_hwcap &= ~isa2hwcap [RISCV_ISA_EXT_v ];
593
- clear_bit (RISCV_ISA_EXT_v , isainfo -> isa );
651
+ clear_bit (RISCV_ISA_EXT_v , source_isa );
594
652
}
595
653
654
+ riscv_resolve_isa (source_isa , isainfo -> isa , & this_hwcap , isa2hwcap );
655
+
596
656
/*
597
657
* All "okay" hart should have same isa. Set HWCAP based on
598
658
* common capabilities of every "okay" hart, in case they don't
@@ -621,6 +681,7 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
621
681
unsigned long this_hwcap = 0 ;
622
682
struct device_node * cpu_node ;
623
683
struct riscv_isainfo * isainfo = & hart_isa [cpu ];
684
+ DECLARE_BITMAP (source_isa , RISCV_ISA_EXT_MAX ) = { 0 };
624
685
625
686
cpu_node = of_cpu_device_node_get (cpu );
626
687
if (!cpu_node ) {
@@ -640,22 +701,11 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
640
701
ext -> property ) < 0 )
641
702
continue ;
642
703
643
- if (ext -> subset_ext_size ) {
644
- for (int j = 0 ; j < ext -> subset_ext_size ; j ++ ) {
645
- if (riscv_isa_extension_check (ext -> subset_ext_ids [j ]))
646
- set_bit (ext -> subset_ext_ids [j ], isainfo -> isa );
647
- }
648
- }
649
-
650
- if (riscv_isa_extension_check (ext -> id )) {
651
- set_bit (ext -> id , isainfo -> isa );
652
-
653
- /* Only single letter extensions get set in hwcap */
654
- if (strnlen (riscv_isa_ext [i ].name , 2 ) == 1 )
655
- this_hwcap |= isa2hwcap [riscv_isa_ext [i ].id ];
656
- }
704
+ riscv_isa_set_ext (ext , source_isa );
657
705
}
658
706
707
+ riscv_resolve_isa (source_isa , isainfo -> isa , & this_hwcap , isa2hwcap );
708
+
659
709
of_node_put (cpu_node );
660
710
661
711
/*
0 commit comments