FAILED: patch "[PATCH] MIPS: KVM: Fix modular KVM under QEMU" failed to apply to 3.14-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 3.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
797179bc4fe06c89e47a9f36f886f68640b423f8Mon Sep 17 00:00:00 2001
From: James Hogan <[email protected]>
Date: Thu, 9 Jun 2016 10:50:43 +0100
Subject: [PATCH] MIPS: KVM: Fix modular KVM under QEMU
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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.
arch/mips/include/asm/kvm_host.h +1 -0
@@ -338,6 +338,7 @@ struct kvm_mips_tlb {#define KVM_MIPS_GUEST_TLB_SIZE 64struct 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;
arch/mips/kvm/interrupt.h +1 -0
@@ -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[];
arch/mips/kvm/locore.S +1 -0
@@ -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. */
arch/mips/kvm/mips.c +10 -1
@@ -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 ();
[BACKPORT 3.14.y] MIPS: KVM: Fix modular KVM under QEMU
commit 797179bc4fe06c89e47a9f36f886f68640b423f8 upstream.
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.
--- arch/mips/include/asm/kvm_host.h | 1 + arch/mips/kvm/kvm_locore.S | 1 + arch/mips/kvm/kvm_mips.c | 11 ++++++++++- arch/mips/kvm/kvm_mips_int.h | 2 ++ 4 files changed, 14 insertions(+), 1 deletion(-)
arch/mips/include/asm/kvm_host.h +1 -0
@@ -342,6 +342,7 @@ struct kvm_mips_tlb {#define KVM_MIPS_GUEST_TLB_SIZE 64struct 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;
arch/mips/kvm/kvm_locore.S +1 -0
@@ -229,6 +229,7 @@ FEXPORT(__kvm_mips_load_k0k1) /* Jump to guest */ eret +EXPORT(__kvm_mips_vcpu_run_end) VECTOR(MIPSX(exception), unknown) /*
arch/mips/kvm/kvm_mips.c +10 -1
@@ -348,6 +348,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 */ mips32_SyncICache ((unsigned long ) gebase,ALIGN (size,PAGE_SIZE ));
@@ -431,7 +440,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)kvm_guest_enter (); - r =__kvm_mips_vcpu_run (run, vcpu); + r = vcpu->arch.vcpu_run (run, vcpu);kvm_guest_exit ();local_irq_enable ();
arch/mips/kvm/kvm_mips_int.h +2 -0
@@ -27,6 +27,8 @@#define MIPS_EXC_MAX 12/* XXXSL More to follow */ +extern char __kvm_mips_vcpu_run_end[]; +#define C_TI (_ULCAST_(1) << 30)#define KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE (0)
Signature · 1 line
2.4.10
Jiri Slaby
AppliedRe: [BACKPORT 3.14.y] MIPS: KVM: Fix modular KVM under QEMU
Quoted 1 line · James Hogan
commit
797179bc4fe06c89e47a9f36f886f68640b423f8upstream.
Applied to 3.12 too. Thanks!
Signature · 2 lines
js suse labs
Re: [BACKPORT 3.14.y] MIPS: KVM: Fix modular KVM under QEMU
In reply to James HoganQuoted 21 lines · James Hogan
commit
797179bc4fe06c89e47a9f36f886f68640b423f8upstream.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.
Quoted 9 lines
Signed-off-by James Hogan <[email protected]>Cc Paolo Bonzini <[email protected]>Cc Radim Krčmář <[email protected]>Cc Ralf Baechle <[email protected]>Signed-off-by Paolo Bonzini <[email protected]>[[email protected]: backported for stable 3.14]Signed-off-by James Hogan <[email protected]>
[...]
Belatedly queued this up for 3.16.
Ben.
Signature · 2 lines
Ben Hutchings compatible: Gracefully accepts erroneous data from any source