linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Gleb Natapov <gleb@redhat.com>
To: kvm@vger.kernel.org
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: [PATCH 08/11] Add "wait for page" hypercall.
Date: Sun,  1 Nov 2009 13:56:27 +0200	[thread overview]
Message-ID: <1257076590-29559-9-git-send-email-gleb@redhat.com> (raw)
In-Reply-To: <1257076590-29559-1-git-send-email-gleb@redhat.com>

We want to be able to inject async pagefault into guest event if a guest
is not executing userspace code. But in this case guest may receive
async page fault in non-sleepable context. In this case it will be
able to make "wait for page" hypercall vcpu will be put to sleep until
page is swapped in and guest can continue without reschedule.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
 arch/x86/include/asm/kvm_host.h |    2 ++
 arch/x86/kvm/mmu.c              |   35 ++++++++++++++++++++++++++++++++++-
 arch/x86/kvm/mmutrace.h         |   19 +++++++++++++++++++
 arch/x86/kvm/x86.c              |    5 +++++
 include/linux/kvm_para.h        |    1 +
 5 files changed, 61 insertions(+), 1 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6c781ea..d404b14 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -456,6 +456,7 @@ struct kvm_vm_stat {
 
 struct kvm_vcpu_stat {
 	u32 pf_fixed;
+	u32 pf_async_wait;
 	u32 pf_guest;
 	u32 tlb_flush;
 	u32 invlpg;
@@ -676,6 +677,7 @@ void kvm_mmu_unload(struct kvm_vcpu *vcpu);
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
 void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu);
 void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu);
+int kvm_pv_wait_for_async_pf(struct kvm_vcpu *vcpu);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index abe1ce9..3d33994 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2281,7 +2281,7 @@ static void async_pf_execute(struct slow_work *work)
 					apf->gva);
 
 	if (waitqueue_active(q))
-		wake_up_interruptible(q);
+		wake_up(q);
 
 	mmdrop(apf->mm);
 }
@@ -2351,6 +2351,39 @@ void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu)
 	async_pf_work_free(work);
 }
 
+static bool kvm_asyc_pf_is_done(struct kvm_vcpu *vcpu)
+{
+	struct kvm_mmu_async_pf *p, *node;
+	bool found = false;
+
+	spin_lock(&vcpu->arch.mmu_async_pf_lock);
+	list_for_each_entry_safe(p, node, &vcpu->arch.mmu_async_pf_done, link) {
+		if (p->guest_task != vcpu->arch.pv_shm->current_task)
+			continue;
+		list_del(&p->link);
+		found = true;
+		break;
+	}
+	spin_unlock(&vcpu->arch.mmu_async_pf_lock);
+	if (found) {
+		vcpu->arch.mmu.page_fault(vcpu, (gpa_t)-1, p->gva,
+					  p->error_code);
+		put_page(p->page);
+		async_pf_work_free(p);
+		trace_kvm_mmu_async_pf_wait(vcpu->arch.pv_shm->current_task, 0);
+	}
+	return found;
+}
+
+int kvm_pv_wait_for_async_pf(struct kvm_vcpu *vcpu)
+{
+	++vcpu->stat.pf_async_wait;
+	trace_kvm_mmu_async_pf_wait(vcpu->arch.pv_shm->current_task, 1);
+	wait_event(vcpu->wq, kvm_asyc_pf_is_done(vcpu));
+
+	return 0;
+}
+
 static bool can_do_async_pf(struct kvm_vcpu *vcpu)
 {
 	struct kvm_segment kvm_seg;
diff --git a/arch/x86/kvm/mmutrace.h b/arch/x86/kvm/mmutrace.h
index d6dd63c..a74f718 100644
--- a/arch/x86/kvm/mmutrace.h
+++ b/arch/x86/kvm/mmutrace.h
@@ -274,6 +274,25 @@ TRACE_EVENT(
 		  __entry->gva, __entry->address, page_to_pfn(__entry->page))
 );
 
+TRACE_EVENT(
+	kvm_mmu_async_pf_wait,
+	TP_PROTO(u64 task, bool wait),
+	TP_ARGS(task, wait),
+
+	TP_STRUCT__entry(
+		__field(u64, task)
+		__field(bool, wait)
+		),
+
+	TP_fast_assign(
+		__entry->task = task;
+		__entry->wait = wait;
+		),
+
+	TP_printk("task %#llx %s", __entry->task, __entry->wait ?
+		  "waits for PF" : "end wait for PF")
+);
+
 #endif /* _TRACE_KVMMMU_H */
 
 /* This part must be outside protection */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e6bd3ad..9208796 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -109,6 +109,7 @@ static DEFINE_PER_CPU(struct kvm_shared_msrs, shared_msrs);
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "pf_fixed", VCPU_STAT(pf_fixed) },
+	{ "pf_async_wait", VCPU_STAT(pf_async_wait) },
 	{ "pf_guest", VCPU_STAT(pf_guest) },
 	{ "tlb_flush", VCPU_STAT(tlb_flush) },
 	{ "invlpg", VCPU_STAT(invlpg) },
