mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-01 09:42:10 +00:00
hv: vCAT: implementing the vCAT MSRs write handler
Implement the write_vcbm() function to handle the MSR_IA32_type_MASK_n vCBM MSRs write request Call write_vclosid() to handle MSR_IA32_PQR_ASSOC MSR write request Several vCAT P2V (physical to virtual) and V2P (virtual to physical) mappings exist: struct acrn_vm_config *vm_config = get_vm_config(vm_id) max_pcbm = vm_config->max_type_pcbm (type: l2 or l3) mask_shift = ffs64(max_pcbm) vclosid = vmsr - MSR_IA32_type_MASK_0 pclosid = vm_config->pclosids[vclosid] pmsr = MSR_IA32_type_MASK_0 + pclosid pcbm = vcbm << mask_shift vcbm = pcbm >> mask_shift Where MSR_IA32_type_MASK_n: L2 or L3 mask msr address for CLOSIDn, from 0C90H through 0D8FH (inclusive). max_pcbm: a bitmask that selects all the physical cache ways assigned to the VM vclosid: virtual CLOSID, always starts from 0 pclosid: corresponding physical CLOSID for a given vclosid vmsr: virtual msr address, passed to vCAT handlers by the caller functions rdmsr_vmexit_handler()/wrmsr_vmexit_handler() pmsr: physical msr address vcbm: virtual CBM, passed to vCAT handlers by the caller functions rdmsr_vmexit_handler()/wrmsr_vmexit_handler() pcbm: physical CBM 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
3ab50f2ef5
commit
a7014f4654
@ -209,20 +209,97 @@ int32_t read_vcbm(const struct acrn_vcpu *vcpu, uint32_t vmsr, uint64_t *rval)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Map vCBM to pCBM
|
||||
*
|
||||
* @pre vm != NULL && ((vcbm & vcat_get_max_vcbm(vm, res)) == vcbm)
|
||||
*/
|
||||
static uint64_t vcbm_to_pcbm(const struct acrn_vm *vm, uint64_t vcbm, 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);
|
||||
|
||||
return vcbm << low;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if bitmask is contiguous:
|
||||
* All (and only) contiguous '1' combinations are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.)
|
||||
*/
|
||||
static bool is_contiguous(uint64_t bitmask)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (bitmask != 0UL) {
|
||||
uint16_t low = ffs64(bitmask);
|
||||
uint16_t high = fls64(bitmask);
|
||||
|
||||
if (((2UL << high) - (1UL << low)) == bitmask) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief vCBM MSR write handler
|
||||
*
|
||||
* @pre vcpu != NULL && vcpu->vm != NULL
|
||||
*/
|
||||
int32_t write_vcbm(__unused struct acrn_vcpu *vcpu, __unused uint32_t vmsr, __unused uint64_t val)
|
||||
int32_t write_vcbm(struct acrn_vcpu *vcpu, uint32_t vmsr, uint64_t val)
|
||||
{
|
||||
/*
|
||||
* TODO: this is going to be implemented in a subsequent commit, will perform the following actions:
|
||||
* write vCBM
|
||||
* vmsr to pmsr and vcbm to pcbm
|
||||
* write pCBM
|
||||
*/
|
||||
return -EACCES;
|
||||
int ret = -EACCES;
|
||||
struct acrn_vm *vm = vcpu->vm;
|
||||
int res = -1;
|
||||
uint32_t msr_base;
|
||||
|
||||
if (is_vcat_configured(vm)) {
|
||||
if (is_l2_vcbm_msr(vm, vmsr)) {
|
||||
res = RDT_RESOURCE_L2;
|
||||
msr_base = MSR_IA32_L2_MASK_BASE;
|
||||
} else if (is_l3_vcbm_msr(vm, vmsr)) {
|
||||
res = RDT_RESOURCE_L3;
|
||||
msr_base = MSR_IA32_L3_MASK_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
if (res >= 0) {
|
||||
/*
|
||||
* vcbm set bits should only be in the range of [0, vcbm_len) (vcat_get_max_vcbm),
|
||||
* so mask with vcat_get_max_vcbm to prevent erroneous vCBM value
|
||||
*/
|
||||
uint64_t masked_vcbm = val & vcat_get_max_vcbm(vm, res);
|
||||
|
||||
/*
|
||||
* Validity check on val:
|
||||
* Bits 63:32 of val are reserved and must be written with zeros
|
||||
* (satisfied by the masked_vcbm == val condition)
|
||||
* vCBM must be contiguous
|
||||
*/
|
||||
if ((masked_vcbm == val) && is_contiguous(val)) {
|
||||
uint32_t pmsr;
|
||||
uint16_t vclosid;
|
||||
uint64_t pcbm, pvalue;
|
||||
|
||||
/* Write vCBM first: */
|
||||
vcpu_set_guest_msr(vcpu, vmsr, val);
|
||||
|
||||
/* Write pCBM: */
|
||||
vclosid = (uint16_t)(vmsr - msr_base);
|
||||
pmsr = msr_base + (uint32_t)vclosid_to_pclosid(vm, vclosid);
|
||||
pcbm = vcbm_to_pcbm(vm, val, res);
|
||||
/* Preserve reserved bits, and only set the pCBM bits */
|
||||
pvalue = (msr_read(pmsr) & ~get_max_pcbm(vm, res)) | pcbm;
|
||||
msr_write(pmsr, pvalue);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1098,6 +1098,19 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
case MSR_IA32_L2_MASK_BASE ... (MSR_IA32_L2_MASK_BASE + NUM_VCAT_L2_MSRS - 1U):
|
||||
case MSR_IA32_L3_MASK_BASE ... (MSR_IA32_L3_MASK_BASE + NUM_VCAT_L3_MSRS - 1U):
|
||||
{
|
||||
err = write_vcbm(vcpu, msr, v);
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_PQR_ASSOC:
|
||||
{
|
||||
err = write_vclosid(vcpu, v);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
if (is_x2apic_msr(msr)) {
|
||||
|
@ -16,7 +16,9 @@ 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);
|
||||
int32_t read_vcbm(const struct acrn_vcpu *vcpu, uint32_t vmsr, uint64_t *rval);
|
||||
int32_t write_vcbm(struct acrn_vcpu *vcpu, uint32_t vmsr, uint64_t val);
|
||||
int32_t read_vclosid(const struct acrn_vcpu *vcpu, uint64_t *rval);
|
||||
int32_t write_vclosid(struct acrn_vcpu *vcpu, uint64_t val);
|
||||
|
||||
#endif /* VCAT_H_ */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user