aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2016-10-25 11:08:19 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2016-10-26 07:43:41 -0400
commit9078210ef4016539c909fb67164d3f1c27323d8b (patch)
tree810f0275af6c948768d0581668f64c715f903641 /arch/mips/kvm
parent07d9a380680d1c0eb51ef87ff2eab5c994949e69 (diff)
KVM: MIPS: Fix lazy user ASID regenerate for SMP
kvm_mips_check_asids() runs before entering the guest and performs lazy regeneration of host ASID for guest usermode, using last_user_gasid to track the last guest ASID in the VCPU that was used by guest usermode on any host CPU. last_user_gasid is reset after performing the lazy ASID regeneration on the current CPU, and by kvm_arch_vcpu_load() if the host ASID for guest usermode is regenerated due to staleness (to cancel outstanding lazy ASID regenerations). Unfortunately neither case handles SMP hosts correctly: - When the lazy ASID regeneration is performed it should apply to all CPUs (as last_user_gasid does), so reset the ASID on other CPUs to zero to trigger regeneration when the VCPU is next loaded on those CPUs. - When the ASID is found to be stale on the current CPU, we should not cancel lazy ASID regenerations globally, so drop the reset of last_user_gasid altogether here. Both cases would require a guest ASID change and two host CPU migrations (and in the latter case one of the CPUs to start a new ASID cycle) before guest usermode could potentially access stale user pages from a previously running ASID in the same VCPU. Fixes: 25b08c7fb0e4 ("KVM: MIPS: Invalidate TLB by regenerating ASIDs") Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: "Radim Krčmář <rkrcmar@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/mips/kvm')
-rw-r--r--arch/mips/kvm/mips.c5
-rw-r--r--arch/mips/kvm/mmu.c4
2 files changed, 4 insertions, 5 deletions
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index 622037d851a3..06a60b19acfb 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -426,7 +426,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
426static void kvm_mips_check_asids(struct kvm_vcpu *vcpu) 426static void kvm_mips_check_asids(struct kvm_vcpu *vcpu)
427{ 427{
428 struct mips_coproc *cop0 = vcpu->arch.cop0; 428 struct mips_coproc *cop0 = vcpu->arch.cop0;
429 int cpu = smp_processor_id(); 429 int i, cpu = smp_processor_id();
430 unsigned int gasid; 430 unsigned int gasid;
431 431
432 /* 432 /*
@@ -442,6 +442,9 @@ static void kvm_mips_check_asids(struct kvm_vcpu *vcpu)
442 vcpu); 442 vcpu);
443 vcpu->arch.guest_user_asid[cpu] = 443 vcpu->arch.guest_user_asid[cpu] =
444 vcpu->arch.guest_user_mm.context.asid[cpu]; 444 vcpu->arch.guest_user_mm.context.asid[cpu];
445 for_each_possible_cpu(i)
446 if (i != cpu)
447 vcpu->arch.guest_user_asid[cpu] = 0;
445 vcpu->arch.last_user_gasid = gasid; 448 vcpu->arch.last_user_gasid = gasid;
446 } 449 }
447 } 450 }
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
index 03883ba806e2..3b677c851be0 100644
--- a/arch/mips/kvm/mmu.c
+++ b/arch/mips/kvm/mmu.c
@@ -260,13 +260,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
260 260
261 if ((vcpu->arch.guest_user_asid[cpu] ^ asid_cache(cpu)) & 261 if ((vcpu->arch.guest_user_asid[cpu] ^ asid_cache(cpu)) &
262 asid_version_mask(cpu)) { 262 asid_version_mask(cpu)) {
263 u32 gasid = kvm_read_c0_guest_entryhi(vcpu->arch.cop0) &
264 KVM_ENTRYHI_ASID;
265
266 kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu); 263 kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu);
267 vcpu->arch.guest_user_asid[cpu] = 264 vcpu->arch.guest_user_asid[cpu] =
268 vcpu->arch.guest_user_mm.context.asid[cpu]; 265 vcpu->arch.guest_user_mm.context.asid[cpu];
269 vcpu->arch.last_user_gasid = gasid;
270 newasid++; 266 newasid++;
271 267
272 kvm_debug("[%d]: cpu_context: %#lx\n", cpu, 268 kvm_debug("[%d]: cpu_context: %#lx\n", cpu,