summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/mips/include/asm/kvm_host.h3
-rw-r--r--arch/mips/kvm/mips.c34
-rw-r--r--arch/mips/kvm/mmu.c21
-rw-r--r--arch/mips/kvm/tlb.c44
4 files changed, 22 insertions, 80 deletions
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index f7680999e28a..e38e11184c1c 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -159,9 +159,6 @@ struct kvm_arch {
/* Guest GVA->HPA page table */
unsigned long *guest_pmap;
unsigned long guest_pmap_npages;
-
- /* Wired host TLB used for the commpage */
- int commpage_tlb;
};
#define N_MIPS_COPROC_REGS 32
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index c369fdd19fbc..c4fc52e39f34 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -92,28 +92,10 @@ void kvm_arch_check_processor_compat(void *rtn)
*(int *)rtn = 0;
}
-static void kvm_mips_init_tlbs(struct kvm *kvm)
-{
- unsigned long wired;
-
- /*
- * Add a wired entry to the TLB, it is used to map the commpage to
- * the Guest kernel
- */
- wired = read_c0_wired();
- write_c0_wired(wired + 1);
- mtc0_tlbw_hazard();
- kvm->arch.commpage_tlb = wired;
-
- kvm_debug("[%d] commpage TLB: %d\n", smp_processor_id(),
- kvm->arch.commpage_tlb);
-}
-
static void kvm_mips_init_vm_percpu(void *arg)
{
struct kvm *kvm = (struct kvm *)arg;
- kvm_mips_init_tlbs(kvm);
kvm_mips_callbacks->vm_init(kvm);
}
@@ -165,25 +147,11 @@ void kvm_mips_free_vcpus(struct kvm *kvm)
mutex_unlock(&kvm->lock);
}
-static void kvm_mips_uninit_tlbs(void *arg)
-{
- /* Restore wired count */
- write_c0_wired(0);
- mtc0_tlbw_hazard();
- /* Clear out all the TLBs */
- kvm_local_flush_tlb_all();
-}
-
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvm_mips_free_vcpus(kvm);
- /* If this is the last instance, restore wired count */
- if (atomic_dec_return(&kvm_mips_instance) == 0) {
- kvm_debug("%s: last KVM instance, restoring TLB parameters\n",
- __func__);
- on_each_cpu(kvm_mips_uninit_tlbs, NULL, 1);
- }
+ atomic_dec(&kvm_mips_instance);
}
long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl,
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
index 62122d297e52..98f1a7715a68 100644
--- a/arch/mips/kvm/mmu.c
+++ b/arch/mips/kvm/mmu.c
@@ -449,6 +449,27 @@ int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
return 0;
}
+int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
+ struct kvm_vcpu *vcpu)
+{
+ kvm_pfn_t pfn;
+ pte_t *ptep;
+
+ ptep = kvm_trap_emul_pte_for_gva(vcpu, badvaddr);
+ if (!ptep) {
+ kvm_err("No ptep for commpage %lx\n", badvaddr);
+ return -1;
+ }
+
+ pfn = PFN_DOWN(virt_to_phys(vcpu->arch.kseg0_commpage));
+ /* Also set valid and dirty, so refill handler doesn't have to */
+ *ptep = pte_mkyoung(pte_mkdirty(pfn_pte(pfn, PAGE_SHARED)));
+
+ /* Invalidate this entry in the TLB, guest kernel ASID only */
+ kvm_mips_host_tlb_inv(vcpu, badvaddr, false, true);
+ return 0;
+}
+
void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
struct kvm_vcpu *vcpu)
{
diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c
index 2fb76869d017..919252662d5a 100644
--- a/arch/mips/kvm/tlb.c
+++ b/arch/mips/kvm/tlb.c
@@ -52,11 +52,6 @@ static u32 kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
return cpu_asid(cpu, user_mm);
}
-inline u32 kvm_mips_get_commpage_asid(struct kvm_vcpu *vcpu)
-{
- return vcpu->kvm->arch.commpage_tlb;
-}
-
/* Structure defining an tlb entry data set. */
void kvm_mips_dump_host_tlbs(void)
@@ -104,45 +99,6 @@ void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_mips_dump_guest_tlbs);
-int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
- struct kvm_vcpu *vcpu)
-{
- kvm_pfn_t pfn;
- unsigned long flags, old_entryhi = 0, vaddr = 0;
- unsigned long entrylo[2] = { 0, 0 };
- unsigned int pair_idx;
-
- pfn = PFN_DOWN(virt_to_phys(vcpu->arch.kseg0_commpage));
- pair_idx = (badvaddr >> PAGE_SHIFT) & 1;
- entrylo[pair_idx] = mips3_paddr_to_tlbpfn(pfn << PAGE_SHIFT) |
- ((_page_cachable_default >> _CACHE_SHIFT) << ENTRYLO_C_SHIFT) |
- ENTRYLO_D | ENTRYLO_V;
-
- local_irq_save(flags);
-
- old_entryhi = read_c0_entryhi();
- vaddr = badvaddr & (PAGE_MASK << 1);
- write_c0_entryhi(vaddr | kvm_mips_get_kernel_asid(vcpu));
- write_c0_entrylo0(entrylo[0]);
- write_c0_entrylo1(entrylo[1]);
- write_c0_index(kvm_mips_get_commpage_asid(vcpu));
- mtc0_tlbw_hazard();
- tlb_write_indexed();
- tlbw_use_hazard();
-
- kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n",
- vcpu->arch.pc, read_c0_index(), read_c0_entryhi(),
- read_c0_entrylo0(), read_c0_entrylo1());
-
- /* Restore old ASID */
- write_c0_entryhi(old_entryhi);
- mtc0_tlbw_hazard();
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(kvm_mips_handle_commpage_tlb_fault);
-
int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
{
int i;