aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/process.c')
-rw-r--r--arch/sparc64/kernel/process.c133
1 files changed, 57 insertions, 76 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 059b0d025224..1c7ca2f712d9 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -44,83 +44,61 @@
44#include <asm/fpumacro.h> 44#include <asm/fpumacro.h>
45#include <asm/head.h> 45#include <asm/head.h>
46#include <asm/cpudata.h> 46#include <asm/cpudata.h>
47#include <asm/mmu_context.h>
47#include <asm/unistd.h> 48#include <asm/unistd.h>
49#include <asm/hypervisor.h>
48 50
49/* #define VERBOSE_SHOWREGS */ 51/* #define VERBOSE_SHOWREGS */
50 52
51/* 53static void sparc64_yield(void)
52 * Nothing special yet...
53 */
54void default_idle(void)
55{
56}
57
58#ifndef CONFIG_SMP
59
60/*
61 * the idle loop on a Sparc... ;)
62 */
63void cpu_idle(void)
64{ 54{
65 /* endless idle loop with no priority at all */ 55 if (tlb_type != hypervisor)
66 for (;;) { 56 return;
67 /* If current->work.need_resched is zero we should really
68 * setup for a system wakup event and execute a shutdown
69 * instruction.
70 *
71 * But this requires writing back the contents of the
72 * L2 cache etc. so implement this later. -DaveM
73 */
74 while (!need_resched())
75 barrier();
76 57
77 preempt_enable_no_resched(); 58 clear_thread_flag(TIF_POLLING_NRFLAG);
78 schedule(); 59 smp_mb__after_clear_bit();
79 preempt_disable(); 60
80 check_pgt_cache(); 61 while (!need_resched()) {
62 unsigned long pstate;
63
64 /* Disable interrupts. */
65 __asm__ __volatile__(
66 "rdpr %%pstate, %0\n\t"
67 "andn %0, %1, %0\n\t"
68 "wrpr %0, %%g0, %%pstate"
69 : "=&r" (pstate)
70 : "i" (PSTATE_IE));
71
72 if (!need_resched())
73 sun4v_cpu_yield();
74
75 /* Re-enable interrupts. */
76 __asm__ __volatile__(
77 "rdpr %%pstate, %0\n\t"
78 "or %0, %1, %0\n\t"
79 "wrpr %0, %%g0, %%pstate"
80 : "=&r" (pstate)
81 : "i" (PSTATE_IE));
81 } 82 }
82}
83 83
84#else 84 set_thread_flag(TIF_POLLING_NRFLAG);
85}
85 86
86/* 87/* The idle loop on sparc64. */
87 * the idle loop on a UltraMultiPenguin...
88 *
89 * TIF_POLLING_NRFLAG is set because we do not sleep the cpu
90 * inside of the idler task, so an interrupt is not needed
91 * to get a clean fast response.
92 *
93 * XXX Reverify this assumption... -DaveM
94 *
95 * Addendum: We do want it to do something for the signal
96 * delivery case, we detect that by just seeing
97 * if we are trying to send this to an idler or not.
98 */
99void cpu_idle(void) 88void cpu_idle(void)
100{ 89{
101 cpuinfo_sparc *cpuinfo = &local_cpu_data();
102 set_thread_flag(TIF_POLLING_NRFLAG); 90 set_thread_flag(TIF_POLLING_NRFLAG);
103 91
104 while(1) { 92 while(1) {
105 if (need_resched()) { 93 if (need_resched()) {
106 cpuinfo->idle_volume = 0;
107 preempt_enable_no_resched(); 94 preempt_enable_no_resched();
108 schedule(); 95 schedule();
109 preempt_disable(); 96 preempt_disable();
110 check_pgt_cache();
111 } 97 }
112 cpuinfo->idle_volume++; 98 sparc64_yield();
113
114 /* The store ordering is so that IRQ handlers on
115 * other cpus see our increasing idleness for the buddy
116 * redistribution algorithm. -DaveM
117 */
118 membar_storeload_storestore();
119 } 99 }
120} 100}
121 101
122#endif
123
124extern char reboot_command []; 102extern char reboot_command [];
125 103
126extern void (*prom_palette)(int); 104extern void (*prom_palette)(int);
@@ -354,6 +332,7 @@ void show_regs(struct pt_regs *regs)
354 extern long etrap, etraptl1; 332 extern long etrap, etraptl1;
355#endif 333#endif
356 __show_regs(regs); 334 __show_regs(regs);
335#if 0
357#ifdef CONFIG_SMP 336#ifdef CONFIG_SMP
358 { 337 {
359 extern void smp_report_regs(void); 338 extern void smp_report_regs(void);
@@ -361,6 +340,7 @@ void show_regs(struct pt_regs *regs)
361 smp_report_regs(); 340 smp_report_regs();
362 } 341 }
363#endif 342#endif
343#endif
364 344
365#ifdef VERBOSE_SHOWREGS 345#ifdef VERBOSE_SHOWREGS
366 if (regs->tpc >= &etrap && regs->tpc < &etraptl1 && 346 if (regs->tpc >= &etrap && regs->tpc < &etraptl1 &&
@@ -433,30 +413,15 @@ void exit_thread(void)
433void flush_thread(void) 413void flush_thread(void)
434{ 414{
435 struct thread_info *t = current_thread_info(); 415 struct thread_info *t = current_thread_info();
416 struct mm_struct *mm;
436 417
437 if (t->flags & _TIF_ABI_PENDING) 418 if (t->flags & _TIF_ABI_PENDING)
438 t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); 419 t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
439 420
440 if (t->task->mm) { 421 mm = t->task->mm;
441 unsigned long pgd_cache = 0UL; 422 if (mm)
442 if (test_thread_flag(TIF_32BIT)) { 423 tsb_context_switch(mm);
443 struct mm_struct *mm = t->task->mm;
444 pgd_t *pgd0 = &mm->pgd[0];
445 pud_t *pud0 = pud_offset(pgd0, 0);
446 424
447 if (pud_none(*pud0)) {
448 pmd_t *page = pmd_alloc_one(mm, 0);
449 pud_set(pud0, page);
450 }
451 pgd_cache = get_pgd_cache(pgd0);
452 }
453 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
454 "membar #Sync"
455 : /* no outputs */
456 : "r" (pgd_cache),
457 "r" (TSB_REG),
458 "i" (ASI_DMMU));
459 }
460 set_thread_wsaved(0); 425 set_thread_wsaved(0);
461 426
462 /* Turn off performance counters if on. */ 427 /* Turn off performance counters if on. */
@@ -555,6 +520,18 @@ void synchronize_user_stack(void)
555 } 520 }
556} 521}
557 522
523static void stack_unaligned(unsigned long sp)
524{
525 siginfo_t info;
526
527 info.si_signo = SIGBUS;
528 info.si_errno = 0;
529 info.si_code = BUS_ADRALN;
530 info.si_addr = (void __user *) sp;
531 info.si_trapno = 0;
532 force_sig_info(SIGBUS, &info, current);
533}
534
558void fault_in_user_windows(void) 535void fault_in_user_windows(void)
559{ 536{
560 struct thread_info *t = current_thread_info(); 537 struct thread_info *t = current_thread_info();
@@ -570,13 +547,17 @@ void fault_in_user_windows(void)
570 flush_user_windows(); 547 flush_user_windows();
571 window = get_thread_wsaved(); 548 window = get_thread_wsaved();
572 549
573 if (window != 0) { 550 if (likely(window != 0)) {
574 window -= 1; 551 window -= 1;
575 do { 552 do {
576 unsigned long sp = (t->rwbuf_stkptrs[window] + bias); 553 unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
577 struct reg_window *rwin = &t->reg_window[window]; 554 struct reg_window *rwin = &t->reg_window[window];
578 555
579 if (copy_to_user((char __user *)sp, rwin, winsize)) 556 if (unlikely(sp & 0x7UL))
557 stack_unaligned(sp);
558
559 if (unlikely(copy_to_user((char __user *)sp,
560 rwin, winsize)))
580 goto barf; 561 goto barf;
581 } while (window--); 562 } while (window--);
582 } 563 }