aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2015-10-01 07:20:22 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2015-10-01 07:30:44 -0400
commitfc07e76ac7ffa3afd621a1c3858a503386a14281 (patch)
tree666420f710cccb20cb17cded72f3595fb1aa49e1
parentbcf166a9942c3aabd8b752a7c38a49f57c54cfb8 (diff)
Revert "KVM: SVM: use NPT page attributes"
This reverts commit 3c2e7f7de3240216042b61073803b61b9b3cfb22. Initializing the mapping from MTRR to PAT values was reported to fail nondeterministically, and it also caused extremely slow boot (due to caching getting disabled---bug 103321) with assigned devices. Reported-by: Markus Trippelsdorf <markus@trippelsdorf.de> Reported-by: Sebastian Schuette <dracon@ewetel.net> Cc: stable@vger.kernel.org # 4.2+ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/svm.c101
1 files changed, 5 insertions, 96 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 7c242b7007ac..99b3c5f40bf7 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -866,64 +866,6 @@ static void svm_disable_lbrv(struct vcpu_svm *svm)
866 set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0); 866 set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
867} 867}
868 868
869#define MTRR_TYPE_UC_MINUS 7
870#define MTRR2PROTVAL_INVALID 0xff
871
872static u8 mtrr2protval[8];
873
874static u8 fallback_mtrr_type(int mtrr)
875{
876 /*
877 * WT and WP aren't always available in the host PAT. Treat
878 * them as UC and UC- respectively. Everything else should be
879 * there.
880 */
881 switch (mtrr)
882 {
883 case MTRR_TYPE_WRTHROUGH:
884 return MTRR_TYPE_UNCACHABLE;
885 case MTRR_TYPE_WRPROT:
886 return MTRR_TYPE_UC_MINUS;
887 default:
888 BUG();
889 }
890}
891
892static void build_mtrr2protval(void)
893{
894 int i;
895 u64 pat;
896
897 for (i = 0; i < 8; i++)
898 mtrr2protval[i] = MTRR2PROTVAL_INVALID;
899
900 /* Ignore the invalid MTRR types. */
901 mtrr2protval[2] = 0;
902 mtrr2protval[3] = 0;
903
904 /*
905 * Use host PAT value to figure out the mapping from guest MTRR
906 * values to nested page table PAT/PCD/PWT values. We do not
907 * want to change the host PAT value every time we enter the
908 * guest.
909 */
910 rdmsrl(MSR_IA32_CR_PAT, pat);
911 for (i = 0; i < 8; i++) {
912 u8 mtrr = pat >> (8 * i);
913
914 if (mtrr2protval[mtrr] == MTRR2PROTVAL_INVALID)
915 mtrr2protval[mtrr] = __cm_idx2pte(i);
916 }
917
918 for (i = 0; i < 8; i++) {
919 if (mtrr2protval[i] == MTRR2PROTVAL_INVALID) {
920 u8 fallback = fallback_mtrr_type(i);
921 mtrr2protval[i] = mtrr2protval[fallback];
922 BUG_ON(mtrr2protval[i] == MTRR2PROTVAL_INVALID);
923 }
924 }
925}
926
927static __init int svm_hardware_setup(void) 869static __init int svm_hardware_setup(void)
928{ 870{
929 int cpu; 871 int cpu;
@@ -990,7 +932,6 @@ static __init int svm_hardware_setup(void)
990 } else 932 } else
991 kvm_disable_tdp(); 933 kvm_disable_tdp();
992 934
993 build_mtrr2protval();
994 return 0; 935 return 0;
995 936
996err: 937err:
@@ -1145,42 +1086,6 @@ static u64 svm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
1145 return target_tsc - tsc; 1086 return target_tsc - tsc;
1146} 1087}
1147 1088
1148static void svm_set_guest_pat(struct vcpu_svm *svm, u64 *g_pat)
1149{
1150 struct kvm_vcpu *vcpu = &svm->vcpu;
1151
1152 /* Unlike Intel, AMD takes the guest's CR0.CD into account.
1153 *
1154 * AMD does not have IPAT. To emulate it for the case of guests
1155 * with no assigned devices, just set everything to WB. If guests
1156 * have assigned devices, however, we cannot force WB for RAM
1157 * pages only, so use the guest PAT directly.
1158 */
1159 if (!kvm_arch_has_assigned_device(vcpu->kvm))
1160 *g_pat = 0x0606060606060606;
1161 else
1162 *g_pat = vcpu->arch.pat;
1163}
1164
1165static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
1166{
1167 u8 mtrr;
1168
1169 /*
1170 * 1. MMIO: always map as UC
1171 * 2. No passthrough: always map as WB, and force guest PAT to WB as well
1172 * 3. Passthrough: can't guarantee the result, try to trust guest.
1173 */
1174 if (is_mmio)
1175 return _PAGE_NOCACHE;
1176
1177 if (!kvm_arch_has_assigned_device(vcpu->kvm))
1178 return 0;
1179
1180 mtrr = kvm_mtrr_get_guest_memory_type(vcpu, gfn);
1181 return mtrr2protval[mtrr];
1182}
1183
1184static void init_vmcb(struct vcpu_svm *svm, bool init_event) 1089static void init_vmcb(struct vcpu_svm *svm, bool init_event)
1185{ 1090{
1186 struct vmcb_control_area *control = &svm->vmcb->control; 1091 struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1277,7 +1182,6 @@ static void init_vmcb(struct vcpu_svm *svm, bool init_event)
1277 clr_cr_intercept(svm, INTERCEPT_CR3_READ); 1182 clr_cr_intercept(svm, INTERCEPT_CR3_READ);
1278 clr_cr_intercept(svm, INTERCEPT_CR3_WRITE); 1183 clr_cr_intercept(svm, INTERCEPT_CR3_WRITE);
1279 save->g_pat = svm->vcpu.arch.pat; 1184 save->g_pat = svm->vcpu.arch.pat;
1280 svm_set_guest_pat(svm, &save->g_pat);
1281 save->cr3 = 0; 1185 save->cr3 = 0;
1282 save->cr4 = 0; 1186 save->cr4 = 0;
1283 } 1187 }
@@ -4187,6 +4091,11 @@ static bool svm_has_high_real_mode_segbase(void)
4187 return true; 4091 return true;
4188} 4092}
4189 4093
4094static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
4095{
4096 return 0;
4097}
4098
4190static void svm_cpuid_update(struct kvm_vcpu *vcpu) 4099static void svm_cpuid_update(struct kvm_vcpu *vcpu)
4191{ 4100{
4192} 4101}