1
This patch aims to fix idle routine while the CPU receive an interrupt,
1
This patch aims to fix idle routine while the CPU receive an interrupt,
2
because __r4k_wait() only checks if TIF_NEED_RESCHED is set before
2
because __r4k_wait() only checks if TIF_NEED_RESCHED is set before
3
going to sleep.
3
going to sleep.
4
The same behavior has been changed in LoongArch [1].
4
The same behavior has been changed in LoongArch [1].
5
5
6
Code (cross) compiled successfully and I manage to test it on a VM
6
Code (cross) compiled successfully and I manage to test it on a VM
7
emulating a malta board. I ran QEMU with:
7
emulating a malta board. I ran QEMU with:
...
...
11
11
12
rootfs generated using buildroot (malta default configuration).
12
rootfs generated using buildroot (malta default configuration).
13
13
14
- [1] https://github.com/chenhuacai/linux/commit/a8aa673ea46c03b3f62992ffa4ffe810ac84f6e3
14
- [1] https://github.com/chenhuacai/linux/commit/a8aa673ea46c03b3f62992ffa4ffe810ac84f6e3
15
15
16
---
17
Changes in v3:
18
- changed "daddiu k0, 1" with PTR_ADDIU k0, 5
19
- replaced CONFIG_CPU_MICROMIPS with 3 _ssnop followed by _ehb
20
- integrated the commit message with explanation about
21
CONFIG_CPU_MICROMIPS replacement
22
23
Changes in v2:
24
- Changes introduced by Huacai:
25
https://lore.kernel.org/linux-mips/20250214105047.150835-1-marco.crivellari@suse.com/T/#m75d9c587829e15e0d7baec13078be4e65c936408
26
16
Marco Crivellari (1):
27
Marco Crivellari (1):
17
MIPS: Fix idle VS timer enqueue
28
MIPS: Fix idle VS timer enqueue
18
29
19
arch/mips/kernel/genex.S | 36 ++++++++++++++++++++----------------
30
arch/mips/kernel/genex.S | 42 ++++++++++++++++++++++------------------
20
arch/mips/kernel/idle.c | 1 -
31
arch/mips/kernel/idle.c | 1 -
21
2 files changed, 20 insertions(+), 17 deletions(-)
32
2 files changed, 23 insertions(+), 20 deletions(-)
22
33
23
--
34
--
24
2.48.1
35
2.48.1
diff view generated by jsdifflib
...
...
14
14
15
Fix this with fast-forwarding idle IRQs return address to the end of the
15
Fix this with fast-forwarding idle IRQs return address to the end of the
16
idle routine instead of the beginning, so that the generic idle loop
16
idle routine instead of the beginning, so that the generic idle loop
17
handles both TIF_NEED_RESCHED and pending timers.
17
handles both TIF_NEED_RESCHED and pending timers.
18
18
19
CONFIG_CPU_MICROMIPS has been removed along with the nop instructions.
20
There, NOPs are 2 byte in size, so change the code with 3 _ssnop which are
21
always 4 byte and remove the ifdef. Added ehb to make sure the hazard
22
is always cleared.
23
19
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
24
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
20
---
25
---
21
arch/mips/kernel/genex.S | 36 ++++++++++++++++++++----------------
26
arch/mips/kernel/genex.S | 42 ++++++++++++++++++++++------------------
22
arch/mips/kernel/idle.c | 1 -
27
arch/mips/kernel/idle.c | 1 -
23
2 files changed, 20 insertions(+), 17 deletions(-)
28
2 files changed, 23 insertions(+), 20 deletions(-)
24
29
25
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
30
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
26
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
27
--- a/arch/mips/kernel/genex.S
32
--- a/arch/mips/kernel/genex.S
28
+++ b/arch/mips/kernel/genex.S
33
+++ b/arch/mips/kernel/genex.S
...
...
41
-    andi    t0, _TIF_NEED_RESCHED
46
-    andi    t0, _TIF_NEED_RESCHED
42
-    bnez    t0, 1f
47
-    bnez    t0, 1f
43
-     nop
48
-     nop
44
-    nop
49
-    nop
45
-    nop
50
-    nop
51
-#ifdef CONFIG_CPU_MICROMIPS
52
-    nop
53
-    nop
54
-    nop
55
-    nop
56
-#endif
46
+    /* start of idle interrupt region */
57
+    /* start of idle interrupt region */
47
+    MFC0    k0, CP0_STATUS
58
+    MFC0    t0, CP0_STATUS
48
+    /* Enable Interrupt */
59
+    /* Enable Interrput */
49
+    ori     k0, 0x1f
60
+    ori     t0, 0x1f
50
+    xori    k0, 0x1e
61
+    xori    t0, 0x1e
51
+    MTC0    k0, CP0_STATUS
62
+    MTC0    t0, CP0_STATUS
52
#ifdef CONFIG_CPU_MICROMIPS
63
+    _ssnop
53
    nop
