diff options
author | David S. Miller <davem@davemloft.net> | 2006-01-31 18:31:06 -0800 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 01:11:16 -0800 |
commit | 09f94287f7260e03bbeab497e743691fafcc22c3 (patch) | |
tree | ebdb365a7cfe25a1587a930d852f2eaa0e1e773a /arch | |
parent | 56fb4df6da76c35dca22036174e2d1edef83ff1f (diff) |
[SPARC64]: TSB refinements.
Move {init_new,destroy}_context() out of line.
Do not put huge pages into the TSB, only base page size translations.
There are some clever things we could do here, but for now let's be
correct instead of fancy.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/kernel/tsb.S | 11 | ||||
-rw-r--r-- | arch/sparc64/mm/tsb.c | 28 |
2 files changed, 39 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S index 50752c51877..76f2c0b01f3 100644 --- a/arch/sparc64/kernel/tsb.S +++ b/arch/sparc64/kernel/tsb.S @@ -55,6 +55,17 @@ tsb_reload: brgez,a,pn %g5, tsb_do_fault stx %g0, [%g1] + /* If it is larger than the base page size, don't + * bother putting it into the TSB. + */ + srlx %g5, 32, %g2 + sethi %hi(_PAGE_ALL_SZ_BITS >> 32), %g4 + sethi %hi(_PAGE_SZBITS >> 32), %g7 + and %g2, %g4, %g2 + cmp %g2, %g7 + bne,a,pn %xcc, tsb_tlb_reload + stx %g0, [%g1] + TSB_WRITE(%g1, %g5, %g6) /* Finally, load TLB and return from trap. */ diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c index 15e8af58b1d..2f84cef6c1b 100644 --- a/arch/sparc64/mm/tsb.c +++ b/arch/sparc64/mm/tsb.c @@ -8,6 +8,7 @@ #include <asm/page.h> #include <asm/tlbflush.h> #include <asm/tlb.h> +#include <asm/mmu_context.h> #define TSB_ENTRY_ALIGNMENT 16 @@ -82,3 +83,30 @@ void flush_tsb_user(struct mmu_gather *mp) } } } + +int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + unsigned long page = get_zeroed_page(GFP_KERNEL); + + mm->context.sparc64_ctx_val = 0UL; + if (unlikely(!page)) + return -ENOMEM; + + mm->context.sparc64_tsb = (unsigned long *) page; + + return 0; +} + +void destroy_context(struct mm_struct *mm) +{ + free_page((unsigned long) mm->context.sparc64_tsb); + + spin_lock(&ctx_alloc_lock); + + if (CTX_VALID(mm->context)) { + unsigned long nr = CTX_NRBITS(mm->context); + mmu_context_bmap[nr>>6] &= ~(1UL << (nr & 63)); + } + + spin_unlock(&ctx_alloc_lock); +} |