aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include
diff options
context:
space:
mode:
authorPaulius Zaleckas <paulius.zaleckas@teltonika.lt>2009-03-25 04:58:47 -0400
committerPaulius Zaleckas <paulius.zaleckas@teltonika.lt>2009-03-25 04:58:47 -0400
commitbba7d0b9ba0f04d25145de8170a17a3a07bbfdde (patch)
treee832a36e27088294753953a307ed1fb215ef171b /arch/arm/include
parent8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff)
ARM: tlbflush.h: introduce TLB_BTB flag
Signed-off-by: Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
Diffstat (limited to 'arch/arm/include')
-rw-r--r--arch/arm/include/asm/tlbflush.h19
1 files changed, 6 insertions, 13 deletions
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index b543a054a17e..ffedd2494eab 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -39,6 +39,7 @@
39#define TLB_V6_D_ASID (1 << 17) 39#define TLB_V6_D_ASID (1 << 17)
40#define TLB_V6_I_ASID (1 << 18) 40#define TLB_V6_I_ASID (1 << 18)
41 41
42#define TLB_BTB (1 << 28)
42#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ 43#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */
43#define TLB_DCLEAN (1 << 30) 44#define TLB_DCLEAN (1 << 30)
44#define TLB_WB (1 << 31) 45#define TLB_WB (1 << 31)
@@ -140,7 +141,7 @@
140# define v4wb_always_flags (-1UL) 141# define v4wb_always_flags (-1UL)
141#endif 142#endif
142 143
143#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ 144#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
144 TLB_V6_I_FULL | TLB_V6_D_FULL | \ 145 TLB_V6_I_FULL | TLB_V6_D_FULL | \
145 TLB_V6_I_PAGE | TLB_V6_D_PAGE | \ 146 TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
146 TLB_V6_I_ASID | TLB_V6_D_ASID) 147 TLB_V6_I_ASID | TLB_V6_D_ASID)
@@ -297,9 +298,7 @@ static inline void local_flush_tlb_all(void)
297 if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) 298 if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
298 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc"); 299 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
299 300
300 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | 301 if (tlb_flag(TLB_BTB)) {
301 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
302 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
303 /* flush the branch target cache */ 302 /* flush the branch target cache */
304 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); 303 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
305 dsb(); 304 dsb();
@@ -334,9 +333,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
334 if (tlb_flag(TLB_V6_I_ASID)) 333 if (tlb_flag(TLB_V6_I_ASID))
335 asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); 334 asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
336 335
337 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | 336 if (tlb_flag(TLB_BTB)) {
338 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
339 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
340 /* flush the branch target cache */ 337 /* flush the branch target cache */
341 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); 338 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
342 dsb(); 339 dsb();
@@ -374,9 +371,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
374 if (tlb_flag(TLB_V6_I_PAGE)) 371 if (tlb_flag(TLB_V6_I_PAGE))
375 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); 372 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
376 373
377 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | 374 if (tlb_flag(TLB_BTB)) {
378 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
379 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
380 /* flush the branch target cache */ 375 /* flush the branch target cache */
381 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); 376 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
382 dsb(); 377 dsb();
@@ -411,9 +406,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
411 if (tlb_flag(TLB_V6_I_PAGE)) 406 if (tlb_flag(TLB_V6_I_PAGE))
412 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc"); 407 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
413 408
414 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | 409 if (tlb_flag(TLB_BTB)) {
415 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
416 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
417 /* flush the branch target cache */ 410 /* flush the branch target cache */
418 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); 411 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
419 dsb(); 412 dsb();
span> kthread_stop_info.err = ret; complete(&kthread_stop_info.done); } return 0; } /* We are keventd: create a thread. */ static void keventd_create_kthread(void *_create) { struct kthread_create_info *create = _create; int pid; /* We want our own signal handler (we take no signals by default). */ pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD); if (pid < 0) { create->result = ERR_PTR(pid); } else { wait_for_completion(&create->started); read_lock(&tasklist_lock); create->result = find_task_by_pid(pid); read_unlock(&tasklist_lock); } complete(&create->done); } struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...) { struct kthread_create_info create; DECLARE_WORK(work, keventd_create_kthread, &create); create.threadfn = threadfn; create.data = data; init_completion(&create.started); init_completion(&create.done); /* * The workqueue needs to start up first: */ if (!helper_wq) work.func(work.data); else { queue_work(helper_wq, &work); wait_for_completion(&create.done); } if (!IS_ERR(create.result)) { va_list args; va_start(args, namefmt); vsnprintf(create.result->comm, sizeof(create.result->comm), namefmt, args); va_end(args); } return create.result; } EXPORT_SYMBOL(kthread_create); void kthread_bind(struct task_struct *k, unsigned int cpu) { BUG_ON(k->state != TASK_INTERRUPTIBLE); /* Must have done schedule() in kthread() before we set_task_cpu */ wait_task_inactive(k); set_task_cpu(k, cpu); k->cpus_allowed = cpumask_of_cpu(cpu); } EXPORT_SYMBOL(kthread_bind); int kthread_stop(struct task_struct *k) { return kthread_stop_sem(k, NULL); } EXPORT_SYMBOL(kthread_stop); int kthread_stop_sem(struct task_struct *k, struct semaphore *s) { int ret; mutex_lock(&kthread_stop_lock); /* It could exit after stop_info.k set, but before wake_up_process. */ get_task_struct(k); /* Must init completion *before* thread sees kthread_stop_info.k */ init_completion(&kthread_stop_info.done); smp_wmb(); /* Now set kthread_should_stop() to true, and wake it up. */ kthread_stop_info.k = k; if (s) up(s); else wake_up_process(k); put_task_struct(k); /* Once it dies, reset stop ptr, gather result and we're done. */ wait_for_completion(&kthread_stop_info.done); kthread_stop_info.k = NULL; ret = kthread_stop_info.err; mutex_unlock(&kthread_stop_lock); return ret; } EXPORT_SYMBOL(kthread_stop_sem); static __init int helper_init(void) { helper_wq = create_singlethread_workqueue("kthread"); BUG_ON(!helper_wq); return 0; } core_initcall(helper_init);