465
CPUX86State *env = &x86_cpu->env;
466
uint32_t eax, ebx, ecx, edx;
467
uint32_t leaf, subleaf;
468
- size_t max_leaf = 0x1F;
469
- size_t max_subleaf = 0x20;
470
-
471
- uint32_t leaves_with_subleaves[] = {0x4, 0x7, 0xD, 0xF, 0x10};
468
+ uint32_t max_basic_leaf, max_extended_leaf;
469
+ uint32_t max_subleaf = 0x20;
470
+ uint32_t leaves_with_subleaves[] = {0x04, 0x07, 0x0d, 0x0f, 0x10};
471
int n_subleaf_leaves = ARRAY_SIZE(leaves_with_subleaves);
472
474
- /* Regular leaves without subleaves */
475
- for (leaf = 0; leaf <= max_leaf; leaf++) {
473
+ /* Get maximum basic and and extended CPUID leaves */
474
+ cpu_x86_cpuid(env, 0, 0, &max_basic_leaf, &ebx, &ecx, &edx);
475
+ cpu_x86_cpuid(env, 0x80000000, 0, &max_extended_leaf, &ebx, &ecx, &edx);
476
+
477
+ /* Collect basic leaves (0x0 to max_basic_leaf) */
478
+ for (leaf = 0; leaf <= max_basic_leaf; leaf++) {
479
bool has_subleaves = false;
480
for (int i = 0; i < n_subleaf_leaves; i++) {
481
if (leaf == leaves_with_subleaves[i]) {
486
487
if (!has_subleaves) {
488
cpu_x86_cpuid(env, leaf, 0, &eax, &ebx, &ecx, &edx);
486
- if (eax == 0 && ebx == 0 && ecx == 0 && edx == 0) {
487
- /* all zeroes indicates no more leaves */
488
- continue;
489
- }
490
-
489
add_cpuid_entry(cpuid_entries, leaf, 0, eax, ebx, ecx, edx);
490
continue;
491
}
492
493
+ /*
494
+ * Valid XSAVE components can exist at a higher index se we need to set
495
+ * all subleaves for leaf 0x0d, even if we encounter an empty one.
496
+ */
497
+ if (leaf == 0x0d) {
498
+ for (subleaf = 0; subleaf <= 63; subleaf++) {
499
+ cpu_x86_cpuid(env, leaf, subleaf, &eax, &ebx, &ecx, &edx);
500
+ add_cpuid_entry(cpuid_entries, leaf, subleaf,
501
+ eax, ebx, ecx, edx);
502
+ }
503
+ continue;
504
+ }
505
+
506
subleaf = 0;
507
while (subleaf < max_subleaf) {
508
cpu_x86_cpuid(env, leaf, subleaf, &eax, &ebx, &ecx, &edx);
509
510
if (eax == 0 && ebx == 0 && ecx == 0 && edx == 0) {
500
- /* all zeroes indicates no more leaves */
511
break;
512
}
503
- add_cpuid_entry(cpuid_entries, leaf, 0, eax, ebx, ecx, edx);
513
+ add_cpuid_entry(cpuid_entries, leaf, subleaf, eax, ebx, ecx, edx);
514
subleaf++;
515
}
516
}
517
+
518
+ /* Collect extended leaves (0x80000000 to max_extended_leaf) */
519
+ for (leaf = 0x80000000; leaf <= max_extended_leaf; leaf++) {
520
+ cpu_x86_cpuid(env, leaf, 0, &eax, &ebx, &ecx, &edx);
521
+ add_cpuid_entry(cpuid_entries, leaf, 0, eax, ebx, ecx, edx);
522
+ }
523
}
524
525
static int register_intercept_result_cpuid_entry(const CPUState *cpu,
592
subleaf_specific = 0;
593
always_override = 1;
594
579
- /* Intel */
580
- /* 0xb - Extended Topology Enumeration Leaf */
581
- /* 0x1f - V2 Extended Topology Enumeration Leaf */
582
- /* AMD */
583
- /* 0x8000_001e - Processor Topology Information */
584
- /* 0x8000_0026 - Extended CPU Topology */
585
- if (entry->function == 0xb
586
- || entry->function == 0x1f
587
- || entry->function == 0x8000001e
588
- || entry->function == 0x80000026) {
595
+ /*
596
+ * Intel
597
+ * 0xb - Extended Topology Enumeration Leaf
598
+ * 0x1f - V2 Extended Topology Enumeration Leaf
599
+ * AMD
600
+ * 0x8000_001e - Processor Topology Information
601
+ * 0x8000_0026 - Extended CPU Topology
602
+ */
603
+ if (entry->function == 0xb ||
604
+ entry->function == 0x1f ||
605
+ entry->function == 0x8000001e ||
606
+ entry->function == 0x80000026) {
607
+ subleaf_specific = 1;
608
+ always_override = 1;
609
+ /*
610
+ * Feature enumeration leaves (subleaf-specific)
611
+ * 0x04: Deterministic Cache Parameters
612
+ * 0x07: Structured Extended Feature Flags
613
+ * 0x0D: Processor Extended State Enumeration
614
+ * 0x0F: Platform QoS Monitoring
615
+ * 0x10: Platform QoS Enforcement
616
+ */
617
+ } else if (entry->function == 0x04 ||
618
+ entry->function == 0x07 ||
619
+ entry->function == 0x0d ||
620
+ entry->function == 0x0f ||
621
+ entry->function == 0x10) {
622
subleaf_specific = 1;
623
always_override = 1;
591
- } else if (entry->function == 0x00000001
592
- || entry->function == 0x80000000
593
- || entry->function == 0x80000001
594
- || entry->function == 0x80000008) {
624
+ /* Basic feature leaves (no subleaves) */
625
+ } else if (entry->function == 0x00000001 ||
626
+ entry->function == 0x80000000 ||
627
+ entry->function == 0x80000001 ||
628
+ entry->function == 0x80000008) {
629
subleaf_specific = 0;
630
always_override = 1;
631
}