diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index a3a2c32459..c52044e63c 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2810,6 +2810,8 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, switch ( input ) { + unsigned int sub_leaf, _eax, _ebx, _ecx, _edx; + case 0x1: /* Fix up VLAPIC details. */ *ebx &= 0x00FFFFFFu; @@ -2843,8 +2845,6 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, *edx = v->vcpu_id * 2; break; case 0xd: - { - unsigned int sub_leaf, _eax, _ebx, _ecx, _edx; /* EBX value of main leaf 0 depends on enabled xsave features */ if ( count == 0 && v->arch.xcr0 ) { @@ -2861,7 +2861,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, } } break; - } + case 0x80000001: /* We expose RDTSCP feature to guest only when tsc_mode == TSC_MODE_DEFAULT and host_tsc_is_safe() returns 1 */ @@ -2875,6 +2875,23 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, if ( !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) ) *edx &= ~cpufeat_mask(X86_FEATURE_PSE36); break; + + case 0x80000008: + count = cpuid_eax(0x80000008); + count = (count >> 16) & 0xff ?: count & 0xff; + if ( (*eax & 0xff) > count ) + *eax = (*eax & ~0xff) | count; + + hvm_cpuid(1, NULL, NULL, NULL, &_edx); + count = _edx & (cpufeat_mask(X86_FEATURE_PAE) | + cpufeat_mask(X86_FEATURE_PSE36)) ? 36 : 32; + if ( (*eax & 0xff) < count ) + *eax = (*eax & ~0xff) | count; + + hvm_cpuid(0x80000001, NULL, NULL, NULL, &_edx); + *eax = (*eax & ~0xffff00) | (_edx & cpufeat_mask(X86_FEATURE_LM) + ? 0x3000 : 0x2000); + break; } } diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c index 146c2e6b7f..1ee08edb65 100644 --- a/xen/arch/x86/hvm/mtrr.c +++ b/xen/arch/x86/hvm/mtrr.c @@ -145,7 +145,7 @@ bool_t is_var_mtrr_overlapped(struct mtrr_state *m) static int hvm_mtrr_pat_init(void) { - unsigned int i, j, phys_addr; + unsigned int i, j; memset(&mtrr_epat_tbl, INVALID_MEM_TYPE, sizeof(mtrr_epat_tbl)); for ( i = 0; i < MTRR_NUM_TYPES; i++ ) @@ -172,11 +172,7 @@ static int hvm_mtrr_pat_init(void) } } - phys_addr = 36; - if ( cpuid_eax(0x80000000) >= 0x80000008 ) - phys_addr = (uint8_t)cpuid_eax(0x80000008); - - size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1); + size_or_mask = ~((1 << (paddr_bits - PAGE_SHIFT)) - 1); return 0; } @@ -468,16 +464,21 @@ bool_t mtrr_var_range_msr_set( type == 4 || type == 5 || type == 6)) ) return 0; - phys_addr = 36; - domain_cpuid(d, 0x80000000, 0, &eax, &ebx, &ecx, &edx); - if ( eax >= 0x80000008 ) + if ( d == current->domain ) { - domain_cpuid(d, 0x80000008, 0, &eax, &ebx, &ecx, &edx); - phys_addr = (uint8_t)eax; + phys_addr = 36; + hvm_cpuid(0x80000000, &eax, &ebx, &ecx, &edx); + if ( eax >= 0x80000008 ) + { + hvm_cpuid(0x80000008, &eax, &ebx, &ecx, &edx); + phys_addr = (uint8_t)eax; + } } + else + phys_addr = paddr_bits; msr_mask = ~((((uint64_t)1) << phys_addr) - 1); msr_mask |= (index & 1) ? 0x7ffUL : 0xf00UL; - if ( unlikely(msr_content && (msr_content & msr_mask)) ) + if ( unlikely(msr_content & msr_mask) ) { HVM_DBG_LOG(DBG_LEVEL_MSR, "invalid msr content:%"PRIx64"\n", msr_content);