Skip to content

Commit 8e310e6

Browse files
binbinwu1Eddie Dong
authored andcommitted
hv: vcpuid: modify vcpuid according to msr ia32_misc_enable
According to SDM Vol4 2.1, modify vcpuid according to msr ia32_misc_enable: - Clear CPUID.01H: ECX[3] if guest disabled monitor/mwait. - Clear CPUID.80000001H: EDX[20] if guest set XD Bit Disable. - Limit the CPUID leave maximum value to 2 if guest set Limit CPUID MAXVal. Tracked-On: #2834 Signed-off-by: Binbin Wu <binbin.wu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent ef19ed8 commit 8e310e6

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

hypervisor/arch/x86/guest/vcpuid.c

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
280280
if (result == 0) {
281281
limit = entry.eax;
282282
vm->vcpuid_xlevel = limit;
283-
for (i = 0x80000001U; i <= limit; i++) {
283+
for (i = 0x80000002U; i <= limit; i++) {
284284
init_vcpuid_entry(i, 0U, 0U, &entry);
285285
result = set_vcpuid_entry(vm, &entry);
286286
if (result != 0) {
@@ -296,12 +296,13 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
296296

297297
static inline bool is_percpu_related(uint32_t leaf)
298298
{
299-
return ((leaf == 0x1U) || (leaf == 0xbU) || (leaf == 0xdU));
299+
return ((leaf == 0x1U) || (leaf == 0xbU) || (leaf == 0xdU) || (leaf == 0x80000001U));
300300
}
301301

302302
static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
303303
{
304304
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);
305306

306307
cpuid(0x1U, eax, ebx, ecx, edx);
307308
/* Patching initial APIC ID */
@@ -334,6 +335,11 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
334335
/* set Hypervisor Present Bit */
335336
*ecx |= CPUID_ECX_HV;
336337

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+
337343
/*no xsave support for guest if it is not enabled on host*/
338344
if ((*ecx & CPUID_ECX_OSXSAVE) == 0U) {
339345
*ecx &= ~CPUID_ECX_XSAVE;
@@ -413,6 +419,50 @@ static void guest_cpuid_0dh(__unused struct acrn_vcpu *vcpu, uint32_t *eax, uint
413419
}
414420
}
415421

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+
416466
void guest_cpuid(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
417467
{
418468
uint32_t leaf = *eax;
@@ -448,14 +498,20 @@ void guest_cpuid(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t
448498
guest_cpuid_0dh(vcpu, eax, ebx, ecx, edx);
449499
break;
450500

501+
case 0x80000001U:
502+
guest_cpuid_80000001h(vcpu, eax, ebx, ecx, edx);
503+
break;
504+
451505
default:
452506
/*
453507
* 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
455509
* before this switch statement.
456510
* Gracefully return if prior case clauses have not been met.
457511
*/
458512
break;
459513
}
460514
}
515+
516+
guest_limit_cpuid(vcpu, leaf, eax, ebx, ecx, edx);
461517
}

hypervisor/include/arch/x86/cpuid.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@
100100
#define CPUID_EAX_XCR0_BNDREGS (1U<<3U)
101101
/* CPUID.0DH.EAX.XCR0_BNDCSR */
102102
#define CPUID_EAX_XCR0_BNDCSR (1U<<4U)
103+
/* CPUID.80000001H.EDX.XD_BIT_AVAILABLE */
104+
#define CPUID_EDX_XD_BIT_AVIL (1U<<20U)
103105

104106
/* CPUID source operands */
105107
#define CPUID_VENDORSTRING 0U

0 commit comments

Comments
 (0)