@@ -2610,6 +2610,16 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
26102610 uint32_t reserved2 : 4 ;
26112611 };
26122612 } cpuid_eax ;
2613+ struct vm_t * vm = vcpu -> vm ;
2614+ hax_list_head * list ;
2615+ int vcpu_count = 0 ;
2616+
2617+ hax_mutex_lock (vm -> vm_lock );
2618+ hax_list_for_each (list , (hax_list_head * )(& vm -> vcpu_list )) {
2619+ vcpu_count ++ ;
2620+ }
2621+ hax_mutex_unlock (vm -> vm_lock );
2622+
26132623 cpuid_eax .raw = state -> _eax ;
26142624
26152625 if (0xF != cpuid_eax .familyID )
@@ -2651,6 +2661,9 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
26512661 // (see IA SDM Vol. 3A 3.2, Table 3-14)
26522662 0x00 ;
26532663
2664+ if (vcpu_count > 1 )
2665+ state -> _ebx |= (vcpu_count ) << 16 ;
2666+
26542667 // Report only the features specified, excluding any features not
26552668 // supported by the host CPU, but including "hypervisor", which is
26562669 // desirable for VMMs.
@@ -2673,8 +2686,23 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
26732686 return ;
26742687 }
26752688 case 4 : { // Deterministic Cache Parameters
2676- // [31:26] cores per package - 1
2677- // Use host cache values.
2689+ // Use host cache values, but change maximum number of addresable
2690+ // IDs according to the number of virtual CPUs (bits [31:26]).
2691+ state -> _eax &= ~0xFC000000 ;
2692+ if (state -> _eax & 31 ) {
2693+ struct vm_t * vm = vcpu -> vm ;
2694+ hax_list_head * list ;
2695+ int vcpu_count = 0 ;
2696+
2697+ hax_mutex_lock (vm -> vm_lock );
2698+ hax_list_for_each (list , (hax_list_head * )(& vm -> vcpu_list )) {
2699+ vcpu_count ++ ;
2700+ }
2701+ hax_mutex_unlock (vm -> vm_lock );
2702+
2703+ if (vcpu_count > 1 )
2704+ state -> _eax |= (vcpu_count - 1 ) << 26 ;
2705+ }
26782706 return ;
26792707 }
26802708 case 5 : // MONITOR/MWAIT
@@ -2772,13 +2800,26 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
27722800 return ;
27732801 }
27742802 case 0x80000008 : { // Virtual/Physical Address Size
2803+ struct vm_t * vm = vcpu -> vm ;
2804+ hax_list_head * list ;
2805+ int vcpu_count = 0 ;
2806+
2807+ hax_mutex_lock (vm -> vm_lock );
2808+ hax_list_for_each (list , (hax_list_head * )(& vm -> vcpu_list )) {
2809+ vcpu_count ++ ;
2810+ }
2811+ hax_mutex_unlock (vm -> vm_lock );
2812+
27752813 // Bit mask to identify the reserved bits in paging structure high
27762814 // order address field
27772815 physical_address_size = (uint8_t )state -> _eax & 0xff ;
27782816 pw_reserved_bits_high_mask =
27792817 ~((1 << (physical_address_size - 32 )) - 1 );
27802818
27812819 state -> _ebx = state -> _ecx = state -> _edx = 0 ;
2820+
2821+ if (vcpu_count > 1 )
2822+ state -> _ecx |= vcpu_count - 1 ;
27822823 return ;
27832824 }
27842825 }
0 commit comments