summaryrefslogtreecommitdiff
path: root/Kernel/Arch/aarch64/CPUID.cpp
blob: bb2ebbf3ddde90ce68910c85f5aeb252580f7f78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
/*
 * Copyright (c) 2023, Konrad <konrad@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <Kernel/Arch/aarch64/CPUID.h>

namespace Kernel {

CPUFeature::Type detect_cpu_features()
{
    auto features = CPUFeature::Type(0u);
    return features;
}

// https://developer.arm.com/downloads/-/exploration-tools/feature-names-for-a-profile
StringView cpu_feature_to_name(CPUFeature::Type const& feature)
{
    // 2022 Architecture Extensions
    if (feature == CPUFeature::ABLE)
        return "ABLE"sv;
    if (feature == CPUFeature::ADERR)
        return "ADERR"sv;
    if (feature == CPUFeature::ANERR)
        return "ANERR"sv;
    if (feature == CPUFeature::AIE)
        return "AIE"sv;
    if (feature == CPUFeature::B16B16)
        return "B16B16"sv;
    if (feature == CPUFeature::CLRBHB)
        return "CLRBHB"sv;
    if (feature == CPUFeature::CHK)
        return "CHK"sv;
    if (feature == CPUFeature::CSSC)
        return "CSSC"sv;
    if (feature == CPUFeature::CSV2_2)
        return "CSV2_2"sv;
    if (feature == CPUFeature::CSV2_3)
        return "CSV2_3"sv;
    if (feature == CPUFeature::D128)
        return "D128"sv;
    if (feature == CPUFeature::Debugv8p9)
        return "Debugv8p9"sv;
    if (feature == CPUFeature::DoubleFault2)
        return "DoubleFault2"sv;
    if (feature == CPUFeature::EBEP)
        return "EBEP"sv;
    if (feature == CPUFeature::ECBHB)
        return "ECBHB"sv;
    if (feature == CPUFeature::ETEv1p3)
        return "ETEv1p3"sv;
    if (feature == CPUFeature::FGT2)
        return "FGT2"sv;
    if (feature == CPUFeature::GCS)
        return "GCS"sv;
    if (feature == CPUFeature::HAFT)
        return "HAFT"sv;
    if (feature == CPUFeature::ITE)
        return "ITE"sv;
    if (feature == CPUFeature::LRCPC3)
        return "LRCPC3"sv;
    if (feature == CPUFeature::LSE128)
        return "LSE128"sv;
    if (feature == CPUFeature::LVA3)
        return "LVA3"sv;
    if (feature == CPUFeature::MEC)
        return "MEC"sv;
    if (feature == CPUFeature::MTE4)
        return "MTE4"sv;
    if (feature == CPUFeature::MTE_CANONICAL_TAGS)
        return "MTE_CANONICAL_TAGS"sv;
    if (feature == CPUFeature::MTE_TAGGED_FAR)
        return "MTE_TAGGED_FAR"sv;
    if (feature == CPUFeature::MTE_STORE_ONLY)
        return "MTE_STORE_ONLY"sv;
    if (feature == CPUFeature::MTE_NO_ADDRESS_TAGS)
        return "MTE_NO_ADDRESS_TAGS"sv;
    if (feature == CPUFeature::MTE_ASYM_FAULT)
        return "MTE_ASYM_FAULT"sv;
    if (feature == CPUFeature::MTE_ASYNC)
        return "MTE_ASYNC"sv;
    if (feature == CPUFeature::MTE_PERM)
        return "MTE_PERM"sv;
    if (feature == CPUFeature::PCSRv8p9)
        return "PCSRv8p9"sv;
    if (feature == CPUFeature::PIE)
        return "PIE"sv;
    if (feature == CPUFeature::POE)
        return "POE"sv;
    if (feature == CPUFeature::S1PIE)
        return "S1PIE"sv;
    if (feature == CPUFeature::S2PIE)
        return "S2PIE"sv;
    if (feature == CPUFeature::S1POE)
        return "S1POE"sv;
    if (feature == CPUFeature::S2POE)
        return "S2POE"sv;
    if (feature == CPUFeature::PMUv3p9)
        return "PMUv3p9"sv;
    if (feature == CPUFeature::PMUv3_EDGE)
        return "PMUv3_EDGE"sv;
    if (feature == CPUFeature::PMUv3_ICNTR)
        return "PMUv3_ICNTR"sv;
    if (feature == CPUFeature::PMUv3_SS)
        return "PMUv3_SS"sv;
    if (feature == CPUFeature::PRFMSLC)
        return "PRFMSLC"sv;
    if (feature == CPUFeature::PFAR)
        return "PFAR"sv;
    if (feature == CPUFeature::RASv2)
        return "RASv2"sv;
    if (feature == CPUFeature::RPZ)
        return "RPZ"sv;
    if (feature == CPUFeature::RPRFM)
        return "RPRFM"sv;
    if (feature == CPUFeature::SCTLR2)
        return "SCTLR2"sv;
    if (feature == CPUFeature::SEBEP)
        return "SEBEP"sv;
    if (feature == CPUFeature::SME_F16F16)
        return "SME_F16F16"sv;
    if (feature == CPUFeature::SME2)
        return "SME2"sv;
    if (feature == CPUFeature::SME2p1)
        return "SME2p1"sv;
    if (feature == CPUFeature::SPECRES2)
        return "SPECRES2"sv;
    if (feature == CPUFeature::SPMU)
        return "SPMU"sv;
    if (feature == CPUFeature::SPEv1p4)
        return "SPEv1p4"sv;
    if (feature == CPUFeature::SPE_FDS)
        return "SPE_FDS"sv;
    if (feature == CPUFeature::SVE2p1)
        return "SVE2p1"sv;
    if (feature == CPUFeature::SYSINSTR128)
        return "SYSINSTR128"sv;
    if (feature == CPUFeature::SYSREG128)
        return "SYSREG128"sv;
    if (feature == CPUFeature::TCR2)
        return "TCR2"sv;
    if (feature == CPUFeature::THE)
        return "THE"sv;
    if (feature == CPUFeature::TRBE_EXT)
        return "TRBE_EXT"sv;
    if (feature == CPUFeature::TRBE_MPAM)
        return "TRBE_MPAM"sv;

    // 2021 Architecture Extensions
    if (feature == CPUFeature::CMOW)
        return "CMOW"sv;
    if (feature == CPUFeature::CONSTPACFIELD)
        return "CONSTPACFIELD"sv;
    if (feature == CPUFeature::Debugv8p8)
        return "Debugv8p8"sv;
    if (feature == CPUFeature::HBC)
        return "HBC"sv;
    if (feature == CPUFeature::HPMN0)
        return "HPMN0"sv;
    if (feature == CPUFeature::NMI)
        return "NMI"sv;
    if (feature == CPUFeature::GICv3_NMI)
        return "GICv3_NMI"sv;
    if (feature == CPUFeature::MOPS)
        return "MOPS"sv;
    if (feature == CPUFeature::PACQARMA3)
        return "PACQARMA3"sv;
    if (feature == CPUFeature::PMUv3_TH)
        return "PMUv3_TH"sv;
    if (feature == CPUFeature::PMUv3p8)
        return "PMUv3p8"sv;
    if (feature == CPUFeature::PMUv3_EXT64)
        return "PMUv3_EXT64"sv;
    if (feature == CPUFeature::PMUv3_EXT32)
        return "PMUv3_EXT32"sv;
    if (feature == CPUFeature::RNG_TRAP)
        return "RNG_TRAP"sv;
    if (feature == CPUFeature::SPEv1p3)
        return "SPEv1p3"sv;
    if (feature == CPUFeature::TIDCP1)
        return "TIDCP1"sv;
    if (feature == CPUFeature::BRBEv1p1)
        return "BRBEv1p1"sv;

    // 2020 Architecture Extensions
    if (feature == CPUFeature::AFP)
        return "AFP"sv;
    if (feature == CPUFeature::HCX)
        return "HCX"sv;
    if (feature == CPUFeature::LPA2)
        return "LPA2"sv;
    if (feature == CPUFeature::LS64)
        return "LS64"sv;
    if (feature == CPUFeature::LS64_V)
        return "LS64_V"sv;
    if (feature == CPUFeature::LS64_ACCDATA)
        return "LS64_ACCDATA"sv;
    if (feature == CPUFeature::MTE3)
        return "MTE3"sv;
    if (feature == CPUFeature::PAN3)
        return "PAN3"sv;
    if (feature == CPUFeature::PMUv3p7)
        return "PMUv3p7"sv;
    if (feature == CPUFeature::RPRES)
        return "RPRES"sv;
    if (feature == CPUFeature::RME)
        return "RME"sv;
    if (feature == CPUFeature::SME_FA64)
        return "SME_FA64"sv;
    if (feature == CPUFeature::SME_F64F64)
        return "SME_F64F64"sv;
    if (feature == CPUFeature::SME_I16I64)
        return "SME_I16I64"sv;
    if (feature == CPUFeature::EBF16)
        return "EBF16"sv;
    if (feature == CPUFeature::SPEv1p2)
        return "SPEv1p2"sv;
    if (feature == CPUFeature::WFxT)
        return "WFxT"sv;
    if (feature == CPUFeature::XS)
        return "XS"sv;
    if (feature == CPUFeature::BRBE)
        return "BRBE"sv;

    // Features introduced prior to 2020
    if (feature == CPUFeature::AdvSIMD)
        return "AdvSIMD"sv;
    if (feature == CPUFeature::AES)
        return "AES"sv;
    if (feature == CPUFeature::PMULL)
        return "PMULL"sv;
    if (feature == CPUFeature::CP15SDISABLE2)
        return "CP15SDISABLE2"sv;
    if (feature == CPUFeature::CSV2)
        return "CSV2"sv;
    if (feature == CPUFeature::CSV2_1p1)
        return "CSV2_1p1"sv;
    if (feature == CPUFeature::CSV2_1p2)
        return "CSV2_1p2"sv;
    if (feature == CPUFeature::CSV2)
        return "CSV2"sv;
    if (feature == CPUFeature::CSV3)
        return "CSV3"sv;
    if (feature == CPUFeature::DGH)
        return "DGH"sv;
    if (feature == CPUFeature::DoubleLock)
        return "DoubleLock"sv;
    if (feature == CPUFeature::ETS)
        return "ETS"sv;
    if (feature == CPUFeature::FP)
        return "FP"sv;
    if (feature == CPUFeature::IVIPT)
        return "IVIPT"sv;
    if (feature == CPUFeature::PCSRv8)
        return "PCSRv8"sv;
    if (feature == CPUFeature::SPECRES)
        return "SPECRES"sv;
    if (feature == CPUFeature::RAS)
        return "RAS"sv;
    if (feature == CPUFeature::SB)
        return "SB"sv;
    if (feature == CPUFeature::SHA1)
        return "SHA1"sv;
    if (feature == CPUFeature::SHA256)
        return "SHA256"sv;
    if (feature == CPUFeature::SSBS)
        return "SSBS2"sv;
    if (feature == CPUFeature::SSBS2)
        return "SSBS2"sv;
    if (feature == CPUFeature::CRC32)
        return "CRC32"sv;
    if (feature == CPUFeature::nTLBPA)
        return "nTLBPA"sv;
    if (feature == CPUFeature::Debugv8p1)
        return "Debugv8p1"sv;
    if (feature == CPUFeature::HPDS)
        return "HPDS"sv;
    if (feature == CPUFeature::LOR)
        return "LOR"sv;
    if (feature == CPUFeature::LSE)
        return "LSE"sv;
    if (feature == CPUFeature::PAN)
        return "PAN"sv;
    if (feature == CPUFeature::PMUv3p1)
        return "PMUv3p1"sv;
    if (feature == CPUFeature::RDM)
        return "RDM"sv;
    if (feature == CPUFeature::HAFDBS)
        return "HAFDBS"sv;
    if (feature == CPUFeature::VHE)
        return "VHE"sv;
    if (feature == CPUFeature::VMID16)
        return "VMID16"sv;
    if (feature == CPUFeature::AA32BF16)
        return "AA32BF16"sv;
    if (feature == CPUFeature::AA32HPD)
        return "AA32HPD"sv;
    if (feature == CPUFeature::AA32I8MM)
        return "AA32I8MM"sv;
    if (feature == CPUFeature::PAN2)
        return "PAN2"sv;
    if (feature == CPUFeature::BF16)
        return "BF16"sv;
    if (feature == CPUFeature::DPB2)
        return "DPB2"sv;
    if (feature == CPUFeature::DPB)
        return "DPB"sv;
    if (feature == CPUFeature::Debugv8p2)
        return "Debugv8p2"sv;
    if (feature == CPUFeature::DotProd)
        return "DotProd"sv;
    if (feature == CPUFeature::EVT)
        return "EVT"sv;
    if (feature == CPUFeature::F32MM)
        return "F32MM"sv;
    if (feature == CPUFeature::F64MM)
        return "F64MM"sv;
    if (feature == CPUFeature::FHM)
        return "FHM"sv;
    if (feature == CPUFeature::FP16)
        return "FP16"sv;
    if (feature == CPUFeature::I8MM)
        return "I8MM"sv;
    if (feature == CPUFeature::IESB)
        return "IESB"sv;
    if (feature == CPUFeature::LPA)
        return "LPA"sv;
    if (feature == CPUFeature::LSMAOC)
        return "LSMAOC"sv;
    if (feature == CPUFeature::LVA)
        return "LVA"sv;
    if (feature == CPUFeature::MPAM)
        return "MPAM"sv;
    if (feature == CPUFeature::PCSRv8p2)
        return "PCSRv8p2"sv;
    if (feature == CPUFeature::SHA3)
        return "SHA3"sv;
    if (feature == CPUFeature::SHA512)
        return "SHA512"sv;
    if (feature == CPUFeature::SM3)
        return "SM3"sv;
    if (feature == CPUFeature::SM4)
        return "SM4"sv;
    if (feature == CPUFeature::SPE)
        return "SPE"sv;
    if (feature == CPUFeature::SVE)
        return "SVE"sv;
    if (feature == CPUFeature::TTCNP)
        return "TTCNP"sv;
    if (feature == CPUFeature::HPDS2)
        return "HPDS2"sv;
    if (feature == CPUFeature::XNX)
        return "XNX"sv;
    if (feature == CPUFeature::UAO)
        return "UAO"sv;
    if (feature == CPUFeature::VPIPT)
        return "VPIPT"sv;
    if (feature == CPUFeature::CCIDX)
        return "CCIDX"sv;
    if (feature == CPUFeature::FCMA)
        return "FCMA"sv;
    if (feature == CPUFeature::DoPD)
        return "DoPD"sv;
    if (feature == CPUFeature::EPAC)
        return "EPAC"sv;
    if (feature == CPUFeature::FPAC)
        return "FPAC"sv;
    if (feature == CPUFeature::FPACCOMBINE)
        return "FPACCOMBINE"sv;
    if (feature == CPUFeature::JSCVT)
        return "JSCVT"sv;
    if (feature == CPUFeature::LRCPC)
        return "LRCPC"sv;
    if (feature == CPUFeature::NV)
        return "NV"sv;
    if (feature == CPUFeature::PACQARMA5)
        return "PACQARMA5"sv;
    if (feature == CPUFeature::PACIMP)
        return "PACIMP"sv;
    if (feature == CPUFeature::PAuth)
        return "PAuth"sv;
    if (feature == CPUFeature::PAuth2)
        return "PAuth2"sv;
    if (feature == CPUFeature::SPEv1p1)
        return "SPEv1p1"sv;
    if (feature == CPUFeature::AMUv1)
        return "AMUv1"sv;
    if (feature == CPUFeature::CNTSC)
        return "CNTSC"sv;
    if (feature == CPUFeature::Debugv8p4)
        return "Debugv8p4"sv;
    if (feature == CPUFeature::DoubleFault)
        return "DoubleFault"sv;
    if (feature == CPUFeature::DIT)
        return "DIT"sv;
    if (feature == CPUFeature::FlagM)
        return "FlagM"sv;
    if (feature == CPUFeature::IDST)
        return "IDST"sv;
    if (feature == CPUFeature::LRCPC2)
        return "LRCPC2"sv;
    if (feature == CPUFeature::LSE2)
        return "LSE2"sv;
    if (feature == CPUFeature::NV2)
        return "NV2"sv;
    if (feature == CPUFeature::PMUv3p4)
        return "PMUv3p4"sv;
    if (feature == CPUFeature::RASv1p1)
        return "RASv1p1"sv;
    if (feature == CPUFeature::S2FWB)
        return "S2FWB"sv;
    if (feature == CPUFeature::SEL2)
        return "SEL2"sv;
    if (feature == CPUFeature::TLBIOS)
        return "TLBIOS"sv;
    if (feature == CPUFeature::TLBIRANGE)
        return "TLBIRANGE"sv;
    if (feature == CPUFeature::TRF)
        return "TRF"sv;
    if (feature == CPUFeature::TTL)
        return "TTL"sv;
    if (feature == CPUFeature::BBM)
        return "BBM"sv;
    if (feature == CPUFeature::TTST)
        return "TTST"sv;
    if (feature == CPUFeature::BTI)
        return "BTI"sv;
    if (feature == CPUFeature::FlagM2)
        return "FlagM2"sv;
    if (feature == CPUFeature::ExS)
        return "ExS"sv;
    if (feature == CPUFeature::E0PD)
        return "E0PD"sv;
    if (feature == CPUFeature::FRINTTS)
        return "FRINTTS"sv;
    if (feature == CPUFeature::GTG)
        return "GTG"sv;
    if (feature == CPUFeature::MTE)
        return "MTE"sv;
    if (feature == CPUFeature::MTE2)
        return "MTE2"sv;
    if (feature == CPUFeature::PMUv3p5)
        return "PMUv3p5"sv;
    if (feature == CPUFeature::RNG)
        return "RNG"sv;
    if (feature == CPUFeature::AMUv1p1)
        return "AMUv1p1"sv;
    if (feature == CPUFeature::ECV)
        return "ECV"sv;
    if (feature == CPUFeature::FGT)
        return "FGT"sv;
    if (feature == CPUFeature::MPAMv0p1)
        return "MPAMv0p1"sv;
    if (feature == CPUFeature::MPAMv1p1)
        return "MPAMv1p1"sv;
    if (feature == CPUFeature::MTPMU)
        return "MTPMU"sv;
    if (feature == CPUFeature::TWED)
        return "TWED"sv;
    if (feature == CPUFeature::ETMv4)
        return "ETMv4"sv;
    if (feature == CPUFeature::ETMv4p1)
        return "ETMv4p1"sv;
    if (feature == CPUFeature::ETMv4p2)
        return "ETMv4p2"sv;
    if (feature == CPUFeature::ETMv4p3)
        return "ETMv4p3"sv;
    if (feature == CPUFeature::ETMv4p4)
        return "ETMv4p4"sv;
    if (feature == CPUFeature::ETMv4p5)
        return "ETMv4p5"sv;
    if (feature == CPUFeature::ETMv4p6)
        return "ETMv4p6"sv;
    if (feature == CPUFeature::GICv3)
        return "GICv3"sv;
    if (feature == CPUFeature::GICv3p1)
        return "GICv3p1"sv;
    if (feature == CPUFeature::GICv3_LEGACY)
        return "GICv3_LEGACY"sv;
    if (feature == CPUFeature::GICv3_TDIR)
        return "GICv3_TDIR"sv;
    if (feature == CPUFeature::GICv4)
        return "GICv4"sv;
    if (feature == CPUFeature::GICv4p1)
        return "GICv4p1"sv;
    if (feature == CPUFeature::PMUv3)
        return "PMUv3"sv;
    if (feature == CPUFeature::ETE)
        return "ETE"sv;
    if (feature == CPUFeature::ETEv1p1)
        return "ETEv1p1"sv;
    if (feature == CPUFeature::SVE2)
        return "SVE2"sv;
    if (feature == CPUFeature::SVE_AES)
        return "SVE_AES"sv;
    if (feature == CPUFeature::SVE_PMULL128)
        return "SVE_PMULL128"sv;
    if (feature == CPUFeature::SVE_BitPerm)
        return "SVE_BitPerm"sv;
    if (feature == CPUFeature::SVE_SHA3)
        return "SVE_SHA3"sv;
    if (feature == CPUFeature::SVE_SM4)
        return "SVE_SM4"sv;
    if (feature == CPUFeature::TME)
        return "TME"sv;
    if (feature == CPUFeature::TRBE)
        return "TRBE"sv;
    if (feature == CPUFeature::SME)
        return "SME"sv;

    VERIFY_NOT_REACHED();
}

// https://developer.arm.com/downloads/-/exploration-tools/feature-names-for-a-profile
StringView cpu_feature_to_description(CPUFeature::Type const& feature)
{
    // 2022 Architecture Extensions
    if (feature == CPUFeature::ABLE)
        return "Address Breakpoint Linking extension"sv;
    if (feature == CPUFeature::ADERR)
        return "RASv2 Additional Error syndrome reporting, for Device memory"sv;
    if (feature == CPUFeature::ANERR)
        return "RASv2 Additional Error syndrome reporting, for Normal memory"sv;
    if (feature == CPUFeature::AIE)
        return "Memory Attribute Index Enhancement"sv;
    if (feature == CPUFeature::B16B16)
        return "Non-widening BFloat16 to BFloat16 arithmetic for SVE2.1 and SME2.1"sv;
    if (feature == CPUFeature::CLRBHB)
        return "A new instruction CLRBHB is added in HINT space"sv;
    if (feature == CPUFeature::CHK)
        return "Detect when Guarded Control Stacks are implemented"sv;
    if (feature == CPUFeature::CSSC)
        return "Common Short Sequence Compression scalar integer instructions"sv;
    if (feature == CPUFeature::CSV2_3)
        return "New identification mechanism for Branch History information"sv;
    if (feature == CPUFeature::D128)
        return "128-bit Translation Tables, 56 bit PA"sv;
    if (feature == CPUFeature::Debugv8p9)
        return "Debug 2022"sv;
    if (feature == CPUFeature::DoubleFault2)
        return "Error exception routing extensions"sv; // NOTE: removed trailing dot compared to source!
    if (feature == CPUFeature::EBEP)
        return "Exception-based event profiling"sv;
    if (feature == CPUFeature::ECBHB)
        return "Imposes restrictions on branch history speculation around exceptions"sv;
    if (feature == CPUFeature::ETEv1p3)
        return "ETE support for v9.3"sv;
    if (feature == CPUFeature::FGT2)
        return "Fine-grained traps 2"sv;
    if (feature == CPUFeature::GCS)
        return "Guarded Control Stack Extension"sv;
    if (feature == CPUFeature::HAFT)
        return "Hardware managed Access Flag for Table descriptors"sv;
    if (feature == CPUFeature::ITE)
        return "Instrumentation trace extension"sv;
    if (feature == CPUFeature::LRCPC3)
        return "Load-Acquire RCpc instructions version 3"sv;
    if (feature == CPUFeature::LSE128)
        return "128-bit Atomics"sv;
    if (feature == CPUFeature::LVA3)
        return "56-bit VA"sv;
    if (feature == CPUFeature::MEC)
        return "Memory Encryption Contexts"sv;
    if (feature == CPUFeature::MTE4)
        return "Support for Canonical tag checking, reporting of all non-address bits on a fault, Store-only Tag checking, Memory tagging with Address tagging disabled"sv;
    if (feature == CPUFeature::MTE_CANONICAL_TAGS)
        return "Support for Canonical tag checking"sv;
    if (feature == CPUFeature::MTE_TAGGED_FAR)
        return "Support for reporting of all non-address bits on a fault"sv;
    if (feature == CPUFeature::MTE_STORE_ONLY)
        return "Support for Store-only Tag checking"sv;
    if (feature == CPUFeature::MTE_NO_ADDRESS_TAGS)
        return "Support for Memory tagging with Address tagging disabled"sv;
    if (feature == CPUFeature::MTE_ASYM_FAULT)
        return "Asymmetric Tag Check Fault handling"sv;
    if (feature == CPUFeature::MTE_ASYNC)
        return "Asynchronous Tag Check Fault handling"sv;
    if (feature == CPUFeature::MTE_PERM)
        return "Allocation tag access permission"sv;
    if (feature == CPUFeature::PCSRv8p9)
        return "PCSR disable control"sv;
    if (feature == CPUFeature::PIE)
        return "Permission model enhancements"sv;
    if (feature == CPUFeature::POE)
        return "Permission model enhancements"sv;
    if (feature == CPUFeature::S1PIE)
        return "Permission model enhancements"sv;
    if (feature == CPUFeature::S2PIE)
        return "Permission model enhancements"sv;
    if (feature == CPUFeature::S1POE)
        return "Permission model enhancements"sv;
    if (feature == CPUFeature::S2POE)
        return "Permission model enhancements"sv;
    if (feature == CPUFeature::PMUv3p9)
        return "EL0 access controls for PMU event counters"sv;
    if (feature == CPUFeature::PMUv3_EDGE)
        return "PMU event edge detection"sv;
    if (feature == CPUFeature::PMUv3_ICNTR)
        return "PMU instruction counter"sv;
    if (feature == CPUFeature::PMUv3_SS)
        return "PMU snapshot"sv;
    if (feature == CPUFeature::PRFMSLC)
        return "Prefetching enhancements"sv;
    if (feature == CPUFeature::PFAR)
        // https://developer.arm.com/documentation/ddi0602/2022-12/Shared-Pseudocode/Shared-Functions?lang=en
        // Library pseudocode for shared/functions/extension/HavePFAR
        return "Physical Fault Address Extension (RASv2)"sv;
    if (feature == CPUFeature::RASv2)
        return "Reliability, Availability, and Serviceability (RAS) Extension version 2"sv;
    if (feature == CPUFeature::RPZ)
        return "RPZ (RASv2)"sv; // Note: not really known
    if (feature == CPUFeature::RPRFM)
        return "RPRFM range prefetch hint instruction"sv;
    if (feature == CPUFeature::SCTLR2)
        return "Extension to SCTLR_ELx"sv;
    if (feature == CPUFeature::SEBEP)
        return "Synchronous Exception-based event profiling"sv;
    if (feature == CPUFeature::SME_F16F16)
        return "Non-widening half-precision FP16 to FP16 arithmetic for SME2.1"sv;
    if (feature == CPUFeature::SME2)
        return "Scalable Matrix Extension version 2"sv;
    if (feature == CPUFeature::SME2p1)
        return "Scalable Matrix Extension version 2.1"sv;
    if (feature == CPUFeature::SPECRES2)
        return "Adds new Clear Other Speculative Predictions instruction"sv;
    if (feature == CPUFeature::SPMU)
        return "System PMU"sv;
    if (feature == CPUFeature::SPEv1p4)
        return "Additional SPE events"sv;
    if (feature == CPUFeature::SPE_FDS)
        return "SPE filtering by data source"sv;
    if (feature == CPUFeature::SVE2p1)
        return "Scalable Vector Extension version SVE2.1"sv;
    if (feature == CPUFeature::SYSINSTR128)
        return "128-bit System instructions"sv;
    if (feature == CPUFeature::SYSREG128)
        return "128-bit System registers"sv;
    if (feature == CPUFeature::TCR2)
        return "Extension to TCR_ELx"sv;
    if (feature == CPUFeature::THE)
        return "Translation Hardening Extension"sv;
    if (feature == CPUFeature::TRBE_EXT)
        return "Represents TRBE external mode"sv;
    if (feature == CPUFeature::TRBE_MPAM)
        return "Trace Buffer MPAM extensions"sv;

    // 2021 Architecture Extensions
    if (feature == CPUFeature::CMOW)
        return "Control for cache maintenance permission"sv;
    if (feature == CPUFeature::CONSTPACFIELD)
        return "PAC Algorithm enhancement"sv;
    if (feature == CPUFeature::Debugv8p8)
        return "Debug v8.8"sv;
    if (feature == CPUFeature::HBC)
        return "Hinted conditional branches"sv;
    if (feature == CPUFeature::HPMN0)
        return "Setting of MDCR_EL2.HPMN to zero"sv;
    if (feature == CPUFeature::NMI)
        return "Non-maskable Interrupts"sv;
    if (feature == CPUFeature::GICv3_NMI)
        return "Non-maskable Interrupts"sv;
    if (feature == CPUFeature::MOPS)
        return "Standardization of memory operations"sv;
    if (feature == CPUFeature::PACQARMA3)
        return "Pointer authentication - QARMA3 algorithm"sv;
    if (feature == CPUFeature::PMUv3_TH)
        return "Event counting threshold"sv;
    if (feature == CPUFeature::PMUv3p8)
        return "Armv8.8 PMU Extensions"sv;
    if (feature == CPUFeature::PMUv3_EXT64)
        return "Optional 64-bit external interface to the Performance Monitors"sv;
    if (feature == CPUFeature::PMUv3_EXT32)
        return "Represents the original mostly 32-bit external interface to the Performance Monitors"sv;
    if (feature == CPUFeature::RNG_TRAP)
        return "Trapping support for RNDR and RNDRRS"sv;
    if (feature == CPUFeature::SPEv1p3)
        return "Armv8.8 Statistical Profiling Extensions"sv;
    if (feature == CPUFeature::TIDCP1)
        return "EL0 use of IMPLEMENTATION DEFINED functionality"sv;
    if (feature == CPUFeature::BRBEv1p1)
        return "Branch Record Buffer Extensions version 1.1"sv;

    // 2020 Architecture Extensions
    if (feature == CPUFeature::AFP)
        return "Alternate floating-point behavior"sv;
    if (feature == CPUFeature::HCX)
        return "Support for the HCRX_EL2 register"sv;
    if (feature == CPUFeature::LPA2)
        return "Larger physical address for 4KB and 16KB translation granules"sv;
    if (feature == CPUFeature::LS64)
        return "Support for 64 byte loads/stores without return"sv;
    if (feature == CPUFeature::LS64_V)
        return "Support for 64-byte stores with return"sv;
    if (feature == CPUFeature::LS64_ACCDATA)
        return "Support for 64-byte EL0 stores with return"sv;
    if (feature == CPUFeature::MTE3)
        return "MTE Asymmetric Fault Handling"sv;
    if (feature == CPUFeature::PAN3)
        return "Support for SCTLR_ELx.EPAN"sv;
    if (feature == CPUFeature::PMUv3p7)
        return "Armv8.7 PMU Extensions"sv;
    if (feature == CPUFeature::RPRES)
        return "Increased precision of Reciprocal Estimate and Reciprocal Square Root Estimate"sv;
    if (feature == CPUFeature::RME)
        return "Realm Management Extension"sv;
    if (feature == CPUFeature::SME_FA64)
        return "Additional instructions for the SME Extension"sv;
    if (feature == CPUFeature::SME_F64F64)
        return "Additional instructions for the SME Extension"sv;
    if (feature == CPUFeature::SME_I16I64)
        return "Additional instructions for the SME Extension"sv;
    if (feature == CPUFeature::EBF16)
        return "Additional instructions for the SME Extension"sv;
    if (feature == CPUFeature::SPEv1p2)
        return "Armv8.7 SPE"sv;
    if (feature == CPUFeature::WFxT)
        return "WFE and WFI instructions with timeout"sv;
    if (feature == CPUFeature::XS)
        return "XS attribute"sv;
    if (feature == CPUFeature::BRBE)
        return "Branch Record Buffer Extensions"sv;

    // Features introduced prior to 2020
    if (feature == CPUFeature::AdvSIMD)
        return "Advanced SIMD Extension"sv;
    if (feature == CPUFeature::AES)
        return "Advanced SIMD AES instructions"sv;
    if (feature == CPUFeature::PMULL)
        return "Advanced SIMD PMULL instructions"sv; // ARMv8.0-AES is split into AES and PMULL
    if (feature == CPUFeature::CP15SDISABLE2)
        return "CP15DISABLE2"sv;
    if (feature == CPUFeature::CSV2)
        return "Cache Speculation Variant 2"sv;
    if (feature == CPUFeature::CSV2_1p1)
        return "Cache Speculation Variant 2 version 1.1"sv;
    if (feature == CPUFeature::CSV2_1p2)
        return "Cache Speculation Variant 2 version 1.2"sv;
    if (feature == CPUFeature::CSV2_2)
        return "Cache Speculation Variant 2 version 2"sv; // NOTE: name mistake in source!
    if (feature == CPUFeature::CSV3)
        return "Cache Speculation Variant 3"sv;
    if (feature == CPUFeature::DGH)
        return "Data Gathering Hint"sv;
    if (feature == CPUFeature::DoubleLock)
        return "Double Lock"sv;
    if (feature == CPUFeature::ETS)
        return "Enhanced Translation Synchronization"sv;
    if (feature == CPUFeature::FP)
        return "Floating point extension"sv;
    if (feature == CPUFeature::IVIPT)
        return "The IVIPT Extension"sv;
    if (feature == CPUFeature::PCSRv8)
        return "PC Sample-base Profiling extension (not EL3 and EL2)"sv;
    if (feature == CPUFeature::SPECRES)
        return "Speculation restriction instructions"sv;
    if (feature == CPUFeature::RAS)
        return "Reliability, Availability, and Serviceability (RAS) Extension"sv;
    if (feature == CPUFeature::SB)
        return "Speculation barrier"sv;
    if (feature == CPUFeature::SHA1)
        return "Advanced SIMD SHA1 instructions"sv;
    if (feature == CPUFeature::SHA256)
        return "Advanced SIMD SHA256 instructions"sv; // ARMv8.2-SHA is split into SHA-256, SHA-512 and SHA-3
    if (feature == CPUFeature::SSBS)
        return "Speculative Store Bypass Safe Instruction"sv; // ARMv8.0-SSBS is split into SSBS and SSBS2
    if (feature == CPUFeature::SSBS2)
        return "MRS and MSR instructions for SSBS"sv; // ARMv8.0-SSBS is split into SSBS and SSBS2
    if (feature == CPUFeature::CRC32)
        return "CRC32 instructions"sv;
    if (feature == CPUFeature::nTLBPA)
        return "No intermediate caching by output address in TLB"sv;
    if (feature == CPUFeature::Debugv8p1)
        return "Debug with VHE"sv;
    if (feature == CPUFeature::HPDS)
        return "Hierarchical permission disables in translation tables"sv;
    if (feature == CPUFeature::LOR)
        return "Limited ordering regions"sv;
    if (feature == CPUFeature::LSE)
        return "Large System Extensions"sv;
    if (feature == CPUFeature::PAN)
        return "Privileged access-never"sv;
    if (feature == CPUFeature::PMUv3p1)
        return "PMU extensions version 3.1"sv;
    if (feature == CPUFeature::RDM)
        return "Rounding double multiply accumulate"sv;
    if (feature == CPUFeature::HAFDBS)
        return "Hardware updates to access flag and dirty state in translation tables"sv;
    if (feature == CPUFeature::VHE)
        return "Virtualization Host Extensions"sv;
    if (feature == CPUFeature::VMID16)
        return "16-bit VMID"sv;
    if (feature == CPUFeature::AA32BF16)
        return "AArch32 BFloat16 instructions"sv;
    if (feature == CPUFeature::AA32HPD)
        return "AArch32 Hierarchical permission disables"sv;
    if (feature == CPUFeature::AA32I8MM)
        return "AArch32 Int8 Matrix Multiplication"sv;
    if (feature == CPUFeature::PAN2)
        return "AT S1E1R and AT S1E1W instruction variants for PAN"sv;
    if (feature == CPUFeature::BF16)
        return "AArch64 BFloat16 instructions"sv; // NOTE: typo in source!
    if (feature == CPUFeature::DPB2)
        return "DC CVADP instruction"sv;
    if (feature == CPUFeature::DPB)
        return "DC CVAP instruction"sv;
    if (feature == CPUFeature::Debugv8p2)
        return "ARMv8.2 Debug"sv;
    if (feature == CPUFeature::DotProd)
        return "Advanced SIMD Int8 dot product instructions"sv;
    if (feature == CPUFeature::EVT)
        return "Enhanced Virtualization Traps"sv;
    if (feature == CPUFeature::F32MM)
        return "SVE single-precision floating-point matrix multiply instruction"sv;
    if (feature == CPUFeature::F64MM)
        return "SVE double-precision floating-point matrix multiply instruction"sv;
    if (feature == CPUFeature::FHM)
        return "Half-precision floating-point FMLAL instructions"sv;
    if (feature == CPUFeature::FP16)
        return "Half-precision floating-point data processing"sv;
    if (feature == CPUFeature::I8MM)
        return "Int8 Matrix Multiplication"sv;
    if (feature == CPUFeature::IESB)
        return "Implicit Error synchronization event"sv;
    if (feature == CPUFeature::LPA)
        return "Large PA and IPA support"sv;
    if (feature == CPUFeature::LSMAOC)
        return "Load/Store instruction multiple atomicity and ordering controls"sv;
    if (feature == CPUFeature::LVA)
        return "Large VA support"sv;
    if (feature == CPUFeature::MPAM)
        return "Memory Partitioning and Monitoring"sv;
    if (feature == CPUFeature::PCSRv8p2)
        return "PC Sample-based profiling version 8.2"sv;
    if (feature == CPUFeature::SHA3)
        return "Advanced SIMD EOR3, RAX1, XAR, and BCAX instructions"sv; // ARMv8.2-SHA is split into SHA-256, SHA-512 and SHA-3
    if (feature == CPUFeature::SHA512)
        return "Advanced SIMD SHA512 instructions"sv; // ARMv8.2-SHA is split into SHA-256, SHA-512 and SHA-3
    if (feature == CPUFeature::SM3)
        return "Advanced SIMD SM3 instructions"sv; // Split into SM3 and SM4
    if (feature == CPUFeature::SM4)
        return "Advanced SIMD SM4 instructions"sv; // Split into SM3 and SM4
    if (feature == CPUFeature::SPE)
        return "Statistical Profiling Extension"sv;
    if (feature == CPUFeature::SVE)
        return "Scalable Vector Extension"sv;
    if (feature == CPUFeature::TTCNP)
        return "Common not private translations"sv;
    if (feature == CPUFeature::HPDS2)
        return "Heirarchical permission disables in translation tables 2"sv;
    if (feature == CPUFeature::XNX)
        return "Execute-never control distinction by Exception level at stage 2"sv;
    if (feature == CPUFeature::UAO)
        return "Unprivileged Access Override control"sv;
    if (feature == CPUFeature::VPIPT)
        return "VMID-aware PIPT instruction cache"sv;
    if (feature == CPUFeature::CCIDX)
        return "Extended cache index"sv;
    if (feature == CPUFeature::FCMA)
        return "Floating-point FCMLA and FCADD instructions"sv;
    if (feature == CPUFeature::DoPD)
        return "Debug over Powerdown"sv;
    if (feature == CPUFeature::EPAC)
        return "Enhanced Pointer authentication"sv;
    if (feature == CPUFeature::FPAC)
        return "Faulting on pointer authentication instructions"sv;
    if (feature == CPUFeature::FPACCOMBINE)
        return "Faulting on combined pointer authentication instructions"sv;
    if (feature == CPUFeature::JSCVT)
        return "JavaScript FJCVTS conversion instruction"sv;
    if (feature == CPUFeature::LRCPC)
        return "Load-acquire RCpc instructions"sv;
    if (feature == CPUFeature::NV)
        return "Nested virtualization"sv;
    if (feature == CPUFeature::PACQARMA5)
        return "Pointer authentication - QARMA5 algorithm"sv;
    if (feature == CPUFeature::PACIMP)
        return "Pointer authentication - IMPLEMENTATION DEFINED algorithm"sv;
    if (feature == CPUFeature::PAuth)
        return "Pointer authentication"sv;
    if (feature == CPUFeature::PAuth2)
        return "Enhancements to pointer authentication"sv;
    if (feature == CPUFeature::SPEv1p1)
        return "Statistical Profiling Extensions version 1.1"sv;
    if (feature == CPUFeature::AMUv1)
        return "Activity Monitors Extension"sv;
    if (feature == CPUFeature::CNTSC)
        return "Generic Counter Scaling"sv;
    if (feature == CPUFeature::Debugv8p4)
        return "Debug relaxations and extensions version 8.4"sv;
    if (feature == CPUFeature::DoubleFault)
        return "Double Fault Extension"sv;
    if (feature == CPUFeature::DIT)
        return "Data Independent Timing instructions"sv;
    if (feature == CPUFeature::FlagM)
        return "Condition flag manipulation"sv;
    if (feature == CPUFeature::IDST)
        return "ID space trap handling"sv;
    if (feature == CPUFeature::LRCPC2)
        return "Load-acquire RCpc instructions version 2"sv;
    if (feature == CPUFeature::LSE2)
        return "Large System Extensions version 2"sv;
    if (feature == CPUFeature::NV2)
        return "Enhanced support for nested virtualization"sv;
    if (feature == CPUFeature::PMUv3p4)
        return "PMU extension version 3.4"sv;
    if (feature == CPUFeature::RASv1p1)
        return "Reliability, Availability, and Serviceability (RAS) Extension version 1.1"sv;
    if (feature == CPUFeature::S2FWB)
        return "Stage 2 forced write-back"sv;
    if (feature == CPUFeature::SEL2)
        return "Secure EL2"sv;
    if (feature == CPUFeature::TLBIOS)
        return "TLB invalidate outer-shared instructions"sv; // Split into TLBIOS and TLBIRANGE
    if (feature == CPUFeature::TLBIRANGE)
        return "TLB range invalidate range instructions"sv; // Split into TLBIOS and TLBIRANGE
    if (feature == CPUFeature::TRF)
        return "Self hosted Trace Extensions"sv;
    if (feature == CPUFeature::TTL)
        return "Translation Table Level"sv;
    if (feature == CPUFeature::BBM)
        return "Translation table break before make levels"sv;
    if (feature == CPUFeature::TTST)
        return "Small translation tables"sv;
    if (feature == CPUFeature::BTI)
        return "Branch target identification"sv;
    if (feature == CPUFeature::FlagM2)
        return "Condition flag manipulation version 2"sv;
    if (feature == CPUFeature::ExS)
        return "Disabling context synchronizing exception entry and exit"sv;
    if (feature == CPUFeature::E0PD)
        return "Preventing EL0 access to halves of address maps"sv;
    if (feature == CPUFeature::FRINTTS)
        return "FRINT32Z, FRINT32X, FRINT64Z, and FRINT64X instructions"sv;
    if (feature == CPUFeature::GTG)
        return "Guest translation granule size"sv;
    if (feature == CPUFeature::MTE)
        return "Instruction-only Memory Tagging Extension"sv;
    if (feature == CPUFeature::MTE2)
        return "Full Memory Tagging Extension"sv;
    if (feature == CPUFeature::PMUv3p5)
        return "PMU Extension version 3.5"sv;
    if (feature == CPUFeature::RNG)
        return "Random number generator"sv;
    if (feature == CPUFeature::AMUv1p1)
        return "Activity Monitors Extension version 1.1"sv;
    if (feature == CPUFeature::ECV)
        return "Enhanced counter virtualization"sv;
    if (feature == CPUFeature::FGT)
        return "Fine Grain Traps"sv;
    if (feature == CPUFeature::MPAMv0p1)
        return "Memory Partitioning and Monitoring version 0.1"sv;
    if (feature == CPUFeature::MPAMv1p1)
        return "Memory Partitioning and Monitoring version 1.1"sv;
    if (feature == CPUFeature::MTPMU)
        return "Multi-threaded PMU Extensions"sv;
    if (feature == CPUFeature::TWED)
        return "Delayed trapping of WFE"sv;
    if (feature == CPUFeature::ETMv4)
        return "Embedded Trace Macrocell version4"sv;
    if (feature == CPUFeature::ETMv4p1)
        return "Embedded Trace Macrocell version 4.1"sv;
    if (feature == CPUFeature::ETMv4p2)
        return "Embedded Trace Macrocell version 4.2"sv;
    if (feature == CPUFeature::ETMv4p3)
        return "Embedded Trace Macrocell version 4.3"sv;
    if (feature == CPUFeature::ETMv4p4)
        return "Embedded Trace Macrocell version 4.3"sv;
    if (feature == CPUFeature::ETMv4p5)
        return "Embedded Trace Macrocell version 4.4"sv;
    if (feature == CPUFeature::ETMv4p6)
        return "Embedded Trace Macrocell version 4.5"sv;
    if (feature == CPUFeature::GICv3)
        return "Generic Interrupt Controller version 3"sv;
    if (feature == CPUFeature::GICv3p1)
        return "Generic Interrupt Controller version 3.1"sv;
    if (feature == CPUFeature::GICv3_LEGACY)
        return "Support for GICv2 legacy operation"sv; // Note: missing in source
    if (feature == CPUFeature::GICv3_TDIR)
        return "Trapping Non-secure EL1 writes to ICV_DIR"sv;
    if (feature == CPUFeature::GICv4)
        return "Generic Interrupt Controller version 4"sv;
    if (feature == CPUFeature::GICv4p1)
        return "Generic Interrupt Controller version 4.1"sv;
    if (feature == CPUFeature::PMUv3)
        return "PMU extension version 3"sv;
    if (feature == CPUFeature::ETE)
        return "Embedded Trace Extension"sv;
    if (feature == CPUFeature::ETEv1p1)
        return "Embedded Trace Extension, version 1.1"sv;
    if (feature == CPUFeature::SVE2)
        return "SVE version 2"sv;
    if (feature == CPUFeature::SVE_AES)
        return "SVE AES instructions"sv;
    if (feature == CPUFeature::SVE_PMULL128)
        return "SVE PMULL instructions"sv; // SVE2-AES is split into AES and PMULL support
    if (feature == CPUFeature::SVE_BitPerm)
        return "SVE Bit Permute"sv;
    if (feature == CPUFeature::SVE_SHA3)
        return "SVE SHA-3 instructions"sv;
    if (feature == CPUFeature::SVE_SM4)
        return "SVE SM4 instructions"sv;
    if (feature == CPUFeature::TME)
        return "Transactional Memory Extension"sv;
    if (feature == CPUFeature::TRBE)
        return "Trace Buffer Extension"sv;
    if (feature == CPUFeature::SME)
        return "Scalable Matrix Extension"sv;

    VERIFY_NOT_REACHED();
}

NonnullOwnPtr<KString> build_cpu_feature_names(CPUFeature::Type const& features)
{
    StringBuilder builder;
    bool first = true;
    for (auto feature = CPUFeature::Type(1u); feature != CPUFeature::__End; feature <<= 1u) {
        if (features.has_flag(feature)) {
            if (first)
                first = false;
            else
                MUST(builder.try_append(' '));
            auto name = cpu_feature_to_name(feature);
            MUST(builder.try_append(name));
        }
    }
    return KString::must_create(builder.string_view());
}

}