1ff53604bSXiao Guangrong /* 2ff53604bSXiao Guangrong * vMTRR implementation 3ff53604bSXiao Guangrong * 4ff53604bSXiao Guangrong * Copyright (C) 2006 Qumranet, Inc. 5ff53604bSXiao Guangrong * Copyright 2010 Red Hat, Inc. and/or its affiliates. 6ff53604bSXiao Guangrong * Copyright(C) 2015 Intel Corporation. 7ff53604bSXiao Guangrong * 8ff53604bSXiao Guangrong * Authors: 9ff53604bSXiao Guangrong * Yaniv Kamay <yaniv@qumranet.com> 10ff53604bSXiao Guangrong * Avi Kivity <avi@qumranet.com> 11ff53604bSXiao Guangrong * Marcelo Tosatti <mtosatti@redhat.com> 12ff53604bSXiao Guangrong * Paolo Bonzini <pbonzini@redhat.com> 13ff53604bSXiao Guangrong * Xiao Guangrong <guangrong.xiao@linux.intel.com> 14ff53604bSXiao Guangrong * 15ff53604bSXiao Guangrong * This work is licensed under the terms of the GNU GPL, version 2. See 16ff53604bSXiao Guangrong * the COPYING file in the top-level directory. 17ff53604bSXiao Guangrong */ 18ff53604bSXiao Guangrong 19ff53604bSXiao Guangrong #include <linux/kvm_host.h> 20ff53604bSXiao Guangrong #include <asm/mtrr.h> 21ff53604bSXiao Guangrong 22ff53604bSXiao Guangrong #include "cpuid.h" 23ff53604bSXiao Guangrong #include "mmu.h" 24ff53604bSXiao Guangrong 25ff53604bSXiao Guangrong static bool msr_mtrr_valid(unsigned msr) 26ff53604bSXiao Guangrong { 27ff53604bSXiao Guangrong switch (msr) { 28ff53604bSXiao Guangrong case 0x200 ... 0x200 + 2 * KVM_NR_VAR_MTRR - 1: 29ff53604bSXiao Guangrong case MSR_MTRRfix64K_00000: 30ff53604bSXiao Guangrong case MSR_MTRRfix16K_80000: 31ff53604bSXiao Guangrong case MSR_MTRRfix16K_A0000: 32ff53604bSXiao Guangrong case MSR_MTRRfix4K_C0000: 33ff53604bSXiao Guangrong case MSR_MTRRfix4K_C8000: 34ff53604bSXiao Guangrong case MSR_MTRRfix4K_D0000: 35ff53604bSXiao Guangrong case MSR_MTRRfix4K_D8000: 36ff53604bSXiao Guangrong case MSR_MTRRfix4K_E0000: 37ff53604bSXiao Guangrong case MSR_MTRRfix4K_E8000: 38ff53604bSXiao Guangrong case MSR_MTRRfix4K_F0000: 39ff53604bSXiao Guangrong case MSR_MTRRfix4K_F8000: 40ff53604bSXiao Guangrong case MSR_MTRRdefType: 41ff53604bSXiao Guangrong case MSR_IA32_CR_PAT: 42ff53604bSXiao Guangrong return true; 43ff53604bSXiao Guangrong case 0x2f8: 44ff53604bSXiao Guangrong return true; 45ff53604bSXiao Guangrong } 46ff53604bSXiao Guangrong return false; 47ff53604bSXiao Guangrong } 48ff53604bSXiao Guangrong 49ff53604bSXiao Guangrong static bool valid_pat_type(unsigned t) 50ff53604bSXiao Guangrong { 51ff53604bSXiao Guangrong return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */ 52ff53604bSXiao Guangrong } 53ff53604bSXiao Guangrong 54ff53604bSXiao Guangrong static bool valid_mtrr_type(unsigned t) 55ff53604bSXiao Guangrong { 56ff53604bSXiao Guangrong return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */ 57ff53604bSXiao Guangrong } 58ff53604bSXiao Guangrong 59ff53604bSXiao Guangrong bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) 60ff53604bSXiao Guangrong { 61ff53604bSXiao Guangrong int i; 62ff53604bSXiao Guangrong u64 mask; 63ff53604bSXiao Guangrong 64ff53604bSXiao Guangrong if (!msr_mtrr_valid(msr)) 65ff53604bSXiao Guangrong return false; 66ff53604bSXiao Guangrong 67ff53604bSXiao Guangrong if (msr == MSR_IA32_CR_PAT) { 68ff53604bSXiao Guangrong for (i = 0; i < 8; i++) 69ff53604bSXiao Guangrong if (!valid_pat_type((data >> (i * 8)) & 0xff)) 70ff53604bSXiao Guangrong return false; 71ff53604bSXiao Guangrong return true; 72ff53604bSXiao Guangrong } else if (msr == MSR_MTRRdefType) { 73ff53604bSXiao Guangrong if (data & ~0xcff) 74ff53604bSXiao Guangrong return false; 75ff53604bSXiao Guangrong return valid_mtrr_type(data & 0xff); 76ff53604bSXiao Guangrong } else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) { 77ff53604bSXiao Guangrong for (i = 0; i < 8 ; i++) 78ff53604bSXiao Guangrong if (!valid_mtrr_type((data >> (i * 8)) & 0xff)) 79ff53604bSXiao Guangrong return false; 80ff53604bSXiao Guangrong return true; 81ff53604bSXiao Guangrong } 82ff53604bSXiao Guangrong 83ff53604bSXiao Guangrong /* variable MTRRs */ 84ff53604bSXiao Guangrong WARN_ON(!(msr >= 0x200 && msr < 0x200 + 2 * KVM_NR_VAR_MTRR)); 85ff53604bSXiao Guangrong 86ff53604bSXiao Guangrong mask = (~0ULL) << cpuid_maxphyaddr(vcpu); 87ff53604bSXiao Guangrong if ((msr & 1) == 0) { 88ff53604bSXiao Guangrong /* MTRR base */ 89ff53604bSXiao Guangrong if (!valid_mtrr_type(data & 0xff)) 90ff53604bSXiao Guangrong return false; 91ff53604bSXiao Guangrong mask |= 0xf00; 92ff53604bSXiao Guangrong } else 93ff53604bSXiao Guangrong /* MTRR mask */ 94ff53604bSXiao Guangrong mask |= 0x7ff; 95ff53604bSXiao Guangrong if (data & mask) { 96ff53604bSXiao Guangrong kvm_inject_gp(vcpu, 0); 97ff53604bSXiao Guangrong return false; 98ff53604bSXiao Guangrong } 99ff53604bSXiao Guangrong 100ff53604bSXiao Guangrong return true; 101ff53604bSXiao Guangrong } 102ff53604bSXiao Guangrong EXPORT_SYMBOL_GPL(kvm_mtrr_valid); 103ff53604bSXiao Guangrong 104ff53604bSXiao Guangrong static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr) 105ff53604bSXiao Guangrong { 106*70109e7dSXiao Guangrong struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state; 107ff53604bSXiao Guangrong unsigned char mtrr_enabled = mtrr_state->enabled; 108ff53604bSXiao Guangrong gfn_t start, end, mask; 109ff53604bSXiao Guangrong int index; 110ff53604bSXiao Guangrong bool is_fixed = true; 111ff53604bSXiao Guangrong 112ff53604bSXiao Guangrong if (msr == MSR_IA32_CR_PAT || !tdp_enabled || 113ff53604bSXiao Guangrong !kvm_arch_has_noncoherent_dma(vcpu->kvm)) 114ff53604bSXiao Guangrong return; 115ff53604bSXiao Guangrong 116ff53604bSXiao Guangrong if (!(mtrr_enabled & 0x2) && msr != MSR_MTRRdefType) 117ff53604bSXiao Guangrong return; 118ff53604bSXiao Guangrong 119ff53604bSXiao Guangrong switch (msr) { 120ff53604bSXiao Guangrong case MSR_MTRRfix64K_00000: 121ff53604bSXiao Guangrong start = 0x0; 122ff53604bSXiao Guangrong end = 0x80000; 123ff53604bSXiao Guangrong break; 124ff53604bSXiao Guangrong case MSR_MTRRfix16K_80000: 125ff53604bSXiao Guangrong start = 0x80000; 126ff53604bSXiao Guangrong end = 0xa0000; 127ff53604bSXiao Guangrong break; 128ff53604bSXiao Guangrong case MSR_MTRRfix16K_A0000: 129ff53604bSXiao Guangrong start = 0xa0000; 130ff53604bSXiao Guangrong end = 0xc0000; 131ff53604bSXiao Guangrong break; 132ff53604bSXiao Guangrong case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000: 133ff53604bSXiao Guangrong index = msr - MSR_MTRRfix4K_C0000; 134ff53604bSXiao Guangrong start = 0xc0000 + index * (32 << 10); 135ff53604bSXiao Guangrong end = start + (32 << 10); 136ff53604bSXiao Guangrong break; 137ff53604bSXiao Guangrong case MSR_MTRRdefType: 138ff53604bSXiao Guangrong is_fixed = false; 139ff53604bSXiao Guangrong start = 0x0; 140ff53604bSXiao Guangrong end = ~0ULL; 141ff53604bSXiao Guangrong break; 142ff53604bSXiao Guangrong default: 143ff53604bSXiao Guangrong /* variable range MTRRs. */ 144ff53604bSXiao Guangrong is_fixed = false; 145ff53604bSXiao Guangrong index = (msr - 0x200) / 2; 146ff53604bSXiao Guangrong start = (((u64)mtrr_state->var_ranges[index].base_hi) << 32) + 147ff53604bSXiao Guangrong (mtrr_state->var_ranges[index].base_lo & PAGE_MASK); 148ff53604bSXiao Guangrong mask = (((u64)mtrr_state->var_ranges[index].mask_hi) << 32) + 149ff53604bSXiao Guangrong (mtrr_state->var_ranges[index].mask_lo & PAGE_MASK); 150ff53604bSXiao Guangrong mask |= ~0ULL << cpuid_maxphyaddr(vcpu); 151ff53604bSXiao Guangrong 152ff53604bSXiao Guangrong end = ((start & mask) | ~mask) + 1; 153ff53604bSXiao Guangrong } 154ff53604bSXiao Guangrong 155ff53604bSXiao Guangrong if (is_fixed && !(mtrr_enabled & 0x1)) 156ff53604bSXiao Guangrong return; 157ff53604bSXiao Guangrong 158ff53604bSXiao Guangrong kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end)); 159ff53604bSXiao Guangrong } 160ff53604bSXiao Guangrong 161ff53604bSXiao Guangrong int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data) 162ff53604bSXiao Guangrong { 163ff53604bSXiao Guangrong u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges; 164ff53604bSXiao Guangrong 165ff53604bSXiao Guangrong if (!kvm_mtrr_valid(vcpu, msr, data)) 166ff53604bSXiao Guangrong return 1; 167ff53604bSXiao Guangrong 168ff53604bSXiao Guangrong if (msr == MSR_MTRRdefType) { 169ff53604bSXiao Guangrong vcpu->arch.mtrr_state.def_type = data; 170ff53604bSXiao Guangrong vcpu->arch.mtrr_state.enabled = (data & 0xc00) >> 10; 171ff53604bSXiao Guangrong } else if (msr == MSR_MTRRfix64K_00000) 172ff53604bSXiao Guangrong p[0] = data; 173ff53604bSXiao Guangrong else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000) 174ff53604bSXiao Guangrong p[1 + msr - MSR_MTRRfix16K_80000] = data; 175ff53604bSXiao Guangrong else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000) 176ff53604bSXiao Guangrong p[3 + msr - MSR_MTRRfix4K_C0000] = data; 177ff53604bSXiao Guangrong else if (msr == MSR_IA32_CR_PAT) 178ff53604bSXiao Guangrong vcpu->arch.pat = data; 179ff53604bSXiao Guangrong else { /* Variable MTRRs */ 180ff53604bSXiao Guangrong int idx, is_mtrr_mask; 181ff53604bSXiao Guangrong u64 *pt; 182ff53604bSXiao Guangrong 183ff53604bSXiao Guangrong idx = (msr - 0x200) / 2; 184ff53604bSXiao Guangrong is_mtrr_mask = msr - 0x200 - 2 * idx; 185ff53604bSXiao Guangrong if (!is_mtrr_mask) 186ff53604bSXiao Guangrong pt = 187ff53604bSXiao Guangrong (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].base_lo; 188ff53604bSXiao Guangrong else 189ff53604bSXiao Guangrong pt = 190ff53604bSXiao Guangrong (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].mask_lo; 191ff53604bSXiao Guangrong *pt = data; 192ff53604bSXiao Guangrong } 193ff53604bSXiao Guangrong 194ff53604bSXiao Guangrong update_mtrr(vcpu, msr); 195ff53604bSXiao Guangrong return 0; 196ff53604bSXiao Guangrong } 197ff53604bSXiao Guangrong 198ff53604bSXiao Guangrong int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) 199ff53604bSXiao Guangrong { 200ff53604bSXiao Guangrong u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges; 201ff53604bSXiao Guangrong 202eb839917SXiao Guangrong /* MSR_MTRRcap is a readonly MSR. */ 203eb839917SXiao Guangrong if (msr == MSR_MTRRcap) { 204eb839917SXiao Guangrong /* 205eb839917SXiao Guangrong * SMRR = 0 206eb839917SXiao Guangrong * WC = 1 207eb839917SXiao Guangrong * FIX = 1 208eb839917SXiao Guangrong * VCNT = KVM_NR_VAR_MTRR 209eb839917SXiao Guangrong */ 210eb839917SXiao Guangrong *pdata = 0x500 | KVM_NR_VAR_MTRR; 211eb839917SXiao Guangrong return 0; 212eb839917SXiao Guangrong } 213eb839917SXiao Guangrong 214ff53604bSXiao Guangrong if (!msr_mtrr_valid(msr)) 215ff53604bSXiao Guangrong return 1; 216ff53604bSXiao Guangrong 217ff53604bSXiao Guangrong if (msr == MSR_MTRRdefType) 218ff53604bSXiao Guangrong *pdata = vcpu->arch.mtrr_state.def_type + 219ff53604bSXiao Guangrong (vcpu->arch.mtrr_state.enabled << 10); 220ff53604bSXiao Guangrong else if (msr == MSR_MTRRfix64K_00000) 221ff53604bSXiao Guangrong *pdata = p[0]; 222ff53604bSXiao Guangrong else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000) 223ff53604bSXiao Guangrong *pdata = p[1 + msr - MSR_MTRRfix16K_80000]; 224ff53604bSXiao Guangrong else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000) 225ff53604bSXiao Guangrong *pdata = p[3 + msr - MSR_MTRRfix4K_C0000]; 226ff53604bSXiao Guangrong else if (msr == MSR_IA32_CR_PAT) 227ff53604bSXiao Guangrong *pdata = vcpu->arch.pat; 228ff53604bSXiao Guangrong else { /* Variable MTRRs */ 229ff53604bSXiao Guangrong int idx, is_mtrr_mask; 230ff53604bSXiao Guangrong u64 *pt; 231ff53604bSXiao Guangrong 232ff53604bSXiao Guangrong idx = (msr - 0x200) / 2; 233ff53604bSXiao Guangrong is_mtrr_mask = msr - 0x200 - 2 * idx; 234ff53604bSXiao Guangrong if (!is_mtrr_mask) 235ff53604bSXiao Guangrong pt = 236ff53604bSXiao Guangrong (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].base_lo; 237ff53604bSXiao Guangrong else 238ff53604bSXiao Guangrong pt = 239ff53604bSXiao Guangrong (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].mask_lo; 240ff53604bSXiao Guangrong *pdata = *pt; 241ff53604bSXiao Guangrong } 242ff53604bSXiao Guangrong 243ff53604bSXiao Guangrong return 0; 244ff53604bSXiao Guangrong } 245ff53604bSXiao Guangrong 246ff53604bSXiao Guangrong /* 247ff53604bSXiao Guangrong * The function is based on mtrr_type_lookup() in 248ff53604bSXiao Guangrong * arch/x86/kernel/cpu/mtrr/generic.c 249ff53604bSXiao Guangrong */ 250*70109e7dSXiao Guangrong static int get_mtrr_type(struct kvm_mtrr *mtrr_state, 251ff53604bSXiao Guangrong u64 start, u64 end) 252ff53604bSXiao Guangrong { 253ff53604bSXiao Guangrong u64 base, mask; 254ff53604bSXiao Guangrong u8 prev_match, curr_match; 255ff53604bSXiao Guangrong int i, num_var_ranges = KVM_NR_VAR_MTRR; 256ff53604bSXiao Guangrong 257ff53604bSXiao Guangrong /* MTRR is completely disabled, use UC for all of physical memory. */ 258ff53604bSXiao Guangrong if (!(mtrr_state->enabled & 0x2)) 259ff53604bSXiao Guangrong return MTRR_TYPE_UNCACHABLE; 260ff53604bSXiao Guangrong 261ff53604bSXiao Guangrong /* Make end inclusive end, instead of exclusive */ 262ff53604bSXiao Guangrong end--; 263ff53604bSXiao Guangrong 264ff53604bSXiao Guangrong /* Look in fixed ranges. Just return the type as per start */ 265*70109e7dSXiao Guangrong if ((mtrr_state->enabled & 0x1) && (start < 0x100000)) { 266ff53604bSXiao Guangrong int idx; 267ff53604bSXiao Guangrong 268ff53604bSXiao Guangrong if (start < 0x80000) { 269ff53604bSXiao Guangrong idx = 0; 270ff53604bSXiao Guangrong idx += (start >> 16); 271ff53604bSXiao Guangrong return mtrr_state->fixed_ranges[idx]; 272ff53604bSXiao Guangrong } else if (start < 0xC0000) { 273ff53604bSXiao Guangrong idx = 1 * 8; 274ff53604bSXiao Guangrong idx += ((start - 0x80000) >> 14); 275ff53604bSXiao Guangrong return mtrr_state->fixed_ranges[idx]; 276ff53604bSXiao Guangrong } else if (start < 0x1000000) { 277ff53604bSXiao Guangrong idx = 3 * 8; 278ff53604bSXiao Guangrong idx += ((start - 0xC0000) >> 12); 279ff53604bSXiao Guangrong return mtrr_state->fixed_ranges[idx]; 280ff53604bSXiao Guangrong } 281ff53604bSXiao Guangrong } 282ff53604bSXiao Guangrong 283ff53604bSXiao Guangrong /* 284ff53604bSXiao Guangrong * Look in variable ranges 285ff53604bSXiao Guangrong * Look of multiple ranges matching this address and pick type 286ff53604bSXiao Guangrong * as per MTRR precedence 287ff53604bSXiao Guangrong */ 288ff53604bSXiao Guangrong prev_match = 0xFF; 289ff53604bSXiao Guangrong for (i = 0; i < num_var_ranges; ++i) { 290ff53604bSXiao Guangrong unsigned short start_state, end_state; 291ff53604bSXiao Guangrong 292ff53604bSXiao Guangrong if (!(mtrr_state->var_ranges[i].mask_lo & (1 << 11))) 293ff53604bSXiao Guangrong continue; 294ff53604bSXiao Guangrong 295ff53604bSXiao Guangrong base = (((u64)mtrr_state->var_ranges[i].base_hi) << 32) + 296ff53604bSXiao Guangrong (mtrr_state->var_ranges[i].base_lo & PAGE_MASK); 297ff53604bSXiao Guangrong mask = (((u64)mtrr_state->var_ranges[i].mask_hi) << 32) + 298ff53604bSXiao Guangrong (mtrr_state->var_ranges[i].mask_lo & PAGE_MASK); 299ff53604bSXiao Guangrong 300ff53604bSXiao Guangrong start_state = ((start & mask) == (base & mask)); 301ff53604bSXiao Guangrong end_state = ((end & mask) == (base & mask)); 302ff53604bSXiao Guangrong if (start_state != end_state) 303ff53604bSXiao Guangrong return 0xFE; 304ff53604bSXiao Guangrong 305ff53604bSXiao Guangrong if ((start & mask) != (base & mask)) 306ff53604bSXiao Guangrong continue; 307ff53604bSXiao Guangrong 308ff53604bSXiao Guangrong curr_match = mtrr_state->var_ranges[i].base_lo & 0xff; 309ff53604bSXiao Guangrong if (prev_match == 0xFF) { 310ff53604bSXiao Guangrong prev_match = curr_match; 311ff53604bSXiao Guangrong continue; 312ff53604bSXiao Guangrong } 313ff53604bSXiao Guangrong 314ff53604bSXiao Guangrong if (prev_match == MTRR_TYPE_UNCACHABLE || 315ff53604bSXiao Guangrong curr_match == MTRR_TYPE_UNCACHABLE) 316ff53604bSXiao Guangrong return MTRR_TYPE_UNCACHABLE; 317ff53604bSXiao Guangrong 318ff53604bSXiao Guangrong if ((prev_match == MTRR_TYPE_WRBACK && 319ff53604bSXiao Guangrong curr_match == MTRR_TYPE_WRTHROUGH) || 320ff53604bSXiao Guangrong (prev_match == MTRR_TYPE_WRTHROUGH && 321ff53604bSXiao Guangrong curr_match == MTRR_TYPE_WRBACK)) { 322ff53604bSXiao Guangrong prev_match = MTRR_TYPE_WRTHROUGH; 323ff53604bSXiao Guangrong curr_match = MTRR_TYPE_WRTHROUGH; 324ff53604bSXiao Guangrong } 325ff53604bSXiao Guangrong 326ff53604bSXiao Guangrong if (prev_match != curr_match) 327ff53604bSXiao Guangrong return MTRR_TYPE_UNCACHABLE; 328ff53604bSXiao Guangrong } 329ff53604bSXiao Guangrong 330ff53604bSXiao Guangrong if (prev_match != 0xFF) 331ff53604bSXiao Guangrong return prev_match; 332ff53604bSXiao Guangrong 333ff53604bSXiao Guangrong return mtrr_state->def_type; 334ff53604bSXiao Guangrong } 335ff53604bSXiao Guangrong 336ff53604bSXiao Guangrong u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn) 337ff53604bSXiao Guangrong { 338ff53604bSXiao Guangrong u8 mtrr; 339ff53604bSXiao Guangrong 340ff53604bSXiao Guangrong mtrr = get_mtrr_type(&vcpu->arch.mtrr_state, gfn << PAGE_SHIFT, 341ff53604bSXiao Guangrong (gfn << PAGE_SHIFT) + PAGE_SIZE); 342ff53604bSXiao Guangrong if (mtrr == 0xfe || mtrr == 0xff) 343ff53604bSXiao Guangrong mtrr = MTRR_TYPE_WRBACK; 344ff53604bSXiao Guangrong return mtrr; 345ff53604bSXiao Guangrong } 346ff53604bSXiao Guangrong EXPORT_SYMBOL_GPL(kvm_mtrr_get_guest_memory_type); 347