diff options
Diffstat (limited to 'arch/xtensa/kernel/coprocessor.S')
-rw-r--r-- | arch/xtensa/kernel/coprocessor.S | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S new file mode 100644 index 000000000000..356192a4d39d --- /dev/null +++ b/arch/xtensa/kernel/coprocessor.S | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * arch/xtensa/kernel/coprocessor.S | ||
3 | * | ||
4 | * Xtensa processor configuration-specific table of coprocessor and | ||
5 | * other custom register layout information. | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | * | ||
11 | * Copyright (C) 2003 - 2005 Tensilica Inc. | ||
12 | * | ||
13 | * Marc Gauthier <marc@tensilica.com> <marc@alumni.uwaterloo.ca> | ||
14 | */ | ||
15 | |||
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 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/linkage.h> | ||
29 | #include <asm/processor.h> | ||
30 | |||
31 | #if XCHAL_HAVE_CP | ||
32 | |||
33 | #define CP_LAST ((XCHAL_CP_MAX - 1) * COPROCESSOR_INFO_SIZE) | ||
34 | |||
35 | ENTRY(release_coprocessors) | ||
36 | |||
37 | entry a1, 16 | ||
38 | # a2: task | ||
39 | movi a3, 1 << XCHAL_CP_MAX # a3: coprocessor-bit | ||
40 | movi a4, coprocessor_info+CP_LAST # a4: owner-table | ||
41 | # a5: tmp | ||
42 | movi a6, 0 # a6: 0 | ||
43 | rsil a7, LOCKLEVEL # a7: PS | ||
44 | |||
45 | 1: /* Check if task is coprocessor owner of coprocessor[i]. */ | ||
46 | |||
47 | l32i a5, a4, COPROCESSOR_INFO_OWNER | ||
48 | srli a3, a3, 1 | ||
49 | beqz a3, 1f | ||
50 | addi a4, a4, -8 | ||
51 | beq a2, a5, 1b | ||
52 | |||
53 | /* Found an entry: Clear entry CPENABLE bit to disable CP. */ | ||
54 | |||
55 | rsr a5, CPENABLE | ||
56 | s32i a6, a4, COPROCESSOR_INFO_OWNER | ||
57 | xor a5, a3, a5 | ||
58 | wsr a5, CPENABLE | ||
59 | |||
60 | bnez a3, 1b | ||
61 | |||
62 | 1: wsr a7, PS | ||
63 | rsync | ||
64 | retw | ||
65 | |||
66 | |||
67 | ENTRY(disable_coprocessor) | ||
68 | entry sp, 16 | ||
69 | rsil a7, LOCKLEVEL | ||
70 | rsr a3, CPENABLE | ||
71 | movi a4, 1 | ||
72 | ssl a2 | ||
73 | sll a4, a4 | ||
74 | and a4, a3, a4 | ||
75 | xor a3, a3, a4 | ||
76 | wsr a3, CPENABLE | ||
77 | wsr a7, PS | ||
78 | rsync | ||
79 | retw | ||
80 | |||
81 | ENTRY(enable_coprocessor) | ||
82 | entry sp, 16 | ||
83 | rsil a7, LOCKLEVEL | ||
84 | rsr a3, CPENABLE | ||
85 | movi a4, 1 | ||
86 | ssl a2 | ||
87 | sll a4, a4 | ||
88 | or a3, a3, a4 | ||
89 | wsr a3, CPENABLE | ||
90 | wsr a7, PS | ||
91 | rsync | ||
92 | retw | ||
93 | |||
94 | #endif | ||
95 | |||
96 | ENTRY(save_coprocessor_extra) | ||
97 | entry sp, 16 | ||
98 | xchal_extra_store_funcbody | ||
99 | retw | ||
100 | |||
101 | ENTRY(restore_coprocessor_extra) | ||
102 | entry sp, 16 | ||
103 | xchal_extra_load_funcbody | ||
104 | retw | ||
105 | |||
106 | ENTRY(save_coprocessor_registers) | ||
107 | entry sp, 16 | ||
108 | xchal_cpi_store_funcbody | ||
109 | retw | ||
110 | |||
111 | ENTRY(restore_coprocessor_registers) | ||
112 | entry sp, 16 | ||
113 | xchal_cpi_load_funcbody | ||
114 | retw | ||
115 | |||
116 | |||
117 | /* | ||
118 | * The Xtensa compile-time HAL (core.h) XCHAL_*_SA_CONTENTS_LIBDB macros | ||
119 | * describe the contents of coprocessor & extra save areas in terms of | ||
120 | * undefined CONTENTS_LIBDB_{SREG,UREG,REGF} macros. We define these | ||
121 | * latter macros here; they expand into a table of the format we want. | ||
122 | * The general format is: | ||
123 | * | ||
124 | * CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum, | ||
125 | * bitmask, rsv2, rsv3) | ||
126 | * CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum, | ||
127 | * bitmask, rsv2, rsv3) | ||
128 | * CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, | ||
129 | * numentries, contentsize, regname_base, | ||
130 | * regfile_name, rsv2, rsv3) | ||
131 | * | ||
132 | * For this table, we only care about the <libdbnum>, <offset> and <size> | ||
133 | * fields. | ||
134 | */ | ||
135 | |||
136 | /* Map all XCHAL CONTENTS macros to the reg_entry asm macro defined below: */ | ||
137 | |||
138 | #define CONTENTS_LIBDB_SREG(libdbnum,offset,size,align,rsv1,name,sregnum, \ | ||
139 | bitmask, rsv2, rsv3) \ | ||
140 | reg_entry libdbnum, offset, size ; | ||
141 | #define CONTENTS_LIBDB_UREG(libdbnum,offset,size,align,rsv1,name,uregnum, \ | ||
142 | bitmask, rsv2, rsv3) \ | ||
143 | reg_entry libdbnum, offset, size ; | ||
144 | #define CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, \ | ||
145 | numentries, contentsize, regname_base, \ | ||
146 | regfile_name, rsv2, rsv3) \ | ||
147 | reg_entry libdbnum, offset, size ; | ||
148 | |||
149 | /* A single table entry: */ | ||
150 | .macro reg_entry libdbnum, offset, size | ||
151 | .ifne (__last_offset-(__last_group_offset+\offset)) | ||
152 | /* padding entry */ | ||
153 | .word (0xFC000000+__last_offset-(__last_group_offset+\offset)) | ||
154 | .endif | ||
155 | .word \libdbnum /* actual entry */ | ||
156 | .set __last_offset, __last_group_offset+\offset+\size | ||
157 | .endm /* reg_entry */ | ||
158 | |||
159 | |||
160 | /* Table entry that marks the beginning of a group (coprocessor or "extra"): */ | ||
161 | .macro reg_group cpnum, num_entries, align | ||
162 | .set __last_group_offset, (__last_offset + \align- 1) & -\align | ||
163 | .ifne \num_entries | ||
164 | .word 0xFD000000+(\cpnum<<16)+\num_entries | ||
165 | .endif | ||
166 | .endm /* reg_group */ | ||
167 | |||
168 | /* | ||
169 | * Register info tables. | ||
170 | */ | ||
171 | |||
172 | .section .rodata, "a" | ||
173 | .globl _xtensa_reginfo_tables | ||
174 | .globl _xtensa_reginfo_table_size | ||
175 | .align 4 | ||
176 | _xtensa_reginfo_table_size: | ||
177 | .word _xtensa_reginfo_table_end - _xtensa_reginfo_tables | ||
178 | |||
179 | _xtensa_reginfo_tables: | ||
180 | .set __last_offset, 0 | ||
181 | reg_group 0xFF, XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM, XCHAL_EXTRA_SA_ALIGN | ||
182 | XCHAL_EXTRA_SA_CONTENTS_LIBDB | ||
183 | reg_group 0, XCHAL_CP0_SA_CONTENTS_LIBDB_NUM, XCHAL_CP0_SA_ALIGN | ||
184 | XCHAL_CP0_SA_CONTENTS_LIBDB | ||
185 | reg_group 1, XCHAL_CP1_SA_CONTENTS_LIBDB_NUM, XCHAL_CP1_SA_ALIGN | ||
186 | XCHAL_CP1_SA_CONTENTS_LIBDB | ||
187 | reg_group 2, XCHAL_CP2_SA_CONTENTS_LIBDB_NUM, XCHAL_CP2_SA_ALIGN | ||
188 | XCHAL_CP2_SA_CONTENTS_LIBDB | ||
189 | reg_group 3, XCHAL_CP3_SA_CONTENTS_LIBDB_NUM, XCHAL_CP3_SA_ALIGN | ||
190 | XCHAL_CP3_SA_CONTENTS_LIBDB | ||
191 | reg_group 4, XCHAL_CP4_SA_CONTENTS_LIBDB_NUM, XCHAL_CP4_SA_ALIGN | ||
192 | XCHAL_CP4_SA_CONTENTS_LIBDB | ||
193 | reg_group 5, XCHAL_CP5_SA_CONTENTS_LIBDB_NUM, XCHAL_CP5_SA_ALIGN | ||
194 | XCHAL_CP5_SA_CONTENTS_LIBDB | ||
195 | reg_group 6, XCHAL_CP6_SA_CONTENTS_LIBDB_NUM, XCHAL_CP6_SA_ALIGN | ||
196 | XCHAL_CP6_SA_CONTENTS_LIBDB | ||
197 | reg_group 7, XCHAL_CP7_SA_CONTENTS_LIBDB_NUM, XCHAL_CP7_SA_ALIGN | ||
198 | XCHAL_CP7_SA_CONTENTS_LIBDB | ||
199 | .word 0xFC000000 /* invalid register number,marks end of table*/ | ||
200 | _xtensa_reginfo_table_end: | ||
201 | |||