@@ -3484,6 +3485,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 	case KVM_HC_SETUP_SHM:
 		r = kvm_pv_setup_shm(vcpu, a0, a1, a2, &ret);
 		break;
+	case KVM_HC_WAIT_FOR_ASYNC_PF:
+		r = kvm_pv_wait_for_async_pf(vcpu);
+		ret = 0;
+		break;
 	default:
 		ret = -KVM_ENOSYS;
 		break;
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index 1c37495..50296a6 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -19,6 +19,7 @@
 #define KVM_HC_VAPIC_POLL_IRQ		1
 #define KVM_HC_MMU_OP			2
 #define KVM_HC_SETUP_SHM		3
+#define KVM_HC_WAIT_FOR_ASYNC_PF	4
 
 /*
  * hypercalls use architecture specific
-- 
1.6.3.3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  parent reply	other threads:[~2009-11-01 11:56 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-01 11:56 [PATCH 00/11] KVM: Add asynchronous page fault for PV guest Gleb Natapov
2009-11-01 11:56 ` [PATCH 01/11] Add shared memory hypercall to PV Linux guest Gleb Natapov
2009-11-02  4:27   ` Rik van Riel
2009-11-02  7:07     ` Gleb Natapov
2009-11-02 12:18   ` Avi Kivity
2009-11-02 16:18     ` Gleb Natapov
2009-11-03  5:15       ` Avi Kivity
2009-11-03  7:16         ` Gleb Natapov
2009-11-03  7:40           ` Avi Kivity
2009-11-01 11:56 ` [PATCH 02/11] Add "handle page fault" PV helper Gleb Natapov
2009-11-02  9:22   ` Ingo Molnar
2009-11-02 16:04     ` Gleb Natapov
2009-11-02 16:12       ` Ingo Molnar
2009-11-02 16:22         ` Gleb Natapov
2009-11-02 16:29           ` Ingo Molnar
2009-11-02 16:31             ` Gleb Natapov
2009-11-02 17:42             ` Gleb Natapov
2009-11-08 11:36               ` Ingo Molnar
2009-11-08 12:43                 ` Avi Kivity
2009-11-08 12:51                   ` Ingo Molnar
2009-11-08 13:01                     ` Avi Kivity
2009-11-08 13:05                       ` Ingo Molnar
2009-11-08 13:08                         ` Avi Kivity
2009-11-08 16:44                     ` H. Peter Anvin
2009-11-08 16:47                       ` Ingo Molnar
2009-11-02 19:03     ` Rik van Riel
2009-11-02 19:33       ` Avi Kivity
2009-11-02 23:35         ` Rik van Riel
2009-11-03  4:57           ` Avi Kivity
2009-11-05  6:44             ` Tian, Kevin
2009-11-05  8:22               ` Avi Kivity
2009-11-01 11:56 ` [PATCH 03/11] Handle asynchronous page fault in a PV guest Gleb Natapov
2009-11-02 12:38   ` Avi Kivity
2009-11-02 15:54     ` Gleb Natapov
2009-11-03 14:14   ` Marcelo Tosatti
2009-11-03 14:25     ` Gleb Natapov
2009-11-03 14:32       ` Marcelo Tosatti
2009-11-03 14:38         ` Avi Kivity
2009-11-01 11:56 ` [PATCH 04/11] Export __get_user_pages_fast Gleb Natapov
2009-11-02  9:23   ` Ingo Molnar
2009-11-01 11:56 ` [PATCH 05/11] Add get_user_pages() variant that fails if major fault is required Gleb Natapov
2009-11-02 19:05   ` Rik van Riel
2009-11-01 11:56 ` [PATCH 06/11] Inject asynchronous page fault into a guest if page is swapped out Gleb Natapov
2009-11-02 12:56   ` Avi Kivity
2009-11-02 15:41     ` Gleb Natapov
2009-11-01 11:56 ` [PATCH 07/11] Retry fault before vmentry Gleb Natapov
2009-11-02 13:03   ` Avi Kivity
2009-11-01 11:56 ` Gleb Natapov [this message]
2009-11-02 13:05   ` [PATCH 08/11] Add "wait for page" hypercall Avi Kivity
2009-11-02 15:13     ` Gleb Natapov
2009-11-02 15:19       ` Avi Kivity
2009-11-01 11:56 ` [PATCH 09/11] Maintain preemptability count even for !CONFIG_PREEMPT kernels Gleb Natapov
2009-11-02  9:24   ` Ingo Molnar
2009-11-01 11:56 ` [PATCH 10/11] Handle async PF in non preemptable context Gleb Natapov
2009-11-01 11:56 ` [PATCH 11/11] Send async PF when guest is not in userspace too Gleb Natapov

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=1257076590-29559-9-git-send-email-gleb@redhat.com \
    --to=gleb@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox