Skip to content

Commit

Permalink
[SPARC64]: Use sun4v_cpu_idle() in cpu_idle() on SUN4V.
Browse files Browse the repository at this point in the history
We have to turn off the "polling nrflag" bit when we sleep
the cpu like this, so that we'll get a cross-cpu interrupt
to wake the processor up from the yield.

We also have to disable PSTATE_IE in %pstate around the yield
call and recheck need_resched() in order to avoid any races.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 20, 2006
1 parent 689126a commit 30c91d5
Showing 1 changed file with 32 additions and 49 deletions.
81 changes: 32 additions & 49 deletions arch/sparc64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,76 +46,59 @@
#include <asm/cpudata.h>
#include <asm/mmu_context.h>
#include <asm/unistd.h>
#include <asm/hypervisor.h>

/* #define VERBOSE_SHOWREGS */

/*
* Nothing special yet...
*/
void default_idle(void)
{
}



#ifndef CONFIG_SMP

/*
* the idle loop on a Sparc... ;)
*/
void cpu_idle(void)
static void sparc64_yield(void)
{
/* endless idle loop with no priority at all */
for (;;) {
/* If current->work.need_resched is zero we should really
* setup for a system wakup event and execute a shutdown
* instruction.
*
* But this requires writing back the contents of the
* L2 cache etc. so implement this later. -DaveM
*/
while (!need_resched())
barrier();
if (tlb_type != hypervisor)
return;

preempt_enable_no_resched();
schedule();
preempt_disable();
check_pgt_cache();
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();

while (!need_resched()) {
unsigned long pstate;

/* Disable interrupts. */
__asm__ __volatile__(
"rdpr %%pstate, %0\n\t"
"andn %0, %1, %0\n\t"
"wrpr %0, %%g0, %%pstate"
: "=&r" (pstate)
: "i" (PSTATE_IE));

if (!need_resched())
sun4v_cpu_yield();

/* Re-enable interrupts. */
__asm__ __volatile__(
"rdpr %%pstate, %0\n\t"
"or %0, %1, %0\n\t"
"wrpr %0, %%g0, %%pstate"
: "=&r" (pstate)
: "i" (PSTATE_IE));
}
}

#else
set_thread_flag(TIF_POLLING_NRFLAG);
}

/*
* the idle loop on a UltraMultiPenguin...
*
* TIF_POLLING_NRFLAG is set because we do not sleep the cpu
* inside of the idler task, so an interrupt is not needed
* to get a clean fast response.
*
* XXX Reverify this assumption... -DaveM
*
* Addendum: We do want it to do something for the signal
* delivery case, we detect that by just seeing
* if we are trying to send this to an idler or not.
*/
/* The idle loop on sparc64. */
void cpu_idle(void)
{
cpuinfo_sparc *cpuinfo = &local_cpu_data();
set_thread_flag(TIF_POLLING_NRFLAG);

while(1) {
if (need_resched()) {
preempt_enable_no_resched();
schedule();
preempt_disable();
check_pgt_cache();
}
sparc64_yield();
}
}

#endif

extern char reboot_command [];

extern void (*prom_palette)(int);
Expand Down

0 comments on commit 30c91d5

Please sign in to comment.