Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

arch/risc-v: Improve speed of context switch #5731

Merged
merged 1 commit into from
Mar 25, 2022

Conversation

no1wudi
Copy link
Contributor

@no1wudi no1wudi commented Mar 13, 2022

Summary

Follow #5645

Impact

RISC-V

Testing

maix-bit/rv-virt:nsh/smp on qemu

arch/risc-v/src/qemu-rv/qemu_rv_head.S Outdated Show resolved Hide resolved
arch/risc-v/src/k210/k210_head.S Outdated Show resolved Hide resolved
arch/risc-v/src/common/riscv_schedulesigaction.c Outdated Show resolved Hide resolved
arch/risc-v/src/common/riscv_schedulesigaction.c Outdated Show resolved Hide resolved
arch/risc-v/src/common/riscv_initialstate.c Outdated Show resolved Hide resolved
arch/risc-v/src/common/riscv_schedulesigaction.c Outdated Show resolved Hide resolved
arch/risc-v/src/common/riscv_schedulesigaction.c Outdated Show resolved Hide resolved
arch/risc-v/src/common/riscv_schedulesigaction.c Outdated Show resolved Hide resolved
arch/risc-v/src/common/riscv_schedulesigaction.c Outdated Show resolved Hide resolved
@masayuki2009
Copy link
Contributor

@no1wudi

I tried this PR with maix-bit:kostest on QEMU but the ASSERTION happened.

$ ~/opensource/QEMU/qemu-5.2/build/riscv64-softmmu/qemu-system-riscv64 -nographic -machine sifive_u -device loader,file=nuttx.bin,addr=0x80000000 -device loader,file=nuttx_user.bin,addr=0x80100000
ABCDstdio_test: write fd=1
stdio_test: Standard I/O Check: printf
stdio_test: write fd=2
stdio_test: Standard I/O Check: fprintf to stderr
ostest_main: putenv(Variable1=BadValue3)
ostest_main: setenv(Variable1, GoodValue1, TRUE)
ostest_main: setenv(Variable2, BadValue1, FALSE)
ostest_main: setenv(Variable2, GoodValue2, TRUE)
ostest_main: setenv(Variable3, Variable3, FALSE)
ostest_main: setenv(Variable3, Variable3, FALSE)
show_variable: Variable=Variable1 has value=GoodValue1
show_variable: Variable=Variable2 has value=GoodValue2
show_variable: Variable=Variable3 has value=GoodValue3
ostest_main: Started user_main at PID=2
...
user_main: waitpid test

Test waitpid()
waitpid_start_child: Started waitpid_main at PID=7
waitpid_start_child: Started waitpid_main at PID=11
waitpid_main: PID 7 Started
waitpid_main: PID 11 Started
waitpid_main: PID 12 Started
up_assert: Assertion failed at file:stdio/lib_libfilesem.c line: 106 task: ostest
riscv_registerdump: EPC: 00000000800062be
riscv_registerdump: A0: 0000000000000000 A1: 0000000080404960 A2: 000000000000003f A3: 0000000000000002
riscv_registerdump: A4: 0000000010010000 A5: 0000000080404960 A6: 000000000000006c A7: 0000000000000068
riscv_registerdump: T0: 0000000000000030 T1: 0000000000000009 T2: 0000000000000020 T3: 000000000000002a
riscv_registerdump: T4: 000000000000002e T5: 00000000000001ff T6: 000000000000002d
riscv_registerdump: S0: 00000000800008fe S1: 0000000080404908 S2: 0000000080481930 S3: 0000000080401188
riscv_registerdump: S4: 0000000080102502 S5: 000000008010a210 S6: 0000000080404b48 S7: 000000008010a27b
riscv_registerdump: S8: 0000000000000a00 S9: 0000000000001000 S10: 0000000000000800 S11: deadbeefdeadbeef
riscv_registerdump: SP: 0000000080404908 FP: 00000000800008fe TP: deadbeefdeadbeef RA: 0000000080005fbe
riscv_dumpstate: sp:     0000000080404908
riscv_dumpstate: IRQ stack:
riscv_dumpstate:   base: 00000000804000b0
riscv_dumpstate:   size: 0000000000000800
riscv_dumpstate: User stack:
riscv_dumpstate:   base: 0000000080402df0
riscv_dumpstate:   size: 0000000000001fb0
riscv_dumpstate: ERROR: Stack pointer is not within allocated stack
riscv_stackdump: 0000000080402de0: 67724100 72410033 00003467 00000000 deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402e00: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402e20: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef

