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>
This commit is contained in:
parent
ef19ed8961
commit
8e310e6ea1
|
@ -280,7 +280,7 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
|
|||
if (result == 0) {
|
||||
limit = entry.eax;
|
||||
vm->vcpuid_xlevel = limit;
|
||||
for (i = 0x80000001U; i <= limit; i++) {
|
||||
for (i = 0x80000002U; i <= limit; i++) {
|
||||
init_vcpuid_entry(i, 0U, 0U, &entry);
|
||||
result = set_vcpuid_entry(vm, &entry);
|
||||
if (result != 0) {
|
||||
|
@ -296,12 +296,13 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
|
|||
|
||||
static inline bool is_percpu_related(uint32_t leaf)
|
||||
{
|
||||
return ((leaf == 0x1U) || (leaf == 0xbU) || (leaf == 0xdU));
|
||||
return ((leaf == 0x1U) || (leaf == 0xbU) || (leaf == 0xdU) || (leaf == 0x80000001U));
|
||||
}
|
||||
|
||||
static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
uint32_t apicid = vlapic_get_apicid(vcpu_vlapic(vcpu));
|
||||
uint64_t guest_ia32_misc_enable = vcpu_get_guest_msr(vcpu, MSR_IA32_MISC_ENABLE);
|
||||
|
||||
cpuid(0x1U, eax, ebx, ecx, edx);
|
||||
/* Patching initial APIC ID */
|
||||
|
@ -334,6 +335,11 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
|
|||
/* set Hypervisor Present Bit */
|
||||
*ecx |= CPUID_ECX_HV;
|
||||
|
||||
/* if guest disabed monitor/mwait, clear cpuid.01h[3] */
|
||||
if ((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_MONITOR_ENA) == 0UL) {
|
||||
*ecx &= ~CPUID_ECX_MONITOR;
|
||||
}
|
||||
|
||||
/*no xsave support for guest if it is not enabled on host*/
|
||||
if ((*ecx & CPUID_ECX_OSXSAVE) == 0U) {
|
||||
*ecx &= ~CPUID_ECX_XSAVE;
|
||||
|
@ -413,6 +419,50 @@ static void guest_cpuid_0dh(__unused struct acrn_vcpu *vcpu, uint32_t *eax, uint
|
|||
}
|
||||
}
|
||||
|
||||
static void guest_cpuid_80000001h(const struct acrn_vcpu *vcpu,
|
||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
const struct vcpuid_entry *entry_check = find_vcpuid_entry(vcpu, 0x80000000U, 0);
|
||||
uint64_t guest_ia32_misc_enable = vcpu_get_guest_msr(vcpu, MSR_IA32_MISC_ENABLE);
|
||||
uint32_t leaf = 0x80000001U;
|
||||
|
||||
if ((entry_check != NULL) && (entry_check->eax >= leaf)) {
|
||||
cpuid(leaf, eax, ebx, ecx, edx);
|
||||
/* SDM Vol4 2.1, XD Bit Disable of MSR_IA32_MISC_ENABLE
|
||||
* When set to 1, the Execute Disable Bit feature (XD Bit) is disabled and the XD Bit
|
||||
* extended feature flag will be clear (CPUID.80000001H: EDX[20]=0)
|
||||
*/
|
||||
if ((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_XD_DISABLE) != 0UL) {
|
||||
*edx = *edx & ~CPUID_EDX_XD_BIT_AVIL;
|
||||
}
|
||||
} else {
|
||||
*eax = 0U;
|
||||
*ebx = 0U;
|
||||
*ecx = 0U;
|
||||
*edx = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
static void guest_limit_cpuid(const struct acrn_vcpu *vcpu, uint32_t leaf,
|
||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
uint64_t guest_ia32_misc_enable = vcpu_get_guest_msr(vcpu, MSR_IA32_MISC_ENABLE);
|
||||
|
||||
if ((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) != 0UL) {
|
||||
/* limit the leaf number to 2 */
|
||||
if (leaf == 0U) {
|
||||
*eax = 2U;
|
||||
} else if (leaf > 2U) {
|
||||
*eax = 0U;
|
||||
*ebx = 0U;
|
||||
*ecx = 0U;
|
||||
*edx = 0U;
|
||||
} else {
|
||||
/* In this case, leaf is 1U, return the cpuid value get above */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void guest_cpuid(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
uint32_t leaf = *eax;
|
||||
|
@ -448,14 +498,20 @@ void guest_cpuid(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t
|
|||
guest_cpuid_0dh(vcpu, eax, ebx, ecx, edx);
|
||||
break;
|
||||
|
||||
case 0x80000001U:
|
||||
guest_cpuid_80000001h(vcpu, eax, ebx, ecx, edx);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* In this switch statement, leaf shall either be 0x01U or 0x0bU
|
||||
* or 0x0dU. All the other cases have been handled properly
|
||||
* or 0x0dU or 0x80000001U. All the other cases have been handled properly
|
||||
* before this switch statement.
|
||||
* Gracefully return if prior case clauses have not been met.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
guest_limit_cpuid(vcpu, leaf, eax, ebx, ecx, edx);
|
||||
}
|
||||
|
|
|
@ -100,6 +100,8 @@
|
|||
#define CPUID_EAX_XCR0_BNDREGS (1U<<3U)
|
||||
/* CPUID.0DH.EAX.XCR0_BNDCSR */
|
||||
#define CPUID_EAX_XCR0_BNDCSR (1U<<4U)
|
||||
/* CPUID.80000001H.EDX.XD_BIT_AVAILABLE */
|
||||
#define CPUID_EDX_XD_BIT_AVIL (1U<<20U)
|
||||
|
||||
/* CPUID source operands */
|
||||
#define CPUID_VENDORSTRING 0U
|
||||
|
|
Loading…
Reference in New Issue