162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_X86_KVM_PAGE_TRACK_H
362306a36Sopenharmony_ci#define _ASM_X86_KVM_PAGE_TRACK_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/kvm_types.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * The notifier represented by @kvm_page_track_notifier_node is linked into
1062306a36Sopenharmony_ci * the head which will be notified when guest is triggering the track event.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Write access on the head is protected by kvm->mmu_lock, read access
1362306a36Sopenharmony_ci * is protected by track_srcu.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_cistruct kvm_page_track_notifier_head {
1662306a36Sopenharmony_ci	struct srcu_struct track_srcu;
1762306a36Sopenharmony_ci	struct hlist_head track_notifier_list;
1862306a36Sopenharmony_ci};
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct kvm_page_track_notifier_node {
2162306a36Sopenharmony_ci	struct hlist_node node;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	/*
2462306a36Sopenharmony_ci	 * It is called when guest is writing the write-tracked page
2562306a36Sopenharmony_ci	 * and write emulation is finished at that time.
2662306a36Sopenharmony_ci	 *
2762306a36Sopenharmony_ci	 * @gpa: the physical address written by guest.
2862306a36Sopenharmony_ci	 * @new: the data was written to the address.
2962306a36Sopenharmony_ci	 * @bytes: the written length.
3062306a36Sopenharmony_ci	 * @node: this node
3162306a36Sopenharmony_ci	 */
3262306a36Sopenharmony_ci	void (*track_write)(gpa_t gpa, const u8 *new, int bytes,
3362306a36Sopenharmony_ci			    struct kvm_page_track_notifier_node *node);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	/*
3662306a36Sopenharmony_ci	 * Invoked when a memory region is removed from the guest.  Or in KVM
3762306a36Sopenharmony_ci	 * terms, when a memslot is deleted.
3862306a36Sopenharmony_ci	 *
3962306a36Sopenharmony_ci	 * @gfn:       base gfn of the region being removed
4062306a36Sopenharmony_ci	 * @nr_pages:  number of pages in the to-be-removed region
4162306a36Sopenharmony_ci	 * @node:      this node
4262306a36Sopenharmony_ci	 */
4362306a36Sopenharmony_ci	void (*track_remove_region)(gfn_t gfn, unsigned long nr_pages,
4462306a36Sopenharmony_ci				    struct kvm_page_track_notifier_node *node);
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciint kvm_page_track_register_notifier(struct kvm *kvm,
4862306a36Sopenharmony_ci				     struct kvm_page_track_notifier_node *n);
4962306a36Sopenharmony_civoid kvm_page_track_unregister_notifier(struct kvm *kvm,
5062306a36Sopenharmony_ci					struct kvm_page_track_notifier_node *n);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ciint kvm_write_track_add_gfn(struct kvm *kvm, gfn_t gfn);
5362306a36Sopenharmony_ciint kvm_write_track_remove_gfn(struct kvm *kvm, gfn_t gfn);
5462306a36Sopenharmony_ci#else
5562306a36Sopenharmony_ci/*
5662306a36Sopenharmony_ci * Allow defining a node in a structure even if page tracking is disabled, e.g.
5762306a36Sopenharmony_ci * to play nice with testing headers via direct inclusion from the command line.
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_cistruct kvm_page_track_notifier_node {};
6062306a36Sopenharmony_ci#endif /* CONFIG_KVM_EXTERNAL_WRITE_TRACKING */
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#endif
63