diff options
Diffstat (limited to 'include/asm-sparc64/mmu_context.h')
-rw-r--r-- | include/asm-sparc64/mmu_context.h | 46 |
1 files changed, 13 insertions, 33 deletions
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h index 57ee7b306189..34640a370ab4 100644 --- a/include/asm-sparc64/mmu_context.h +++ b/include/asm-sparc64/mmu_context.h | |||
@@ -25,7 +25,13 @@ extern void get_new_mmu_context(struct mm_struct *mm); | |||
25 | * This just needs to set mm->context to an invalid context. | 25 | * This just needs to set mm->context to an invalid context. |
26 | */ | 26 | */ |
27 | #define init_new_context(__tsk, __mm) \ | 27 | #define init_new_context(__tsk, __mm) \ |
28 | (((__mm)->context.sparc64_ctx_val = 0UL), 0) | 28 | ({ unsigned long __pg = get_zeroed_page(GFP_KERNEL); \ |
29 | (__mm)->context.sparc64_ctx_val = 0UL; \ | ||
30 | (__mm)->context.sparc64_tsb = \ | ||
31 | (unsigned long *) __pg; \ | ||
32 | (__pg ? 0 : -ENOMEM); \ | ||
33 | }) | ||
34 | |||
29 | 35 | ||
30 | /* Destroy a dead context. This occurs when mmput drops the | 36 | /* Destroy a dead context. This occurs when mmput drops the |
31 | * mm_users count to zero, the mmaps have been released, and | 37 | * mm_users count to zero, the mmaps have been released, and |
@@ -35,7 +41,8 @@ extern void get_new_mmu_context(struct mm_struct *mm); | |||
35 | * this task if valid. | 41 | * this task if valid. |
36 | */ | 42 | */ |
37 | #define destroy_context(__mm) \ | 43 | #define destroy_context(__mm) \ |
38 | do { spin_lock(&ctx_alloc_lock); \ | 44 | do { free_page((unsigned long)(__mm)->context.sparc64_tsb); \ |
45 | spin_lock(&ctx_alloc_lock); \ | ||
39 | if (CTX_VALID((__mm)->context)) { \ | 46 | if (CTX_VALID((__mm)->context)) { \ |
40 | unsigned long nr = CTX_NRBITS((__mm)->context); \ | 47 | unsigned long nr = CTX_NRBITS((__mm)->context); \ |
41 | mmu_context_bmap[nr>>6] &= ~(1UL << (nr & 63)); \ | 48 | mmu_context_bmap[nr>>6] &= ~(1UL << (nr & 63)); \ |
@@ -43,35 +50,7 @@ do { spin_lock(&ctx_alloc_lock); \ | |||
43 | spin_unlock(&ctx_alloc_lock); \ | 50 | spin_unlock(&ctx_alloc_lock); \ |
44 | } while(0) | 51 | } while(0) |
45 | 52 | ||
46 | /* Reload the two core values used by TLB miss handler | 53 | extern unsigned long tsb_context_switch(unsigned long pgd_pa, unsigned long *tsb); |
47 | * processing on sparc64. They are: | ||
48 | * 1) The physical address of mm->pgd, when full page | ||
49 | * table walks are necessary, this is where the | ||
50 | * search begins. | ||
51 | * 2) A "PGD cache". For 32-bit tasks only pgd[0] is | ||
52 | * ever used since that maps the entire low 4GB | ||
53 | * completely. To speed up TLB miss processing we | ||
54 | * make this value available to the handlers. This | ||
55 | * decreases the amount of memory traffic incurred. | ||
56 | */ | ||
57 | #define reload_tlbmiss_state(__tsk, __mm) \ | ||
58 | do { \ | ||
59 | register unsigned long paddr asm("o5"); \ | ||
60 | register unsigned long pgd_cache asm("o4"); \ | ||
61 | paddr = __pa((__mm)->pgd); \ | ||
62 | pgd_cache = 0UL; \ | ||
63 | if (task_thread_info(__tsk)->flags & _TIF_32BIT) \ | ||
64 | pgd_cache = get_pgd_cache((__mm)->pgd); \ | ||
65 | __asm__ __volatile__("wrpr %%g0, 0x494, %%pstate\n\t" \ | ||
66 | "mov %3, %%g4\n\t" \ | ||
67 | "mov %0, %%g7\n\t" \ | ||
68 | "stxa %1, [%%g4] %2\n\t" \ | ||
69 | "membar #Sync\n\t" \ | ||
70 | "wrpr %%g0, 0x096, %%pstate" \ | ||
71 | : /* no outputs */ \ | ||
72 | : "r" (paddr), "r" (pgd_cache),\ | ||
73 | "i" (ASI_DMMU), "i" (TSB_REG)); \ | ||
74 | } while(0) | ||
75 | 54 | ||
76 | /* Set MMU context in the actual hardware. */ | 55 | /* Set MMU context in the actual hardware. */ |
77 | #define load_secondary_context(__mm) \ | 56 | #define load_secondary_context(__mm) \ |
@@ -101,7 +80,8 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str | |||
101 | 80 | ||
102 | if (!ctx_valid || (old_mm != mm)) { | 81 | if (!ctx_valid || (old_mm != mm)) { |
103 | load_secondary_context(mm); | 82 | load_secondary_context(mm); |
104 | reload_tlbmiss_state(tsk, mm); | 83 | tsb_context_switch(__pa(mm->pgd), |
84 | mm->context.sparc64_tsb); | ||
105 | } | 85 | } |
106 | 86 | ||
107 | /* Even if (mm == old_mm) we _must_ check | 87 | /* Even if (mm == old_mm) we _must_ check |
@@ -139,7 +119,7 @@ static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm | |||
139 | 119 | ||
140 | load_secondary_context(mm); | 120 | load_secondary_context(mm); |
141 | __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT); | 121 | __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT); |
142 | reload_tlbmiss_state(current, mm); | 122 | tsb_context_switch(__pa(mm->pgd), mm->context.sparc64_tsb); |
143 | } | 123 | } |
144 | 124 | ||
145 | #endif /* !(__ASSEMBLY__) */ | 125 | #endif /* !(__ASSEMBLY__) */ |