* WAIT vs. tickless kernel
@ 2007-10-31 15:49 Atsushi Nemoto
2007-10-31 16:13 ` Ralf Baechle
0 siblings, 1 reply; 10+ messages in thread
From: Atsushi Nemoto @ 2007-10-31 15:49 UTC (permalink / raw)
To: linux-mips
On some CPUs, there is a small window in the idle task which might
cause a large latency to wakeup a process.
http://www.linux-mips.org/archives/linux-mips/2005-11/msg00114.html
This can be avoided on some CPUs which can use xxx_wait_irqoff(), but
still there are many CPUs out of luck.
And now we have dyntick/tickless kernel. On tickless kernel the
problem might become more serious. We cannot know the worst latency
time. Theoretically a task can lose wakeup-event forever.
Of course "nowait" kernel option will help, but are there any other
good solutions?
Just an idea: If we put an WAIT in hazard area of the MTC0 which
enables interrupts, can we accomplish something like
atomic-test-and-wait operation?
void r4k_wait_bulletproof(void)
{
local_irq_disable();
if (!need_resched())
__asm__(
" .set push \n"
" .set mips3 \n"
" .set noat \n"
" .align 4 \n" /* avoid stall on wait */
" mfc0 $1, $12 \n"
" ori $1, 1 \n"
" mtc0 $1, $12 \n"
" wait \n"
" xori $1, 1 \n"
" mtc0 $1, $12 \n"
" .set pop \n");
local_irq_enable();
}
If this work as expected? Comments from pipeline gurus are welcome ;)
---
Atsushi Nemoto
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-10-31 15:49 WAIT vs. tickless kernel Atsushi Nemoto
@ 2007-10-31 16:13 ` Ralf Baechle
2007-10-31 16:31 ` Atsushi Nemoto
0 siblings, 1 reply; 10+ messages in thread
From: Ralf Baechle @ 2007-10-31 16:13 UTC (permalink / raw)
To: Atsushi Nemoto; +Cc: linux-mips
On Thu, Nov 01, 2007 at 12:49:06AM +0900, Atsushi Nemoto wrote:
> On some CPUs, there is a small window in the idle task which might
> cause a large latency to wakeup a process.
>
> http://www.linux-mips.org/archives/linux-mips/2005-11/msg00114.html
>
> This can be avoided on some CPUs which can use xxx_wait_irqoff(), but
> still there are many CPUs out of luck.
>
> And now we have dyntick/tickless kernel. On tickless kernel the
> problem might become more serious. We cannot know the worst latency
> time. Theoretically a task can lose wakeup-event forever.
>
> Of course "nowait" kernel option will help, but are there any other
> good solutions?
>
> Just an idea: If we put an WAIT in hazard area of the MTC0 which
> enables interrupts, can we accomplish something like
> atomic-test-and-wait operation?
>
> void r4k_wait_bulletproof(void)
> {
> local_irq_disable();
> if (!need_resched())
> __asm__(
> " .set push \n"
> " .set mips3 \n"
> " .set noat \n"
> " .align 4 \n" /* avoid stall on wait */
> " mfc0 $1, $12 \n"
> " ori $1, 1 \n"
> " mtc0 $1, $12 \n"
> " wait \n"
> " xori $1, 1 \n"
> " mtc0 $1, $12 \n"
> " .set pop \n");
> local_irq_enable();
> }
>
> If this work as expected? Comments from pipeline gurus are welcome ;)
This one is definately playing with the fire. Or alternatively requires
detailed knowledge of the pipeline and pipelines tend to change. MIPS
Technologies does regular maintenance releases of its cores which also
add features and may change the pipelines in subtle way that may break
something like this.
The only safe but ugly workaround is to change the return from exception
code to detect if the EPC is in the range startin from the condition
check in the idle loop to including the WAIT instruction and if so to
patch the EPC to resume execution at the condition check or the
instruction following the WAIT.
Ralf
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-10-31 16:13 ` Ralf Baechle
@ 2007-10-31 16:31 ` Atsushi Nemoto
2007-10-31 16:39 ` Ralf Baechle
0 siblings, 1 reply; 10+ messages in thread
From: Atsushi Nemoto @ 2007-10-31 16:31 UTC (permalink / raw)
To: ralf; +Cc: linux-mips
On Wed, 31 Oct 2007 16:13:33 +0000, Ralf Baechle <ralf@linux-mips.org> wrote:
> This one is definately playing with the fire. Or alternatively requires
> detailed knowledge of the pipeline and pipelines tend to change. MIPS
> Technologies does regular maintenance releases of its cores which also
> add features and may change the pipelines in subtle way that may break
> something like this.
Yes, I never think this is robust or guaranteed...
> The only safe but ugly workaround is to change the return from exception
> code to detect if the EPC is in the range startin from the condition
> check in the idle loop to including the WAIT instruction and if so to
> patch the EPC to resume execution at the condition check or the
> instruction following the WAIT.
I'm also thinking of this approach. Still wondering if it is worth to
implement.
---
Atsushi Nemoto
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-10-31 16:31 ` Atsushi Nemoto
@ 2007-10-31 16:39 ` Ralf Baechle
2007-11-02 16:46 ` Atsushi Nemoto
0 siblings, 1 reply; 10+ messages in thread
From: Ralf Baechle @ 2007-10-31 16:39 UTC (permalink / raw)
To: Atsushi Nemoto; +Cc: linux-mips
On Thu, Nov 01, 2007 at 01:31:24AM +0900, Atsushi Nemoto wrote:
> On Wed, 31 Oct 2007 16:13:33 +0000, Ralf Baechle <ralf@linux-mips.org> wrote:
> > This one is definately playing with the fire. Or alternatively requires
> > detailed knowledge of the pipeline and pipelines tend to change. MIPS
> > Technologies does regular maintenance releases of its cores which also
> > add features and may change the pipelines in subtle way that may break
> > something like this.
>
> Yes, I never think this is robust or guaranteed...
>
> > The only safe but ugly workaround is to change the return from exception
> > code to detect if the EPC is in the range startin from the condition
> > check in the idle loop to including the WAIT instruction and if so to
> > patch the EPC to resume execution at the condition check or the
> > instruction following the WAIT.
>
> I'm also thinking of this approach. Still wondering if it is worth to
> implement.
The tickless kernel is very interesting for the low power fraction. And
it's especially those users who would suffer most the loss of the ability
to use the WAIT instruction. For a system running from two AAA cells the
tradeoff is clear ... So I think it's become a must.
Ralf
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-10-31 16:39 ` Ralf Baechle
@ 2007-11-02 16:46 ` Atsushi Nemoto
2007-11-06 15:39 ` Atsushi Nemoto
0 siblings, 1 reply; 10+ messages in thread
From: Atsushi Nemoto @ 2007-11-02 16:46 UTC (permalink / raw)
To: ralf; +Cc: linux-mips
On Wed, 31 Oct 2007 16:39:00 +0000, Ralf Baechle <ralf@linux-mips.org> wrote:
> > > The only safe but ugly workaround is to change the return from exception
> > > code to detect if the EPC is in the range startin from the condition
> > > check in the idle loop to including the WAIT instruction and if so to
> > > patch the EPC to resume execution at the condition check or the
> > > instruction following the WAIT.
> >
> > I'm also thinking of this approach. Still wondering if it is worth to
> > implement.
>
> The tickless kernel is very interesting for the low power fraction. And
> it's especially those users who would suffer most the loss of the ability
> to use the WAIT instruction. For a system running from two AAA cells the
> tradeoff is clear ... So I think it's become a must.
Then, something like this? Selecting in build-time is not so good,
but there are some CPUs which do not need this hack at all.
Synthesizing the ret_from_irq() at runtime might satisfy everyone?
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c8c47a2..621130c 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -51,12 +51,17 @@ static void r39xx_wait(void)
* But it is implementation-dependent wheter the pipelie restarts when
* a non-enabled interrupt is requested.
*/
+#ifdef CONFIG_ROLLBACK_CPU_WAIT
+extern void cpu_wait_rollback(void);
+#define r4k_wait cpu_wait_rollback
+#else
static void r4k_wait(void)
{
__asm__(" .set mips3 \n"
" wait \n"
" .set mips0 \n");
}
+#endif
/*
* This variant is preferable as it allows testing need_resched and going to
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index e29598a..ffa043c 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -27,6 +27,20 @@
#endif
.text
+#ifdef CONFIG_ROLLBACK_CPU_WAIT
+ .align 6
+FEXPORT(cpu_wait_rollback)
+ LONG_L t0, TI_FLAGS($28)
+ andi t0, _TIF_NEED_RESCHED
+ bnez t0, 1f
+ .set mips3
+ wait
+ .set mips0
+1:
+ jr ra
+ .align 6
+cpu_wait_rollback_end:
+#endif
.align 5
#ifndef CONFIG_PREEMPT
FEXPORT(ret_from_exception)
@@ -35,6 +49,14 @@ FEXPORT(ret_from_exception)
#endif
FEXPORT(ret_from_irq)
LONG_S s0, TI_REGS($28)
+#ifdef CONFIG_ROLLBACK_CPU_WAIT
+ LONG_L t0, PT_EPC(sp)
+ ori t0, 0x3f
+ xori t0, 0x3f
+ PTR_LA t1, cpu_wait_rollback
+ bne t0, t1, __ret_from_irq
+ LONG_S t0, PT_EPC(sp) # return to cpu_wait_rollback
+#endif
FEXPORT(__ret_from_irq)
LONG_L t0, PT_STATUS(sp) # returning to kernel mode?
andi t0, t0, KU_USER
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-11-02 16:46 ` Atsushi Nemoto
@ 2007-11-06 15:39 ` Atsushi Nemoto
2007-11-06 15:58 ` David Daney
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Atsushi Nemoto @ 2007-11-06 15:39 UTC (permalink / raw)
To: ralf; +Cc: linux-mips
On Sat, 03 Nov 2007 01:46:49 +0900 (JST), Atsushi Nemoto <anemo@mba.ocn.ne.jp> wrote:
> > The tickless kernel is very interesting for the low power fraction. And
> > it's especially those users who would suffer most the loss of the ability
> > to use the WAIT instruction. For a system running from two AAA cells the
> > tradeoff is clear ... So I think it's become a must.
>
> Then, something like this? Selecting in build-time is not so good,
> but there are some CPUs which do not need this hack at all.
> Synthesizing the ret_from_irq() at runtime might satisfy everyone?
Revised.
As Ralf said on IRC, the adjustment can be done at beginning of
handler, instead of ret_from_irq. So we can enable this hack at
runtime. I introduced BUILD_ROLLBACK_PROLOGUE macro to build prologue
code for handle_int and except_vec_vi. I'm not sure except_vec4 needs
the prologue or not.
And if the EPC was just after WAIT (i.e. normal wakeup from WAIT) the
rollback is not needed. So I arranged r4k_wait so that the rollback
region exactly fit to 32 byte.
How about this?
------------------------------------------------------------------------
Subject: Fix potential latency problem due to non-atomic cpu_wait.
If an interrupt happened between checking of NEED_RESCHED and WAIT
instruction, adjust EPC to restart from checking of NEED_RESCHED.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
---
arch/mips/kernel/cpu-probe.c | 16 ++--------------
arch/mips/kernel/genex.S | 38 ++++++++++++++++++++++++++++++++++++++
arch/mips/kernel/traps.c | 22 ++++++++++++++++------
3 files changed, 56 insertions(+), 20 deletions(-)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c8c47a2..c745b91 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -45,18 +45,7 @@ static void r39xx_wait(void)
local_irq_enable();
}
-/*
- * There is a race when WAIT instruction executed with interrupt
- * enabled.
- * But it is implementation-dependent wheter the pipelie restarts when
- * a non-enabled interrupt is requested.
- */
-static void r4k_wait(void)
-{
- __asm__(" .set mips3 \n"
- " wait \n"
- " .set mips0 \n");
-}
+extern void r4k_wait(void);
/*
* This variant is preferable as it allows testing need_resched and going to
@@ -128,7 +117,7 @@ static int __init wait_disable(char *s)
__setup("nowait", wait_disable);
-static inline void check_wait(void)
+void __init check_wait(void)
{
struct cpuinfo_mips *c = ¤t_cpu_data;
@@ -239,7 +228,6 @@ static inline void check_errata(void)
void __init check_bugs32(void)
{
- check_wait();
check_errata();
}
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index c0f19d6..bb72c3a 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -20,6 +20,7 @@
#include <asm/stackframe.h>
#include <asm/war.h>
#include <asm/page.h>
+#include <asm/thread_info.h>
#define PANIC_PIC(msg) \
.set push; \
@@ -126,7 +127,43 @@ handle_vcei:
__FINIT
+ .align 5 /* 32 byte rollback region */
+LEAF(r4k_wait)
+ .set push
+ .set noreorder
+ /* start of rollback region */
+ LONG_L t0, TI_FLAGS($28)
+ nop
+ andi t0, _TIF_NEED_RESCHED
+ bnez t0, 1f
+ nop
+ nop
+ nop
+ .set mips3
+ wait
+ .set mips0
+ /* end of rollback region (the region size must be power of two) */
+ .set pop
+1:
+ jr ra
+ END(r4k_wait)
+
+ .macro BUILD_ROLLBACK_PROLOGUE handler
+ FEXPORT(rollback_\handler)
+ .set push
+ .set noat
+ MFC0 k0, CP0_EPC
+ ori k0, 0x1f /* 32 byte rollback region */
+ xori k0, 0x1f
+ PTR_LA k1, r4k_wait
+ bne k0, k1, 9f
+ MTC0 k0, CP0_EPC
+9:
+ .set pop
+ .endm
+
.align 5
+BUILD_ROLLBACK_PROLOGUE handle_int
NESTED(handle_int, PT_SIZE, sp)
#ifdef CONFIG_TRACE_IRQFLAGS
/*
@@ -201,6 +238,7 @@ NESTED(except_vec_ejtag_debug, 0, sp)
* This prototype is copied to ebase + n*IntCtl.VS and patched
* to invoke the handler
*/
+BUILD_ROLLBACK_PROLOGUE except_vec_vi
NESTED(except_vec_vi, 0, sp)
SAVE_SOME
SAVE_AT
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index fa50078..0b2cc58 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -43,6 +43,9 @@
#include <asm/types.h>
#include <asm/stacktrace.h>
+extern void check_wait(void);
+extern asmlinkage void r4k_wait(void);
+extern asmlinkage void rollback_handle_int(void);
extern asmlinkage void handle_int(void);
extern asmlinkage void handle_tlbm(void);
extern asmlinkage void handle_tlbl(void);
@@ -1198,6 +1201,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
extern char except_vec_vi, except_vec_vi_lui;
extern char except_vec_vi_ori, except_vec_vi_end;
+ extern char rollback_except_vec_vi;
+ char *vec_start = (cpu_wait == r4k_wait) ?
+ &rollback_except_vec_vi : &except_vec_vi;
#ifdef CONFIG_MIPS_MT_SMTC
/*
* We need to provide the SMTC vectored interrupt handler
@@ -1205,11 +1211,11 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
* Status.IM bit to be masked before going there.
*/
extern char except_vec_vi_mori;
- const int mori_offset = &except_vec_vi_mori - &except_vec_vi;
+ const int mori_offset = &except_vec_vi_mori - vec_start;
#endif /* CONFIG_MIPS_MT_SMTC */
- const int handler_len = &except_vec_vi_end - &except_vec_vi;
- const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
- const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
+ const int handler_len = &except_vec_vi_end - vec_start;
+ const int lui_offset = &except_vec_vi_lui - vec_start;
+ const int ori_offset = &except_vec_vi_ori - vec_start;
if (handler_len > VECTORSPACING) {
/*
@@ -1219,7 +1225,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
panic("VECTORSPACING too small");
}
- memcpy(b, &except_vec_vi, handler_len);
+ memcpy(b, vec_start, handler_len);
#ifdef CONFIG_MIPS_MT_SMTC
BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
@@ -1497,6 +1503,10 @@ void __init trap_init(void)
extern char except_vec3_generic, except_vec3_r4000;
extern char except_vec4;
unsigned long i;
+ int rollback;
+
+ check_wait();
+ rollback = (cpu_wait == r4k_wait);
if (cpu_has_veic || cpu_has_vint)
ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
@@ -1558,7 +1568,7 @@ void __init trap_init(void)
if (board_be_init)
board_be_init();
- set_except_vector(0, handle_int);
+ set_except_vector(0, rollback ? rollback_handle_int : handle_int);
set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-11-06 15:39 ` Atsushi Nemoto
@ 2007-11-06 15:58 ` David Daney
2007-11-06 16:02 ` Atsushi Nemoto
2007-11-07 14:23 ` Atsushi Nemoto
2007-11-11 17:05 ` Atsushi Nemoto
2 siblings, 1 reply; 10+ messages in thread
From: David Daney @ 2007-11-06 15:58 UTC (permalink / raw)
To: Atsushi Nemoto; +Cc: ralf, linux-mips
Atsushi Nemoto wrote:
> +LEAF(r4k_wait)
> + .set push
> + .set noreorder
> + /* start of rollback region */
> + LONG_L t0, TI_FLAGS($28)
> + nop
> + andi t0, _TIF_NEED_RESCHED
> + bnez t0, 1f
> + nop
> + nop
> + nop
> + .set mips3
> + wait
> + .set mips0
> + /* end of rollback region (the region size must be power of two) */
> + .set pop
>
The .set mips0 is redundant as .set pop immediately follows.
David Daney
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-11-06 15:58 ` David Daney
@ 2007-11-06 16:02 ` Atsushi Nemoto
0 siblings, 0 replies; 10+ messages in thread
From: Atsushi Nemoto @ 2007-11-06 16:02 UTC (permalink / raw)
To: ddaney; +Cc: ralf, linux-mips
On Tue, 06 Nov 2007 07:58:46 -0800, David Daney <ddaney@avtrex.com> wrote:
> > + .set mips0
> > + /* end of rollback region (the region size must be power of two) */
> > + .set pop
> >
>
> The .set mips0 is redundant as .set pop immediately follows.
Oh yes. I'll drop it on next revision. Thanks.
---
Atsushi Nemoto
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-11-06 15:39 ` Atsushi Nemoto
2007-11-06 15:58 ` David Daney
@ 2007-11-07 14:23 ` Atsushi Nemoto
2007-11-11 17:05 ` Atsushi Nemoto
2 siblings, 0 replies; 10+ messages in thread
From: Atsushi Nemoto @ 2007-11-07 14:23 UTC (permalink / raw)
To: ralf; +Cc: linux-mips
On Wed, 07 Nov 2007 00:39:25 +0900 (JST), Atsushi Nemoto <anemo@mba.ocn.ne.jp> wrote:
> + MFC0 k0, CP0_EPC
> + ori k0, 0x1f /* 32 byte rollback region */
> + xori k0, 0x1f
> + PTR_LA k1, r4k_wait
Well, this part should be like this, for better pipelining.
MFC0 k0, CP0_EPC
PTR_LA k1, r4k_wait
ori k0, 0x1f /* 32 byte rollback region */
xori k0, 0x1f
> + bne k0, k1, 9f
> + MTC0 k0, CP0_EPC
> +9:
And if we could assume branch-likely, this can be:
.set noreorder
beql k0, k1, 9f
MTC0 k0, CP0_EPC
9:
But not sure if it really have points.
> .align 5
> +BUILD_ROLLBACK_PROLOGUE handle_int
> NESTED(handle_int, PT_SIZE, sp)
And one more question: should we put one more ".align 5" just befor
handle_int for CPUs do not need the rollback?
---
Atsushi Nemoto
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: WAIT vs. tickless kernel
2007-11-06 15:39 ` Atsushi Nemoto
2007-11-06 15:58 ` David Daney
2007-11-07 14:23 ` Atsushi Nemoto
@ 2007-11-11 17:05 ` Atsushi Nemoto
2 siblings, 0 replies; 10+ messages in thread
From: Atsushi Nemoto @ 2007-11-11 17:05 UTC (permalink / raw)
To: ralf; +Cc: linux-mips
Take 3. Remove unnecessary .mips0 and make rollback_handler a bit
faster.
------------------------------------------------------------------------
Subject: Fix potential latency problem due to non-atomic cpu_wait.
If an interrupt happened between checking of NEED_RESCHED and WAIT
instruction, adjust EPC to restart from checking of NEED_RESCHED.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
---
arch/mips/kernel/cpu-probe.c | 16 ++--------------
arch/mips/kernel/genex.S | 37 +++++++++++++++++++++++++++++++++++++
arch/mips/kernel/traps.c | 22 ++++++++++++++++------
3 files changed, 55 insertions(+), 20 deletions(-)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 5c27943..1f71fec 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -45,18 +45,7 @@ static void r39xx_wait(void)
local_irq_enable();
}
-/*
- * There is a race when WAIT instruction executed with interrupt
- * enabled.
- * But it is implementation-dependent wheter the pipelie restarts when
- * a non-enabled interrupt is requested.
- */
-static void r4k_wait(void)
-{
- __asm__(" .set mips3 \n"
- " wait \n"
- " .set mips0 \n");
-}
+extern void r4k_wait(void);
/*
* This variant is preferable as it allows testing need_resched and going to
@@ -128,7 +117,7 @@ static int __init wait_disable(char *s)
__setup("nowait", wait_disable);
-static inline void check_wait(void)
+void __init check_wait(void)
{
struct cpuinfo_mips *c = ¤t_cpu_data;
@@ -239,7 +228,6 @@ static inline void check_errata(void)
void __init check_bugs32(void)
{
- check_wait();
check_errata();
}
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index e76a76b..96f46b3 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -20,6 +20,7 @@
#include <asm/stackframe.h>
#include <asm/war.h>
#include <asm/page.h>
+#include <asm/thread_info.h>
#define PANIC_PIC(msg) \
.set push; \
@@ -126,7 +127,42 @@ handle_vcei:
__FINIT
+ .align 5 /* 32 byte rollback region */
+LEAF(r4k_wait)
+ .set push
+ .set noreorder
+ /* start of rollback region */
+ LONG_L t0, TI_FLAGS($28)
+ nop
+ andi t0, _TIF_NEED_RESCHED
+ bnez t0, 1f
+ nop
+ nop
+ nop
+ .set mips3
+ wait
+ /* end of rollback region (the region size must be power of two) */
+ .set pop
+1:
+ jr ra
+ END(r4k_wait)
+
+ .macro BUILD_ROLLBACK_PROLOGUE handler
+ FEXPORT(rollback_\handler)
+ .set push
+ .set noat
+ MFC0 k0, CP0_EPC
+ PTR_LA k1, r4k_wait
+ ori k0, 0x1f /* 32 byte rollback region */
+ xori k0, 0x1f
+ bne k0, k1, 9f
+ MTC0 k0, CP0_EPC
+9:
+ .set pop
+ .endm
+
.align 5
+BUILD_ROLLBACK_PROLOGUE handle_int
NESTED(handle_int, PT_SIZE, sp)
#ifdef CONFIG_TRACE_IRQFLAGS
/*
@@ -201,6 +237,7 @@ NESTED(except_vec_ejtag_debug, 0, sp)
* This prototype is copied to ebase + n*IntCtl.VS and patched
* to invoke the handler
*/
+BUILD_ROLLBACK_PROLOGUE except_vec_vi
NESTED(except_vec_vi, 0, sp)
SAVE_SOME
SAVE_AT
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 23e73d0..23807c6 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -43,6 +43,9 @@
#include <asm/types.h>
#include <asm/stacktrace.h>
+extern void check_wait(void);
+extern asmlinkage void r4k_wait(void);
+extern asmlinkage void rollback_handle_int(void);
extern asmlinkage void handle_int(void);
extern asmlinkage void handle_tlbm(void);
extern asmlinkage void handle_tlbl(void);
@@ -1146,6 +1149,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
extern char except_vec_vi, except_vec_vi_lui;
extern char except_vec_vi_ori, except_vec_vi_end;
+ extern char rollback_except_vec_vi;
+ char *vec_start = (cpu_wait == r4k_wait) ?
+ &rollback_except_vec_vi : &except_vec_vi;
#ifdef CONFIG_MIPS_MT_SMTC
/*
* We need to provide the SMTC vectored interrupt handler
@@ -1153,11 +1159,11 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
* Status.IM bit to be masked before going there.
*/
extern char except_vec_vi_mori;
- const int mori_offset = &except_vec_vi_mori - &except_vec_vi;
+ const int mori_offset = &except_vec_vi_mori - vec_start;
#endif /* CONFIG_MIPS_MT_SMTC */
- const int handler_len = &except_vec_vi_end - &except_vec_vi;
- const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
- const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
+ const int handler_len = &except_vec_vi_end - vec_start;
+ const int lui_offset = &except_vec_vi_lui - vec_start;
+ const int ori_offset = &except_vec_vi_ori - vec_start;
if (handler_len > VECTORSPACING) {
/*
@@ -1167,7 +1173,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
panic("VECTORSPACING too small");
}
- memcpy(b, &except_vec_vi, handler_len);
+ memcpy(b, vec_start, handler_len);
#ifdef CONFIG_MIPS_MT_SMTC
BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
@@ -1437,6 +1443,10 @@ void __init trap_init(void)
extern char except_vec3_generic, except_vec3_r4000;
extern char except_vec4;
unsigned long i;
+ int rollback;
+
+ check_wait();
+ rollback = (cpu_wait == r4k_wait);
if (cpu_has_veic || cpu_has_vint)
ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
@@ -1496,7 +1506,7 @@ void __init trap_init(void)
if (board_be_init)
board_be_init();
- set_except_vector(0, handle_int);
+ set_except_vector(0, rollback ? rollback_handle_int : handle_int);
set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2007-11-11 17:03 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-31 15:49 WAIT vs. tickless kernel Atsushi Nemoto
2007-10-31 16:13 ` Ralf Baechle
2007-10-31 16:31 ` Atsushi Nemoto
2007-10-31 16:39 ` Ralf Baechle
2007-11-02 16:46 ` Atsushi Nemoto
2007-11-06 15:39 ` Atsushi Nemoto
2007-11-06 15:58 ` David Daney
2007-11-06 16:02 ` Atsushi Nemoto
2007-11-07 14:23 ` Atsushi Nemoto
2007-11-11 17:05 ` Atsushi Nemoto
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.