All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <error27@gmail.com>
To: mlevitsk@redhat.com
Cc: kvm@vger.kernel.org
Subject: [bug report] KVM: x86: allow L1 to not intercept triple fault
Date: Mon, 28 Nov 2022 07:31:15 +0300	[thread overview]
Message-ID: <Y4Q5k9Xd5KgBCKit@kili> (raw)

Hello Maxim Levitsky,

The patch 92e7d5c83aff: "KVM: x86: allow L1 to not intercept triple
fault" from Nov 3, 2022, leads to the following Smatch static checker
warning:

	arch/x86/kvm/x86.c:10873 vcpu_enter_guest()
	error: uninitialized symbol 'r'.

arch/x86/kvm/x86.c
    10509 static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
    10510 {
    10511         int r;
    10512         bool req_int_win =
    10513                 dm_request_for_irq_injection(vcpu) &&
    10514                 kvm_cpu_accept_dm_intr(vcpu);
    10515         fastpath_t exit_fastpath;
    10516 
    10517         bool req_immediate_exit = false;
    10518 
    10519         if (kvm_request_pending(vcpu)) {
    10520                 if (kvm_check_request(KVM_REQ_VM_DEAD, vcpu)) {
    10521                         r = -EIO;
    10522                         goto out;
    10523                 }
    10524 
    10525                 if (kvm_dirty_ring_check_request(vcpu)) {
    10526                         r = 0;
    10527                         goto out;
    10528                 }
    10529 
    10530                 if (kvm_check_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu)) {
    10531                         if (unlikely(!kvm_x86_ops.nested_ops->get_nested_state_pages(vcpu))) {
    10532                                 r = 0;
    10533                                 goto out;
    10534                         }
    10535                 }
    10536                 if (kvm_check_request(KVM_REQ_MMU_FREE_OBSOLETE_ROOTS, vcpu))
    10537                         kvm_mmu_free_obsolete_roots(vcpu);
    10538                 if (kvm_check_request(KVM_REQ_MIGRATE_TIMER, vcpu))
    10539                         __kvm_migrate_timers(vcpu);
    10540                 if (kvm_check_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu))
    10541                         kvm_update_masterclock(vcpu->kvm);
    10542                 if (kvm_check_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu))
    10543                         kvm_gen_kvmclock_update(vcpu);
    10544                 if (kvm_check_request(KVM_REQ_CLOCK_UPDATE, vcpu)) {
    10545                         r = kvm_guest_time_update(vcpu);
    10546                         if (unlikely(r))
    10547                                 goto out;
    10548                 }
    10549                 if (kvm_check_request(KVM_REQ_MMU_SYNC, vcpu))
    10550                         kvm_mmu_sync_roots(vcpu);
    10551                 if (kvm_check_request(KVM_REQ_LOAD_MMU_PGD, vcpu))
    10552                         kvm_mmu_load_pgd(vcpu);
    10553                 if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu)) {
    10554                         kvm_vcpu_flush_tlb_all(vcpu);
    10555 
    10556                         /* Flushing all ASIDs flushes the current ASID... */
    10557                         kvm_clear_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
    10558                 }
    10559                 kvm_service_local_tlb_flush_requests(vcpu);
    10560 
    10561                 if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) {
    10562                         vcpu->run->exit_reason = KVM_EXIT_TPR_ACCESS;
    10563                         r = 0;
    10564                         goto out;
    10565                 }
    10566                 if (kvm_test_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {
    10567                         if (is_guest_mode(vcpu))
    10568                                 kvm_x86_ops.nested_ops->triple_fault(vcpu);
    10569 
    10570                         if (kvm_check_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {
    10571                                 vcpu->run->exit_reason = KVM_EXIT_SHUTDOWN;
    10572                                 vcpu->mmio_needed = 0;
    10573                                 r = 0;
    10574                         }

"r" not initialized on else path.  Forgetting to set the error code is
the canonical bug for do-nothing gotos.

    10575                         goto out;
    10576                 }
    10577                 if (kvm_check_request(KVM_REQ_APF_HALT, vcpu)) {
    10578                         /* Page is swapped out. Do synthetic halt */
    10579                         vcpu->arch.apf.halted = true;
    10580                         r = 1;
    10581                         goto out;
    10582                 }
    10583                 if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
    10584                         record_steal_time(vcpu);
    10585                 if (kvm_check_request(KVM_REQ_SMI, vcpu))
    10586                         process_smi(vcpu);
    10587                 if (kvm_check_request(KVM_REQ_NMI, vcpu))
    10588                         process_nmi(vcpu);
    10589                 if (kvm_check_request(KVM_REQ_PMU, vcpu))
    10590                         kvm_pmu_handle_event(vcpu);
    10591                 if (kvm_check_request(KVM_REQ_PMI, vcpu))
    10592                         kvm_pmu_deliver_pmi(vcpu);
    10593                 if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
    10594                         BUG_ON(vcpu->arch.pending_ioapic_eoi > 255);
    10595                         if (test_bit(vcpu->arch.pending_ioapic_eoi,
    10596                                      vcpu->arch.ioapic_handled_vectors)) {
    10597                                 vcpu->run->exit_reason = KVM_EXIT_IOAPIC_EOI;
    10598                                 vcpu->run->eoi.vector =
    10599                                                 vcpu->arch.pending_ioapic_eoi;
    10600                                 r = 0;
    10601                                 goto out;
    10602                         }
    10603                 }
    10604                 if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu))
    10605                         vcpu_scan_ioapic(vcpu);
    10606                 if (kvm_check_request(KVM_REQ_LOAD_EOI_EXITMAP, vcpu))
    10607                         vcpu_load_eoi_exitmap(vcpu);
    10608                 if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
    10609                         kvm_vcpu_reload_apic_access_page(vcpu);
    10610                 if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) {
    10611                         vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
    10612                         vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH;
    10613                         vcpu->run->system_event.ndata = 0;
    10614                         r = 0;
    10615                         goto out;
    10616                 }
    10617                 if (kvm_check_request(KVM_REQ_HV_RESET, vcpu)) {
    10618                         vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
    10619                         vcpu->run->system_event.type = KVM_SYSTEM_EVENT_RESET;
    10620                         vcpu->run->system_event.ndata = 0;
    10621                         r = 0;
    10622                         goto out;
    10623                 }
    10624                 if (kvm_check_request(KVM_REQ_HV_EXIT, vcpu)) {
    10625                         struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
    10626 
    10627                         vcpu->run->exit_reason = KVM_EXIT_HYPERV;
    10628                         vcpu->run->hyperv = hv_vcpu->exit;
    10629                         r = 0;
    10630                         goto out;
    10631                 }
    10632 
    10633                 /*
    10634                  * KVM_REQ_HV_STIMER has to be processed after
    10635                  * KVM_REQ_CLOCK_UPDATE, because Hyper-V SynIC timers
    10636                  * depend on the guest clock being up-to-date
    10637                  */
    10638                 if (kvm_check_request(KVM_REQ_HV_STIMER, vcpu))
    10639                         kvm_hv_process_stimers(vcpu);
    10640                 if (kvm_check_request(KVM_REQ_APICV_UPDATE, vcpu))
    10641                         kvm_vcpu_update_apicv(vcpu);
    10642                 if (kvm_check_request(KVM_REQ_APF_READY, vcpu))
    10643                         kvm_check_async_pf_completion(vcpu);
    10644                 if (kvm_check_request(KVM_REQ_MSR_FILTER_CHANGED, vcpu))
    10645                         static_call(kvm_x86_msr_filter_changed)(vcpu);
    10646 
    10647                 if (kvm_check_request(KVM_REQ_UPDATE_CPU_DIRTY_LOGGING, vcpu))
    10648                         static_call(kvm_x86_update_cpu_dirty_logging)(vcpu);
    10649         }
    10650 
    10651         if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win ||
    10652             kvm_xen_has_interrupt(vcpu)) {
    10653                 ++vcpu->stat.req_event;
    10654                 r = kvm_apic_accept_events(vcpu);
    10655                 if (r < 0) {
    10656                         r = 0;
    10657                         goto out;
    10658                 }
    10659                 if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
    10660                         r = 1;
    10661                         goto out;
    10662                 }
    10663 
    10664                 r = kvm_check_and_inject_events(vcpu, &req_immediate_exit);
    10665                 if (r < 0) {
    10666                         r = 0;
    10667                         goto out;
    10668                 }
    10669                 if (req_int_win)
    10670                         static_call(kvm_x86_enable_irq_window)(vcpu);
    10671 
    10672                 if (kvm_lapic_enabled(vcpu)) {
    10673                         update_cr8_intercept(vcpu);
    10674                         kvm_lapic_sync_to_vapic(vcpu);
    10675                 }
    10676         }
    10677 
    10678         r = kvm_mmu_reload(vcpu);
    10679         if (unlikely(r)) {
    10680                 goto cancel_injection;
    10681         }
    10682 
    10683         preempt_disable();
    10684 
    10685         static_call(kvm_x86_prepare_switch_to_guest)(vcpu);
    10686 
    10687         /*
    10688          * Disable IRQs before setting IN_GUEST_MODE.  Posted interrupt
    10689          * IPI are then delayed after guest entry, which ensures that they
    10690          * result in virtual interrupt delivery.
    10691          */
    10692         local_irq_disable();
    10693 
    10694         /* Store vcpu->apicv_active before vcpu->mode.  */
    10695         smp_store_release(&vcpu->mode, IN_GUEST_MODE);
    10696 
    10697         kvm_vcpu_srcu_read_unlock(vcpu);
    10698 
    10699         /*
    10700          * 1) We should set ->mode before checking ->requests.  Please see
    10701          * the comment in kvm_vcpu_exiting_guest_mode().
    10702          *
    10703          * 2) For APICv, we should set ->mode before checking PID.ON. This
    10704          * pairs with the memory barrier implicit in pi_test_and_set_on
    10705          * (see vmx_deliver_posted_interrupt).
    10706          *
    10707          * 3) This also orders the write to mode from any reads to the page
    10708          * tables done while the VCPU is running.  Please see the comment
    10709          * in kvm_flush_remote_tlbs.
    10710          */
    10711         smp_mb__after_srcu_read_unlock();
    10712 
    10713         /*
    10714          * Process pending posted interrupts to handle the case where the
    10715          * notification IRQ arrived in the host, or was never sent (because the
    10716          * target vCPU wasn't running).  Do this regardless of the vCPU's APICv
    10717          * status, KVM doesn't update assigned devices when APICv is inhibited,
    10718          * i.e. they can post interrupts even if APICv is temporarily disabled.
    10719          */
    10720         if (kvm_lapic_enabled(vcpu))
    10721                 static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu);
    10722 
    10723         if (kvm_vcpu_exit_request(vcpu)) {
    10724                 vcpu->mode = OUTSIDE_GUEST_MODE;
    10725                 smp_wmb();
    10726                 local_irq_enable();
    10727                 preempt_enable();
    10728                 kvm_vcpu_srcu_read_lock(vcpu);
    10729                 r = 1;
    10730                 goto cancel_injection;
    10731         }
    10732 
    10733         if (req_immediate_exit) {
    10734                 kvm_make_request(KVM_REQ_EVENT, vcpu);
    10735                 static_call(kvm_x86_request_immediate_exit)(vcpu);
    10736         }
    10737 
    10738         fpregs_assert_state_consistent();
    10739         if (test_thread_flag(TIF_NEED_FPU_LOAD))
    10740                 switch_fpu_return();
    10741 
    10742         if (vcpu->arch.guest_fpu.xfd_err)
    10743                 wrmsrl(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
    10744 
    10745         if (unlikely(vcpu->arch.switch_db_regs)) {
    10746                 set_debugreg(0, 7);
    10747                 set_debugreg(vcpu->arch.eff_db[0], 0);
    10748                 set_debugreg(vcpu->arch.eff_db[1], 1);
    10749                 set_debugreg(vcpu->arch.eff_db[2], 2);
    10750                 set_debugreg(vcpu->arch.eff_db[3], 3);
    10751         } else if (unlikely(hw_breakpoint_active())) {
    10752                 set_debugreg(0, 7);
    10753         }
    10754 
    10755         guest_timing_enter_irqoff();
    10756 
    10757         for (;;) {
    10758                 /*
    10759                  * Assert that vCPU vs. VM APICv state is consistent.  An APICv
    10760                  * update must kick and wait for all vCPUs before toggling the
    10761                  * per-VM state, and responsing vCPUs must wait for the update
    10762                  * to complete before servicing KVM_REQ_APICV_UPDATE.
    10763                  */
    10764                 WARN_ON_ONCE((kvm_vcpu_apicv_activated(vcpu) != kvm_vcpu_apicv_active(vcpu)) &&
    10765                              (kvm_get_apic_mode(vcpu) != LAPIC_MODE_DISABLED));
    10766 
    10767                 exit_fastpath = static_call(kvm_x86_vcpu_run)(vcpu);
    10768                 if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST))
    10769                         break;
    10770 
    10771                 if (kvm_lapic_enabled(vcpu))
    10772                         static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu);
    10773 
    10774                 if (unlikely(kvm_vcpu_exit_request(vcpu))) {
    10775                         exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED;
    10776                         break;
    10777                 }
    10778         }
    10779 
    10780         /*
    10781          * Do this here before restoring debug registers on the host.  And
    10782          * since we do this before handling the vmexit, a DR access vmexit
    10783          * can (a) read the correct value of the debug registers, (b) set
    10784          * KVM_DEBUGREG_WONT_EXIT again.
    10785          */
    10786         if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
    10787                 WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
    10788                 static_call(kvm_x86_sync_dirty_debug_regs)(vcpu);
    10789                 kvm_update_dr0123(vcpu);
    10790                 kvm_update_dr7(vcpu);
    10791         }
    10792 
    10793         /*
    10794          * If the guest has used debug registers, at least dr7
    10795          * will be disabled while returning to the host.
    10796          * If we don't have active breakpoints in the host, we don't
    10797          * care about the messed up debug address registers. But if
    10798          * we have some of them active, restore the old state.
    10799          */
    10800         if (hw_breakpoint_active())
    10801                 hw_breakpoint_restore();
    10802 
    10803         vcpu->arch.last_vmentry_cpu = vcpu->cpu;
    10804         vcpu->arch.last_guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
    10805 
    10806         vcpu->mode = OUTSIDE_GUEST_MODE;
    10807         smp_wmb();
    10808 
    10809         /*
    10810          * Sync xfd before calling handle_exit_irqoff() which may
    10811          * rely on the fact that guest_fpu::xfd is up-to-date (e.g.
    10812          * in #NM irqoff handler).
    10813          */
    10814         if (vcpu->arch.xfd_no_write_intercept)
    10815                 fpu_sync_guest_vmexit_xfd_state();
    10816 
    10817         static_call(kvm_x86_handle_exit_irqoff)(vcpu);
    10818 
    10819         if (vcpu->arch.guest_fpu.xfd_err)
    10820                 wrmsrl(MSR_IA32_XFD_ERR, 0);
    10821 
    10822         /*
    10823          * Consume any pending interrupts, including the possible source of
    10824          * VM-Exit on SVM and any ticks that occur between VM-Exit and now.
    10825          * An instruction is required after local_irq_enable() to fully unblock
    10826          * interrupts on processors that implement an interrupt shadow, the
    10827          * stat.exits increment will do nicely.
    10828          */
    10829         kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
    10830         local_irq_enable();
    10831         ++vcpu->stat.exits;
    10832         local_irq_disable();
    10833         kvm_after_interrupt(vcpu);
    10834 
    10835         /*
    10836          * Wait until after servicing IRQs to account guest time so that any
    10837          * ticks that occurred while running the guest are properly accounted
    10838          * to the guest.  Waiting until IRQs are enabled degrades the accuracy
    10839          * of accounting via context tracking, but the loss of accuracy is
    10840          * acceptable for all known use cases.
    10841          */
    10842         guest_timing_exit_irqoff();
    10843 
    10844         local_irq_enable();
    10845         preempt_enable();
    10846 
    10847         kvm_vcpu_srcu_read_lock(vcpu);
    10848 
    10849         /*
    10850          * Profile KVM exit RIPs:
    10851          */
    10852         if (unlikely(prof_on == KVM_PROFILING)) {
    10853                 unsigned long rip = kvm_rip_read(vcpu);
    10854                 profile_hit(KVM_PROFILING, (void *)rip);
    10855         }
    10856 
    10857         if (unlikely(vcpu->arch.tsc_always_catchup))
    10858                 kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
    10859 
    10860         if (vcpu->arch.apic_attention)
    10861                 kvm_lapic_sync_from_vapic(vcpu);
    10862 
    10863         r = static_call(kvm_x86_handle_exit)(vcpu, exit_fastpath);
    10864         return r;
    10865 
    10866 cancel_injection:
    10867         if (req_immediate_exit)
    10868                 kvm_make_request(KVM_REQ_EVENT, vcpu);
    10869         static_call(kvm_x86_cancel_injection)(vcpu);
    10870         if (unlikely(vcpu->arch.apic_attention))
    10871                 kvm_lapic_sync_from_vapic(vcpu);
    10872 out:
--> 10873         return r;
    10874 }

regards,
dan carpenter

             reply	other threads:[~2022-11-28  4:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-28  4:31 Dan Carpenter [this message]
2022-11-28 15:13 ` [bug report] KVM: x86: allow L1 to not intercept triple fault Maxim Levitsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y4Q5k9Xd5KgBCKit@kili \
    --to=error27@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=mlevitsk@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.