summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2009-03-17 20:06:58 +0100
committerNeal H. Walfield <neal@gnu.org>2009-03-17 20:07:27 +0100
commit76cd36c5b4fb6a3fac688c23a1294745082e08c2 (patch)
tree6fbaa4b0241690d47208073408265b65f7d34789
parent3a31ee11ba3ee140b6cc3444c5fd9b93ea5d614b (diff)
Reduce the page table pool to 4%. Batch tlb invalidations.
-rw-r--r--viengoos/sysdeps/x86_64/thread-arch.c1
-rw-r--r--viengoos/sysdeps/x86_64/vm.c45
2 files changed, 44 insertions, 2 deletions
diff --git a/viengoos/sysdeps/x86_64/thread-arch.c b/viengoos/sysdeps/x86_64/thread-arch.c
index 8c7f9d9..7086288 100644
--- a/viengoos/sysdeps/x86_64/thread-arch.c
+++ b/viengoos/sysdeps/x86_64/thread-arch.c
@@ -167,6 +167,7 @@ thread_resume (void)
}
#endif
+ vm_as_install (current_thread);
#ifndef NDEBUG
if (current_thread->pml4)
diff --git a/viengoos/sysdeps/x86_64/vm.c b/viengoos/sysdeps/x86_64/vm.c
index 754f02f..0a4e261 100644
--- a/viengoos/sysdeps/x86_64/vm.c
+++ b/viengoos/sysdeps/x86_64/vm.c
@@ -86,7 +86,10 @@ pool_free (void *page)
static void
pool_init (void)
{
- int frames = memory_total / 8;
+ /* Use about 4% of memory for page tables. On a machine with 1GB of
+ RAM, this translates to being able to map about 10GB of memory,
+ assuming that leaf page tables are half full. */
+ int frames = memory_total / 25;
debug (0, "Reserving %d (of %"PRId32") frames for page tables",
frames, memory_total);
@@ -204,11 +207,49 @@ vm_as_maybe_init (struct thread *thread)
/* The current address space. */
static struct thread *current_as;
+/* The (direct) cost of a cr3 in terms of invlpg's is 5-10 (at least
+ on AMD64 processors). There are indirect costs associated with
+ reloading cr3 as opposed to invalidating individual pages, namely,
+ that potentially useful translations will be flushed. As such, we
+ use the upper bound. */
+#define CR3_RELOAD_IN_INVLPGS 10
+static uintptr_t shootdown_queue[CR3_RELOAD_IN_INVLPGS];
+static int shootdown_queue_length;
+
+static void
+shootdown_enqueue (uintptr_t addr)
+{
+ assert ((addr & (PAGESIZE - 1)) == 0);
+ assert (addr < KERNEL_OFFSET);
+
+ if (shootdown_queue_length >= CR3_RELOAD_IN_INVLPGS)
+ shootdown_queue_length = CR3_RELOAD_IN_INVLPGS + 1;
+ else
+ shootdown_queue[shootdown_queue_length ++] = addr;
+}
+
void
vm_as_install (struct thread *thread)
{
if (current_as == thread)
- return;
+ {
+ if (unlikely (shootdown_queue_length))
+ {
+ if (shootdown_queue_length > CR3_RELOAD_IN_INVLPGS)
+ asm ("mov %0, %%cr3" :: "r" (current_thread->pml4));
+ else
+ {
+ int i;
+ for (i = 0; i < CR3_RELOAD_IN_INVLPGS; i ++)
+ pte_shootdown (shootdown_queue[i]);
+ }
+
+ shootdown_queue_length = 0;
+ }
+
+ return;
+ }
+ shootdown_queue_length = 0;
vm_as_maybe_init (thread);