``

@no1wudi
Copy link
Contributor Author

no1wudi commented Mar 14, 2022

@masayuki2009 Emm, I meet another problem with qemu-6.2 with mainline or this PR:

> Executing task: qemu-system-riscv64 -M sifive_u -device loader,file=nuttx/nuttx.bin,addr=0x80000000 -device loader,file=nuttx/nuttx_user.bin,addr=0x80100000 -nographic <

ABCDriscv_fault: EPC: 00000000800001ae
riscv_fault: Fault IRQ=2
riscv_fault: A0: 00000000801005ec A1: 0000000000000001 A2: 0000000080401fa0 A3: 0000000080401fa0
riscv_fault: A4: 00000000801005ec A5: 0000000000000001 A6: 0000000000000101 A7: 0000000000000000
riscv_fault: T0: 0000000000000000 T1: 0000000000000000 T2: 0000000000000000 T3: 0000000000000000
riscv_fault: T4: 0000000000000000 T5: 0000000000000000 T6: 0000000000000000
riscv_fault: S0: 0000000000000000 S1: 0000000000000000 S2: 0000000000000000 S3: 0000000000000000
riscv_fault: S4: 0000000000000000 S5: 0000000000000000 S6: 0000000000000000 S7: 0000000000000000
riscv_fault: S8: 0000000000000000 S9: 0000000000000000 S10: 0000000000000000 S11: 0000000000000000
riscv_fault: SP: 0000000080402b80 FP: 0000000000000000 TP: 0000000000000000 RA: 00000000800019f0
up_assert: Assertion failed at file:chip/k210_irq_dispatch.c line: 91 task: ostest_main
riscv_registerdump: EPC: 00000000800001ae
riscv_registerdump: A0: 00000000801005ec A1: 0000000000000001 A2: 0000000080401fa0 A3: 0000000080401fa0
riscv_registerdump: A4: 00000000801005ec A5: 0000000000000001 A6: 0000000000000101 A7: 0000000000000000
riscv_registerdump: T0: 0000000000000000 T1: 0000000000000000 T2: 0000000000000000 T3: 0000000000000000
riscv_registerdump: T4: 0000000000000000 T5: 0000000000000000 T6: 0000000000000000
riscv_registerdump: S0: 0000000000000000 S1: 0000000000000000 S2: 0000000000000000 S3: 0000000000000000
riscv_registerdump: S4: 0000000000000000 S5: 0000000000000000 S6: 0000000000000000 S7: 0000000000000000
riscv_registerdump: S8: 0000000000000000 S9: 0000000000000000 S10: 0000000000000000 S11: 0000000000000000
riscv_registerdump: SP: 0000000080402b80 FP: 0000000000000000 TP: 0000000000000000 RA: 00000000800019f0
riscv_dumpstate: sp:     0000000080400840
riscv_dumpstate: IRQ stack:
riscv_dumpstate:   base: 00000000804000c0
riscv_dumpstate:   size: 0000000000000800
riscv_stackdump: 0000000080400840: 0000005b 00000000 8000ffb8 00000000 00000000 00000000 00000002 00000000
riscv_stackdump: 0000000080400860: 80402a78 00000000 804012a0 00000000 00000002 00000000 8000475c 00000000
riscv_stackdump: 0000000080400880: 00000002 00000000 80000260 00000000 deadbeef deadbeef 00000000 00000000
riscv_stackdump: 00000000804008a0: 00000000 00000000 00000000 00000000 00000000 00000000 80000164 00000000
riscv_dumpstate: sp:     0000000080402b80
riscv_dumpstate: User stack:
riscv_dumpstate:   base: 0000000080401fc0
riscv_dumpstate:   size: 0000000000000be0
riscv_dumpstate: ERROR: Stack pointer is not within allocated stack
riscv_stackdump: 0000000080401fc0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080401fe0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402000: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402020: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402040: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402060: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402080: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804020a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804020c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804020e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402100: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402120: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402140: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402160: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402180: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804021a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804021c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804021e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402200: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402220: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402240: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402260: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402280: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804022a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804022c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804022e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402300: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402320: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402340: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402360: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402380: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804023a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804023c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804023e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402400: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402420: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402440: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402460: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402480: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804024a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804024c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804024e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402500: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402520: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402540: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402560: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402580: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804025a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804025c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804025e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402600: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402620: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402640: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402660: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402680: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804026a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804026c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804026e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402700: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402720: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402740: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402760: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402780: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804027a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804027c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804027e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402800: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402820: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402840: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402860: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402880: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804028a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804028c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804028e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402900: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402920: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402940: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402960: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402980: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804029a0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804029c0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 00000000804029e0: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402a00: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402a20: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402a40: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
riscv_stackdump: 0000000080402a60: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef 800001ae 00000000
riscv_stackdump: 0000000080402a80: 800019f0 00000000 80402b80 00000000 deadbeef deadbeef 00000000 00000000
riscv_stackdump: 0000000080402aa0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
riscv_stackdump: 0000000080402ac0: 00000000 00000000 801005ec 00000000 00000001 00000000 80401fa0 00000000
riscv_stackdump: 0000000080402ae0: 80401fa0 00000000 801005ec 00000000 00000001 00000000 00000101 00000000
riscv_stackdump: 0000000080402b00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
riscv_stackdump: 0000000080402b20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
riscv_stackdump: 0000000080402b40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
riscv_stackdump: 0000000080402b60: 00000000 00000000 00000000 00000000 00000000 00000000 00001800 0000000a
riscv_stackdump: 0000000080402b80: deadbeef deadbeef 800019f0 00000000 deadbeef deadbeef 00000000 00000000
riscv_showtasks:    PID    PRI      USED     STACK   FILLED    COMMAND
riscv_showtasks:   ----   ----       656      2048    32.0%    irq
riscv_dump_task:      0      0       528      2000    26.4%    Idle Task
riscv_dump_task:      1    100       296      3040     9.7%    ostest_main

