@@ -280,7 +280,7 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
280
280
if (result == 0 ) {
281
281
limit = entry .eax ;
282
282
vm -> vcpuid_xlevel = limit ;
283
- for (i = 0x80000001U ; i <= limit ; i ++ ) {
283
+ for (i = 0x80000002U ; i <= limit ; i ++ ) {
284
284
init_vcpuid_entry (i , 0U , 0U , & entry );
285
285
result = set_vcpuid_entry (vm , & entry );
286
286
if (result != 0 ) {
@@ -296,12 +296,13 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
296
296
297
297
static inline bool is_percpu_related (uint32_t leaf )
298
298
{
299
- return ((leaf == 0x1U ) || (leaf == 0xbU ) || (leaf == 0xdU ));
299
+ return ((leaf == 0x1U ) || (leaf == 0xbU ) || (leaf == 0xdU ) || ( leaf == 0x80000001U ) );
300
300
}
301
301
302
302
static void guest_cpuid_01h (struct acrn_vcpu * vcpu , uint32_t * eax , uint32_t * ebx , uint32_t * ecx , uint32_t * edx )
303
303
{
304
304
uint32_t apicid = vlapic_get_apicid (vcpu_vlapic (vcpu ));
305
+ uint64_t guest_ia32_misc_enable = vcpu_get_guest_msr (vcpu , MSR_IA32_MISC_ENABLE );
305
306
306
307
cpuid (0x1U , eax , ebx , ecx , edx );
307
308
/* Patching initial APIC ID */
@@ -334,6 +335,11 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
334
335
/* set Hypervisor Present Bit */
335
336
* ecx |= CPUID_ECX_HV ;
336
337
338
+ /* if guest disabed monitor/mwait, clear cpuid.01h[3] */
339
+ if ((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_MONITOR_ENA ) == 0UL ) {
340
+ * ecx &= ~CPUID_ECX_MONITOR ;
341
+ }
342
+
337
343
/*no xsave support for guest if it is not enabled on host*/
338
344
if ((* ecx & CPUID_ECX_OSXSAVE ) == 0U ) {
339
345
* ecx &= ~CPUID_ECX_XSAVE ;
@@ -413,6 +419,50 @@ static void guest_cpuid_0dh(__unused struct acrn_vcpu *vcpu, uint32_t *eax, uint
413
419
}
414
420
}
415
421
422
+ static void guest_cpuid_80000001h (const struct acrn_vcpu * vcpu ,
423
+ uint32_t * eax , uint32_t * ebx , uint32_t * ecx , uint32_t * edx )
424
+ {
425
+ const struct vcpuid_entry * entry_check = find_vcpuid_entry (vcpu , 0x80000000U , 0 );
426
+ uint64_t guest_ia32_misc_enable = vcpu_get_guest_msr (vcpu , MSR_IA32_MISC_ENABLE );
427
+ uint32_t leaf = 0x80000001U ;
428
+
429
+ if ((entry_check != NULL ) && (entry_check -> eax >= leaf )) {
430
+ cpuid (leaf , eax , ebx , ecx , edx );
431
+ /* SDM Vol4 2.1, XD Bit Disable of MSR_IA32_MISC_ENABLE
432
+ * When set to 1, the Execute Disable Bit feature (XD Bit) is disabled and the XD Bit
433
+ * extended feature flag will be clear (CPUID.80000001H: EDX[20]=0)
434
+ */
435
+ if ((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_XD_DISABLE ) != 0UL ) {
436
+ * edx = * edx & ~CPUID_EDX_XD_BIT_AVIL ;
437
+ }
438
+ } else {
439
+ * eax = 0U ;
440
+ * ebx = 0U ;
441
+ * ecx = 0U ;
442
+ * edx = 0U ;
443
+ }
444
+ }
445
+
446
+ static void guest_limit_cpuid (const struct acrn_vcpu * vcpu , uint32_t leaf ,
447
+ uint32_t * eax , uint32_t * ebx , uint32_t * ecx , uint32_t * edx )
448
+ {
449
+ uint64_t guest_ia32_misc_enable = vcpu_get_guest_msr (vcpu , MSR_IA32_MISC_ENABLE );
450
+
451
+ if ((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID ) != 0UL ) {
452
+ /* limit the leaf number to 2 */
453
+ if (leaf == 0U ) {
454
+ * eax = 2U ;
455
+ } else if (leaf > 2U ) {
456
+ * eax = 0U ;
457
+ * ebx = 0U ;
458
+ * ecx = 0U ;
459
+ * edx = 0U ;
460
+ } else {
461
+ /* In this case, leaf is 1U, return the cpuid value get above */
462
+ }
463
+ }
464
+ }
465
+
416
466
void guest_cpuid (struct acrn_vcpu * vcpu , uint32_t * eax , uint32_t * ebx , uint32_t * ecx , uint32_t * edx )
417
467
{
418
468
uint32_t leaf = * eax ;
@@ -448,14 +498,20 @@ void guest_cpuid(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t
448
498
guest_cpuid_0dh (vcpu , eax , ebx , ecx , edx );
449
499
break ;
450
500
501
+ case 0x80000001U :
502
+ guest_cpuid_80000001h (vcpu , eax , ebx , ecx , edx );
503
+ break ;
504
+
451
505
default :
452
506
/*
453
507
* In this switch statement, leaf shall either be 0x01U or 0x0bU
454
- * or 0x0dU. All the other cases have been handled properly
508
+ * or 0x0dU or 0x80000001U . All the other cases have been handled properly
455
509
* before this switch statement.
456
510
* Gracefully return if prior case clauses have not been met.
457
511
*/
458
512
break ;
459
513
}
460
514
}
515
+
516
+ guest_limit_cpuid (vcpu , leaf , eax , ebx , ecx , edx );
461
517
}
0 commit comments