hv: hide thermal interface from guests

Thermal events are delivered through lapic thermal LVT. Currently
ACRN does not support delivering those interrupts to guests by
virtual lapic. They need to be virtualized to provide guests some
thermal management abilities. Currently we just hide thermal
lvt from guests, including:

1. Thermal LVT:
There is no way to hide thermal LVT from guests. But we need do
something to make sure no interrupt can be actually trigered:
  - skip thermal LVT in vlapic_trigger_lvt()
  - trap-and-emulate thermal LVT in lapic-pt mode

2. As We have plan to introduce virtualization of thermal monitor in the
future, we use a vm flag GUEST_FLAG_VTM which is default 0 to control
the access to it. So that it can help enabling VTM in the future.

Tracked-On: #8414
Signed-off-by: Wu Zhou <wu.zhou@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Wu Zhou 2023-06-15 20:07:43 +08:00 committed by acrnsi-robot
parent ac29ec2c6b
commit db83648a8d
5 changed files with 27 additions and 3 deletions

View File

@ -862,9 +862,9 @@ vlapic_trigger_lvt(struct acrn_vlapic *vlapic, uint32_t lvt_index)
{
uint32_t lvt;
int32_t ret = 0;
struct acrn_vcpu *vcpu = vlapic2vcpu(vlapic);
if (!vlapic_enabled(vlapic)) {
struct acrn_vcpu *vcpu = vlapic2vcpu(vlapic);
/*
* When the local APIC is global/hardware disabled,
* LINT[1:0] pins are configured as INTR and NMI pins,
@ -906,7 +906,12 @@ vlapic_trigger_lvt(struct acrn_vlapic *vlapic, uint32_t lvt_index)
lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_PERF_LVT);
break;
case APIC_LVT_THERMAL:
lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_THERM_LVT);
if (is_vtm_configured(vcpu->vm)) {
lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_THERM_LVT);
} else {
lvt = 0U;
ret = -EINVAL;
}
break;
case APIC_LVT_CMCI:
lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_CMCI_LVT);
@ -1530,7 +1535,6 @@ static int32_t vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_
break;
}
/* falls through */
default:
ret = -EACCES;
/* Read only */
@ -2123,6 +2127,7 @@ int32_t vlapic_x2apic_read(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
switch (msr) {
case MSR_IA32_EXT_APIC_LDR:
case MSR_IA32_EXT_XAPICID:
case MSR_IA32_EXT_APIC_LVT_THERMAL:
offset = x2apic_msr_to_regoff(msr);
error = vlapic_read(vlapic, offset, val);
break;
@ -2158,6 +2163,10 @@ int32_t vlapic_x2apic_write(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t val)
case MSR_IA32_EXT_APIC_ICR:
error = vlapic_x2apic_pt_icr_access(vcpu, val);
break;
case MSR_IA32_EXT_APIC_LVT_THERMAL:
offset = x2apic_msr_to_regoff(msr);
error = vlapic_write(vlapic, offset, val);
break;
default:
pr_err("%s: unexpected MSR[0x%x] write with lapic_pt", __func__, msr);
break;

View File

@ -223,6 +223,16 @@ bool is_vhwp_configured(const struct acrn_vm *vm)
return ((vm_config->guest_flags & GUEST_FLAG_VHWP) != 0U);
}
/**
* @pre vm != NULL && vm_config != NULL && vm->vmid < CONFIG_MAX_VM_NUM
*/
bool is_vtm_configured(const struct acrn_vm *vm)
{
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
return ((vm_config->guest_flags & GUEST_FLAG_VTM) != 0U);
}
/**
* @brief VT-d PI posted mode can possibly be used for PTDEVs assigned
* to this VM if platform supports VT-d PI AND lapic passthru is not configured

View File

@ -1314,5 +1314,8 @@ void update_msr_bitmap_x2apic_passthru(struct acrn_vcpu *vcpu)
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_XAPICID, INTERCEPT_READ);
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_LDR, INTERCEPT_READ);
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_ICR, INTERCEPT_WRITE);
if (!is_vtm_configured(vcpu->vm)) {
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_LVT_THERMAL, INTERCEPT_READ_WRITE);
}
set_tsc_msr_interception(vcpu, exec_vmread64(VMX_TSC_OFFSET_FULL) != 0UL);
}

View File

@ -275,6 +275,7 @@ bool vm_hide_mtrr(const struct acrn_vm *vm);
void update_vm_vlapic_state(struct acrn_vm *vm);
enum vm_vlapic_mode check_vm_vlapic_mode(const struct acrn_vm *vm);
bool is_vhwp_configured(const struct acrn_vm *vm);
bool is_vtm_configured(const struct acrn_vm *vm);
/*
* @pre vm != NULL
*/

View File

@ -64,6 +64,7 @@
#define GUEST_FLAG_REE (1UL << 10U) /* Whether the VM is REE VM */
#define GUEST_FLAG_PMU_PASSTHROUGH (1UL << 11U) /* Whether PMU is passed through */
#define GUEST_FLAG_VHWP (1UL << 12U) /* Whether the VM supports vHWP */
#define GUEST_FLAG_VTM (1UL << 13U) /* Whether the VM supports virtual thermal monitor */
/* TODO: We may need to get this addr from guest ACPI instead of hardcode here */
#define VIRTUAL_SLEEP_CTL_ADDR 0x400U /* Pre-launched VM uses ACPI reduced HW mode and sleep control register */