@@ -2506,22 +2506,91 @@ 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+ 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+
25092575static void handle_cpuid (struct vcpu_t * vcpu , struct hax_tunnel * htun )
25102576{
25112577 struct vcpu_state_t * state = vcpu -> state ;
25122578 uint32_t a = state -> _eax , c = state -> _ecx ;
25132579 cpuid_args_t args ;
25142580
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 ;
25242591
2592+ handle_cpuid_virtual (vcpu , a , c );
2593+ }
25252594 hax_log (HAX_LOGD , "CPUID %08x %08x: %08x %08x %08x %08x\n" , a , c ,
25262595 state -> _eax , state -> _ebx , state -> _ecx , state -> _edx );
25272596 htun -> _exit_reason = vmx (vcpu , exit_reason ).basic_reason ;
0 commit comments