The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Rusty Russell <rusty@rustcorp.com.au>
To: Andrew Morton <akpm@osdl.org>
Cc: Andi Kleen <ak@muc.de>,
	lkml - Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH 6/9] lguest: pin stack page optimization
Date: Fri, 09 Mar 2007 14:19:08 +1100	[thread overview]
Message-ID: <1173410348.32234.81.camel@localhost.localdomain> (raw)
In-Reply-To: <1173410264.32234.78.camel@localhost.localdomain>

We make sure that the stack is always mapped in pin_stack_pages by
simply calling demand_page, but that calls get_user_pages() to find
the pfn, which is way overkill since the page is almost certainly
already mapped.  So don't call pin_stack_pages every context switch
(unless genuinely a completely clean context, all the kernel mappings
are kept in sync), and when we do call it, have it check if it needs
to call demand_page().

This speeds guest context switch by 25%:

Before:
Time for one context switch via pipe: 10606 nsec
After:
Time for one context switch via pipe: 7805 nsec
Native:
Time for one context switch via pipe: 4701 nsec

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

diff -r 06b3a533da77 arch/i386/lguest/page_tables.c
--- a/arch/i386/lguest/page_tables.c	Wed Feb 21 12:20:20 2007 +1100
+++ b/arch/i386/lguest/page_tables.c	Wed Feb 21 18:13:00 2007 +1100
@@ -155,14 +158,29 @@ int demand_page(struct lguest *lg, u32 v
 	return page_in(lg, vaddr, (write ? _PAGE_DIRTY : 0)|_PAGE_ACCESSED);
 }
 
+/* This is much faster than the full demand_page logic. */
+static int page_writable(struct lguest *lg, unsigned long vaddr)
+{
+	u32 *top, *pte;
+
+	top = toplev(lg, lg->pgdidx, vaddr);
+	if (!(*top & _PAGE_PRESENT))
+		return 0;
+
+	pte = pteof(lg, *top, vaddr);
+	return (*pte & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW);
+}
+
 void pin_stack_pages(struct lguest *lg)
 {
 	unsigned int i;
 	u32 stack = lg->state->tss.esp1;
 
-	for (i = 0; i < lg->stack_pages; i++)
-		if (!demand_page(lg, stack - i*PAGE_SIZE, 1))
+	for (i = 0; i < lg->stack_pages; i++) {
+		if (!page_writable(lg, stack - i * PAGE_SIZE)
+		    && !demand_page(lg, stack - i * PAGE_SIZE, 1))
 			kill_guest(lg, "bad stack page %i@%#x", i, stack);
+	}
 }
 
 static unsigned int find_pgdir(struct lguest *lg, u32 pgtable)
@@ -198,7 +216,7 @@ void guest_pagetable_flush_user(struct l
 	flush_user_mappings(lg, lg->pgdidx);
 }
 
-static unsigned int new_pgdir(struct lguest *lg, u32 cr3)
+static unsigned int new_pgdir(struct lguest *lg, u32 cr3, int *blank_pgdir)
 {
 	unsigned int next;
 
@@ -207,6 +225,9 @@ static unsigned int new_pgdir(struct lgu
 		lg->pgdirs[next].pgdir = (u32 *)get_zeroed_page(GFP_KERNEL);
 		if (!lg->pgdirs[next].pgdir)
 			next = lg->pgdidx;
+		else
+			/* There are no mappings: you'll need to re-pin */
+			*blank_pgdir = 1;
 	}
 	lg->pgdirs[next].cr3 = cr3;
 	/* Release all the non-kernel mappings. */
@@ -217,14 +238,15 @@ static unsigned int new_pgdir(struct lgu
 
 void guest_new_pagetable(struct lguest *lg, u32 pgtable)
 {
-	int newpgdir;
+	int newpgdir, repin = 0;
 
 	newpgdir = find_pgdir(lg, pgtable);
 	if (newpgdir == ARRAY_SIZE(lg->pgdirs))
-		newpgdir = new_pgdir(lg, pgtable);
+		newpgdir = new_pgdir(lg, pgtable, &repin);
 	lg->pgdidx = newpgdir;
 	lg->cr3 = __pa(lg->pgdirs[lg->pgdidx].pgdir);
-	pin_stack_pages(lg);
+	if (repin)
+		pin_stack_pages(lg);
 }
 
 static void release_all_pagetables(struct lguest *lg)



  reply	other threads:[~2007-03-09  3:20 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-03-09  3:05 [PATCH 1/9] lguest: block device speedup Rusty Russell
2007-03-09  3:08 ` [PATCH 2/9] lguest: bridging support in example code Rusty Russell
2007-03-09  3:12   ` [PATCH 3/9] lguest: cleanup: allocate separate pages for switcher code Rusty Russell
2007-03-09  3:16     ` [PATCH 4/9] lguest: cleanup: clean up regs save/restore Rusty Russell
2007-03-09  3:17       ` [PATCH 5/9] lguest: documentation fixes Rusty Russell
2007-03-09  3:19         ` Rusty Russell [this message]
2007-03-09  3:23           ` [PATCH 7/9] lguest: use read-only pages rather than segments to protect high-mapped switcher Rusty Russell
2007-03-09  3:30             ` [PATCH 8/9] lguest: Optimize away copy in and out of per-cpu guest pages Rusty Russell
2007-03-09  3:32               ` [PATCH 9/9] lguest: don't crash host on NMI Rusty Russell
2007-03-09  7:51 ` [PATCH 1/9] lguest: block device speedup Christoph Hellwig
2007-03-09  8:09   ` Jens Axboe

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=1173410348.32234.81.camel@localhost.localdomain \
    --to=rusty@rustcorp.com.au \
    --cc=ak@muc.de \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.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