I'll try it again with qemu 5.2

@no1wudi
Copy link
Contributor Author

no1wudi commented Mar 14, 2022

@masayuki2009 I can't reproduce this issue but the problem mentioned in #5672 occured:

user_main: nested signal handler test
signest_test: Starting signal waiter task at priority 101
waiter_main: Waiter started
waiter_main: Setting signal mask
waiter_main: Registering signal handler
waiter_main: Waiting on semaphore
signest_test: Started waiter_main pid=86
signest_test: Starting interfering task at priority 102
interfere_main: Waiting on semaphore
signest_test: Started interfere_main pid=87
[CPU1] riscv_fault: EPC: 0000000080004fe8
[CPU1] riscv_fault: Fault IRQ=7
[CPU1] riscv_fault: A0: 0000000080481480 A1: 0000000080483368 A2: 0000000080402588 A3: 0000000080402578
[CPU1] riscv_fault: A4: 0000000000000000 A5: 0000000000000000 A6: 000000000000000c A7: 000000008010a03e
[CPU1] riscv_fault: T0: 0000000080004c58 T1: 0000000080003da2 T2: 0000000000000000 T3: 0000000000000000
[CPU1] riscv_fault: T4: 0000000000000000 T5: 0000000000000000 T6: 0000000000000000
[CPU1] riscv_fault: S0: 00000000804832d0 S1: 0000000080481480 S2: 0000000000000000 S3: 0000000000000000
[CPU1] riscv_fault: S4: 0000000080483368 S5: 0000000000000004 S6: 0000000000000004 S7: 0000000080483358
[CPU1] riscv_fault: S8: 0000000000000002 S9: 0000000000000088 S10: 0000000000000000 S11: 0000000000000000
[CPU1] riscv_fault: SP: 000000008040b1d0 FP: 00000000804832d0 TP: 0000000000000000 RA: 0000000080001dca
[CPU1] up_assert: Assertion failed CPU1 at file:chip/k210_irq_dispatch.c line: 91 task: waiter
[CPU1] riscv_registerdump: EPC: 0000000080004fe8
[CPU1] riscv_registerdump: A0: 0000000080481480 A1: 0000000080483368 A2: 0000000080402588 A3: 0000000080402578
[CPU1] riscv_registerdump: A4: 0000000000000000 A5: 0000000000000000 A6: 000000000000000c A7: 000000008010a03e
[CPU1] riscv_registerdump: T0: 0000000080004c58 T1: 0000000080003da2 T2: 0000000000000000 T3: 0000000000000000
[CPU1] riscv_registerdump: T4: 0000000000000000 T5: 0000000000000000 T6: 0000000000000000

