public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] lguest: speed up PARAVIRT_LAZY_FLUSH handling
@ 2007-05-31  7:23 Rusty Russell
  2007-05-31  7:24 ` [PATCH 2/3] lguest: more lazy_hcalls Rusty Russell
  0 siblings, 1 reply; 3+ messages in thread
From: Rusty Russell @ 2007-05-31  7:23 UTC (permalink / raw)
  To: lkml - Kernel Mailing List; +Cc: Andrew Morton, virtualization

When Zach Amsden added PARAVIRT_LAZY_FLUSH I didn't realize how often
it would get called.  We only need to do something if we're actually
in lazy mode.

Before:
Time for one context switch via pipe: 10509 (9863 - 18761)
Time for one Copy-on-Write fault: 71796 (20625 - 207750)
Time to exec client once: 1076218 (1066203 - 1085937)
Time for one fork/exit/wait: 1193125 (574750 - 1197750)
Time for two PTE updates: 10844 (10659 - 20703)

After:
Time for one context switch via pipe: 6745 (6521 - 13966)
Time for one Copy-on-Write fault: 44734 (11468 - 91988)
Time to exec client once: 815984 (801218 - 878218)
Time for one fork/exit/wait: 1023250 (397687 - 1030375)
Time for two PTE updates: 6699 (6475 - 9279)

(Native for comparison):
Time for one context switch via pipe: 4031 (3212 - 4146)
Time for one Copy-on-Write fault: 4402 (4388 - 4426)
Time to exec client once: 343859 (336859 - 349484)
Time for one fork/exit/wait: 120234 (118500 - 136140)
Time for two PTE updates: 2269 (2261 - 2272)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff -r 077496256739 drivers/lguest/lguest.c
--- a/drivers/lguest/lguest.c	Thu May 31 16:34:17 2007 +1000
+++ b/drivers/lguest/lguest.c	Thu May 31 16:36:23 2007 +1000
@@ -58,9 +58,10 @@ static enum paravirt_lazy_mode lazy_mode
 static enum paravirt_lazy_mode lazy_mode;
 static void lguest_lazy_mode(enum paravirt_lazy_mode mode)
 {
-	if (mode == PARAVIRT_LAZY_FLUSH)
-		hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);
-	else {
+	if (mode == PARAVIRT_LAZY_FLUSH) {
+		if (unlikely(lazy_mode != PARAVIRT_LAZY_NONE))
+			hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);
+	} else {
 		lazy_mode = mode;
 		if (mode == PARAVIRT_LAZY_NONE)
 			hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);



^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/3] lguest: more lazy_hcalls
  2007-05-31  7:23 [PATCH 1/3] lguest: speed up PARAVIRT_LAZY_FLUSH handling Rusty Russell
@ 2007-05-31  7:24 ` Rusty Russell
  2007-05-31  7:25   ` [PATCH 3/3] lguest: faster tls switching Rusty Russell
  0 siblings, 1 reply; 3+ messages in thread
From: Rusty Russell @ 2007-05-31  7:24 UTC (permalink / raw)
  To: lkml - Kernel Mailing List; +Cc: Andrew Morton, virtualization

Some hypercalls can be batched: lazy_hcall is the wrapper which
determines this, so it's pretty harmless to use lazy_hcall() instead of
hcall().

Before:
Time for one context switch via pipe: 6745 (6521 - 13966)

After:
Time for one context switch via pipe: 5406 (5170 - 7467)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 drivers/lguest/lguest.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

===================================================================
--- a/drivers/lguest/lguest.c
+++ b/drivers/lguest/lguest.c
@@ -225,7 +225,7 @@ static unsigned long current_cr0, curren
 static unsigned long current_cr0, current_cr3;
 static void lguest_write_cr0(unsigned long val)
 {
-	hcall(LHCALL_TS, val & 8, 0, 0);
+	lazy_hcall(LHCALL_TS, val & 8, 0, 0);
 	current_cr0 = val;
 }
 
@@ -247,7 +247,7 @@ static unsigned long lguest_read_cr2(voi
 
 static void lguest_write_cr3(unsigned long cr3)
 {
-	hcall(LHCALL_NEW_PGTABLE, cr3, 0, 0);
+	lazy_hcall(LHCALL_NEW_PGTABLE, cr3, 0, 0);
 	current_cr3 = cr3;
 }
 
@@ -287,7 +287,7 @@ static void lguest_set_pte(pte_t *ptep, 
 	*ptep = pteval;
 	/* Don't bother with hypercall before initial setup. */
 	if (current_cr3)
-		hcall(LHCALL_FLUSH_TLB, 1, 0, 0);
+		lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0);
 }
 
 static void lguest_flush_tlb_single(unsigned long addr)



^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 3/3] lguest: faster tls switching
  2007-05-31  7:24 ` [PATCH 2/3] lguest: more lazy_hcalls Rusty Russell
