@@ -2506,22 +2506,91 @@ static int exit_cpuid(struct vcpu_t *vcpu, struct hax_tunnel *htun)
2506
2506
return HAX_RESUME ;
2507
2507
}
2508
2508
2509
+ bool is_cpuid_supported (struct hax_cpuid * cpuid_data )
2510
+ {
2511
+ uint32_t cpuid_i ;
2512
+ for (cpuid_i = 0 ; cpuid_i < cpuid_data -> nent ; cpuid_i ++ ) {
2513
+ switch (cpuid_data -> entries [cpuid_i ].function ) {
2514
+ case 0 : {
2515
+ if (cpuid_data -> entries [cpuid_i ].eax > 0xa ) {
2516
+ hax_log (HAX_LOGE , "Unsupported cpuid level %d\n" ,
2517
+ cpuid_data -> entries [cpuid_i ].eax );
2518
+ return false;
2519
+ }
2520
+ break ;
2521
+ }
2522
+ case 0x80000000 : {
2523
+ if (cpuid_data -> entries [cpuid_i ].eax > 0x80000008 ) {
2524
+ hax_log (HAX_LOGE , "Unsupported cpuid xlevel %d\n" ,
2525
+ cpuid_data -> entries [cpuid_i ].eax );
2526
+ return false;
2527
+ }
2528
+ break ;
2529
+ }
2530
+ case 1 : {
2531
+ // Disallow to clear these feature bits, since MSR handling
2532
+ // code is written as if these are supported.
2533
+ uint32_t nonDisabledFlags = FEATURE (MCE ) | FEATURE (APIC ) |
2534
+ FEATURE (MTRR ) | FEATURE (PAT );
2535
+ if ((cpuid_data -> entries [cpuid_i ].edx & nonDisabledFlags ) !=
2536
+ nonDisabledFlags ) {
2537
+ hax_log (HAX_LOGE , "MCE/APIC/MTRR/PAT disabling in cpuid "
2538
+ "not supported\n" );
2539
+ return false;
2540
+ }
2541
+ break ;
2542
+ }
2543
+ }
2544
+ }
2545
+ return true;
2546
+ }
2547
+
2548
+ static int get_vm_cpuid (struct vcpu_t * vcpu , uint32_t a , uint32_t c )
2549
+ {
2550
+ struct hax_cpuid_entry * cpuid_entry ;
2551
+ struct vcpu_state_t * state = vcpu -> state ;
2552
+
2553
+ cpuid_entry = & vcpu -> vm -> cpuid_data -> entries [0 ];
2554
+ for (uint32_t cpuid_i = 0 ; cpuid_i < vcpu -> vm -> cpuid_data -> nent ;
2555
+ cpuid_i ++ ) {
2556
+ if (cpuid_entry [cpuid_i ].function == a &&
2557
+ (!(cpuid_entry [cpuid_i ].flags & HAX_CPUID_FLAG_SIGNIFCANT_INDEX ) ||
2558
+ cpuid_entry [cpuid_i ].index == c )) {
2559
+
2560
+ state -> _eax = cpuid_entry [cpuid_i ].eax ;
2561
+ state -> _ecx = cpuid_entry [cpuid_i ].ecx ;
2562
+ state -> _edx = cpuid_entry [cpuid_i ].edx ;
2563
+ state -> _ebx = cpuid_entry [cpuid_i ].ebx ;
2564
+ return 1 ;
2565
+ }
2566
+ }
2567
+
2568
+ state -> _eax = 0 ;
2569
+ state -> _ecx = 0 ;
2570
+ state -> _edx = 0 ;
2571
+ state -> _ebx = 0 ;
2572
+ return 0 ;
2573
+ }
2574
+
2509
2575
static void handle_cpuid (struct vcpu_t * vcpu , struct hax_tunnel * htun )
2510
2576
{
2511
2577
struct vcpu_state_t * state = vcpu -> state ;
2512
2578
uint32_t a = state -> _eax , c = state -> _ecx ;
2513
2579
cpuid_args_t args ;
2514
2580
2515
- args .eax = state -> _eax ;
2516
- args .ecx = state -> _ecx ;
2517
- asm_cpuid (& args );
2518
- state -> _eax = args .eax ;
2519
- state -> _ecx = args .ecx ;
2520
- state -> _edx = args .edx ;
2521
- state -> _ebx = args .ebx ;
2522
-
2523
- handle_cpuid_virtual (vcpu , a , c );
2581
+ if (vcpu -> vm -> cpuid_data ) {
2582
+ get_vm_cpuid (vcpu , a , c );
2583
+ } else {
2584
+ args .eax = state -> _eax ;
2585
+ args .ecx = state -> _ecx ;
2586
+ asm_cpuid (& args );
2587
+ state -> _eax = args .eax ;
2588
+ state -> _ecx = args .ecx ;
2589
+ state -> _edx = args .edx ;
2590
+ state -> _ebx = args .ebx ;
2524
2591
2592
+ handle_cpuid_virtual (vcpu , a , c );
2593
+ }
2525
2594
hax_log (HAX_LOGD , "CPUID %08x %08x: %08x %08x %08x %08x\n" , a , c ,
2526
2595
state -> _eax , state -> _ebx , state -> _ecx , state -> _edx );
2527
2596
htun -> _exit_reason = vmx (vcpu , exit_reason ).basic_reason ;
0 commit comments