mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-18 11:47:30 +00:00
hv: vCAT: expose CAT capabilities to vCAT-enabled VM
Expose CAT feature to vCAT VM by reporting the number of cache ways/CLOSIDs via the 04H/10H cpuid instructions, so that the VM can take advantage of CAT to prioritize and partition cache resource for its own tasks. Add the vcat_pcbm_to_vcbm() function to map pcbm to vcbm Tracked-On: #5917 Signed-off-by: dongshen <dongsheng.x.zhang@intel.com> Acked-by: Eddie Dong <eddie.dong@Intel.com>
This commit is contained in:
parent
77ae989379
commit
be855d2352
@ -151,6 +151,22 @@ static uint64_t vcat_get_max_vcbm(const struct acrn_vm *vm, int res)
|
||||
return max_pcbm >> low;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Map pCBM to vCBM
|
||||
*
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
uint64_t vcat_pcbm_to_vcbm(const struct acrn_vm *vm, uint64_t pcbm, int res)
|
||||
{
|
||||
uint64_t max_pcbm = get_max_pcbm(vm, res);
|
||||
|
||||
/* Find the position low (the first bit set) in max_pcbm */
|
||||
uint16_t low = ffs64(max_pcbm);
|
||||
|
||||
/* pcbm set bits should only be in the range of [low, high] */
|
||||
return (pcbm & max_pcbm) >> low;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief vCBM MSR write handler
|
||||
*
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <asm/sgx.h>
|
||||
#include <asm/tsc.h>
|
||||
#include <logmsg.h>
|
||||
#include <asm/rdt.h>
|
||||
#include <asm/guest/vcat.h>
|
||||
|
||||
static inline const struct vcpuid_entry *local_find_vcpuid_entry(const struct acrn_vcpu *vcpu,
|
||||
uint32_t leaf, uint32_t subleaf)
|
||||
@ -286,6 +288,149 @@ static int32_t set_vcpuid_sgx(struct acrn_vm *vm)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
/**
|
||||
* @brief * Number of ways (CBM length) is detected with CPUID.0x4
|
||||
*
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static int32_t set_vcpuid_vcat_04h(const struct acrn_vm *vm, struct vcpuid_entry *entry)
|
||||
{
|
||||
uint32_t cache_type = entry->eax & 0x1FU; /* EAX bits 04:00 */
|
||||
uint32_t cache_level = (entry->eax >> 5U) & 0x7U; /* EAX bits 07:05 */
|
||||
uint16_t vcbm_len = 0U;
|
||||
|
||||
if (cache_level == 2U) {
|
||||
vcbm_len = vcat_get_vcbm_len(vm, RDT_RESOURCE_L2);
|
||||
} else if (cache_level == 3U) {
|
||||
vcbm_len = vcat_get_vcbm_len(vm, RDT_RESOURCE_L3);
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_type:
|
||||
* 0 = Null - No more caches.
|
||||
* 1 = Data Cache.
|
||||
* 2 = Instruction Cache.
|
||||
* 3 = Unified Cache.
|
||||
* 4-31 = Reserved
|
||||
*
|
||||
* cache_level (starts at 1):
|
||||
* 2 = L2
|
||||
* 3 = L3
|
||||
*/
|
||||
if (((cache_type == 0x1U) || (cache_type == 0x3U)) && (vcbm_len != 0U)) {
|
||||
/*
|
||||
* EBX Bits 11 - 00: L = System Coherency Line Size**.
|
||||
* Bits 21 - 12: P = Physical Line partitions**.
|
||||
* Bits 31 - 22: W = Ways of associativity**.
|
||||
*/
|
||||
entry->ebx &= ~0xFFC00000U;
|
||||
/* Report # of cache ways (CBM length) to guest VM */
|
||||
entry->ebx |= (vcbm_len - 1U) << 22U;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RDT allocation enumeration sub-leaf (EAX = 10H, ECX = 0)
|
||||
* Expose CAT capabilities to guest VM
|
||||
*
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static int32_t set_vcpuid_vcat_10h_subleaf_0(struct acrn_vm *vm, bool l2, bool l3)
|
||||
{
|
||||
struct vcpuid_entry entry;
|
||||
|
||||
init_vcpuid_entry(CPUID_RDT_ALLOCATION, 0U, CPUID_CHECK_SUBLEAF, &entry);
|
||||
|
||||
entry.ebx &= ~0xeU; /* Set the L3/L2/MBA bits (bits 1, 2, and 3) all to 0 (not supported) */
|
||||
|
||||
if (l2) {
|
||||
/* Bit 02: Supports L2 Cache Allocation Technology if 1 */
|
||||
entry.ebx |= 0x4U;
|
||||
}
|
||||
|
||||
if (l3) {
|
||||
/* Bit 01: Supports L3 Cache Allocation Technology if 1 */
|
||||
entry.ebx |= 0x2U;
|
||||
}
|
||||
|
||||
return set_vcpuid_entry(vm, &entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief L2/L3 enumeration sub-leaf
|
||||
*
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static int32_t set_vcpuid_vcat_10h_subleaf_res(struct acrn_vm *vm, uint32_t subleaf, uint16_t num_vclosids)
|
||||
{
|
||||
struct vcpuid_entry entry;
|
||||
uint16_t vcbm_len;
|
||||
int res;
|
||||
|
||||
if (subleaf == 1U) {
|
||||
res = RDT_RESOURCE_L3;
|
||||
} else {
|
||||
res = RDT_RESOURCE_L2;
|
||||
}
|
||||
vcbm_len = vcat_get_vcbm_len(vm, res);
|
||||
|
||||
/* Set cache cbm_len */
|
||||
init_vcpuid_entry(CPUID_RDT_ALLOCATION, subleaf, CPUID_CHECK_SUBLEAF, &entry);
|
||||
|
||||
if ((entry.eax != 0U) && (vcbm_len != 0U)) {
|
||||
/* Bits 4 - 00: Length of the capacity bit mask for the corresponding ResID using minus-one notation */
|
||||
entry.eax = (entry.eax & ~0x1F) | (vcbm_len - 1U);
|
||||
|
||||
/* Bits 31 - 00: Bit-granular map of isolation/contention of allocation units
|
||||
* Each set bit within the length of the CBM indicates the corresponding unit of the L2/L3 allocation
|
||||
* may be used by other entities in the platform. Each cleared bit within the length of the CBM
|
||||
* indicates the corresponding allocation unit can be configured to implement a priority-based
|
||||
* allocation scheme chosen by an OS/VMM without interference with other hardware agents in the system.
|
||||
*/
|
||||
entry.ebx = (uint32_t)vcat_pcbm_to_vcbm(vm, entry.ebx, res);
|
||||
|
||||
/* Do not support CDP for now */
|
||||
entry.ecx &= ~0x4U;
|
||||
|
||||
/* Report max CLOS to guest VM
|
||||
* Bits 15 - 00: Highest COS number supported for this ResID using minus-one notation
|
||||
*/
|
||||
entry.edx = (entry.edx & 0xFFFF0000U) | (num_vclosids - 1U);
|
||||
}
|
||||
|
||||
return set_vcpuid_entry(vm, &entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static int32_t set_vcpuid_vcat_10h(struct acrn_vm *vm)
|
||||
{
|
||||
int32_t result;
|
||||
uint16_t num_vclosids = vcat_get_num_vclosids(vm);
|
||||
bool l2 = is_l2_vcat_configured(vm);
|
||||
bool l3 = is_l3_vcat_configured(vm);
|
||||
|
||||
/* RDT allocation enumeration sub-leaf (EAX=10H, ECX=0) */
|
||||
result = set_vcpuid_vcat_10h_subleaf_0(vm, l2, l3);
|
||||
|
||||
if ((result == 0) && l2) {
|
||||
/* L2 enumeration sub-leaf (EAX=10H, ECX=2) */
|
||||
result = set_vcpuid_vcat_10h_subleaf_res(vm, 2U, num_vclosids);
|
||||
}
|
||||
|
||||
if ((result == 0) && l3) {
|
||||
/* L3 enumeration sub-leaf (EAX=10H, ECX=1) */
|
||||
result = set_vcpuid_vcat_10h_subleaf_res(vm, 1U, num_vclosids);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t set_vcpuid_extended_function(struct acrn_vm *vm)
|
||||
{
|
||||
uint32_t i, limit;
|
||||
@ -376,6 +521,12 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
|
||||
if (entry.eax == 0U) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
if (is_vcat_configured(vm)) {
|
||||
result = set_vcpuid_vcat_04h(vm, &entry);
|
||||
}
|
||||
#endif
|
||||
result = set_vcpuid_entry(vm, &entry);
|
||||
if (result != 0) {
|
||||
/* wants to break out of switch */
|
||||
@ -392,6 +543,13 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
|
||||
if (is_vsgx_supported(vm->vm_id)) {
|
||||
entry.ebx |= CPUID_EBX_SGX;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
if (is_vcat_configured(vm)) {
|
||||
/* Bit 15: Supports Intel Resource Director Technology (Intel RDT) Allocation capability if 1 */
|
||||
entry.ebx |= CPUID_EBX_PQE;
|
||||
}
|
||||
#endif
|
||||
result = set_vcpuid_entry(vm, &entry);
|
||||
break;
|
||||
case 0x12U:
|
||||
@ -408,7 +566,16 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
|
||||
|
||||
/* Intel RDT */
|
||||
case 0x0fU:
|
||||
break;
|
||||
/* Intel RDT */
|
||||
case 0x10U:
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
if (is_vcat_configured(vm)) {
|
||||
result = set_vcpuid_vcat_10h(vm);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* Intel Processor Trace */
|
||||
case 0x14U:
|
||||
/* PCONFIG */
|
||||
|
@ -9,7 +9,12 @@
|
||||
|
||||
#include <asm/guest/vm.h>
|
||||
|
||||
bool is_l2_vcat_configured(const struct acrn_vm *vm);
|
||||
bool is_l3_vcat_configured(const struct acrn_vm *vm);
|
||||
uint16_t vcat_get_vcbm_len(const struct acrn_vm *vm, int res);
|
||||
void init_vcat_msrs(struct acrn_vcpu *vcpu);
|
||||
uint16_t vcat_get_num_vclosids(const struct acrn_vm *vm);
|
||||
uint64_t vcat_pcbm_to_vcbm(const struct acrn_vm *vm, uint64_t pcbm, int res);
|
||||
|
||||
#endif /* VCAT_H_ */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user