diff options
author | James Hogan <james.hogan@imgtec.com> | 2016-10-25 11:08:19 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-10-26 07:43:41 -0400 |
commit | 9078210ef4016539c909fb67164d3f1c27323d8b (patch) | |
tree | 810f0275af6c948768d0581668f64c715f903641 /arch/mips/kvm | |
parent | 07d9a380680d1c0eb51ef87ff2eab5c994949e69 (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.c | 5 | ||||
-rw-r--r-- | arch/mips/kvm/mmu.c | 4 |
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, | |||
426 | static void kvm_mips_check_asids(struct kvm_vcpu *vcpu) | 426 | static 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, |