@no1wudi no1wudi marked this pull request as draft March 14, 2022 10:21
@no1wudi no1wudi marked this pull request as draft March 14, 2022 10:21
@no1wudi no1wudi force-pushed the master branch 3 times, most recently from 9a9ed86 to be94446 Compare March 18, 2022 04:46
@xiaoxiang781216 xiaoxiang781216 marked this pull request as ready for review March 18, 2022 06:52
@no1wudi no1wudi marked this pull request as draft March 18, 2022 08:46
@no1wudi no1wudi force-pushed the master branch 2 times, most recently from 11ed30a to a828df8 Compare March 23, 2022 09:51
@no1wudi no1wudi marked this pull request as ready for review March 23, 2022 09:51
@no1wudi no1wudi marked this pull request as draft March 23, 2022 10:28
@xiaoxiang781216 xiaoxiang781216 marked this pull request as ready for review March 23, 2022 18:03
@xiaoxiang781216
Copy link
Contributor

@no1wudi is it ready for reviewing?

@no1wudi
Copy link
Contributor Author

no1wudi commented Mar 24, 2022

Emm, smp is still not work with latest update.

@no1wudi no1wudi marked this pull request as draft March 24, 2022 03:01
@no1wudi no1wudi force-pushed the master branch 3 times, most recently from 3e0d3c7 to 4807870 Compare March 25, 2022 02:54
@masayuki2009
Copy link
Contributor

@no1wudi
There still remains style changes that should be in a separate commit

@no1wudi no1wudi force-pushed the master branch 4 times, most recently from cb1d69b to c5481cc Compare March 25, 2022 15:41
Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
@masayuki2009 masayuki2009 merged commit 494230a into apache:master Mar 25, 2022
@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

Can someone please explain to me how this change is supposed to work with MMU and address environments ? Am I misunderstanding something ? The xcp.regs are now allocated from the user task's stack memory, prior to this change they were in the kernel's memory space.

Please note the following example


          struct tcb_s *nexttcb = this_task();

#ifdef CONFIG_ARCH_ADDRENV
          /* Make sure that the address environment for the previously
           * running task is closed down gracefully (data caches dump,
           * MMU flushed) and set up the address environment for the new
           * thread at the head of the ready-to-run list.
           */

          (void)group_addrenv(nexttcb);
#endif
          /* Reset scheduler parameters */

          nxsched_resume_scheduler(nexttcb);

          /* Then switch contexts */

          riscv_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);

If rtcb->xpc.regs points to the old task's stack, which resides in its address environment, how can we perform a register save there ?

The old implementation saved the task context in the kernel space memory, which is why it is safe to change the address environment as the memory for xcp.regs[] exists in the kernel space and is always mapped ?

@xiaoxiang781216
Copy link
Contributor

xiaoxiang781216 commented Mar 28, 2022

Can someone please explain to me how this change is supposed to work with MMU and address environments ? Am I misunderstanding something ? The xcp.regs are now allocated from the user task's stack memory, prior to this change they were in the kernel's memory space.

Please note the following example


          struct tcb_s *nexttcb = this_task();

#ifdef CONFIG_ARCH_ADDRENV
          /* Make sure that the address environment for the previously
           * running task is closed down gracefully (data caches dump,
           * MMU flushed) and set up the address environment for the new
           * thread at the head of the ready-to-run list.
           */

          (void)group_addrenv(nexttcb);
#endif
          /* Reset scheduler parameters */

          nxsched_resume_scheduler(nexttcb);

          /* Then switch contexts */

          riscv_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);

If rtcb->xpc.regs points to the old task's stack, which resides in its address environment, how can we perform a register save there ?

since rtcb->xcp.regs itself is still in the kernel space, riscv_switchcontext can update rtcb->xcp.regs to the new context on the stack:
https://github.com/apache/incubator-nuttx/blob/master/arch/risc-v/src/common/riscv_swint.c#L247-L254

The old implementation saved the task context in the kernel space memory, which is why it is safe to change the address environment as the memory for xcp.regs[] exists in the kernel space and is always mapped ?

The problem we can see is that up_schedule_sigaction may touch the stack of non current thread directly:

