Message ID | 20210728230824.1762363-1-zsm@chromium.org |
---|---|
State | New |
Headers | show |
Series | [linux-4.19.y] KVM: x86: determine if an exception has an error code only when injecting it. | expand |
On 29/07/21 01:08, Zubin Mithra wrote: > From: Maxim Levitsky <mlevitsk@redhat.com> > > commit b97f074583736c42fb36f2da1164e28c73758912 upstream. > > A page fault can be queued while vCPU is in real paged mode on AMD, and > AMD manual asks the user to always intercept it > (otherwise result is undefined). > The resulting VM exit, does have an error code. > > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> > Message-Id: <20210225154135.405125-2-mlevitsk@redhat.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > Signed-off-by: Zubin Mithra <zsm@chromium.org> > --- > Backport Note: > * Syzkaller triggered a WARNING with the following stacktrace: > WARNING: CPU: 3 PID: 3489 at arch/x86/kvm/x86.c:8097 kvm_arch_vcpu_ioctl_run+0x42b/0x33d7 > Kernel panic - not syncing: panic_on_warn set ... > > CPU: 3 PID: 3489 Comm: poc Not tainted 4.19.199-00120-ga89b48fe9308 #5 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 > Call Trace: > dump_stack+0x11b/0x19a > panic+0x188/0x2f1 > ? __warn_printk+0xee/0xee > ? __probe_kernel_read+0xad/0xc8 > ? kvm_arch_vcpu_ioctl_run+0x42b/0x33d7 > ? kvm_arch_vcpu_ioctl_run+0x42b/0x33d7 > __warn+0xe9/0x12a > ? kvm_arch_vcpu_ioctl_run+0x42b/0x33d7 > report_bug+0x93/0xdd > fixup_bug+0x28/0x4b > do_error_trap+0xd1/0x1f5 > ? fixup_bug+0x4b/0x4b > ? tick_nohz_tick_stopped+0x2e/0x39 > ? __irq_work_queue_local+0x50/0x96 > ? preempt_count_sub+0xf/0xbf > ? lockdep_hardirqs_off+0x10c/0x115 > ? error_entry+0x72/0xd0 > ? trace_hardirqs_off_caller+0x56/0x116 > ? trace_hardirqs_off_thunk+0x1a/0x1c > invalid_op+0x14/0x20 > RIP: 0010:kvm_arch_vcpu_ioctl_run+0x42b/0x33d7 > > * This commit is present in linux-5.13.y. > > * Conflict arises as the following commit is is not present in > linux-5.10.y and older. > - b3646477d458 ("KVM: x86: use static calls to reduce kvm_x86_ops overhead") > > * Tests run: syzkaller reproducer, Chrome OS tryjobs > > arch/x86/kvm/x86.c | 13 +++++++++---- > 1 file changed, 9 insertions(+), 4 deletions(-) > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 43fb4e296d8d..9cfc669b4a24 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -416,8 +416,6 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, > > if (!vcpu->arch.exception.pending && !vcpu->arch.exception.injected) { > queue: > - if (has_error && !is_protmode(vcpu)) > - has_error = false; > if (reinject) { > /* > * On vmentry, vcpu->arch.exception.pending is only > @@ -7114,6 +7112,13 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu) > kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr); > } > > +static void kvm_inject_exception(struct kvm_vcpu *vcpu) > +{ > + if (vcpu->arch.exception.error_code && !is_protmode(vcpu)) > + vcpu->arch.exception.error_code = false; > + kvm_x86_ops->queue_exception(vcpu); > +} > + > static int inject_pending_event(struct kvm_vcpu *vcpu) > { > int r; > @@ -7121,7 +7126,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu) > /* try to reinject previous events if any */ > > if (vcpu->arch.exception.injected) > - kvm_x86_ops->queue_exception(vcpu); > + kvm_inject_exception(vcpu); > /* > * Do not inject an NMI or interrupt if there is a pending > * exception. Exceptions and interrupts are recognized at > @@ -7175,7 +7180,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu) > kvm_update_dr7(vcpu); > } > > - kvm_x86_ops->queue_exception(vcpu); > + kvm_inject_exception(vcpu); > } > > /* Don't consider new event if we re-injected an event */ > Acked-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 43fb4e296d8d..9cfc669b4a24 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -416,8 +416,6 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, if (!vcpu->arch.exception.pending && !vcpu->arch.exception.injected) { queue: - if (has_error && !is_protmode(vcpu)) - has_error = false; if (reinject) { /* * On vmentry, vcpu->arch.exception.pending is only @@ -7114,6 +7112,13 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu) kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr); } +static void kvm_inject_exception(struct kvm_vcpu *vcpu) +{ + if (vcpu->arch.exception.error_code && !is_protmode(vcpu)) + vcpu->arch.exception.error_code = false; + kvm_x86_ops->queue_exception(vcpu); +} + static int inject_pending_event(struct kvm_vcpu *vcpu) { int r; @@ -7121,7 +7126,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu) /* try to reinject previous events if any */ if (vcpu->arch.exception.injected) - kvm_x86_ops->queue_exception(vcpu); + kvm_inject_exception(vcpu); /* * Do not inject an NMI or interrupt if there is a pending * exception. Exceptions and interrupts are recognized at @@ -7175,7 +7180,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu) kvm_update_dr7(vcpu); } - kvm_x86_ops->queue_exception(vcpu); + kvm_inject_exception(vcpu); } /* Don't consider new event if we re-injected an event */