mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-04 11:07:51 +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;
|
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
|
* @brief vCBM MSR write handler
|
||||||
*
|
*
|
||||||
* @pre vcpu != NULL && vcpu->vm != NULL
|
* @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)
|
||||||
{
|
{
|
||||||
|
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) {
|
||||||
/*
|
/*
|
||||||
* TODO: this is going to be implemented in a subsequent commit, will perform the following actions:
|
* vcbm set bits should only be in the range of [0, vcbm_len) (vcat_get_max_vcbm),
|
||||||
* write vCBM
|
* so mask with vcat_get_max_vcbm to prevent erroneous vCBM value
|
||||||
* vmsr to pmsr and vcbm to pcbm
|
|
||||||
* write pCBM
|
|
||||||
*/
|
*/
|
||||||
return -EACCES;
|
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;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
if (is_x2apic_msr(msr)) {
|
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);
|
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);
|
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 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 read_vclosid(const struct acrn_vcpu *vcpu, uint64_t *rval);
|
||||||
|
int32_t write_vclosid(struct acrn_vcpu *vcpu, uint64_t val);
|
||||||
|
|
||||||
#endif /* VCAT_H_ */
|
#endif /* VCAT_H_ */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user