|
@@ -120,14 +120,22 @@ static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state)
|
|
|
return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK;
|
|
|
}
|
|
|
|
|
|
-static u8 mtrr_disabled_type(void)
|
|
|
+static u8 mtrr_disabled_type(struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
/*
|
|
|
* Intel SDM 11.11.2.2: all MTRRs are disabled when
|
|
|
* IA32_MTRR_DEF_TYPE.E bit is cleared, and the UC
|
|
|
* memory type is applied to all of physical memory.
|
|
|
+ *
|
|
|
+ * However, virtual machines can be run with CPUID such that
|
|
|
+ * there are no MTRRs. In that case, the firmware will never
|
|
|
+ * enable MTRRs and it is obviously undesirable to run the
|
|
|
+ * guest entirely with UC memory and we use WB.
|
|
|
*/
|
|
|
- return MTRR_TYPE_UNCACHABLE;
|
|
|
+ if (guest_cpuid_has_mtrr(vcpu))
|
|
|
+ return MTRR_TYPE_UNCACHABLE;
|
|
|
+ else
|
|
|
+ return MTRR_TYPE_WRBACK;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -267,7 +275,7 @@ static int fixed_mtrr_addr_to_seg(u64 addr)
|
|
|
|
|
|
for (seg = 0; seg < seg_num; seg++) {
|
|
|
mtrr_seg = &fixed_seg_table[seg];
|
|
|
- if (mtrr_seg->start >= addr && addr < mtrr_seg->end)
|
|
|
+ if (mtrr_seg->start <= addr && addr < mtrr_seg->end)
|
|
|
return seg;
|
|
|
}
|
|
|
|
|
@@ -300,7 +308,6 @@ static void var_mtrr_range(struct kvm_mtrr_range *range, u64 *start, u64 *end)
|
|
|
*start = range->base & PAGE_MASK;
|
|
|
|
|
|
mask = range->mask & PAGE_MASK;
|
|
|
- mask |= ~0ULL << boot_cpu_data.x86_phys_bits;
|
|
|
|
|
|
/* This cannot overflow because writing to the reserved bits of
|
|
|
* variable MTRRs causes a #GP.
|
|
@@ -356,10 +363,14 @@ static void set_var_mtrr_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
|
|
if (var_mtrr_range_is_valid(cur))
|
|
|
list_del(&mtrr_state->var_ranges[index].node);
|
|
|
|
|
|
+ /* Extend the mask with all 1 bits to the left, since those
|
|
|
+ * bits must implicitly be 0. The bits are then cleared
|
|
|
+ * when reading them.
|
|
|
+ */
|
|
|
if (!is_mtrr_mask)
|
|
|
cur->base = data;
|
|
|
else
|
|
|
- cur->mask = data;
|
|
|
+ cur->mask = data | (-1LL << cpuid_maxphyaddr(vcpu));
|
|
|
|
|
|
/* add it to the list if it's enabled. */
|
|
|
if (var_mtrr_range_is_valid(cur)) {
|
|
@@ -426,6 +437,8 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
|
|
|
*pdata = vcpu->arch.mtrr_state.var_ranges[index].base;
|
|
|
else
|
|
|
*pdata = vcpu->arch.mtrr_state.var_ranges[index].mask;
|
|
|
+
|
|
|
+ *pdata &= (1ULL << cpuid_maxphyaddr(vcpu)) - 1;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -670,7 +683,7 @@ u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
|
|
|
}
|
|
|
|
|
|
if (iter.mtrr_disabled)
|
|
|
- return mtrr_disabled_type();
|
|
|
+ return mtrr_disabled_type(vcpu);
|
|
|
|
|
|
/* not contained in any MTRRs. */
|
|
|
if (type == -1)
|