mirror of https://gitee.com/openkylin/linux.git
[SPARC64]: Use sun4v_cpu_idle() in cpu_idle() on SUN4V.
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>
This commit is contained in:
parent
689126a48a
commit
30c91d576e
|
@ -46,62 +46,47 @@
|
||||||
#include <asm/cpudata.h>
|
#include <asm/cpudata.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
#include <asm/hypervisor.h>
|
||||||
|
|
||||||
/* #define VERBOSE_SHOWREGS */
|
/* #define VERBOSE_SHOWREGS */
|
||||||
|
|
||||||
/*
|
static void sparc64_yield(void)
|
||||||
* Nothing special yet...
|
|
||||||
*/
|
|
||||||
void default_idle(void)
|
|
||||||
{
|
{
|
||||||
}
|
if (tlb_type != hypervisor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||||
|
smp_mb__after_clear_bit();
|
||||||
|
|
||||||
|
while (!need_resched()) {
|
||||||
|
unsigned long pstate;
|
||||||
|
|
||||||
#ifndef CONFIG_SMP
|
/* 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())
|
||||||
* the idle loop on a Sparc... ;)
|
sun4v_cpu_yield();
|
||||||
*/
|
|
||||||
void cpu_idle(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();
|
|
||||||
|
|
||||||
preempt_enable_no_resched();
|
/* Re-enable interrupts. */
|
||||||
schedule();
|
__asm__ __volatile__(
|
||||||
preempt_disable();
|
"rdpr %%pstate, %0\n\t"
|
||||||
check_pgt_cache();
|
"or %0, %1, %0\n\t"
|
||||||
|
"wrpr %0, %%g0, %%pstate"
|
||||||
|
: "=&r" (pstate)
|
||||||
|
: "i" (PSTATE_IE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
/* The idle loop on sparc64. */
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
void cpu_idle(void)
|
void cpu_idle(void)
|
||||||
{
|
{
|
||||||
cpuinfo_sparc *cpuinfo = &local_cpu_data();
|
|
||||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
|
@ -109,13 +94,11 @@ void cpu_idle(void)
|
||||||
preempt_enable_no_resched();
|
preempt_enable_no_resched();
|
||||||
schedule();
|
schedule();
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
check_pgt_cache();
|
|
||||||
}
|
}
|
||||||
|
sparc64_yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern char reboot_command [];
|
extern char reboot_command [];
|
||||||
|
|
||||||
extern void (*prom_palette)(int);
|
extern void (*prom_palette)(int);
|
||||||
|
|
Loading…
Reference in New Issue