64
+    _ssnop
54
    nop
65
+    _ssnop
55
@@ -XXX,XX +XXX,XX @@ LEAF(__r4k_wait)
66
+    _ehb
56
    nop
57
#endif
58
    .set    MIPS_ISA_ARCH_LEVEL_RAW
67
    .set    MIPS_ISA_ARCH_LEVEL_RAW
59
+    /*
68
+    /*
60
+     * If an interrupt lands here, between enabling interrupts above and
69
+     * If an interrupt lands here, between enabling interrupts above and
61
+     * going idle on the next instruction, we must *NOT* go idle since the
70
+     * going idle on the next instruction, we must *NOT* go idle since the
62
+     * interrupt could have set TIF_NEED_RESCHED or caused a timer to need
71
+     * interrupt could have set TIF_NEED_RESCHED or caused a timer to need
63
+     * resched. Fall through -- see rollback_handler below -- and have
72
+     * resched. Fall through -- see rollback_handler below -- and have
64
+     * the idle loop take care of things.
73
+     * the idle loop take care of things.
65
+     */
74
+     */
66
    wait
75
    wait
67
-    /* end of rollback region (the region size must be power of two) */
76
-    /* end of rollback region (the region size must be power of two) */
68
-1:
77
+    /* end of rollback region */
69
+    /* end of idle interrupt region (the region size must be power of two) */
78
1:
70
+SYM_INNER_LABEL(__r4k_wait_exit, SYM_L_LOCAL)
71
    jr    ra
79
    jr    ra
72
-     nop
80
     nop
73
    .set    pop
74
    END(__r4k_wait)
75
76
@@ -XXX,XX +XXX,XX @@ LEAF(__r4k_wait)
81
@@ -XXX,XX +XXX,XX @@ LEAF(__r4k_wait)
77
    .set    push
82
    .set    push
78
    .set    noat
83
    .set    noat
79
    MFC0    k0, CP0_EPC
84
    MFC0    k0, CP0_EPC
80
-    PTR_LA    k1, __r4k_wait
85
-    PTR_LA    k1, __r4k_wait
81
-    ori    k0, 0x1f    /* 32 byte rollback region */
86
-    ori    k0, 0x1f    /* 32 byte rollback region */
82
-    xori    k0, 0x1f
87
-    xori    k0, 0x1f
83
-    bne    k0, k1, \handler
88
+    PTR_LA    k1, 1b
84
+    PTR_LA    k1, __r4k_wait_exit
89
+    /* 36 byte idle interrupt region */
85
+    /* 3 instructions rollback region */
90
+    ori     k0, 0x1f
86
+    ori     k0, k0, 0x0c
91
+    PTR_ADDIU    k0, 5
87
+    bne     k0, k1, \handler
92
    bne    k0, k1, \handler
88
    MTC0    k0, CP0_EPC
93
    MTC0    k0, CP0_EPC
89
    .set pop
94
    .set pop
90
    .endm
91
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
95
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
92
index XXXXXXX..XXXXXXX 100644
96
index XXXXXXX..XXXXXXX 100644
93
--- a/arch/mips/kernel/idle.c
97
--- a/arch/mips/kernel/idle.c
94
+++ b/arch/mips/kernel/idle.c
98
+++ b/arch/mips/kernel/idle.c
95
@@ -XXX,XX +XXX,XX @@ static void __cpuidle r3081_wait(void)
99
@@ -XXX,XX +XXX,XX @@ static void __cpuidle r3081_wait(void)
...
...
diff view generated by jsdifflib