mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-23 14:07:42 +00:00
HV: Add both HW and SW checks for RDT support
There can be times when user unknowinlgy enables CONFIG_CAT_ENBALED SW flag, but the hardware might not support L3 or L2 CAT. In such case software can end up writing to the CAT MSRs which can cause undefined results. The patch fixes the issue by enabling CAT only when both HW as well software via the CONFIG_CAT_ENABLED supports CAT. The patch also address typo with "clos2prq_msr" function name. It should be "clos2pqr_msr" instead. PQR stands for platform qos register. Tracked-On: #3715 Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
b8a021d658
commit
887e3813bc
@ -184,13 +184,15 @@ bool sanitize_vm_config(void)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cat_cap_info.enabled && (vm_config->clos > cat_cap_info.clos_max)) {
|
||||
pr_err("%s set CLOS(%d) more than system supports(%d)\n", __func__,
|
||||
vm_config->clos, cat_cap_info.clos_max);
|
||||
if (ret &&
|
||||
is_platform_rdt_capable() &&
|
||||
(vm_config->clos >= platform_clos_num)) {
|
||||
pr_err("%s set wrong CLOS. Please set below %d\n", __func__, platform_clos_num);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (((vm_config->epc.size | vm_config->epc.base) & ~PAGE_MASK) != 0UL) {
|
||||
if (ret &&
|
||||
(((vm_config->epc.size | vm_config->epc.base) & ~PAGE_MASK) != 0UL)) {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@ -199,15 +201,18 @@ bool sanitize_vm_config(void)
|
||||
ret = check_vm_uuid_collision(vm_id);
|
||||
}
|
||||
|
||||
/* vuart[1+] are used for VM communications */
|
||||
for (vuart_idx = 1U; vuart_idx < MAX_VUART_NUM_PER_VM; vuart_idx++) {
|
||||
const struct vuart_config *vu_config = &vm_config->vuart[vuart_idx];
|
||||
if (ret) {
|
||||
/* vuart[1+] are used for VM communications */
|
||||
for (vuart_idx = 1U; vuart_idx < MAX_VUART_NUM_PER_VM; vuart_idx++) {
|
||||
const struct vuart_config *vu_config = &vm_config->vuart[vuart_idx];
|
||||
|
||||
if (!(vu_config->type == VUART_LEGACY_PIO) && (vu_config->addr.port_base == INVALID_COM_BASE)) {
|
||||
if ((vu_config->t_vuart.vm_id >= CONFIG_MAX_VM_NUM) ||
|
||||
(vu_config->t_vuart.vm_id == vm_id)) {
|
||||
pr_err("%s invalid vuart configuration for VM %d\n", __func__, vm_id);
|
||||
ret = false;
|
||||
if (!(vu_config->type == VUART_LEGACY_PIO) &&
|
||||
(vu_config->addr.port_base == INVALID_COM_BASE)) {
|
||||
if ((vu_config->t_vuart.vm_id >= CONFIG_MAX_VM_NUM) ||
|
||||
(vu_config->t_vuart.vm_id == vm_id)) {
|
||||
pr_err("%s invalid vuart configuration for VM %d\n", __func__, vm_id);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -302,11 +302,11 @@ static void init_msr_area(struct acrn_vcpu *vcpu)
|
||||
vcpu->arch.msr_area.count++;
|
||||
|
||||
/* only load/restore MSR IA32_PQR_ASSOC when hv and guest have differnt settings */
|
||||
if (cat_cap_info.enabled && (cfg->clos != hv_clos)) {
|
||||
if (is_platform_rdt_capable() && (cfg->clos != hv_clos)) {
|
||||
vcpu->arch.msr_area.guest[MSR_AREA_IA32_PQR_ASSOC].msr_index = MSR_IA32_PQR_ASSOC;
|
||||
vcpu->arch.msr_area.guest[MSR_AREA_IA32_PQR_ASSOC].value = clos2prq_msr(cfg->clos);
|
||||
vcpu->arch.msr_area.guest[MSR_AREA_IA32_PQR_ASSOC].value = clos2pqr_msr(cfg->clos);
|
||||
vcpu->arch.msr_area.host[MSR_AREA_IA32_PQR_ASSOC].msr_index = MSR_IA32_PQR_ASSOC;
|
||||
vcpu->arch.msr_area.host[MSR_AREA_IA32_PQR_ASSOC].value = clos2prq_msr(hv_clos);
|
||||
vcpu->arch.msr_area.host[MSR_AREA_IA32_PQR_ASSOC].value = clos2pqr_msr(hv_clos);
|
||||
vcpu->arch.msr_area.count++;
|
||||
pr_acrnlog("switch clos for VM %u vcpu_id %u, host 0x%x, guest 0x%x",
|
||||
vcpu->vm->vm_id, vcpu->vcpu_id, hv_clos, cfg->clos);
|
||||
|
@ -16,9 +16,9 @@
|
||||
#include <vm_config.h>
|
||||
#include <msr.h>
|
||||
|
||||
struct cat_hw_info cat_cap_info;
|
||||
struct cat_hw_info cat_cap_info = {false, 0U, 0U, 0U, 0U};
|
||||
const uint16_t hv_clos = 0U;
|
||||
static uint16_t platform_clos_num = MAX_PLATFORM_CLOS_NUM;
|
||||
uint16_t platform_clos_num = MAX_PLATFORM_CLOS_NUM;
|
||||
|
||||
int32_t init_cat_cap_info(void)
|
||||
{
|
||||
@ -29,16 +29,16 @@ int32_t init_cat_cap_info(void)
|
||||
cpuid_subleaf(CPUID_RSD_ALLOCATION, 0, &eax, &ebx, &ecx, &edx);
|
||||
/* If support L3 CAT, EBX[1] is set */
|
||||
if ((ebx & 2U) != 0U) {
|
||||
cat_cap_info.enabled = true;
|
||||
cat_cap_info.res_id = CAT_RESID_L3;
|
||||
}
|
||||
|
||||
/* If support L2 CAT, EBX[2] is set */
|
||||
if ((ebx & 4U) != 0U) {
|
||||
cat_cap_info.enabled = true;
|
||||
cat_cap_info.res_id = CAT_RESID_L2;
|
||||
}
|
||||
|
||||
cat_cap_info.enabled = true;
|
||||
|
||||
/* CPUID.(EAX=0x10,ECX=ResID):EAX[4:0] reports the length of CBM supported
|
||||
* CPUID.(EAX=0x10,ECX=ResID):EBX[31:0] indicates the corresponding uints
|
||||
* may be used by other entities such as graphic and H/W outside processor.
|
||||
@ -50,7 +50,8 @@ int32_t init_cat_cap_info(void)
|
||||
cat_cap_info.clos_max = (uint16_t)(edx & 0xffffU);
|
||||
|
||||
if ((platform_clos_num != 0U) && ((cat_cap_info.clos_max + 1U) != platform_clos_num)) {
|
||||
pr_err("%s clos_max:%hu, platform_clos_num:%u\n", __func__, cat_cap_info.clos_max, platform_clos_num);
|
||||
pr_err("%s clos_max:%hu, platform_clos_num:%u\n",
|
||||
__func__, cat_cap_info.clos_max, platform_clos_num);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -58,7 +59,6 @@ int32_t init_cat_cap_info(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void setup_clos(uint16_t pcpu_id)
|
||||
{
|
||||
uint16_t i;
|
||||
@ -66,7 +66,7 @@ void setup_clos(uint16_t pcpu_id)
|
||||
uint64_t val;
|
||||
|
||||
if (cat_cap_info.enabled) {
|
||||
for (i = 0U; i < platform_clos_num; i++) {
|
||||
for (i = 0; i < platform_clos_num; i++) {
|
||||
switch (cat_cap_info.res_id) {
|
||||
case CAT_RESID_L2:
|
||||
msr_index = platform_l2_clos_array[i].msr_index;
|
||||
@ -83,16 +83,21 @@ void setup_clos(uint16_t pcpu_id)
|
||||
}
|
||||
}
|
||||
/* set hypervisor CAT clos */
|
||||
msr_write_pcpu(MSR_IA32_PQR_ASSOC, clos2prq_msr(hv_clos), pcpu_id);
|
||||
msr_write_pcpu(MSR_IA32_PQR_ASSOC, clos2pqr_msr(hv_clos), pcpu_id);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t clos2prq_msr(uint16_t clos)
|
||||
uint64_t clos2pqr_msr(uint16_t clos)
|
||||
{
|
||||
uint64_t prq_assoc;
|
||||
uint64_t pqr_assoc;
|
||||
|
||||
prq_assoc = msr_read(MSR_IA32_PQR_ASSOC);
|
||||
prq_assoc = (prq_assoc & 0xffffffffUL) | ((uint64_t)clos << 32U);
|
||||
pqr_assoc = msr_read(MSR_IA32_PQR_ASSOC);
|
||||
pqr_assoc = (pqr_assoc & 0xffffffffUL) | ((uint64_t)clos << 32U);
|
||||
|
||||
return prq_assoc;
|
||||
return pqr_assoc;
|
||||
}
|
||||
|
||||
bool is_platform_rdt_capable(void)
|
||||
{
|
||||
return cat_cap_info.enabled;
|
||||
}
|
||||
|
@ -19,12 +19,15 @@ struct cat_hw_info {
|
||||
|
||||
extern struct cat_hw_info cat_cap_info;
|
||||
extern const uint16_t hv_clos;
|
||||
extern uint16_t platform_clos_num;
|
||||
void setup_clos(uint16_t pcpu_id);
|
||||
|
||||
|
||||
#define CAT_RESID_L3 1U
|
||||
#define CAT_RESID_L2 2U
|
||||
|
||||
int32_t init_cat_cap_info(void);
|
||||
uint64_t clos2prq_msr(uint16_t clos);
|
||||
uint64_t clos2pqr_msr(uint16_t clos);
|
||||
bool is_platform_rdt_capable(void);
|
||||
|
||||
#endif /* RDT_H */
|
||||
|
Loading…
Reference in New Issue
Block a user