Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: MIPS: Add CONFIG6 and DIAG registers emulation

Loongson-3 has CONFIG6 and DIAG registers which need to be emulated.
CONFIG6 is mostly used to enable/disable FTLB and SFB, while DIAG is
mostly used to flush BTB, ITLB, DTLB, VTLB and FTLB.

Acked-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Reviewed-by: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Message-Id: <1590220602-3547-13-git-send-email-chenhc@lemote.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Huacai Chen and committed by
Paolo Bonzini
8a5097ee 7f2a83f1

+113 -1
+7
arch/mips/include/asm/kvm_host.h
··· 68 68 #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) 69 69 #define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) 70 70 #define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) 71 + #define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6) 71 72 #define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7) 72 73 #define KVM_REG_MIPS_CP0_MAARI MIPS_CP0_64(17, 2) 73 74 #define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) 75 + #define KVM_REG_MIPS_CP0_DIAG MIPS_CP0_32(22, 0) 74 76 #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) 75 77 #define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2) 76 78 #define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3) ··· 260 258 #define MIPS_CP0_WATCH_LO 18 261 259 #define MIPS_CP0_WATCH_HI 19 262 260 #define MIPS_CP0_TLB_XCONTEXT 20 261 + #define MIPS_CP0_DIAG 22 263 262 #define MIPS_CP0_ECC 26 264 263 #define MIPS_CP0_CACHE_ERR 27 265 264 #define MIPS_CP0_TAG_LO 28 ··· 932 929 unsigned int count); 933 930 void kvm_vz_load_guesttlb(const struct kvm_mips_tlb *buf, unsigned int index, 934 931 unsigned int count); 932 + #ifdef CONFIG_CPU_LOONGSON64 933 + void kvm_loongson_clear_guest_vtlb(void); 934 + void kvm_loongson_clear_guest_ftlb(void); 935 + #endif 935 936 #endif 936 937 937 938 void kvm_mips_suspend_mm(int cpu);
+4
arch/mips/include/asm/mipsregs.h
··· 1038 1038 /* Disable Branch Return Cache */ 1039 1039 #define R10K_DIAG_D_BRC (_ULCAST_(1) << 22) 1040 1040 1041 + /* Flush BTB */ 1042 + #define LOONGSON_DIAG_BTB (_ULCAST_(1) << 1) 1041 1043 /* Flush ITLB */ 1042 1044 #define LOONGSON_DIAG_ITLB (_ULCAST_(1) << 2) 1043 1045 /* Flush DTLB */ ··· 2876 2874 __BUILD_SET_C0(cause) 2877 2875 __BUILD_SET_C0(config) 2878 2876 __BUILD_SET_C0(config5) 2877 + __BUILD_SET_C0(config6) 2879 2878 __BUILD_SET_C0(config7) 2879 + __BUILD_SET_C0(diag) 2880 2880 __BUILD_SET_C0(intcontrol) 2881 2881 __BUILD_SET_C0(intctl) 2882 2882 __BUILD_SET_C0(srsmap)
+41
arch/mips/kvm/tlb.c
··· 20 20 21 21 #include <asm/cpu.h> 22 22 #include <asm/bootinfo.h> 23 + #include <asm/mipsregs.h> 23 24 #include <asm/mmu_context.h> 24 25 #include <asm/pgtable.h> 25 26 #include <asm/cacheflush.h> ··· 622 621 tlbw_use_hazard(); 623 622 } 624 623 EXPORT_SYMBOL_GPL(kvm_vz_load_guesttlb); 624 + 625 + #ifdef CONFIG_CPU_LOONGSON64 626 + void kvm_loongson_clear_guest_vtlb(void) 627 + { 628 + int idx = read_gc0_index(); 629 + 630 + /* Set root GuestID for root probe and write of guest TLB entry */ 631 + set_root_gid_to_guest_gid(); 632 + 633 + write_gc0_index(0); 634 + guest_tlbinvf(); 635 + write_gc0_index(idx); 636 + 637 + clear_root_gid(); 638 + set_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB); 639 + } 640 + EXPORT_SYMBOL_GPL(kvm_loongson_clear_guest_vtlb); 641 + 642 + void kvm_loongson_clear_guest_ftlb(void) 643 + { 644 + int i; 645 + int idx = read_gc0_index(); 646 + 647 + /* Set root GuestID for root probe and write of guest TLB entry */ 648 + set_root_gid_to_guest_gid(); 649 + 650 + for (i = current_cpu_data.tlbsizevtlb; 651 + i < (current_cpu_data.tlbsizevtlb + 652 + current_cpu_data.tlbsizeftlbsets); 653 + i++) { 654 + write_gc0_index(i); 655 + guest_tlbinvf(); 656 + } 657 + write_gc0_index(idx); 658 + 659 + clear_root_gid(); 660 + set_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB); 661 + } 662 + EXPORT_SYMBOL_GPL(kvm_loongson_clear_guest_ftlb); 663 + #endif 625 664 626 665 #endif 627 666
+61 -1
arch/mips/kvm/vz.c
··· 127 127 return mask; 128 128 } 129 129 130 + static inline unsigned int kvm_vz_config6_guest_wrmask(struct kvm_vcpu *vcpu) 131 + { 132 + return MIPS_CONF6_LOONGSON_INTIMER | MIPS_CONF6_LOONGSON_EXTIMER; 133 + } 134 + 130 135 /* 131 136 * VZ optionally allows these additional Config bits to be written by root: 132 137 * Config: M, [MT] ··· 184 179 static inline unsigned int kvm_vz_config5_user_wrmask(struct kvm_vcpu *vcpu) 185 180 { 186 181 return kvm_vz_config5_guest_wrmask(vcpu) | MIPS_CONF5_MRP; 182 + } 183 + 184 + static inline unsigned int kvm_vz_config6_user_wrmask(struct kvm_vcpu *vcpu) 185 + { 186 + return kvm_vz_config6_guest_wrmask(vcpu) | 187 + MIPS_CONF6_LOONGSON_SFBEN | MIPS_CONF6_LOONGSON_FTLBDIS; 187 188 } 188 189 189 190 static gpa_t kvm_vz_gva_to_gpa_cb(gva_t gva) ··· 941 930 (sel == 2 || /* SRSCtl */ 942 931 sel == 3)) || /* SRSMap */ 943 932 (rd == MIPS_CP0_CONFIG && 944 - (sel == 7)) || /* Config7 */ 933 + (sel == 6 || /* Config6 */ 934 + sel == 7)) || /* Config7 */ 945 935 (rd == MIPS_CP0_LLADDR && 946 936 (sel == 2) && /* MAARI */ 947 937 cpu_guest_has_maar && ··· 950 938 (rd == MIPS_CP0_ERRCTL && 951 939 (sel == 0))) { /* ErrCtl */ 952 940 val = cop0->reg[rd][sel]; 941 + #ifdef CONFIG_CPU_LOONGSON64 942 + } else if (rd == MIPS_CP0_DIAG && 943 + (sel == 0)) { /* Diag */ 944 + val = cop0->reg[rd][sel]; 945 + #endif 953 946 } else { 954 947 val = 0; 955 948 er = EMULATE_FAIL; ··· 1017 1000 cpu_guest_has_maar && 1018 1001 !cpu_guest_has_dyn_maar) { 1019 1002 kvm_write_maari(vcpu, val); 1003 + } else if (rd == MIPS_CP0_CONFIG && 1004 + (sel == 6)) { 1005 + cop0->reg[rd][sel] = (int)val; 1020 1006 } else if (rd == MIPS_CP0_ERRCTL && 1021 1007 (sel == 0)) { /* ErrCtl */ 1022 1008 /* ignore the written value */ 1009 + #ifdef CONFIG_CPU_LOONGSON64 1010 + } else if (rd == MIPS_CP0_DIAG && 1011 + (sel == 0)) { /* Diag */ 1012 + unsigned long flags; 1013 + 1014 + local_irq_save(flags); 1015 + if (val & LOONGSON_DIAG_BTB) { 1016 + /* Flush BTB */ 1017 + set_c0_diag(LOONGSON_DIAG_BTB); 1018 + } 1019 + if (val & LOONGSON_DIAG_ITLB) { 1020 + /* Flush ITLB */ 1021 + set_c0_diag(LOONGSON_DIAG_ITLB); 1022 + } 1023 + if (val & LOONGSON_DIAG_DTLB) { 1024 + /* Flush DTLB */ 1025 + set_c0_diag(LOONGSON_DIAG_DTLB); 1026 + } 1027 + if (val & LOONGSON_DIAG_VTLB) { 1028 + /* Flush VTLB */ 1029 + kvm_loongson_clear_guest_vtlb(); 1030 + } 1031 + if (val & LOONGSON_DIAG_FTLB) { 1032 + /* Flush FTLB */ 1033 + kvm_loongson_clear_guest_ftlb(); 1034 + } 1035 + local_irq_restore(flags); 1036 + #endif 1023 1037 } else { 1024 1038 er = EMULATE_FAIL; 1025 1039 } ··· 1740 1692 KVM_REG_MIPS_CP0_CONFIG3, 1741 1693 KVM_REG_MIPS_CP0_CONFIG4, 1742 1694 KVM_REG_MIPS_CP0_CONFIG5, 1695 + KVM_REG_MIPS_CP0_CONFIG6, 1743 1696 #ifdef CONFIG_64BIT 1744 1697 KVM_REG_MIPS_CP0_XCONTEXT, 1745 1698 #endif ··· 2068 2019 return -EINVAL; 2069 2020 *v = read_gc0_config5(); 2070 2021 break; 2022 + case KVM_REG_MIPS_CP0_CONFIG6: 2023 + *v = kvm_read_sw_gc0_config6(cop0); 2024 + break; 2071 2025 case KVM_REG_MIPS_CP0_MAAR(0) ... KVM_REG_MIPS_CP0_MAAR(0x3f): 2072 2026 if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar) 2073 2027 return -EINVAL; ··· 2338 2286 if (change) { 2339 2287 v = cur ^ change; 2340 2288 write_gc0_config5(v); 2289 + } 2290 + break; 2291 + case KVM_REG_MIPS_CP0_CONFIG6: 2292 + cur = kvm_read_sw_gc0_config6(cop0); 2293 + change = (cur ^ v) & kvm_vz_config6_user_wrmask(vcpu); 2294 + if (change) { 2295 + v = cur ^ change; 2296 + kvm_write_sw_gc0_config6(cop0, (int)v); 2341 2297 } 2342 2298 break; 2343 2299 case KVM_REG_MIPS_CP0_MAAR(0) ... KVM_REG_MIPS_CP0_MAAR(0x3f):