We haven't found other places will touch the memory pointed by xcp.regs of the non current thread, if you find some please point out.

Since RISCV kernel mode isn't mainlined yet, @anchao will test the same change(#5645) on ARM.

@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

Thank you for your response, yes it is clear that xcp.regs is still in kernel memory and is addressable. However, the memory for the context itself exists in MMU mapped memory only if I'm right. As tcb->stack_alloc_ptr = kumm_malloc(stack_size); uses the userspace heap allocator which works with virtual addresses that exist in the user task's own memory. Obviously the mapping exists for the kernel as well, when the task is in execution.

What I'm concerned about is that calling (void)group_addrenv(nexttcb); prior to the context switch changes the MMU mappings already, and the address environment that is used to store the task that is being preempted is not in place any more. So where does e.g. arm_switchcontext(a,b) actually save the task's context (the task that is removed from execution) ? It pushes it to the stack, but to me it will be the new task's address environment (task that will continue) and the old register set is saved into task b:s stack instead of task a:s stack.

Unless I'm totally missing something here.

@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

I can confirm that for RISC-V the flat and protected targets work (with #5881) but the kernel mode target crashes with a load page fault. I will investigate further but the code was working before i.e. I could enter nsh and run things on the console. Now the SW crashes before nsh is launched.

@xiaoxiang781216
Copy link
Contributor

xiaoxiang781216 commented Mar 28, 2022

Thank you for your response, yes it is clear that xcp.regs is still in kernel memory and is addressable. However, the memory for the context itself exists in MMU mapped memory only if I'm right. As tcb->stack_alloc_ptr = kumm_malloc(stack_size); uses the userspace heap allocator which works with virtual addresses that exist in the user task's own memory. Obviously the mapping exists for the kernel as well, when the task is in execution.

Yes, I think so.

What I'm concerned about is that calling (void)group_addrenv(nexttcb); prior to the context switch changes the MMU mappings already, and the address environment that is used to store the task that is being preempted is not in place any more.

call group_addrenv here is too early, even without @no1wudi 's change, it still can't work as expect, because the current stack is swapped out. The right place is in riscv_swint::SYS_switch_context.

So where does e.g. arm_switchcontext(a,b) actually save the task's context (the task that is removed from execution) ? It pushes it to the stack, but to me it will be the new task's address environment (task that will continue) and the old register set is saved into task b:s stack instead of task a:s stack.

Since the similar code also exist on ARM, @anchao will try to provide a patch fixing this issue.

@xiaoxiang781216
Copy link
Contributor

I can confirm that for RISC-V the flat and protected targets work (with #5881) but the kernel mode target crashes with a load page fault. I will investigate further but the code was working before i.e. I could enter nsh and run things on the console. Now the SW crashes before nsh is launched.

Do you have try the context switch between two user space thread without this change? It work before may just because the next thread is kernel thread.

@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

call group_addrenv here is too early, even without @no1wudi 's change, it still can't work as expect, because the current stack is swapped out. The right place is in riscv_swint::SYS_switch_context.

Yes it is too early, but only with the new context switch change. It worked previously since the tcb.xcp contained memory for the task's context. So calling riscv_switchcontext(a,b) memory for both a and b exist exists in kernel space, so it is always mapped, and safe to use even after calling group_addrenv().

After this riscv_switchcontext(a,b) is using b's stack, which is imo correct.

@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

I can confirm that for RISC-V the flat and protected targets work (with #5881) but the kernel mode target crashes with a load page fault. I will investigate further but the code was working before i.e. I could enter nsh and run things on the console. Now the SW crashes before nsh is launched.

Do you have try the context switch between two user space thread without this change? It work before may just because the next thread is kernel thread.

I had several user tasks running so yes it got tested. As I said previously the memory for tcb.xcp.regs[] was in the tcb itself, which means it is in kernel memory for kernel an user tasks both.

@xiaoxiang781216
Copy link
Contributor

Yes, xcp.regs[] is in the kernel space, but the thread stack pointed by SP isn't.

@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

Yes, xcp.regs[] is in the kernel space, but the thread stack pointed by SP isn't.

Exactly, and now the memory for saving the task context is taken from the stack.

xcp->regs = (uintptr_t *)(
    (uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size - XCPTCONTEXT_SIZE);

Previously the memory was in tcb, as xcp.regs was a buffer, not a pointer: uintptr_t regs[XCPTCONTEXT_REGS];. This is why the old code works, because the buffer is in tcb which is kernel memory, for both tasks.

@xiaoxiang781216
Copy link
Contributor

xiaoxiang781216 commented Mar 28, 2022

But the thread stack also switch out. For example, let's assume that the user space thread call semwait and the count of sem is zero:

  1. Task 1 run on stack 1 call sem_wait and then trigger ecall
  2. The ecall handler switch to S-mode and dispatch to nxsem_wait
  3. nxsem_wait continue execute on stack 1
  4. up_block_task is called since the count is zero
  5. group_addrenv switch the address space to the next task
  6. But the current SP isn't changed and still point to the stack 1(of course, it isn't the memory of stack 1 anymore, but somewhere in task 2 memory space).

So, I think the problem exist in the origin code.

@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

Oops, you are also right, the original code is suspicious too, as the first thing exception_common does is this:

exception_common:
addi sp, sp, -XCPTCONTEXT_SIZE

I assume the same issue is in the ARM implementation too.
In this case the new task's address environment is already in use, but sp still points to the old task.

This is not an issue with the new S-mode function however:

riscv_switchcontext:

  /* Save old context to arg[0] */

  save_ctx   a0                        /* save context */

Saving the context does not use stack, and this is why the old code works on my table.

But indeed, the location for calling group_addrenv() is suspicious, as the context switch is done by using the new tasks environment, even though the old task's registers are still in use.

@xiaoxiang781216
Copy link
Contributor

xiaoxiang781216 commented Mar 28, 2022

Oops, you are also right, the original code is suspicious too, as the first thing exception_common does is this:

exception_common:
addi sp, sp, -XCPTCONTEXT_SIZE

I assume the same issue is in the ARM implementation too. In this case the new task's address environment is already in use, but sp still points to the old task.

Yes, ARM has the similar issue, @anchao hit the problem before like this:

  1. The first task wait on a named semaphore
  2. The second task post this semaphore to wake up the first
  3. And the system panic suddenly

he made a temp fix like this:

  1. Move group_addrenv to arm_syscall::SYS_switch_context
  2. Disable FPU since the lazy fpu save may corrupt the next task memory space

The above problem is fixed. So, to fix this issue:

  1. We need review all place which call group_addrenv and move to the right location
  2. Save and restore FPU in exception_common

@no1wudi please prepare two patches for RISCV tomorrow, so @pussuw can verify with his S-mode change.
@anchao will fix the similar issue on ARM in the next couple days.

This is not an issue with the new S-mode function however:

riscv_switchcontext:

  /* Save old context to arg[0] */

  save_ctx   a0                        /* save context */

Saving the context does not use stack, and this is why the old code works on my table.

If we postpone the address space switch until save_ctx return, this PR should work with your S-mode change, I think.

Yes, but it isn't reliable since we can't control how C compiler generate the machine code which may insert push/pop operation between group_addrenv<->riscv_switchcontext and riscv_switchcontext<->riscv_swint in the new version or different compiler options.

But indeed, the location for calling group_addrenv() is suspicious, as the context switch is done by using the new tasks environment, even though the old task's registers are still in use.

Yes, we move need do the address space change with the interrupt or kernel stack, otherwise we have to write the whole process in assemble code, so we can control the stack usage manually.

@pussuw
Copy link
Contributor

pussuw commented Mar 28, 2022

Yes, but it isn't reliable since we can't control how C compiler generate the machine code which may insert push/pop operation between group_addrenv<->riscv_switchcontext and riscv_switchcontext<->riscv_swint in the new version or different compiler options.

Yes only option is to make sure interrupt or kernel stack is in use. I'm not even sure how the old implementation seemingly works for me. If the return address is put into stack, the SW should get lost when it attempts to return from group_addrenv(), as the memory pointed to by SP is no longer the same.

Unless the next task is always a kernel task when a user task is being suspended, then the address is still mapped, like you already said. I must have gotten lucky in my testing or something.

I guess this is what saves it

  /* Does the group have an address environment? */

  if ((group->tg_flags & GROUP_FLAG_ADDRENV) == 0)
    {
      /* No... just return perhaps leaving a different address environment
       * intact.
       */

      return OK;
    }

So when a kernel task is resumed and a user task is suspended, the user task's environment is left in place, I guess..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants