[PATCH 0/4] MIPS: KVM: Module + non dynamic translating fixes

STALE3700d

7 messages, 2 authors, 2016-06-14 · open the first message on its own page

[PATCH 0/4] MIPS: KVM: Module + non dynamic translating fixes

From: James Hogan <hidden>
Date: 2016-06-09 09:51:05

These patches fix a couple of issues I recently spotted when running KVM
under QEMU (i.e. the host MIPS kernel is running under QEMU on a PC).

Patches 1-2: Fix modular KVM broken by QEMU TLB optimisation (Patch 1
marked for stable).

Patches 3-4: Fix cache instruction emulation, exposed by having dynamic
translation of emulated instructions accidentally turned off.

James Hogan (4):
  MIPS: KVM: Fix modular KVM under QEMU
  MIPS: KVM: Include bit 31 in segment matches
  MIPS: KVM: Don't unwind PC when emulating CACHE
  MIPS: KVM: Fix CACHE triggered exception emulation

 arch/mips/include/asm/kvm_host.h |  3 ++-
 arch/mips/kvm/emulate.c          | 21 ++++++++++++++-------
 arch/mips/kvm/interrupt.h        |  1 +
 arch/mips/kvm/locore.S           |  1 +
 arch/mips/kvm/mips.c             | 11 ++++++++++-
 5 files changed, 28 insertions(+), 9 deletions(-)

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <redacted>
Cc: Ralf Baechle <redacted>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: stable@vger.kernel.org
-- 
2.4.10

[PATCH 1/4] MIPS: KVM: Fix modular KVM under QEMU

From: James Hogan <hidden>
Date: 2016-06-09 09:51:06

Copy __kvm_mips_vcpu_run() into unmapped memory, so that we can never
get a TLB refill exception in it when KVM is built as a module.

This was observed to happen with the host MIPS kernel running under
QEMU, due to a not entirely transparent optimisation in the QEMU TLB
handling where TLB entries replaced with TLBWR are copied to a separate
part of the TLB array. Code in those pages continue to be executable,
but those mappings persist only until the next ASID switch, even if they
are marked global.

An ASID switch happens in __kvm_mips_vcpu_run() at exception level after
switching to the guest exception base. Subsequent TLB mapped kernel
instructions just prior to switching to the guest trigger a TLB refill
exception, which enters the guest exception handlers without updating
EPC. This appears as a guest triggered TLB refill on a host kernel
mapped (host KSeg2) address, which is not handled correctly as user
(guest) mode accesses to kernel (host) segments always generate address
error exceptions.

Signed-off-by: James Hogan <redacted>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <redacted>
Cc: Ralf Baechle <redacted>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: <redacted> # 3.10.x-
---
 arch/mips/include/asm/kvm_host.h |  1 +
 arch/mips/kvm/interrupt.h        |  1 +
 arch/mips/kvm/locore.S           |  1 +
 arch/mips/kvm/mips.c             | 11 ++++++++++-
 4 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 6733ac575da4..2d5bb133d11a 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -338,6 +338,7 @@ struct kvm_mips_tlb {
 #define KVM_MIPS_GUEST_TLB_SIZE	64
 struct kvm_vcpu_arch {
 	void *host_ebase, *guest_ebase;
+	int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);
 	unsigned long host_stack;
 	unsigned long host_gp;
 
diff --git a/arch/mips/kvm/interrupt.h b/arch/mips/kvm/interrupt.h
index 4ab4bdfad703..2143884709e4 100644
--- a/arch/mips/kvm/interrupt.h
+++ b/arch/mips/kvm/interrupt.h
@@ -28,6 +28,7 @@
 #define MIPS_EXC_MAX                12
 /* XXXSL More to follow */
 
+extern char __kvm_mips_vcpu_run_end[];
 extern char mips32_exception[], mips32_exceptionEnd[];
 extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
 
diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S
index 3ef03009de5f..828fcfc1cd7f 100644
--- a/arch/mips/kvm/locore.S
+++ b/arch/mips/kvm/locore.S
@@ -202,6 +202,7 @@ FEXPORT(__kvm_mips_load_k0k1)
 
 	/* Jump to guest */
 	eret
+EXPORT(__kvm_mips_vcpu_run_end)
 
 VECTOR(MIPSX(exception), unknown)
 /* Find out what mode we came from and jump to the proper handler. */
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index dc052fb5c7a2..44da5259f390 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -315,6 +315,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 	memcpy(gebase + offset, mips32_GuestException,
 	       mips32_GuestExceptionEnd - mips32_GuestException);
 
+#ifdef MODULE
+	offset += mips32_GuestExceptionEnd - mips32_GuestException;
+	memcpy(gebase + offset, (char *)__kvm_mips_vcpu_run,
+	       __kvm_mips_vcpu_run_end - (char *)__kvm_mips_vcpu_run);
+	vcpu->arch.vcpu_run = gebase + offset;
+#else
+	vcpu->arch.vcpu_run = __kvm_mips_vcpu_run;
+#endif
+
 	/* Invalidate the icache for these ranges */
 	local_flush_icache_range((unsigned long)gebase,
 				(unsigned long)gebase + ALIGN(size, PAGE_SIZE));
@@ -404,7 +413,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	/* Disable hardware page table walking while in guest */
 	htw_stop();
 
-	r = __kvm_mips_vcpu_run(run, vcpu);
+	r = vcpu->arch.vcpu_run(run, vcpu);
 
 	/* Re-enable HTW before enabling interrupts */
 	htw_start();
-- 
2.4.10

[PATCH 4/4] MIPS: KVM: Fix CACHE triggered exception emulation

From: James Hogan <hidden>
Date: 2016-06-09 09:51:54

When emulating TLB miss / invalid exceptions during CACHE instruction
emulation, be sure to set up the correct PC and host_cp0_badvaddr state
for the kvm_mips_emlulate_tlb*_ld() function to pick up for guest EPC
and BadVAddr.

PC needs to be rewound otherwise the guest EPC will end up pointing at
the next instruction after the faulting CACHE instruction.

host_cp0_badvaddr must be set because guest CACHE instructions trap with
a Coprocessor Unusable exception, which doesn't update the host BadVAddr
as a TLB exception would.

This doesn't tend to get hit when dynamic translation of emulated
instructions is enabled, since only the first execution of each CACHE
instruction actually goes through this code path, with subsequent
executions hitting the SYNCI instruction that it gets replaced with.

Signed-off-by: James Hogan <redacted>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <redacted>
Cc: Ralf Baechle <redacted>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
---
 arch/mips/kvm/emulate.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 52bec0fe2fbb..645c8a1982a7 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -1636,6 +1636,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
 		if (index < 0) {
 			vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
 			vcpu->arch.host_cp0_badvaddr = va;
+			vcpu->arch.pc = curr_pc;
 			er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
 							 vcpu);
 			preempt_enable();
@@ -1647,6 +1648,8 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
 			 * invalid exception to the guest
 			 */
 			if (!TLB_IS_VALID(*tlb, va)) {
+				vcpu->arch.host_cp0_badvaddr = va;
+				vcpu->arch.pc = curr_pc;
 				er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
 								run, vcpu);
 				preempt_enable();
-- 
2.4.10

[PATCH 3/4] MIPS: KVM: Don't unwind PC when emulating CACHE

From: James Hogan <hidden>
Date: 2016-06-09 09:52:10

When a CACHE instruction is emulated by kvm_mips_emulate_cache(), the PC
is first updated to point to the next instruction, and afterwards it
falls through the "dont_update_pc" label, which rewinds the PC back to
its original address.

This works when dynamic translation of emulated instructions is enabled,
since the CACHE instruction is replaced with a SYNCI which works without
trapping, however when dynamic translation is disabled the guest hangs
on CACHE instructions as they always trap and are never stepped over.

Roughly swap the meanings of the "done" and "dont_update_pc" to match
kvm_mips_emulate_CP0(), so that "done" will roll back the PC on failure,
and "dont_update_pc" won't change PC at all (for the sake of exceptions
that have already modified the PC).

Signed-off-by: James Hogan <redacted>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <redacted>
Cc: Ralf Baechle <redacted>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
---
 arch/mips/kvm/emulate.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 396df6eb0a12..52bec0fe2fbb 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -1666,7 +1666,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
 			cache, op, base, arch->gprs[base], offset);
 		er = EMULATE_FAIL;
 		preempt_enable();
-		goto dont_update_pc;
+		goto done;
 
 	}
 
@@ -1694,16 +1694,20 @@ skip_fault:
 		kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
 			cache, op, base, arch->gprs[base], offset);
 		er = EMULATE_FAIL;
-		preempt_enable();
-		goto dont_update_pc;
 	}
 
 	preempt_enable();
-
-dont_update_pc:
-	/* Rollback PC */
-	vcpu->arch.pc = curr_pc;
 done:
+	/* Rollback PC only if emulation was unsuccessful */
+	if (er == EMULATE_FAIL)
+		vcpu->arch.pc = curr_pc;
+
+dont_update_pc:
+	/*
+	 * This is for exceptions whose emulation updates the PC, so do not
+	 * overwrite the PC under any circumstances
+	 */
+
 	return er;
 }
 
-- 
2.4.10

[PATCH 2/4] MIPS: KVM: Include bit 31 in segment matches

From: James Hogan <hidden>
Date: 2016-06-09 09:52:33

When faulting guest addresses are matched against guest segments with
the KVM_GUEST_KSEGX() macro, change the mask to 0xe0000000 so as to
include bit 31.

This is mainly for safety's sake, as it prevents a rogue BadVAddr in the
host kseg2/kseg3 segments (e.g. 0xC*******) after a TLB exception from
matching the guest kseg0 segment (e.g. 0x4*******), triggering an
internal KVM error instead of allowing the corresponding guest kseg0
page to be mapped into the host vmalloc space.

Such a rogue BadVAddr was observed to happen with the host MIPS kernel
running under QEMU with KVM built as a module, due to a not entirely
transparent optimisation in the QEMU TLB handling. This has already been
worked around properly in a previous commit.

Signed-off-by: James Hogan <redacted>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <redacted>
Cc: Ralf Baechle <redacted>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
---
 arch/mips/include/asm/kvm_host.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 2d5bb133d11a..36a391d289aa 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -74,7 +74,7 @@
 #define KVM_GUEST_KUSEG			0x00000000UL
 #define KVM_GUEST_KSEG0			0x40000000UL
 #define KVM_GUEST_KSEG23		0x60000000UL
-#define KVM_GUEST_KSEGX(a)		((_ACAST32_(a)) & 0x60000000)
+#define KVM_GUEST_KSEGX(a)		((_ACAST32_(a)) & 0xe0000000)
 #define KVM_GUEST_CPHYSADDR(a)		((_ACAST32_(a)) & 0x1fffffff)
 
 #define KVM_GUEST_CKSEG0ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0)
-- 
2.4.10

Re: [PATCH 0/4] MIPS: KVM: Module + non dynamic translating fixes

From: Paolo Bonzini <pbonzini@redhat.com>
Date: 2016-06-12 18:45:22


On 09/06/2016 11:50, James Hogan wrote:
These patches fix a couple of issues I recently spotted when running KVM
under QEMU (i.e. the host MIPS kernel is running under QEMU on a PC).

Patches 1-2: Fix modular KVM broken by QEMU TLB optimisation (Patch 1
marked for stable).

Patches 3-4: Fix cache instruction emulation, exposed by having dynamic
translation of emulated instructions accidentally turned off.

James Hogan (4):
  MIPS: KVM: Fix modular KVM under QEMU
  MIPS: KVM: Include bit 31 in segment matches
  MIPS: KVM: Don't unwind PC when emulating CACHE
  MIPS: KVM: Fix CACHE triggered exception emulation

 arch/mips/include/asm/kvm_host.h |  3 ++-
 arch/mips/kvm/emulate.c          | 21 ++++++++++++++-------
 arch/mips/kvm/interrupt.h        |  1 +
 arch/mips/kvm/locore.S           |  1 +
 arch/mips/kvm/mips.c             | 11 ++++++++++-
 5 files changed, 28 insertions(+), 9 deletions(-)

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <redacted>
Cc: Ralf Baechle <redacted>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: stable@vger.kernel.org
Queued for kvm/master.

Paolo

Re: [PATCH 0/4] MIPS: KVM: Module + non dynamic translating fixes

From: Paolo Bonzini <pbonzini@redhat.com>
Date: 2016-06-14 09:03:23


On 12/06/2016 20:45, Paolo Bonzini wrote:

On 09/06/2016 11:50, James Hogan wrote:
quoted
These patches fix a couple of issues I recently spotted when running KVM
under QEMU (i.e. the host MIPS kernel is running under QEMU on a PC).

Patches 1-2: Fix modular KVM broken by QEMU TLB optimisation (Patch 1
marked for stable).

Patches 3-4: Fix cache instruction emulation, exposed by having dynamic
translation of emulated instructions accidentally turned off.

James Hogan (4):
  MIPS: KVM: Fix modular KVM under QEMU
  MIPS: KVM: Include bit 31 in segment matches
  MIPS: KVM: Don't unwind PC when emulating CACHE
  MIPS: KVM: Fix CACHE triggered exception emulation

 arch/mips/include/asm/kvm_host.h |  3 ++-
 arch/mips/kvm/emulate.c          | 21 ++++++++++++++-------
 arch/mips/kvm/interrupt.h        |  1 +
 arch/mips/kvm/locore.S           |  1 +
 arch/mips/kvm/mips.c             | 11 ++++++++++-
 5 files changed, 28 insertions(+), 9 deletions(-)

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <redacted>
Cc: Ralf Baechle <redacted>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: stable@vger.kernel.org
Queued for kvm/master.
... and kvm/next too, since your patches conflict with this one.

Paolo
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help