Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1292779 > unrolled thread
| Started by | Jike Song <jike.song@intel.com> |
|---|---|
| First post | 2015-12-16 07:00 +0100 |
| Last post | 2015-12-16 07:40 +0100 |
| Articles | 2 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [PATCH 07/11] KVM: page track: add notifier support Jike Song <jike.song@intel.com> - 2015-12-16 07:00 +0100
Re: [PATCH 07/11] KVM: page track: add notifier support Xiao Guangrong <guangrong.xiao@linux.intel.com> - 2015-12-16 07:40 +0100
| From | Jike Song <jike.song@intel.com> |
|---|---|
| Date | 2015-12-16 07:00 +0100 |
| Subject | Re: [PATCH 07/11] KVM: page track: add notifier support |
| Message-ID | <qGdi2-69M-1@gated-at.bofh.it> |
On 12/01/2015 02:26 AM, Xiao Guangrong wrote:
> Notifier list is introduced so that any node wants to receive the track
> event can register to the list
>
> Two APIs are introduced here:
> - kvm_page_track_register_notifier(): register the notifier to receive
> track event
>
> - kvm_page_track_unregister_notifier(): stop receiving track event by
> unregister the notifier
>
> The callback, node->track_write() is called when a write access on the
> write tracked page happens
>
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
> arch/x86/include/asm/kvm_host.h | 1 +
> arch/x86/include/asm/kvm_page_track.h | 39 ++++++++++++++++++++
> arch/x86/kvm/page_track.c | 67 +++++++++++++++++++++++++++++++++++
> arch/x86/kvm/x86.c | 4 +++
> 4 files changed, 111 insertions(+)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index afff1f1..0f7b940 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -658,6 +658,7 @@ struct kvm_arch {
> */
> struct list_head active_mmu_pages;
> struct list_head zapped_obsolete_pages;
> + struct kvm_page_track_notifier_head track_notifier_head;
>
> struct list_head assigned_dev_head;
> struct iommu_domain *iommu_domain;
> diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h
> index f223201..6744234 100644
> --- a/arch/x86/include/asm/kvm_page_track.h
> +++ b/arch/x86/include/asm/kvm_page_track.h
> @@ -6,6 +6,36 @@ enum kvm_page_track_mode {
> KVM_PAGE_TRACK_MAX,
> };
>
> +/*
> + * The notifier represented by @kvm_page_track_notifier_node is linked into
> + * the head which will be notified when guest is triggering the track event.
> + *
> + * Write access on the head is protected by kvm->mmu_lock, read access
> + * is protected by track_srcu.
> + */
> +struct kvm_page_track_notifier_head {
> + struct srcu_struct track_srcu;
> + struct hlist_head track_notifier_list;
> +};
> +
> +struct kvm_page_track_notifier_node {
> + struct hlist_node node;
> +
> + /*
> + * It is called when guest is writing the write-tracked page
> + * and write emulation is finished at that time.
> + *
> + * @vcpu: the vcpu where the write access happened.
> + * @gpa: the physical address written by guest.
> + * @new: the data was written to the address.
> + * @bytes: the written length.
> + */
> + void (*track_write)(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
> + int bytes);
Sir, is it possible to make this non-void? as you described below, the
callback may find this gpa isn't the page being tracked, so it probably
want to return something to indicate: not my business, continue :)
> +};
> +
> +void kvm_page_track_init(struct kvm *kvm);
> +
> int kvm_page_track_create_memslot(struct kvm_memory_slot *slot,
> unsigned long npages);
> void kvm_page_track_free_memslot(struct kvm_memory_slot *free,
> @@ -17,4 +47,13 @@ void kvm_page_track_remove_page(struct kvm *kvm, gfn_t gfn,
> enum kvm_page_track_mode mode);
> bool kvm_page_track_check_mode(struct kvm_vcpu *vcpu, gfn_t gfn,
> enum kvm_page_track_mode mode);
> +
> +void
> +kvm_page_track_register_notifier(struct kvm *kvm,
> + struct kvm_page_track_notifier_node *n);
> +void
> +kvm_page_track_unregister_notifier(struct kvm *kvm,
> + struct kvm_page_track_notifier_node *n);
> +void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
> + int bytes);
> #endif
> diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c
> index dc2da12..84420df 100644
> --- a/arch/x86/kvm/page_track.c
> +++ b/arch/x86/kvm/page_track.c
> @@ -165,3 +165,70 @@ bool kvm_page_track_check_mode(struct kvm_vcpu *vcpu, gfn_t gfn,
>
> return !!ACCESS_ONCE(slot->arch.gfn_track[mode][index]);
> }
> +
> +void kvm_page_track_init(struct kvm *kvm)
> +{
> + struct kvm_page_track_notifier_head *head;
> +
> + head = &kvm->arch.track_notifier_head;
> + init_srcu_struct(&head->track_srcu);
> + INIT_HLIST_HEAD(&head->track_notifier_list);
> +}
> +
> +/*
> + * register the notifier so that event interception for the tracked guest
> + * pages can be received.
> + */
> +void
> +kvm_page_track_register_notifier(struct kvm *kvm,
> + struct kvm_page_track_notifier_node *n)
> +{
> + struct kvm_page_track_notifier_head *head;
> +
> + head = &kvm->arch.track_notifier_head;
> +
> + spin_lock(&kvm->mmu_lock);
> + hlist_add_head_rcu(&n->node, &head->track_notifier_list);
> + spin_unlock(&kvm->mmu_lock);
> +}
> +
> +/*
> + * 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;
> +
> + spin_lock(&kvm->mmu_lock);
> + hlist_del_rcu(&n->node);
> + spin_unlock(&kvm->mmu_lock);
> + synchronize_srcu(&head->track_srcu);
> +}
> +
> +/*
> + * 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_vcpu *vcpu, 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 = &vcpu->kvm->arch.track_notifier_head;
> +
> + idx = srcu_read_lock(&head->track_srcu);
> + hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
> + if (n->track_write)
> + n->track_write(vcpu, gpa, new, bytes);
> + srcu_read_unlock(&head->track_srcu, idx);
> +}
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index ad4888a..64dbc69 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -4328,6 +4328,7 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
> if (ret < 0)
> return 0;
> kvm_mmu_pte_write(vcpu, gpa, val, bytes);
> + kvm_page_track_write(vcpu, gpa, val, bytes);
> return 1;
> }
>
> @@ -4586,6 +4587,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
>
> kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
> kvm_mmu_pte_write(vcpu, gpa, new, bytes);
> + kvm_page_track_write(vcpu, gpa, new, bytes);
>
> return X86EMUL_CONTINUE;
>
> @@ -7691,6 +7693,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> INIT_DELAYED_WORK(&kvm->arch.kvmclock_update_work, kvmclock_update_fn);
> INIT_DELAYED_WORK(&kvm->arch.kvmclock_sync_work, kvmclock_sync_fn);
>
> + kvm_page_track_init(kvm);
> +
> return 0;
> }
>
>
--
Thanks,
Jike
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Xiao Guangrong <guangrong.xiao@linux.intel.com> |
|---|---|
| Date | 2015-12-16 07:40 +0100 |
| Message-ID | <qGdUK-6F9-1@gated-at.bofh.it> |
| In reply to | #1292779 |
On 12/16/2015 01:53 PM, Jike Song wrote:
> On 12/01/2015 02:26 AM, Xiao Guangrong wrote:
>> Notifier list is introduced so that any node wants to receive the track
>> event can register to the list
>>
>> Two APIs are introduced here:
>> - kvm_page_track_register_notifier(): register the notifier to receive
>> track event
>>
>> - kvm_page_track_unregister_notifier(): stop receiving track event by
>> unregister the notifier
>>
>> The callback, node->track_write() is called when a write access on the
>> write tracked page happens
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>> arch/x86/include/asm/kvm_host.h | 1 +
>> arch/x86/include/asm/kvm_page_track.h | 39 ++++++++++++++++++++
>> arch/x86/kvm/page_track.c | 67 +++++++++++++++++++++++++++++++++++
>> arch/x86/kvm/x86.c | 4 +++
>> 4 files changed, 111 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
>> index afff1f1..0f7b940 100644
>> --- a/arch/x86/include/asm/kvm_host.h
>> +++ b/arch/x86/include/asm/kvm_host.h
>> @@ -658,6 +658,7 @@ struct kvm_arch {
>> */
>> struct list_head active_mmu_pages;
>> struct list_head zapped_obsolete_pages;
>> + struct kvm_page_track_notifier_head track_notifier_head;
>>
>> struct list_head assigned_dev_head;
>> struct iommu_domain *iommu_domain;
>> diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h
>> index f223201..6744234 100644
>> --- a/arch/x86/include/asm/kvm_page_track.h
>> +++ b/arch/x86/include/asm/kvm_page_track.h
>> @@ -6,6 +6,36 @@ enum kvm_page_track_mode {
>> KVM_PAGE_TRACK_MAX,
>> };
>>
>> +/*
>> + * The notifier represented by @kvm_page_track_notifier_node is linked into
>> + * the head which will be notified when guest is triggering the track event.
>> + *
>> + * Write access on the head is protected by kvm->mmu_lock, read access
>> + * is protected by track_srcu.
>> + */
>> +struct kvm_page_track_notifier_head {
>> + struct srcu_struct track_srcu;
>> + struct hlist_head track_notifier_list;
>> +};
>> +
>> +struct kvm_page_track_notifier_node {
>> + struct hlist_node node;
>> +
>> + /*
>> + * It is called when guest is writing the write-tracked page
>> + * and write emulation is finished at that time.
>> + *
>> + * @vcpu: the vcpu where the write access happened.
>> + * @gpa: the physical address written by guest.
>> + * @new: the data was written to the address.
>> + * @bytes: the written length.
>> + */
>> + void (*track_write)(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
>> + int bytes);
>
> Sir, is it possible to make this non-void? as you described below, the
> callback may find this gpa isn't the page being tracked, so it probably
> want to return something to indicate: not my business, continue :)
Currently the return value is useless and it is not ABI so we can extend
it if it is needed in the future.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web