^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * KVM/MIPS TLB handling, this file is part of the Linux host kernel so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * TLB handlers run from KSEG0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Authors: Sanjay Lal <sanjayl@kymasys.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kvm_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/srcu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/bootinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/tlb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/tlbdebug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #undef CONFIG_MIPS_MT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/r4kcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define CONFIG_MIPS_MT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define KVM_GUEST_PC_TLB 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define KVM_GUEST_SP_TLB 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #ifdef CONFIG_KVM_MIPS_VZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long GUESTID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) EXPORT_SYMBOL_GPL(GUESTID_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned long GUESTID_FIRST_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) EXPORT_SYMBOL_GPL(GUESTID_FIRST_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned long GUESTID_VERSION_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) EXPORT_SYMBOL_GPL(GUESTID_VERSION_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static u32 kvm_mips_get_root_asid(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct mm_struct *gpa_mm = &vcpu->kvm->arch.gpa_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (cpu_has_guestid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return cpu_asid(smp_processor_id(), gpa_mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static u32 kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct mm_struct *kern_mm = &vcpu->arch.guest_kernel_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return cpu_asid(cpu, kern_mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static u32 kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct mm_struct *user_mm = &vcpu->arch.guest_user_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return cpu_asid(cpu, user_mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Structure defining an tlb entry data set. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void kvm_mips_dump_host_tlbs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) kvm_info("HOST TLBs:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dump_tlb_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pr_info("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dump_tlb_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) EXPORT_SYMBOL_GPL(kvm_mips_dump_host_tlbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct mips_coproc *cop0 = vcpu->arch.cop0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct kvm_mips_tlb tlb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) kvm_info("Guest TLBs:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) kvm_info("Guest EntryHi: %#lx\n", kvm_read_c0_guest_entryhi(cop0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) tlb = vcpu->arch.guest_tlb[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) kvm_info("TLB%c%3d Hi 0x%08lx ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) (tlb.tlb_lo[0] | tlb.tlb_lo[1]) & ENTRYLO_V
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ? ' ' : '*',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) i, tlb.tlb_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) kvm_info("Lo0=0x%09llx %c%c attr %lx ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) (u64) mips3_tlbpfn_to_paddr(tlb.tlb_lo[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) (tlb.tlb_lo[0] & ENTRYLO_D) ? 'D' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) (tlb.tlb_lo[0] & ENTRYLO_G) ? 'G' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) (tlb.tlb_lo[0] & ENTRYLO_C) >> ENTRYLO_C_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kvm_info("Lo1=0x%09llx %c%c attr %lx sz=%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) (u64) mips3_tlbpfn_to_paddr(tlb.tlb_lo[1]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) (tlb.tlb_lo[1] & ENTRYLO_D) ? 'D' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) (tlb.tlb_lo[1] & ENTRYLO_G) ? 'G' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) (tlb.tlb_lo[1] & ENTRYLO_C) >> ENTRYLO_C_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) tlb.tlb_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) EXPORT_SYMBOL_GPL(kvm_mips_dump_guest_tlbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct kvm_mips_tlb *tlb = vcpu->arch.guest_tlb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (TLB_HI_VPN2_HIT(tlb[i], entryhi) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) TLB_HI_ASID_HIT(tlb[i], entryhi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) kvm_debug("%s: entryhi: %#lx, index: %d lo0: %#lx, lo1: %#lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) __func__, entryhi, index, tlb[i].tlb_lo[0], tlb[i].tlb_lo[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EXPORT_SYMBOL_GPL(kvm_mips_guest_tlb_lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int _kvm_mips_host_tlb_inv(unsigned long entryhi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) write_c0_entryhi(entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) tlb_probe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) tlb_probe_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) idx = read_c0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (idx >= current_cpu_data.tlbsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (idx >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) write_c0_entryhi(UNIQUE_ENTRYHI(idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) write_c0_entrylo0(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) write_c0_entrylo1(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) tlb_write_indexed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) tlbw_use_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) bool user, bool kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Initialize idx_user and idx_kernel to workaround bogus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * maybe-initialized warning when using GCC 6.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int idx_user = 0, idx_kernel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) unsigned long flags, old_entryhi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) old_entryhi = read_c0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) idx_user = _kvm_mips_host_tlb_inv((va & VPN2_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) kvm_mips_get_user_asid(vcpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) idx_kernel = _kvm_mips_host_tlb_inv((va & VPN2_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) kvm_mips_get_kernel_asid(vcpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) write_c0_entryhi(old_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * We don't want to get reserved instruction exceptions for missing tlb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (cpu_has_vtag_icache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) flush_icache_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (user && idx_user >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) kvm_debug("%s: Invalidated guest user entryhi %#lx @ idx %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) __func__, (va & VPN2_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) kvm_mips_get_user_asid(vcpu), idx_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (kernel && idx_kernel >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) kvm_debug("%s: Invalidated guest kernel entryhi %#lx @ idx %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) __func__, (va & VPN2_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) kvm_mips_get_kernel_asid(vcpu), idx_kernel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) EXPORT_SYMBOL_GPL(kvm_mips_host_tlb_inv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #ifdef CONFIG_KVM_MIPS_VZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* GuestID management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * clear_root_gid() - Set GuestCtl1.RID for normal root operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static inline void clear_root_gid(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (cpu_has_guestid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) clear_c0_guestctl1(MIPS_GCTL1_RID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * set_root_gid_to_guest_gid() - Set GuestCtl1.RID to match GuestCtl1.ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * Sets the root GuestID to match the current guest GuestID, for TLB operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * on the GPA->RPA mappings in the root TLB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * The caller must be sure to disable HTW while the root GID is set, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * possibly longer if TLB registers are modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static inline void set_root_gid_to_guest_gid(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) unsigned int guestctl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (cpu_has_guestid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) back_to_back_c0_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) guestctl1 = read_c0_guestctl1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) guestctl1 = (guestctl1 & ~MIPS_GCTL1_RID) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ((guestctl1 & MIPS_GCTL1_ID) >> MIPS_GCTL1_ID_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) << MIPS_GCTL1_RID_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) write_c0_guestctl1(guestctl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int kvm_vz_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) unsigned long flags, old_entryhi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) htw_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* Set root GuestID for root probe and write of guest TLB entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) set_root_gid_to_guest_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) old_entryhi = read_c0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) idx = _kvm_mips_host_tlb_inv((va & VPN2_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) kvm_mips_get_root_asid(vcpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) write_c0_entryhi(old_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) clear_root_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) htw_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * We don't want to get reserved instruction exceptions for missing tlb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (cpu_has_vtag_icache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) flush_icache_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (idx > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) kvm_debug("%s: Invalidated root entryhi %#lx @ idx %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) __func__, (va & VPN2_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) kvm_mips_get_root_asid(vcpu), idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) EXPORT_SYMBOL_GPL(kvm_vz_host_tlb_inv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * kvm_vz_guest_tlb_lookup() - Lookup a guest VZ TLB mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @vcpu: KVM VCPU pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @gpa: Guest virtual address in a TLB mapped guest segment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * @gpa: Ponter to output guest physical address it maps to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * Converts a guest virtual address in a guest TLB mapped segment to a guest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * physical address, by probing the guest TLB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * Returns: 0 if guest TLB mapping exists for @gva. *@gpa will have been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * -EFAULT if no guest TLB mapping exists for @gva. *@gpa may not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * have been written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int kvm_vz_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long gva,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) unsigned long *gpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned long o_entryhi, o_entrylo[2], o_pagemask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) unsigned int o_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) unsigned long entrylo[2], pagemask, pagemaskbit, pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* Probe the guest TLB for a mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* Set root GuestID for root probe of guest TLB entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) htw_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) set_root_gid_to_guest_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) o_entryhi = read_gc0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) o_index = read_gc0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) write_gc0_entryhi((o_entryhi & 0x3ff) | (gva & ~0xfffl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) guest_tlb_probe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) tlb_probe_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) index = read_gc0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (index < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* No match, fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) write_gc0_entryhi(o_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) write_gc0_index(o_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) clear_root_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) htw_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* Match! read the TLB entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) o_entrylo[0] = read_gc0_entrylo0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) o_entrylo[1] = read_gc0_entrylo1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) o_pagemask = read_gc0_pagemask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mtc0_tlbr_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) guest_tlb_read();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) tlb_read_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) entrylo[0] = read_gc0_entrylo0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) entrylo[1] = read_gc0_entrylo1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) pagemask = ~read_gc0_pagemask() & ~0x1fffl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) write_gc0_entryhi(o_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) write_gc0_index(o_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) write_gc0_entrylo0(o_entrylo[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) write_gc0_entrylo1(o_entrylo[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) write_gc0_pagemask(o_pagemask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) clear_root_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) htw_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* Select one of the EntryLo values and interpret the GPA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pagemaskbit = (pagemask ^ (pagemask & (pagemask - 1))) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) pa = entrylo[!!(gva & pagemaskbit)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * TLB entry may have become invalid since TLB probe if physical FTLB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * entries are shared between threads (e.g. I6400).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (!(pa & ENTRYLO_V))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * Note, this doesn't take guest MIPS32 XPA into account, where PFN is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * split with XI/RI in the middle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pa = (pa << 6) & ~0xfffl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) pa |= gva & ~(pagemask | pagemaskbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *gpa = pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) EXPORT_SYMBOL_GPL(kvm_vz_guest_tlb_lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * kvm_vz_local_flush_roottlb_all_guests() - Flush all root TLB entries for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * guests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Invalidate all entries in root tlb which are GPA mappings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) void kvm_vz_local_flush_roottlb_all_guests(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) unsigned long old_entryhi, old_pagemask, old_guestctl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (WARN_ON(!cpu_has_guestid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) htw_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* TLBR may clobber EntryHi.ASID, PageMask, and GuestCtl1.RID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) old_entryhi = read_c0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) old_pagemask = read_c0_pagemask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) old_guestctl1 = read_c0_guestctl1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * Invalidate guest entries in root TLB while leaving root entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * intact when possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) write_c0_index(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) tlb_read();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) tlb_read_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* Don't invalidate non-guest (RVA) mappings in the root TLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (!(read_c0_guestctl1() & MIPS_GCTL1_RID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* Make sure all entries differ. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) write_c0_entryhi(UNIQUE_ENTRYHI(entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) write_c0_entrylo0(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) write_c0_entrylo1(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) write_c0_guestctl1(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) tlb_write_indexed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) write_c0_entryhi(old_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) write_c0_pagemask(old_pagemask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) write_c0_guestctl1(old_guestctl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) tlbw_use_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) htw_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) EXPORT_SYMBOL_GPL(kvm_vz_local_flush_roottlb_all_guests);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * kvm_vz_local_flush_guesttlb_all() - Flush all guest TLB entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * Invalidate all entries in guest tlb irrespective of guestid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) void kvm_vz_local_flush_guesttlb_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) unsigned long old_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) unsigned long old_entryhi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) unsigned long old_entrylo[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) unsigned long old_pagemask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u64 cvmmemctl2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /* Preserve all clobbered guest registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) old_index = read_gc0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) old_entryhi = read_gc0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) old_entrylo[0] = read_gc0_entrylo0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) old_entrylo[1] = read_gc0_entrylo1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) old_pagemask = read_gc0_pagemask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) switch (current_cpu_type()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) case CPU_CAVIUM_OCTEON3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Inhibit machine check due to multiple matching TLB entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) cvmmemctl2 = read_c0_cvmmemctl2();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) cvmmemctl2 |= CVMMEMCTL2_INHIBITTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) write_c0_cvmmemctl2(cvmmemctl2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Invalidate guest entries in guest TLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) write_gc0_entrylo0(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) write_gc0_entrylo1(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) write_gc0_pagemask(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) for (entry = 0; entry < current_cpu_data.guest.tlbsize; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* Make sure all entries differ. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) write_gc0_index(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) write_gc0_entryhi(UNIQUE_GUEST_ENTRYHI(entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) guest_tlb_write_indexed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (cvmmemctl2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) cvmmemctl2 &= ~CVMMEMCTL2_INHIBITTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) write_c0_cvmmemctl2(cvmmemctl2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) write_gc0_index(old_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) write_gc0_entryhi(old_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) write_gc0_entrylo0(old_entrylo[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) write_gc0_entrylo1(old_entrylo[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) write_gc0_pagemask(old_pagemask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) tlbw_use_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) EXPORT_SYMBOL_GPL(kvm_vz_local_flush_guesttlb_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * kvm_vz_save_guesttlb() - Save a range of guest TLB entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * @buf: Buffer to write TLB entries into.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * @index: Start index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * @count: Number of entries to save.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * Save a range of guest TLB entries. The caller must ensure interrupts are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) void kvm_vz_save_guesttlb(struct kvm_mips_tlb *buf, unsigned int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) unsigned int end = index + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) unsigned long old_entryhi, old_entrylo0, old_entrylo1, old_pagemask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) unsigned int guestctl1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int old_index, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* Save registers we're about to clobber */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) old_index = read_gc0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) old_entryhi = read_gc0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) old_entrylo0 = read_gc0_entrylo0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) old_entrylo1 = read_gc0_entrylo1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) old_pagemask = read_gc0_pagemask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /* Set root GuestID for root probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) htw_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) set_root_gid_to_guest_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (cpu_has_guestid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) guestctl1 = read_c0_guestctl1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /* Read each entry from guest TLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) for (i = index; i < end; ++i, ++buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) write_gc0_index(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) mtc0_tlbr_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) guest_tlb_read();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) tlb_read_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (cpu_has_guestid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) (read_c0_guestctl1() ^ guestctl1) & MIPS_GCTL1_RID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* Entry invalid or belongs to another guest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) buf->tlb_hi = UNIQUE_GUEST_ENTRYHI(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) buf->tlb_lo[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) buf->tlb_lo[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) buf->tlb_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /* Entry belongs to the right guest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) buf->tlb_hi = read_gc0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) buf->tlb_lo[0] = read_gc0_entrylo0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) buf->tlb_lo[1] = read_gc0_entrylo1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) buf->tlb_mask = read_gc0_pagemask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /* Clear root GuestID again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) clear_root_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) htw_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* Restore clobbered registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) write_gc0_index(old_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) write_gc0_entryhi(old_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) write_gc0_entrylo0(old_entrylo0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) write_gc0_entrylo1(old_entrylo1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) write_gc0_pagemask(old_pagemask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) tlbw_use_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) EXPORT_SYMBOL_GPL(kvm_vz_save_guesttlb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * kvm_vz_load_guesttlb() - Save a range of guest TLB entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * @buf: Buffer to read TLB entries from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * @index: Start index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * @count: Number of entries to load.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * Load a range of guest TLB entries. The caller must ensure interrupts are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) void kvm_vz_load_guesttlb(const struct kvm_mips_tlb *buf, unsigned int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) unsigned int end = index + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) unsigned long old_entryhi, old_entrylo0, old_entrylo1, old_pagemask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int old_index, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* Save registers we're about to clobber */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) old_index = read_gc0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) old_entryhi = read_gc0_entryhi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) old_entrylo0 = read_gc0_entrylo0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) old_entrylo1 = read_gc0_entrylo1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) old_pagemask = read_gc0_pagemask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* Set root GuestID for root probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) htw_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) set_root_gid_to_guest_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* Write each entry to guest TLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) for (i = index; i < end; ++i, ++buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) write_gc0_index(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) write_gc0_entryhi(buf->tlb_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) write_gc0_entrylo0(buf->tlb_lo[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) write_gc0_entrylo1(buf->tlb_lo[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) write_gc0_pagemask(buf->tlb_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) mtc0_tlbw_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) guest_tlb_write_indexed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* Clear root GuestID again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) clear_root_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) htw_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* Restore clobbered registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) write_gc0_index(old_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) write_gc0_entryhi(old_entryhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) write_gc0_entrylo0(old_entrylo0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) write_gc0_entrylo1(old_entrylo1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) write_gc0_pagemask(old_pagemask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) tlbw_use_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) EXPORT_SYMBOL_GPL(kvm_vz_load_guesttlb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) #ifdef CONFIG_CPU_LOONGSON64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) void kvm_loongson_clear_guest_vtlb(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) int idx = read_gc0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* Set root GuestID for root probe and write of guest TLB entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) set_root_gid_to_guest_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) write_gc0_index(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) guest_tlbinvf();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) write_gc0_index(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) clear_root_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) set_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) EXPORT_SYMBOL_GPL(kvm_loongson_clear_guest_vtlb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) void kvm_loongson_clear_guest_ftlb(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) int idx = read_gc0_index();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* Set root GuestID for root probe and write of guest TLB entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) set_root_gid_to_guest_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) for (i = current_cpu_data.tlbsizevtlb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) i < (current_cpu_data.tlbsizevtlb +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) current_cpu_data.tlbsizeftlbsets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) write_gc0_index(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) guest_tlbinvf();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) write_gc0_index(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) clear_root_gid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) set_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) EXPORT_SYMBOL_GPL(kvm_loongson_clear_guest_ftlb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * kvm_mips_suspend_mm() - Suspend the active mm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * @cpu The CPU we're running on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * Suspend the active_mm, ready for a switch to a KVM guest virtual address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * space. This is left active for the duration of guest context, including time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * with interrupts enabled, so we need to be careful not to confuse e.g. cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * management IPIs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * kvm_mips_resume_mm() should be called before context switching to a different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * process so we don't need to worry about reference counting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * This needs to be in static kernel code to avoid exporting init_mm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) void kvm_mips_suspend_mm(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) cpumask_clear_cpu(cpu, mm_cpumask(current->active_mm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) current->active_mm = &init_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) EXPORT_SYMBOL_GPL(kvm_mips_suspend_mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * kvm_mips_resume_mm() - Resume the current process mm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * @cpu The CPU we're running on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * Resume the mm of the current process, after a switch back from a KVM guest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * virtual address space (see kvm_mips_suspend_mm()).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) void kvm_mips_resume_mm(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) cpumask_set_cpu(cpu, mm_cpumask(current->mm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) current->active_mm = current->mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) EXPORT_SYMBOL_GPL(kvm_mips_resume_mm);