Skip to content

Commit

Permalink
ARM: !MMU: v7-M: preemption support
Browse files Browse the repository at this point in the history
ICSR RETTOBASE bit indicates whether there is any active exception other
than the exception indicated by current value of IPSR. Existing code
already makes use of it to find whether interrupt occurred during
user(thread) mode. Add preemption support in the code path that executes
upon finding an active exception other than the current interrupt.

Having an active exception during interrupt exception indicates that
the interrupt occurred during SVC or PendSV with current Linux exception
setup. On PendSV, interrupts are disabled at exception entry (applicable
to all) & enabled back just before returning from exception. Hence it
has been assumed that active exception during interrupt is indicating
SVC interruption. This would have to be revisited.

With this change, there is some effect, but not enough to make it
usable, this is being debugged.

A simple character driver that does infinite while loop during read was
used to test it as follows (/dev/mymisc corresponds to the node for the
character driver),

A. Before this change,

A.1
~ # cat /dev/mymisc
[   28.099225] mymisc_open
[   28.101625] mymisc_read: enter

command prompt is not usable (expected), interrupts do happen during
this time.

A.2
~ # cat /dev/mymisc &
[1] 39 cat /dev/mymisc
~ # [   11.699880] mymisc_open
[   11.702274] mymisc_read: enter

command prompt is not usable (expected as preemption not supported).

B. After this change,

B.1
~ # cat /dev/mymisc
[   27.374821] mymisc_open
[   27.377349] mymisc_read: enter

though user will not get control back (as expected as it is fg process),
entering on prompt causes new line, doesn't know what to make out of
this behaviour, this doesn't happen in the A.1 case. Interrupts happen
here as well.

B.2
~ # cat /dev/mymisc &
[1] 41 cat /dev/mymisc
~ # [   44.836417] mymisc_open
[   44.838814] mymisc_read: enter

though prompt is available under the control of user, upon typing
anything on the prompt (typed character doesn't get echoed), it crashes
as follows,

[   44.838814] mymisc_read: enter
[   51.710314]
[   51.710314] Unhandled exception: IPSR = 00000006 LR = fffffffd
[   51.717576] CPU: 0 PID: 37 Comm: sh Not tainted 5.5.0-rc4-00004-g2328d01dbd85 torvalds#105
[   51.725078] Hardware name: STM32 (Device Tree Support)
[   51.730206] PC is at 0x90195958
[   51.733329] LR is at 0x901c4df3
[   51.736471] pc : [<90195958>]    lr : [<901c4df3>]    psr: 21000000
[   51.742713] sp : 901e5a58  ip : 00000000  fp : 901d89fc
[   51.747911] r10: 00000000  r9 : 00000000  r8 : 00000001
[   51.753143] r7 : 000000a8  r6 : 901e5a58  r5 : 901e5b08  r4 : ffffffff
[   51.759643] r3 : 000000a8  r2 : ffffffff  r1 : 00000001  r0 : 00000001
[   51.766122] xPSR: 21000000
[   51.768866] CPU: 0 PID: 37 Comm: sh Not tainted 5.5.0-rc4-00004-g2328d01dbd85 torvalds#105
[   51.776369] Hardware name: STM32 (Device Tree Support)
[   51.781594] [<0800c0c9>] (unwind_backtrace) from [<0800b25b>] (show_stack+0xb/0xc)
[   51.789166] [<0800b25b>] (show_stack) from [<0800b9eb>] (__invalid_entry+0x4b/0x4c)

It is a Usage Fault happening while in thread(user) mode. PC & LR in the
dump is strange in the sense that they do not point to text section.

The change here has been made based on how Cortex-A handles preemption.
Since PAN is not applicable and since it seemed that saving & restoring
thread_info::addr_limit does not make difference on the !MMU Cortex-M
due to single address space being used, there was no additional save &
restore of 'dacr' & 'addr_limit' as done in the case of interrupt during
system call on Cortex-A. Also as DUT was UP Cortex-M4, it seemed that
cache related would not affect in anyway w.r.t preemption, as currently
cache is not enabled for M4 in Linux.

As mentioned above, it was assumed that active exception during
interrupt meant SVC was interrupted, though it could have been PendSV as
well. To ensure that issue is not due to interrupt during PendSV, the
PendSV handling of pending work was lifted & sticked onto __irq_entry
and setting PendSV removed as well. Still the behaviour is same.

Signed-off-by: afzal mohammed <[email protected]>
  • Loading branch information
afzalmam authored and intel-lab-lkp committed Dec 30, 2019
1 parent 6122576 commit bce220c
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion arch/arm/kernel/entry-v7m.S
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,29 @@ __irq_entry:
ldr r1, =BASEADDR_V7M_SCB
ldr r0, [r1, V7M_SCB_ICSR]
tst r0, V7M_SCB_ICSR_RETTOBASE
beq 2f
beq 101f

ldr r2, [tsk, #TI_FLAGS]
tst r2, #_TIF_WORK_MASK
beq 2f @ no work pending
mov r0, #V7M_SCB_ICSR_PENDSVSET
str r0, [r1, V7M_SCB_ICSR] @ raise PendSV
b 2f

101:
#ifdef CONFIG_PREEMPT
ldr r2, [tsk, #TI_PREEMPT]
teq r2, #0 @ preempt count != 0 ?
bne 2f

ldr r0, [tsk, #TI_FLAGS]
tst r0, #_TIF_NEED_RESCHED @ __TIF_NEED_RESCHED set ?
beq 2f
102: bl preempt_schedule_irq
ldr r0, [tsk, #TI_FLAGS]
tst r0, #_TIF_NEED_RESCHED @ __TIF_NEED_RESCHED set ?
bne 102b
#endif
2:
pop {lr}

Expand Down

0 comments on commit bce220c

Please sign in to comment.