diff options
| author | Chris Zankel <chris@zankel.net> | 2008-02-12 16:17:07 -0500 |
|---|---|---|
| committer | Chris Zankel <chris@zankel.net> | 2008-02-13 20:41:43 -0500 |
| commit | c658eac628aa8df040dfe614556d95e6da3a9ffb (patch) | |
| tree | e2211e1d5c894c29e92d4c744f504b38410efe41 | |
| parent | 71d28e6c285548106f551fde13ca6d589433d843 (diff) | |
[XTENSA] Add support for configurable registers and coprocessors
The Xtensa architecture allows to define custom instructions and
registers. Registers that are bound to a coprocessor are only
accessible if the corresponding enable bit is set, which allows
to implement a 'lazy' context switch mechanism. Other registers
needs to be saved and restore at the time of the context switch
or during interrupt handling.
This patch adds support for these additional states:
- save and restore registers that are used by the compiler upon
interrupt entry and exit.
- context switch additional registers unbound to any coprocessor
- 'lazy' context switch of registers bound to a coprocessor
- ptrace interface to provide access to additional registers
- update configuration files in include/asm-xtensa/variant-fsf
Signed-off-by: Chris Zankel <chris@zankel.net>
| -rw-r--r-- | arch/xtensa/kernel/asm-offsets.c | 16 | ||||
| -rw-r--r-- | arch/xtensa/kernel/coprocessor.S | 443 | ||||
| -rw-r--r-- | arch/xtensa/kernel/entry.S | 295 | ||||
| -rw-r--r-- | arch/xtensa/kernel/process.c | 261 | ||||
| -rw-r--r-- | arch/xtensa/kernel/ptrace.c | 347 | ||||
| -rw-r--r-- | arch/xtensa/kernel/signal.c | 65 | ||||
| -rw-r--r-- | arch/xtensa/kernel/traps.c | 16 | ||||
| -rw-r--r-- | include/asm-xtensa/coprocessor.h | 209 | ||||
| -rw-r--r-- | include/asm-xtensa/elf.h | 15 | ||||
| -rw-r--r-- | include/asm-xtensa/processor.h | 13 | ||||
| -rw-r--r-- | include/asm-xtensa/ptrace.h | 44 | ||||
| -rw-r--r-- | include/asm-xtensa/regs.h | 9 | ||||
| -rw-r--r-- | include/asm-xtensa/sigcontext.h | 1 | ||||
| -rw-r--r-- | include/asm-xtensa/system.h | 39 | ||||
| -rw-r--r-- | include/asm-xtensa/thread_info.h | 21 | ||||
| -rw-r--r-- | include/asm-xtensa/variant-fsf/tie-asm.h | 70 | ||||
| -rw-r--r-- | include/asm-xtensa/variant-fsf/tie.h | 75 |
17 files changed, 1065 insertions, 874 deletions
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index 5d9ef515ca1..ef63adadf7f 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c | |||
| @@ -63,6 +63,8 @@ int main(void) | |||
| 63 | DEFINE(PT_SIZE, sizeof(struct pt_regs)); | 63 | DEFINE(PT_SIZE, sizeof(struct pt_regs)); |
| 64 | DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS])); | 64 | DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS])); |
| 65 | DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS])); | 65 | DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS])); |
| 66 | DEFINE(PT_XTREGS_OPT, offsetof(struct pt_regs, xtregs_opt)); | ||
| 67 | DEFINE(XTREGS_OPT_SIZE, sizeof(xtregs_opt_t)); | ||
| 66 | 68 | ||
| 67 | /* struct task_struct */ | 69 | /* struct task_struct */ |
| 68 | DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace)); | 70 | DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace)); |
| @@ -76,7 +78,19 @@ int main(void) | |||
| 76 | /* struct thread_info (offset from start_struct) */ | 78 | /* struct thread_info (offset from start_struct) */ |
| 77 | DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra)); | 79 | DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra)); |
| 78 | DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp)); | 80 | DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp)); |
| 79 | DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save)); | 81 | DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable)); |
| 82 | #if XTENSA_HAVE_COPROCESSORS | ||
| 83 | DEFINE(THREAD_XTREGS_CP0, offsetof (struct thread_info, xtregs_cp)); | ||
| 84 | DEFINE(THREAD_XTREGS_CP1, offsetof (struct thread_info, xtregs_cp)); | ||
| 85 | DEFINE(THREAD_XTREGS_CP2, offsetof (struct thread_info, xtregs_cp)); | ||
| 86 | DEFINE(THREAD_XTREGS_CP3, offsetof (struct thread_info, xtregs_cp)); | ||
| 87 | DEFINE(THREAD_XTREGS_CP4, offsetof (struct thread_info, xtregs_cp)); | ||
| 88 | DEFINE(THREAD_XTREGS_CP5, offsetof (struct thread_info, xtregs_cp)); | ||
| 89 | DEFINE(THREAD_XTREGS_CP6, offsetof (struct thread_info, xtregs_cp)); | ||
| 90 | DEFINE(THREAD_XTREGS_CP7, offsetof (struct thread_info, xtregs_cp)); | ||
| 91 | #endif | ||
| 92 | DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user)); | ||
| 93 | DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t)); | ||
| 80 | DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds)); | 94 | DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds)); |
| 81 | 95 | ||
| 82 | /* struct mm_struct */ | 96 | /* struct mm_struct */ |
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S index 01bcb9fcfcb..2bc1e145c0a 100644 --- a/arch/xtensa/kernel/coprocessor.S +++ b/arch/xtensa/kernel/coprocessor.S | |||
| @@ -8,193 +8,328 @@ | |||
| 8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
| 9 | * for more details. | 9 | * for more details. |
| 10 | * | 10 | * |
| 11 | * Copyright (C) 2003 - 2005 Tensilica Inc. | 11 | * Copyright (C) 2003 - 2007 Tensilica Inc. |
| 12 | * | ||
| 13 | * Marc Gauthier <marc@tensilica.com> <marc@alumni.uwaterloo.ca> | ||
| 14 | */ | 12 | */ |
| 15 | 13 | ||
| 16 | /* | ||
| 17 | * This module contains a table that describes the layout of the various | ||
| 18 | * custom registers and states associated with each coprocessor, as well | ||
| 19 | * as those not associated with any coprocessor ("extra state"). | ||
| 20 | * This table is included with core dumps and is available via the ptrace | ||
| 21 | * interface, allowing the layout of such register/state information to | ||
| 22 | * be modified in the kernel without affecting the debugger. Each | ||
| 23 | * register or state is identified using a 32-bit "libdb target number" | ||
| 24 | * assigned when the Xtensa processor is generated. | ||
| 25 | */ | ||
| 26 | 14 | ||
| 27 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
| 16 | #include <asm/asm-offsets.h> | ||
| 28 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
| 18 | #include <asm/coprocessor.h> | ||
| 19 | #include <asm/thread_info.h> | ||
| 20 | #include <asm/uaccess.h> | ||
| 21 | #include <asm/unistd.h> | ||
| 22 | #include <asm/ptrace.h> | ||
| 23 | #include <asm/current.h> | ||
| 24 | #include <asm/pgtable.h> | ||
| 25 | #include <asm/page.h> | ||
| 26 | #include <asm/signal.h> | ||
| 27 | #include <asm/tlbflush.h> | ||
| 29 | 28 | ||
| 30 | #if XCHAL_HAVE_CP | 29 | /* |
| 30 | * Entry condition: | ||
| 31 | * | ||
| 32 | * a0: trashed, original value saved on stack (PT_AREG0) | ||
| 33 | * a1: a1 | ||
| 34 | * a2: new stack pointer, original in DEPC | ||
| 35 | * a3: dispatch table | ||
| 36 | * depc: a2, original value saved on stack (PT_DEPC) | ||
| 37 | * excsave_1: a3 | ||
| 38 | * | ||
| 39 | * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC | ||
| 40 | * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception | ||
| 41 | */ | ||
| 31 | 42 | ||
| 32 | #define CP_LAST ((XCHAL_CP_MAX - 1) * COPROCESSOR_INFO_SIZE) | 43 | /* IO protection is currently unsupported. */ |
| 33 | 44 | ||
| 34 | ENTRY(release_coprocessors) | 45 | ENTRY(fast_io_protect) |
| 46 | wsr a0, EXCSAVE_1 | ||
| 47 | movi a0, unrecoverable_exception | ||
| 48 | callx0 a0 | ||
| 35 | 49 | ||
| 36 | entry a1, 16 | 50 | #if XTENSA_HAVE_COPROCESSORS |
| 37 | # a2: task | ||
| 38 | movi a3, 1 << XCHAL_CP_MAX # a3: coprocessor-bit | ||
| 39 | movi a4, coprocessor_info+CP_LAST # a4: owner-table | ||
| 40 | # a5: tmp | ||
| 41 | movi a6, 0 # a6: 0 | ||
| 42 | rsil a7, LOCKLEVEL # a7: PS | ||
| 43 | 51 | ||
| 44 | 1: /* Check if task is coprocessor owner of coprocessor[i]. */ | 52 | /* |
| 53 | * Macros for lazy context switch. | ||
| 54 | */ | ||
| 45 | 55 | ||
| 46 | l32i a5, a4, COPROCESSOR_INFO_OWNER | 56 | #define SAVE_CP_REGS(x) \ |
| 47 | srli a3, a3, 1 | 57 | .align 4; \ |
| 48 | beqz a3, 1f | 58 | .Lsave_cp_regs_cp##x: \ |
| 49 | addi a4, a4, -8 | 59 | .if XTENSA_HAVE_COPROCESSOR(x); \ |
| 50 | beq a2, a5, 1b | 60 | xchal_cp##x##_store a2 a4 a5 a6 a7; \ |
| 61 | .endif; \ | ||
| 62 | jx a0 | ||
| 51 | 63 | ||
| 52 | /* Found an entry: Clear entry CPENABLE bit to disable CP. */ | 64 | #define SAVE_CP_REGS_TAB(x) \ |
| 65 | .if XTENSA_HAVE_COPROCESSOR(x); \ | ||
| 66 | .long .Lsave_cp_regs_cp##x - .Lsave_cp_regs_jump_table; \ | ||
| 67 | .else; \ | ||
| 68 | .long 0; \ | ||
| 69 | .endif; \ | ||
| 70 | .long THREAD_XTREGS_CP##x | ||
| 53 | 71 | ||
| 54 | rsr a5, CPENABLE | ||
| 55 | s32i a6, a4, COPROCESSOR_INFO_OWNER | ||
| 56 | xor a5, a3, a5 | ||
| 57 | wsr a5, CPENABLE | ||
| 58 | 72 | ||
| 59 | bnez a3, 1b | 73 | #define LOAD_CP_REGS(x) \ |
| 74 | .align 4; \ | ||
| 75 | .Lload_cp_regs_cp##x: \ | ||
| 76 | .if XTENSA_HAVE_COPROCESSOR(x); \ | ||
| 77 | xchal_cp##x##_load a2 a4 a5 a6 a7; \ | ||
| 78 | .endif; \ | ||
| 79 | jx a0 | ||
| 60 | 80 | ||
| 61 | 1: wsr a7, PS | 81 | #define LOAD_CP_REGS_TAB(x) \ |
| 62 | rsync | 82 | .if XTENSA_HAVE_COPROCESSOR(x); \ |
| 63 | retw | 83 | .long .Lload_cp_regs_cp##x - .Lload_cp_regs_jump_table; \ |
| 84 | .else; \ | ||
| 85 | .long 0; \ | ||
| 86 | .endif; \ | ||
| 87 | .long THREAD_XTREGS_CP##x | ||
| 64 | 88 | ||
| 89 | SAVE_CP_REGS(0) | ||
| 90 | SAVE_CP_REGS(1) | ||
| 91 | SAVE_CP_REGS(2) | ||
| 92 | SAVE_CP_REGS(3) | ||
| 93 | SAVE_CP_REGS(4) | ||
| 94 | SAVE_CP_REGS(5) | ||
| 95 | SAVE_CP_REGS(6) | ||
| 96 | SAVE_CP_REGS(7) | ||
| 65 | 97 | ||
