From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 18:10:26 +0000 (-0700) Subject: 3.5-stable patches X-Git-Tag: v3.5.3~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=96c8d6300ce796357798326db493e5eb7cead69d;p=thirdparty%2Fkernel%2Fstable-queue.git 3.5-stable patches added patches: kvm-pic-call-ack-notifiers-for-irqs-that-are-dropped-form-irr.patch kvm-vmx-fix-ds-es-corruption-on-i386-with-preemption.patch kvm-vmx-fix-kvm_set_sregs-with-big-real-mode-segments.patch kvm-x86-apply-kvmclock-offset-to-guest-wall-clock-time.patch kvm-x86-emulator-fix-byte-sized-movzx-movsx.patch --- diff --git a/queue-3.5/kvm-pic-call-ack-notifiers-for-irqs-that-are-dropped-form-irr.patch b/queue-3.5/kvm-pic-call-ack-notifiers-for-irqs-that-are-dropped-form-irr.patch new file mode 100644 index 00000000000..8a612d0bffa --- /dev/null +++ b/queue-3.5/kvm-pic-call-ack-notifiers-for-irqs-that-are-dropped-form-irr.patch @@ -0,0 +1,58 @@ +From avi@redhat.com Fri Aug 17 11:06:11 2012 +From: Gleb Natapov +Date: Wed, 15 Aug 2012 11:49:01 +0300 +Subject: KVM: PIC: call ack notifiers for irqs that are dropped form irr +To: stable@vger.kernel.org +Cc: Marcelo Tosatti +Message-ID: <1345020545-20962-2-git-send-email-avi@redhat.com> + +From: Gleb Natapov + +(cherry picked from commit aea218f3cbbcaac249b6b2c98930a00d6d931f1e) + +After commit 242ec97c358256 PIT interrupts are no longer delivered after +PIC reset. It happens because PIT injects interrupt only if previous one +was acked, but since on PIC reset it is dropped from irr it will never +be delivered and hence acknowledged. Fix that by calling ack notifier on +PIC reset. + +Signed-off-by: Gleb Natapov +Signed-off-by: Avi Kivity +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/i8259.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/arch/x86/kvm/i8259.c ++++ b/arch/x86/kvm/i8259.c +@@ -305,6 +305,11 @@ static void pic_ioport_write(void *opaqu + addr &= 1; + if (addr == 0) { + if (val & 0x10) { ++ u8 edge_irr = s->irr & ~s->elcr; ++ int i; ++ bool found; ++ struct kvm_vcpu *vcpu; ++ + s->init4 = val & 1; + s->last_irr = 0; + s->irr &= s->elcr; +@@ -322,6 +327,18 @@ static void pic_ioport_write(void *opaqu + if (val & 0x08) + pr_pic_unimpl( + "level sensitive irq not supported"); ++ ++ kvm_for_each_vcpu(i, vcpu, s->pics_state->kvm) ++ if (kvm_apic_accept_pic_intr(vcpu)) { ++ found = true; ++ break; ++ } ++ ++ ++ if (found) ++ for (irq = 0; irq < PIC_NUM_PINS/2; irq++) ++ if (edge_irr & (1 << irq)) ++ pic_clear_isr(s, irq); + } else if (val & 0x08) { + if (val & 0x04) + s->poll = 1; diff --git a/queue-3.5/kvm-vmx-fix-ds-es-corruption-on-i386-with-preemption.patch b/queue-3.5/kvm-vmx-fix-ds-es-corruption-on-i386-with-preemption.patch new file mode 100644 index 00000000000..9635d6e223f --- /dev/null +++ b/queue-3.5/kvm-vmx-fix-ds-es-corruption-on-i386-with-preemption.patch @@ -0,0 +1,91 @@ +From avi@redhat.com Fri Aug 17 11:07:03 2012 +From: Avi Kivity +Date: Wed, 15 Aug 2012 11:49:03 +0300 +Subject: KVM: VMX: Fix ds/es corruption on i386 with preemption +To: stable@vger.kernel.org +Cc: Marcelo Tosatti +Message-ID: <1345020545-20962-4-git-send-email-avi@redhat.com> + +From: Avi Kivity + +(cherry picked from commit aa67f6096c19bcdb1951ef88be3cf3d2118809dc) + +Commit b2da15ac26a0c ("KVM: VMX: Optimize %ds, %es reload") broke i386 +in the following scenario: + + vcpu_load + ... + vmx_save_host_state + vmx_vcpu_run + (ds.rpl, es.rpl cleared by hardware) + + interrupt + push ds, es # pushes bad ds, es + schedule + vmx_vcpu_put + vmx_load_host_state + reload ds, es (with __USER_DS) + pop ds, es # of other thread's stack + iret + # other thread runs + interrupt + push ds, es + schedule # back in vcpu thread + pop ds, es # now with rpl=0 + iret + ... + vcpu_put + resume_userspace + iret # clears ds, es due to mismatched rpl + +(instead of resume_userspace, we might return with SYSEXIT and then +take an exception; when the exception IRETs we end up with cleared +ds, es) + +Fix by avoiding the optimization on i386 and reloading ds, es on the +lightweight exit path. + +Reported-by: Chris Clayron +Signed-off-by: Avi Kivity +Signed-off-by: Marcelo Tosatti +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -1470,13 +1470,6 @@ static void __vmx_load_host_state(struct + loadsegment(ds, vmx->host_state.ds_sel); + loadsegment(es, vmx->host_state.es_sel); + } +-#else +- /* +- * The sysexit path does not restore ds/es, so we must set them to +- * a reasonable value ourselves. +- */ +- loadsegment(ds, __USER_DS); +- loadsegment(es, __USER_DS); + #endif + reload_tss(); + #ifdef CONFIG_X86_64 +@@ -6273,6 +6266,19 @@ static void __noclone vmx_vcpu_run(struc + #endif + ); + ++#ifndef CONFIG_X86_64 ++ /* ++ * The sysexit path does not restore ds/es, so we must set them to ++ * a reasonable value ourselves. ++ * ++ * We can't defer this to vmx_load_host_state() since that function ++ * may be executed in interrupt context, which saves and restore segments ++ * around it, nullifying its effect. ++ */ ++ loadsegment(ds, __USER_DS); ++ loadsegment(es, __USER_DS); ++#endif ++ + vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP) + | (1 << VCPU_EXREG_RFLAGS) + | (1 << VCPU_EXREG_CPL) diff --git a/queue-3.5/kvm-vmx-fix-kvm_set_sregs-with-big-real-mode-segments.patch b/queue-3.5/kvm-vmx-fix-kvm_set_sregs-with-big-real-mode-segments.patch new file mode 100644 index 00000000000..279818009fd --- /dev/null +++ b/queue-3.5/kvm-vmx-fix-kvm_set_sregs-with-big-real-mode-segments.patch @@ -0,0 +1,128 @@ +From avi@redhat.com Fri Aug 17 11:08:14 2012 +From: Avi Kivity +Date: Wed, 15 Aug 2012 11:49:05 +0300 +Subject: KVM: VMX: Fix KVM_SET_SREGS with big real mode segments +To: stable@vger.kernel.org +Cc: Marcelo Tosatti +Message-ID: <1345020545-20962-6-git-send-email-avi@redhat.com> + +From: Orit Wasserman + +(cherry picked from commit b246dd5df139501b974bd6b28f7815e53b3a792f) + +For example migration between Westmere and Nehelem hosts, caught in big real mode. + +The code that fixes the segments for real mode guest was moved from enter_rmode +to vmx_set_segments. enter_rmode calls vmx_set_segments for each segment. + +Signed-off-by: Orit Wasserman +Signed-off-by: Avi Kivity +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 74 ++++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 60 insertions(+), 14 deletions(-) + +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -615,6 +615,10 @@ static void kvm_cpu_vmxon(u64 addr); + static void kvm_cpu_vmxoff(void); + static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3); + static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr); ++static void vmx_set_segment(struct kvm_vcpu *vcpu, ++ struct kvm_segment *var, int seg); ++static void vmx_get_segment(struct kvm_vcpu *vcpu, ++ struct kvm_segment *var, int seg); + + static DEFINE_PER_CPU(struct vmcs *, vmxarea); + static DEFINE_PER_CPU(struct vmcs *, current_vmcs); +@@ -2763,6 +2767,7 @@ static void enter_rmode(struct kvm_vcpu + { + unsigned long flags; + struct vcpu_vmx *vmx = to_vmx(vcpu); ++ struct kvm_segment var; + + if (enable_unrestricted_guest) + return; +@@ -2806,20 +2811,23 @@ static void enter_rmode(struct kvm_vcpu + if (emulate_invalid_guest_state) + goto continue_rmode; + +- vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4); +- vmcs_write32(GUEST_SS_LIMIT, 0xffff); +- vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); +- +- vmcs_write32(GUEST_CS_AR_BYTES, 0xf3); +- vmcs_write32(GUEST_CS_LIMIT, 0xffff); +- if (vmcs_readl(GUEST_CS_BASE) == 0xffff0000) +- vmcs_writel(GUEST_CS_BASE, 0xf0000); +- vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4); +- +- fix_rmode_seg(VCPU_SREG_ES, &vmx->rmode.es); +- fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.ds); +- fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.gs); +- fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.fs); ++ vmx_get_segment(vcpu, &var, VCPU_SREG_SS); ++ vmx_set_segment(vcpu, &var, VCPU_SREG_SS); ++ ++ vmx_get_segment(vcpu, &var, VCPU_SREG_CS); ++ vmx_set_segment(vcpu, &var, VCPU_SREG_CS); ++ ++ vmx_get_segment(vcpu, &var, VCPU_SREG_ES); ++ vmx_set_segment(vcpu, &var, VCPU_SREG_ES); ++ ++ vmx_get_segment(vcpu, &var, VCPU_SREG_DS); ++ vmx_set_segment(vcpu, &var, VCPU_SREG_DS); ++ ++ vmx_get_segment(vcpu, &var, VCPU_SREG_GS); ++ vmx_set_segment(vcpu, &var, VCPU_SREG_GS); ++ ++ vmx_get_segment(vcpu, &var, VCPU_SREG_FS); ++ vmx_set_segment(vcpu, &var, VCPU_SREG_FS); + + continue_rmode: + kvm_mmu_reset_context(vcpu); +@@ -3222,6 +3230,44 @@ static void vmx_set_segment(struct kvm_v + + vmcs_write32(sf->ar_bytes, ar); + __clear_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail); ++ ++ /* ++ * Fix segments for real mode guest in hosts that don't have ++ * "unrestricted_mode" or it was disabled. ++ * This is done to allow migration of the guests from hosts with ++ * unrestricted guest like Westmere to older host that don't have ++ * unrestricted guest like Nehelem. ++ */ ++ if (!enable_unrestricted_guest && vmx->rmode.vm86_active) { ++ switch (seg) { ++ case VCPU_SREG_CS: ++ vmcs_write32(GUEST_CS_AR_BYTES, 0xf3); ++ vmcs_write32(GUEST_CS_LIMIT, 0xffff); ++ if (vmcs_readl(GUEST_CS_BASE) == 0xffff0000) ++ vmcs_writel(GUEST_CS_BASE, 0xf0000); ++ vmcs_write16(GUEST_CS_SELECTOR, ++ vmcs_readl(GUEST_CS_BASE) >> 4); ++ break; ++ case VCPU_SREG_ES: ++ fix_rmode_seg(VCPU_SREG_ES, &vmx->rmode.es); ++ break; ++ case VCPU_SREG_DS: ++ fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.ds); ++ break; ++ case VCPU_SREG_GS: ++ fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.gs); ++ break; ++ case VCPU_SREG_FS: ++ fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.fs); ++ break; ++ case VCPU_SREG_SS: ++ vmcs_write16(GUEST_SS_SELECTOR, ++ vmcs_readl(GUEST_SS_BASE) >> 4); ++ vmcs_write32(GUEST_SS_LIMIT, 0xffff); ++ vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); ++ break; ++ } ++ } + } + + static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) diff --git a/queue-3.5/kvm-x86-apply-kvmclock-offset-to-guest-wall-clock-time.patch b/queue-3.5/kvm-x86-apply-kvmclock-offset-to-guest-wall-clock-time.patch new file mode 100644 index 00000000000..c5a9cdf9e68 --- /dev/null +++ b/queue-3.5/kvm-x86-apply-kvmclock-offset-to-guest-wall-clock-time.patch @@ -0,0 +1,46 @@ +From avi@redhat.com Fri Aug 17 11:06:38 2012 +From: Bruce Rogers +Date: Wed, 15 Aug 2012 11:49:02 +0300 +Subject: KVM: x86: apply kvmclock offset to guest wall clock time +To: stable@vger.kernel.org +Cc: Marcelo Tosatti +Message-ID: <1345020545-20962-3-git-send-email-avi@redhat.com> + +From: Bruce Rogers + +(cherry picked from commit 4b6486659a7defef82ea51b276024b3aa357fefc) + +When a guest migrates to a new host, the system time difference from the +previous host is used in the updates to the kvmclock system time visible +to the guest, resulting in a continuation of correct kvmclock based guest +timekeeping. + +The wall clock component of the kvmclock provided time is currently not +updated with this same time offset. Since the Linux guest caches the +wall clock based time, this discrepency is not noticed until the guest is +rebooted. After reboot the guest's time calculations are off. + +This patch adjusts the wall clock by the kvmclock_offset, resulting in +correct guest time after a reboot. + +Cc: Zachary Amsden +Signed-off-by: Bruce Rogers +Signed-off-by: Marcelo Tosatti +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/x86.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -907,6 +907,10 @@ static void kvm_write_wall_clock(struct + */ + getboottime(&boot); + ++ if (kvm->arch.kvmclock_offset) { ++ struct timespec ts = ns_to_timespec(kvm->arch.kvmclock_offset); ++ boot = timespec_sub(boot, ts); ++ } + wc.sec = boot.tv_sec; + wc.nsec = boot.tv_nsec; + wc.version = version; diff --git a/queue-3.5/kvm-x86-emulator-fix-byte-sized-movzx-movsx.patch b/queue-3.5/kvm-x86-emulator-fix-byte-sized-movzx-movsx.patch new file mode 100644 index 00000000000..c8d1cb55e7a --- /dev/null +++ b/queue-3.5/kvm-x86-emulator-fix-byte-sized-movzx-movsx.patch @@ -0,0 +1,42 @@ +From avi@redhat.com Fri Aug 17 11:07:31 2012 +From: Avi Kivity +Date: Wed, 15 Aug 2012 11:49:04 +0300 +Subject: KVM: x86 emulator: fix byte-sized MOVZX/MOVSX +To: stable@vger.kernel.org +Cc: Marcelo Tosatti +Message-ID: <1345020545-20962-5-git-send-email-avi@redhat.com> + +From: Avi Kivity + +(cherry picked from commit 361cad2b50a2c92b91b6f568db860fabad3bf149) + +Commit 2adb5ad9fe1 removed ByteOp from MOVZX/MOVSX, replacing them by +SrcMem8, but neglected to fix the dependency in the emulation code +on ByteOp. This caused the instruction not to have any effect in +some circumstances. + +Fix by replacing the check for ByteOp with the equivalent src.op_bytes == 1. + +Signed-off-by: Avi Kivity +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/emulate.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -4426,12 +4426,12 @@ twobyte_insn: + break; + case 0xb6 ... 0xb7: /* movzx */ + ctxt->dst.bytes = ctxt->op_bytes; +- ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val ++ ctxt->dst.val = (ctxt->src.bytes == 1) ? (u8) ctxt->src.val + : (u16) ctxt->src.val; + break; + case 0xbe ... 0xbf: /* movsx */ + ctxt->dst.bytes = ctxt->op_bytes; +- ctxt->dst.val = (ctxt->d & ByteOp) ? (s8) ctxt->src.val : ++ ctxt->dst.val = (ctxt->src.bytes == 1) ? (s8) ctxt->src.val : + (s16) ctxt->src.val; + break; + case 0xc0 ... 0xc1: /* xadd */ diff --git a/queue-3.5/series b/queue-3.5/series index 6241da0362c..2335a0b9e13 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -37,3 +37,8 @@ usb-ftdi_sio-add-vid-pid-for-kondo-serial-usb.patch usb-serial-mos7840-fixup-mos7840_chars_in_buffer.patch usb-gadget-u_ether-fix-kworker-100-cpu-issue-with-still-used-interfaces-in-eth_stop.patch rt2x00-add-support-for-buffalo-wli-uc-gnm2-to-rt2800usb.patch +kvm-pic-call-ack-notifiers-for-irqs-that-are-dropped-form-irr.patch +kvm-x86-apply-kvmclock-offset-to-guest-wall-clock-time.patch +kvm-vmx-fix-ds-es-corruption-on-i386-with-preemption.patch +kvm-x86-emulator-fix-byte-sized-movzx-movsx.patch +kvm-vmx-fix-kvm_set_sregs-with-big-real-mode-segments.patch