diff options
author | Neal H. Walfield <neal@gnu.org> | 2009-03-17 20:06:58 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@gnu.org> | 2009-03-17 20:07:27 +0100 |
commit | 76cd36c5b4fb6a3fac688c23a1294745082e08c2 (patch) | |
tree | 6fbaa4b0241690d47208073408265b65f7d34789 | |
parent | 3a31ee11ba3ee140b6cc3444c5fd9b93ea5d614b (diff) |
Reduce the page table pool to 4%. Batch tlb invalidations.
-rw-r--r-- | viengoos/sysdeps/x86_64/thread-arch.c | 1 | ||||
-rw-r--r-- | viengoos/sysdeps/x86_64/vm.c | 45 |
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); |