@@ -2506,22 +2506,92 @@ static int exit_cpuid(struct vcpu_t *vcpu, struct hax_tunnel *htun)
25062506 return HAX_RESUME ;
25072507}
25082508
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+ uint32_t cpuid_i ;
2551+ struct hax_cpuid_entry * cpuid_entry ;
2552+ struct vcpu_state_t * state = vcpu -> state ;
2553+
2554+ cpuid_entry = & vcpu -> vm -> cpuid_data -> entries [0 ];
2555+ for (cpuid_i = 0 ; cpuid_i < vcpu -> vm -> cpuid_data -> nent ;
2556+ cpuid_i ++ ) {
2557+ if (cpuid_entry [cpuid_i ].function == a &&
2558+ (!(cpuid_entry [cpuid_i ].flags & HAX_CPUID_FLAG_SIGNIFCANT_INDEX ) ||
2559+ cpuid_entry [cpuid_i ].index == c )) {
2560+
2561+ state -> _eax = cpuid_entry [cpuid_i ].eax ;
2562+ state -> _ecx = cpuid_entry [cpuid_i ].ecx ;
2563+ state -> _edx = cpuid_entry [cpuid_i ].edx ;
2564+ state -> _ebx = cpuid_entry [cpuid_i ].ebx ;
2565+ return 1 ;
2566+ }
2567+ }
2568+
2569+ state -> _eax = 0 ;
2570+ state -> _ecx = 0 ;
2571+ state -> _edx = 0 ;
2572+ state -> _ebx = 0 ;
2573+ return 0 ;
2574+ }
2575+
25092576static void handle_cpuid (struct vcpu_t * vcpu , struct hax_tunnel * htun )
25102577{
25112578 struct vcpu_state_t * state = vcpu -> state ;
25122579 uint32_t a = state -> _eax , c = state -> _ecx ;
25132580 cpuid_args_t args ;
25142581
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 );
2582+ if (vcpu -> vm -> cpuid_data ) {
2583+ get_vm_cpuid (vcpu , a , c );
2584+ } else {
2585+ args .eax = state -> _eax ;
2586+ args .ecx = state -> _ecx ;
2587+ asm_cpuid (& args );
2588+ state -> _eax = args .eax ;
2589+ state -> _ecx = args .ecx ;
2590+ state -> _edx = args .edx ;
2591+ state -> _ebx = args .ebx ;
25242592
2593+ handle_cpuid_virtual (vcpu , a , c );
2594+ }
25252595 hax_log (HAX_LOGD , "CPUID %08x %08x: %08x %08x %08x %08x\n" , a , c ,
25262596 state -> _eax , state -> _ebx , state -> _ecx , state -> _edx );
25272597 htun -> _exit_reason = vmx (vcpu , exit_reason ).basic_reason ;
0 commit comments