Unverified Commit a6281729 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!5445 KVM: x86/mmu: Don't advance iterator after restart due to yielding

parents 7d7a9cb8 6bf8f6af
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ static gfn_t round_gfn_for_level(gfn_t gfn, int level)
 */
void tdp_iter_restart(struct tdp_iter *iter)
{
	iter->yielded = false;
	iter->yielded_gfn = iter->next_last_level_gfn;
	iter->level = iter->root_level;

@@ -160,6 +161,11 @@ static bool try_step_up(struct tdp_iter *iter)
 */
void tdp_iter_next(struct tdp_iter *iter)
{
	if (iter->yielded) {
		tdp_iter_restart(iter);
		return;
	}

	if (try_step_down(iter))
		return;

+6 −0
Original line number Diff line number Diff line
@@ -45,6 +45,12 @@ struct tdp_iter {
	 * iterator walks off the end of the paging structure.
	 */
	bool valid;
	/*
	 * True if KVM dropped mmu_lock and yielded in the middle of a walk, in
	 * which case tdp_iter_next() needs to restart the walk at the root
	 * level instead of advancing to the next entry.
	 */
	bool yielded;
};

/*
+16 −13
Original line number Diff line number Diff line
@@ -516,6 +516,8 @@ static inline bool tdp_mmu_set_spte_atomic_no_dirty_log(struct kvm *kvm,
							struct tdp_iter *iter,
							u64 new_spte)
{
	WARN_ON_ONCE(iter->yielded);

	lockdep_assert_held_read(&kvm->mmu_lock);

	/*
@@ -601,6 +603,8 @@ static inline void __tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter,
				      u64 new_spte, bool record_acc_track,
				      bool record_dirty_log)
{
	WARN_ON_ONCE(iter->yielded);

	lockdep_assert_held_write(&kvm->mmu_lock);

	/*
@@ -666,18 +670,19 @@ static inline void tdp_mmu_set_spte_no_dirty_log(struct kvm *kvm,
 * If this function should yield and flush is set, it will perform a remote
 * TLB flush before yielding.
 *
 * If this function yields, it will also reset the tdp_iter's walk over the
 * paging structure and the calling function should skip to the next
 * iteration to allow the iterator to continue its traversal from the
 * paging structure root.
 * If this function yields, iter->yielded is set and the caller must skip to
 * the next iteration, where tdp_iter_next() will reset the tdp_iter's walk
 * over the paging structures to allow the iterator to continue its traversal
 * from the paging structure root.
 *
 * Return true if this function yielded and the iterator's traversal was reset.
 * Return false if a yield was not needed.
 * Returns true if this function yielded.
 */
static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm,
					     struct tdp_iter *iter, bool flush,
					     bool shared)
static inline bool __must_check tdp_mmu_iter_cond_resched(struct kvm *kvm,
							  struct tdp_iter *iter,
							  bool flush, bool shared)
{
	WARN_ON(iter->yielded);

	/* Ensure forward progress has been made before yielding. */
	if (iter->next_last_level_gfn == iter->yielded_gfn)
		return false;
@@ -697,12 +702,10 @@ static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm,

		WARN_ON(iter->gfn > iter->next_last_level_gfn);

		tdp_iter_restart(iter);

		return true;
		iter->yielded = true;
	}

	return false;
	return iter->yielded;
}

/*