diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-03 11:21:29 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-03 11:21:29 -0700 |
commit | d79095eee26f3e2c812f1c92763d5edcb1edae60 (patch) | |
tree | 070a923e69c3abc6b55f5f87661fb805f1edb146 /arch | |
parent | d667319a12c79e31cf17daffca3aa692d2f277ee (diff) | |
parent | aa67f6096c19bcdb1951ef88be3cf3d2118809dc (diff) |
Merge git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM bug fixes from Marcelo Tosatti:
- Fix DS/ES segment register corruption on x86_32.
- Fix kvmclock wallclock migration offset.
- Fix PIT interrupt ACK vs system reset logic bug.
* git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: VMX: Fix ds/es corruption on i386 with preemption
KVM: x86: apply kvmclock offset to guest wall clock time
KVM: PIC: call ack notifiers for irqs that are dropped form irr
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/i8259.c | 17 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 20 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 4 |
3 files changed, 34 insertions, 7 deletions
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 1df8fb9e1d5..e498b18f010 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -316,6 +316,11 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val) 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; @@ -333,6 +338,18 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val) 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/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c39b60707e0..c00f03de1b7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1488,13 +1488,6 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) 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 @@ -6370,6 +6363,19 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) #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/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 59b59508ff0..42bce48f692 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -925,6 +925,10 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) */ 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; |