diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2022-04-15 03:05:31 -0700 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2022-05-01 19:51:23 -0700 |
commit | 11e969bc964a0e50ae64cdba092048e3937d2389 (patch) | |
tree | 99303eb470e622faf5397649005d6f221f46bdb0 /arch/xtensa/kernel/traps.c | |
parent | xtensa: get rid of stack frame in coprocessor_flush (diff) | |
download | linux-dev-11e969bc964a0e50ae64cdba092048e3937d2389.tar.xz linux-dev-11e969bc964a0e50ae64cdba092048e3937d2389.zip |
xtensa: support coprocessors on SMP
Current coprocessor support on xtensa only works correctly on
uniprocessor configurations. Make it work on SMP too and keep it lazy.
Make coprocessor_owner array per-CPU and move it to struct exc_table for
easy access from the fast_coprocessor exception handler. Allow task to
have live coprocessors only on single CPU, record this CPU number in the
struct thread_info::cp_owner_cpu. Change struct thread_info::cpenable
meaning to be 'coprocessors live on cp_owner_cpu'.
Introduce C-level coprocessor exception handler that flushes and
releases live coprocessors of the task taking 'coprocessor disabled'
exception and call it from the fast_coprocessor handler when the task
has live coprocessors on other CPU.
Make coprocessor_flush_all and coprocessor_release_all work correctly
when called from any CPU by sending IPI to the cp_owner_cpu. Add
function coprocessor_flush_release_all to do flush followed by release
atomically. Add function local_coprocessors_flush_release_all to flush
and release all coprocessors on the local CPU and use it to flush
coprocessor contexts from the CPU that goes offline.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to '')
-rw-r--r-- | arch/xtensa/kernel/traps.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 62c497605128..138a86fbe9d7 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -57,6 +57,9 @@ static void do_nmi(struct pt_regs *regs); static void do_unaligned_user(struct pt_regs *regs); #endif static void do_multihit(struct pt_regs *regs); +#if XTENSA_HAVE_COPROCESSORS +static void do_coprocessor(struct pt_regs *regs); +#endif static void do_debug(struct pt_regs *regs); /* @@ -69,7 +72,8 @@ static void do_debug(struct pt_regs *regs); #define USER 0x02 #define COPROCESSOR(x) \ -{ EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER|KRNL, fast_coprocessor } +{ EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER|KRNL, fast_coprocessor },\ +{ EXCCAUSE_COPROCESSOR ## x ## _DISABLED, 0, do_coprocessor } typedef struct { int cause; @@ -327,6 +331,13 @@ static void do_unaligned_user(struct pt_regs *regs) } #endif +#if XTENSA_HAVE_COPROCESSORS +static void do_coprocessor(struct pt_regs *regs) +{ + coprocessor_flush_release_all(current_thread_info()); +} +#endif + /* Handle debug events. * When CONFIG_HAVE_HW_BREAKPOINT is on this handler is called with * preemption disabled to avoid rescheduling and keep mapping of hardware |