@ 2007-05-31  7:25   ` Rusty Russell
  0 siblings, 0 replies; 3+ messages in thread
From: Rusty Russell @ 2007-05-31  7:25 UTC (permalink / raw)
  To: lkml - Kernel Mailing List; +Cc: Andrew Morton, virtualization

1) When the Guest sets the new TLS entries, we don't need to re-verify
   the whole GDT.
2) We also don't need to copy all the GDT entries if only the TLS
   entries have changed.

Before:
Time for one context switch via pipe: 5406 (5170 - 7467)

After:
Time for one context switch via pipe: 4916 (4661 - 7004)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 drivers/lguest/core.c     |    5 ++++-
 drivers/lguest/lg.h       |    2 ++
 drivers/lguest/segments.c |   30 ++++++++++++++++++------------
 3 files changed, 24 insertions(+), 13 deletions(-)

diff -r e5e8dfc0fda2 drivers/lguest/core.c
--- a/drivers/lguest/core.c	Thu May 31 17:04:16 2007 +1000
+++ b/drivers/lguest/core.c	Thu May 31 17:12:24 2007 +1000
@@ -278,6 +278,9 @@ static void copy_in_guest_info(struct lg
 	/* Copy all GDT entries but the TSS. */
 	if (lg->changed & CHANGED_GDT)
 		copy_gdt(lg, pages->state.guest_gdt);
+	/* If only the TLS entries have changed, copy them. */
+	else if (lg->changed & CHANGED_GDT_TLS)
+		copy_gdt_tls(lg, pages->state.guest_gdt);
 
 	lg->changed = 0;
 }
diff -r e5e8dfc0fda2 drivers/lguest/lg.h
--- a/drivers/lguest/lg.h	Thu May 31 17:04:16 2007 +1000
+++ b/drivers/lguest/lg.h	Thu May 31 17:10:20 2007 +1000
@@ -115,6 +115,7 @@ struct lguest_pages
 
 #define CHANGED_IDT		1
 #define CHANGED_GDT		2
+#define CHANGED_GDT_TLS		4 /* Actually a subset of CHANGED_GDT */
 #define CHANGED_ALL	        3
 
 /* The private info the thread maintains about the guest. */
@@ -202,6 +203,7 @@ void load_guest_gdt(struct lguest *lg, u
 void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num);
 void guest_load_tls(struct lguest *lg, unsigned long tls_array);
 void copy_gdt(const struct lguest *lg, struct desc_struct *gdt);
+void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt);
 
 /* page_tables.c: */
 int init_guest_pagetable(struct lguest *lg, unsigned long pgtable);
diff -r e5e8dfc0fda2 drivers/lguest/segments.c
--- a/drivers/lguest/segments.c	Thu May 31 17:04:16 2007 +1000
+++ b/drivers/lguest/segments.c	Thu May 31 17:11:46 2007 +1000
@@ -34,11 +34,11 @@ static void check_segment_use(struct lgu
 		kill_guest(lg, "Removed live GDT entry %u", desc);
 }
 
-static void fixup_gdt_table(struct lguest *lg)
+static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end)
 {
 	unsigned int i;
 
-	for (i = 0; i < ARRAY_SIZE(lg->gdt); i++) {
+	for (i = start; i < end; i++) {
 		/* We never copy these ones to real gdt */
 		if (ignored_gdt(i))
 			continue;
@@ -86,6 +86,16 @@ void setup_guest_gdt(struct lguest *lg)
 	lg->gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
 }
 
+/* This is a fast version for the common case where only the three TLS entries
+ * have changed. */
+void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt)
+{
+	unsigned int i;
+
+	for (i = GDT_ENTRY_TLS_MIN; i <= GDT_ENTRY_TLS_MAX; i++)
+		gdt[i] = lg->gdt[i];
+}
+
 void copy_gdt(const struct lguest *lg, struct desc_struct *gdt)
 {
 	unsigned int i;
@@ -101,7 +111,7 @@ void load_guest_gdt(struct lguest *lg, u
 		kill_guest(lg, "too many gdt entries %i", num);
 
 	lgread(lg, lg->gdt, table, num * sizeof(lg->gdt[0]));
-	fixup_gdt_table(lg);
+	fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->gdt));
 	lg->changed |= CHANGED_GDT;
 }
 
@@ -110,6 +120,6 @@ void guest_load_tls(struct lguest *lg, u
 	struct desc_struct *tls = &lg->gdt[GDT_ENTRY_TLS_MIN];
 
 	lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
-	fixup_gdt_table(lg);
-	lg->changed |= CHANGED_GDT;
+	fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1);
+	lg->changed |= CHANGED_GDT_TLS;
 }



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-05-31  7:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-31  7:23 [PATCH 1/3] lguest: speed up PARAVIRT_LAZY_FLUSH handling Rusty Russell
2007-05-31  7:24 ` [PATCH 2/3] lguest: more lazy_hcalls Rusty Russell
2007-05-31  7:25   ` [PATCH 3/3] lguest: faster tls switching Rusty Russell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox