Expand the size of the variable ranges array to match the size of the underlying hardware, this is a preparatory change for copying the hardware MTRR state for Dom0.
Signed-off-by: Roger Pau Monné <roger....@citrix.com> --- Cc: Jan Beulich <jbeul...@suse.com> Cc: Andrew Cooper <andrew.coop...@citrix.com> --- Changes since v2: - Use Dom%u in hvm_vcpu_cacheattr_init error message. - Print debug error messages in hvm_save_mtrr_msr. - Use ARRAY_SIZE in hvm_save_mtrr_msr to calculate the number of MTRR ranges in the save record. - Calculate MTRR_VCNT_MAX based on current MSR indexes. Changes since v1: - Fix hvm_msr_{read,write}_intercept(). - Relax the checks in hvm_{save/load}_mtrr_msr. --- xen/arch/x86/hvm/hvm.c | 7 +++++-- xen/arch/x86/hvm/mtrr.c | 28 ++++++++++++++++++++++++++-- xen/include/asm-x86/mtrr.h | 3 +++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 247b3eb1bd..b3da4050e2 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3491,10 +3491,13 @@ int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content) index = msr - MSR_MTRRfix4K_C0000; *msr_content = fixed_range_base[index + 3]; break; - case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT-1): + case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT_MAX - 1): if ( !d->arch.cpuid->basic.mtrr ) goto gp_fault; index = msr - MSR_IA32_MTRR_PHYSBASE(0); + if ( (index / 2) >= + MASK_EXTR(v->arch.hvm_vcpu.mtrr.mtrr_cap, MTRRcap_VCNT) ) + goto gp_fault; *msr_content = var_range_base[index]; break; @@ -3652,7 +3655,7 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content, index, msr_content) ) goto gp_fault; break; - case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT-1): + case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT_MAX - 1): if ( !d->arch.cpuid->basic.mtrr ) goto gp_fault; if ( !mtrr_var_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr, diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c index 2f8f8ddd8f..37ac3271d6 100644 --- a/xen/arch/x86/hvm/mtrr.c +++ b/xen/arch/x86/hvm/mtrr.c @@ -154,14 +154,26 @@ uint8_t pat_type_2_pte_flags(uint8_t pat_type) int hvm_vcpu_cacheattr_init(struct vcpu *v) { struct mtrr_state *m = &v->arch.hvm_vcpu.mtrr; + unsigned int num_var_ranges = + is_hardware_domain(v->domain) ? MASK_EXTR(mtrr_state.mtrr_cap, + MTRRcap_VCNT) + : MTRR_VCNT; + + if ( num_var_ranges > MTRR_VCNT_MAX ) + { + ASSERT(is_hardware_domain(v->domain)); + printk("WARNING: limited Dom%u variable range MTRRs from %u to %u\n", + v->domain->domain_id, num_var_ranges, MTRR_VCNT_MAX); + num_var_ranges = MTRR_VCNT_MAX; + } memset(m, 0, sizeof(*m)); - m->var_ranges = xzalloc_array(struct mtrr_var_range, MTRR_VCNT); + m->var_ranges = xzalloc_array(struct mtrr_var_range, num_var_ranges); if ( m->var_ranges == NULL ) return -ENOMEM; - m->mtrr_cap = (1u << 10) | (1u << 8) | MTRR_VCNT; + m->mtrr_cap = (1u << 10) | (1u << 8) | num_var_ranges; v->arch.hvm_vcpu.pat_cr = ((uint64_t)PAT_TYPE_WRBACK) | /* PAT0: WB */ @@ -448,6 +460,9 @@ bool_t mtrr_var_range_msr_set( uint64_t *var_range_base = (uint64_t*)m->var_ranges; index = msr - MSR_IA32_MTRR_PHYSBASE(0); + if ( (index / 2) >= MASK_EXTR(m->mtrr_cap, MTRRcap_VCNT) ) + return 0; + if ( var_range_base[index] == msr_content ) return 1; @@ -691,6 +706,15 @@ static int hvm_save_mtrr_msr(struct domain *d, hvm_domain_context_t *h) }; unsigned int i; + if ( MASK_EXTR(hw_mtrr.msr_mtrr_cap, MTRRcap_VCNT) > + (ARRAY_SIZE(hw_mtrr.msr_mtrr_var) / 2) ) + { + dprintk(XENLOG_G_ERR, + "HVM save: %pv: too many (%lu) variable range MTRRs\n", + v, MASK_EXTR(hw_mtrr.msr_mtrr_cap, MTRRcap_VCNT)); + return -EINVAL; + } + hvm_get_guest_pat(v, &hw_mtrr.msr_pat_cr); for ( i = 0; i < MASK_EXTR(hw_mtrr.msr_mtrr_cap, MTRRcap_VCNT); i++ ) diff --git a/xen/include/asm-x86/mtrr.h b/xen/include/asm-x86/mtrr.h index b1f7af6396..72d0690e28 100644 --- a/xen/include/asm-x86/mtrr.h +++ b/xen/include/asm-x86/mtrr.h @@ -39,6 +39,9 @@ typedef u8 mtrr_type; #define MTRR_PHYSBASE_SHIFT 12 /* Number of variable range MSR pairs we emulate for HVM guests: */ #define MTRR_VCNT 8 +/* Maximum number of variable range MSR pairs if FE is supported. */ +#define MTRR_VCNT_MAX ((MSR_MTRRfix64K_00000 - \ + MSR_IA32_MTRR_PHYSBASE(0)) / 2) struct mtrr_var_range { uint64_t base; -- 2.17.0 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel