mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-29 16:58:10 +00:00
hv: disable guest MONITOR-WAIT support when SW SRAM is configured
Per-core software SRAM L2 cache may be flushed by 'mwait' extension instruction, which guest VM may execute to enter core deep sleep. Such kind of flushing is not expected when software SRAM is enabled for RTVM. Hypervisor disables MONITOR-WAIT support on both hypervisor and VMs sides to protect above software SRAM from being flushed. This patch disable ACRN guest MONITOR-WAIT support if software SRAM is configured. Tracked-On: #5649 Signed-off-by: Yonghua Huang <yonghua.huang@intel.com> Reviewed-by: Fei Li <fei1.li@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
ae43b2a847
commit
1a011bd91b
@ -467,9 +467,14 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
|
|||||||
*ecx &= ~CPUID_ECX_PCID;
|
*ecx &= ~CPUID_ECX_PCID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if guest disabed monitor/mwait, clear cpuid.01h[3] */
|
/* guest monitor/mwait is supported only if it is allowed('vm_mwait_cap' is true)
|
||||||
if ((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_MONITOR_ENA) == 0UL) {
|
* and MSR_IA32_MISC_ENABLE_MONITOR_ENA bit of guest MSR_IA32_MISC_ENABLE is set,
|
||||||
*ecx &= ~CPUID_ECX_MONITOR;
|
* else clear cpuid.01h[3].
|
||||||
|
*/
|
||||||
|
*ecx &= ~CPUID_ECX_MONITOR;
|
||||||
|
if (vcpu->vm->arch_vm.vm_mwait_cap &&
|
||||||
|
((guest_ia32_misc_enable & MSR_IA32_MISC_ENABLE_MONITOR_ENA) != 0UL)) {
|
||||||
|
*ecx |= CPUID_ECX_MONITOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ecx &= ~CPUID_ECX_OSXSAVE;
|
*ecx &= ~CPUID_ECX_OSXSAVE;
|
||||||
|
@ -535,6 +535,7 @@ int32_t create_vm(uint16_t vm_id, uint64_t pcpu_bitmap, struct acrn_vm_config *v
|
|||||||
spinlock_init(&vm->arch_vm.iwkey_backup_lock);
|
spinlock_init(&vm->arch_vm.iwkey_backup_lock);
|
||||||
|
|
||||||
vm->arch_vm.vlapic_mode = VM_VLAPIC_XAPIC;
|
vm->arch_vm.vlapic_mode = VM_VLAPIC_XAPIC;
|
||||||
|
vm->arch_vm.vm_mwait_cap = has_monitor_cap();
|
||||||
vm->intr_inject_delay_delta = 0UL;
|
vm->intr_inject_delay_delta = 0UL;
|
||||||
vm->nr_emul_mmio_regions = 0U;
|
vm->nr_emul_mmio_regions = 0U;
|
||||||
vm->vcpuid_entry_nr = 0U;
|
vm->vcpuid_entry_nr = 0U;
|
||||||
|
@ -707,7 +707,7 @@ static void set_guest_ia32_misc_enalbe(struct acrn_vcpu *vcpu, uint64_t v)
|
|||||||
{
|
{
|
||||||
uint32_t eax, ebx = 0U, ecx = 0U, edx = 0U;
|
uint32_t eax, ebx = 0U, ecx = 0U, edx = 0U;
|
||||||
bool update_vmsr = true;
|
bool update_vmsr = true;
|
||||||
uint64_t msr_value;
|
|
||||||
/* According to SDM Vol4 2.1 & Vol 3A 4.1.4,
|
/* According to SDM Vol4 2.1 & Vol 3A 4.1.4,
|
||||||
* EFER.NXE should be cleared if guest disable XD in IA32_MISC_ENABLE
|
* EFER.NXE should be cleared if guest disable XD in IA32_MISC_ENABLE
|
||||||
*/
|
*/
|
||||||
@ -716,13 +716,9 @@ static void set_guest_ia32_misc_enalbe(struct acrn_vcpu *vcpu, uint64_t v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle MISC_ENABLE_MONITOR_ENA
|
/* Handle MISC_ENABLE_MONITOR_ENA
|
||||||
* If has_monitor_cap() retrn true, this means the feature is enabed on host.
|
* - if guest try to set this bit, do nothing.
|
||||||
* HV will use monitor/mwait.
|
* - if guest try to clear this bit, MISC_ENABLE_MONITOR_ENA bit of guest MSR_IA32_MISC_ENABLE
|
||||||
* - if guest try to set this bit, do nothing since it is already enabled
|
* shall be cleared.
|
||||||
* - if guest try to clear this bit, not allow to disable in physcial MSR,
|
|
||||||
* just clear the corresponding bit in vcpuid.
|
|
||||||
* If has_monitor_cap() retrn false, this means the feature is not enabled on host.
|
|
||||||
* HV will not use monitor/mwait. Allow guest to change the bit to physcial MSR
|
|
||||||
*/
|
*/
|
||||||
if (((v ^ vcpu_get_guest_msr(vcpu, MSR_IA32_MISC_ENABLE)) & MSR_IA32_MISC_ENABLE_MONITOR_ENA) != 0UL) {
|
if (((v ^ vcpu_get_guest_msr(vcpu, MSR_IA32_MISC_ENABLE)) & MSR_IA32_MISC_ENABLE_MONITOR_ENA) != 0UL) {
|
||||||
eax = 1U;
|
eax = 1U;
|
||||||
@ -733,15 +729,11 @@ static void set_guest_ia32_misc_enalbe(struct acrn_vcpu *vcpu, uint64_t v)
|
|||||||
if ((ecx & CPUID_ECX_SSE3) == 0U) {
|
if ((ecx & CPUID_ECX_SSE3) == 0U) {
|
||||||
vcpu_inject_gp(vcpu, 0U);
|
vcpu_inject_gp(vcpu, 0U);
|
||||||
update_vmsr = false;
|
update_vmsr = false;
|
||||||
} else if ((!has_monitor_cap()) && (!is_apl_platform())) {
|
} else if (vcpu->vm->arch_vm.vm_mwait_cap) {
|
||||||
msr_value = msr_read(MSR_IA32_MISC_ENABLE) & ~MSR_IA32_MISC_ENABLE_MONITOR_ENA;
|
/* guest cpuid.01H will be updated when guest executes 'cpuid' with leaf 01H */
|
||||||
msr_value |= v & MSR_IA32_MISC_ENABLE_MONITOR_ENA;
|
v &= ~MSR_IA32_MISC_ENABLE_MONITOR_ENA;
|
||||||
/* This will not change the return value of has_monitor_cap() since the feature values
|
|
||||||
* are cached when platform init.
|
|
||||||
*/
|
|
||||||
msr_write(MSR_IA32_MISC_ENABLE, msr_value);
|
|
||||||
} else {
|
} else {
|
||||||
/* Not allow to change MISC_ENABLE_MONITOR_ENA in MSR */
|
update_vmsr = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ struct vm_arch {
|
|||||||
struct iwkey iwkey_backup;
|
struct iwkey iwkey_backup;
|
||||||
|
|
||||||
/* reference to virtual platform to come here (as needed) */
|
/* reference to virtual platform to come here (as needed) */
|
||||||
|
bool vm_mwait_cap;
|
||||||
} __aligned(PAGE_SIZE);
|
} __aligned(PAGE_SIZE);
|
||||||
|
|
||||||
struct acrn_vm {
|
struct acrn_vm {
|
||||||
|
Loading…
Reference in New Issue
Block a user