arch/x86/kvm/mmu/page_track.c

Source file repositories/reference/linux-study-clean/arch/x86/kvm/mmu/page_track.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kvm/mmu/page_track.c
Extension
.c
Size
9501 bytes
Lines
375
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

kvm_for_each_memslot(slot, bkt, slots) {
			/*
			 * Intentionally do NOT free allocations on failure to
			 * avoid having to track which allocations were made
			 * now versus when the memslot was created.  The
			 * metadata is guaranteed to be freed when the slot is
			 * freed, and will be kept/used if userspace retries
			 * the failed ioctl() instead of killing the VM.
			 */
			r = kvm_page_track_write_tracking_alloc(slot);
			if (r)
				goto out_unlock;
		}
	}

out_success:
	/*
	 * Ensure that external_write_tracking_enabled becomes true strictly
	 * after all the related pointers are set.
	 */
	smp_store_release(&kvm->arch.external_write_tracking_enabled, true);
out_unlock:
	mutex_unlock(&kvm->slots_arch_lock);
	return r;
}

/*
 * register the notifier so that event interception for the tracked guest
 * pages can be received.
 */
int kvm_page_track_register_notifier(struct kvm *kvm,
				     struct kvm_page_track_notifier_node *n)
{
	struct kvm_page_track_notifier_head *head;
	int r;

	if (!kvm || kvm->mm != current->mm)
		return -ESRCH;

	if (!kvm_external_write_tracking_enabled(kvm)) {
		r = kvm_enable_external_write_tracking(kvm);
		if (r)
			return r;
	}

	kvm_get_kvm(kvm);

	head = &kvm->arch.track_notifier_head;

	write_lock(&kvm->mmu_lock);
	hlist_add_head_rcu(&n->node, &head->track_notifier_list);
	write_unlock(&kvm->mmu_lock);
	return 0;
}
EXPORT_SYMBOL_GPL(kvm_page_track_register_notifier);

/*
 * stop receiving the event interception. It is the opposed operation of
 * kvm_page_track_register_notifier().
 */
void kvm_page_track_unregister_notifier(struct kvm *kvm,
					struct kvm_page_track_notifier_node *n)
{
	struct kvm_page_track_notifier_head *head;

	head = &kvm->arch.track_notifier_head;

	write_lock(&kvm->mmu_lock);
	hlist_del_rcu(&n->node);
	write_unlock(&kvm->mmu_lock);
	synchronize_srcu(&head->track_srcu);

	kvm_put_kvm(kvm);
}
EXPORT_SYMBOL_GPL(kvm_page_track_unregister_notifier);

/*
 * Notify the node that write access is intercepted and write emulation is
 * finished at this time.
 *
 * The node should figure out if the written page is the one that node is
 * interested in by itself.
 */
void __kvm_page_track_write(struct kvm *kvm, gpa_t gpa, const u8 *new, int bytes)
{
	struct kvm_page_track_notifier_head *head;
	struct kvm_page_track_notifier_node *n;
	int idx;

	head = &kvm->arch.track_notifier_head;

Annotation

Implementation Notes