aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-xtensa/coprocessor.h
diff options
context:
space:
mode:
authorChris Zankel <chris@zankel.net>2008-02-12 16:17:07 -0500
committerChris Zankel <chris@zankel.net>2008-02-13 20:41:43 -0500
commitc658eac628aa8df040dfe614556d95e6da3a9ffb (patch)
treee2211e1d5c894c29e92d4c744f504b38410efe41 /include/asm-xtensa/coprocessor.h
parent71d28e6c285548106f551fde13ca6d589433d843 (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>
Diffstat (limited to 'include/asm-xtensa/coprocessor.h')
-rw-r--r--include/asm-xtensa/coprocessor.h209
1 files changed, 148 insertions, 61 deletions
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
index aa2121034558..e5849bb9f6cf 100644
--- a/include/asm-xtensa/coprocessor.h
+++ b/include/asm-xtensa/coprocessor.h
@@ -5,81 +5,168 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (C) 2003 - 2005 Tensilica Inc. 8 * Copyright (C) 2003 - 2007 Tensilica Inc.
9 */ 9 */
10 10
11
11#ifndef _XTENSA_COPROCESSOR_H 12#ifndef _XTENSA_COPROCESSOR_H
12#define _XTENSA_COPROCESSOR_H 13#define _XTENSA_COPROCESSOR_H
13 14
14#include <asm/variant/core.h> 15#include <linux/stringify.h>
15#include <asm/variant/tie.h> 16#include <asm/variant/tie.h>
17#include <asm/types.h>
18
19#ifdef __ASSEMBLY__
20# include <asm/variant/tie-asm.h>
21
22.macro xchal_sa_start a b
23 .set .Lxchal_pofs_, 0
24 .set .Lxchal_ofs_, 0
25.endm
26
27.macro xchal_sa_align ptr minofs maxofs ofsalign totalign
28 .set .Lxchal_ofs_, .Lxchal_ofs_ + .Lxchal_pofs_ + \totalign - 1
29 .set .Lxchal_ofs_, (.Lxchal_ofs_ & -\totalign) - .Lxchal_pofs_
30.endm
31
32#define _SELECT ( XTHAL_SAS_TIE | XTHAL_SAS_OPT \
33 | XTHAL_SAS_CC \
34 | XTHAL_SAS_CALR | XTHAL_SAS_CALE | XTHAL_SAS_GLOB )
35
36.macro save_xtregs_opt ptr clb at1 at2 at3 at4 offset
37 .if XTREGS_OPT_SIZE > 0
38 addi \clb, \ptr, \offset
39 xchal_ncp_store \clb \at1 \at2 \at3 \at4 select=_SELECT
40 .endif
41.endm
42
43.macro load_xtregs_opt ptr clb at1 at2 at3 at4 offset
44 .if XTREGS_OPT_SIZE > 0
45 addi \clb, \ptr, \offset
46 xchal_ncp_load \clb \at1 \at2 \at3 \at4 select=_SELECT
47 .endif
48.endm
49#undef _SELECT
50
51#define _SELECT ( XTHAL_SAS_TIE | XTHAL_SAS_OPT \
52 | XTHAL_SAS_NOCC \
53 | XTHAL_SAS_CALR | XTHAL_SAS_CALE | XTHAL_SAS_GLOB )
54
55.macro save_xtregs_user ptr clb at1 at2 at3 at4 offset
56 .if XTREGS_USER_SIZE > 0
57 addi \clb, \ptr, \offset
58 xchal_ncp_store \clb \at1 \at2 \at3 \at4 select=_SELECT
59 .endif
60.endm
61
62.macro load_xtregs_user ptr clb at1 at2 at3 at4 offset
63 .if XTREGS_USER_SIZE > 0
64 addi \clb, \ptr, \offset
65 xchal_ncp_load \clb \at1 \at2 \at3 \at4 select=_SELECT
66 .endif
67.endm
68#undef _SELECT
69
70
71
72#endif /* __ASSEMBLY__ */
16 73
17#if !XCHAL_HAVE_CP
18
19#define XTENSA_CP_EXTRA_OFFSET 0
20#define XTENSA_CP_EXTRA_ALIGN 1 /* must be a power of 2 */
21#define XTENSA_CP_EXTRA_SIZE 0
22
23#else
24
25#define XTOFS(last_start,last_size,align) \
26 ((last_start+last_size+align-1) & -align)
27
28#define XTENSA_CP_EXTRA_OFFSET 0
29#define XTENSA_CP_EXTRA_ALIGN XCHAL_EXTRA_SA_ALIGN
30
31#define XTENSA_CPE_CP0_OFFSET \
32 XTOFS(XTENSA_CP_EXTRA_OFFSET, XCHAL_EXTRA_SA_SIZE, XCHAL_CP0_SA_ALIGN)
33#define XTENSA_CPE_CP1_OFFSET \
34 XTOFS(XTENSA_CPE_CP0_OFFSET, XCHAL_CP0_SA_SIZE, XCHAL_CP1_SA_ALIGN)
35#define XTENSA_CPE_CP2_OFFSET \
36 XTOFS(XTENSA_CPE_CP1_OFFSET, XCHAL_CP1_SA_SIZE, XCHAL_CP2_SA_ALIGN)
37#define XTENSA_CPE_CP3_OFFSET \
38 XTOFS(XTENSA_CPE_CP2_OFFSET, XCHAL_CP2_SA_SIZE, XCHAL_CP3_SA_ALIGN)
39#define XTENSA_CPE_CP4_OFFSET \
40 XTOFS(XTENSA_CPE_CP3_OFFSET, XCHAL_CP3_SA_SIZE, XCHAL_CP4_SA_ALIGN)
41#define XTENSA_CPE_CP5_OFFSET \
42 XTOFS(XTENSA_CPE_CP4_OFFSET, XCHAL_CP4_SA_SIZE, XCHAL_CP5_SA_ALIGN)
43#define XTENSA_CPE_CP6_OFFSET \
44 XTOFS(XTENSA_CPE_CP5_OFFSET, XCHAL_CP5_SA_SIZE, XCHAL_CP6_SA_ALIGN)
45#define XTENSA_CPE_CP7_OFFSET \
46 XTOFS(XTENSA_CPE_CP6_OFFSET, XCHAL_CP6_SA_SIZE, XCHAL_CP7_SA_ALIGN)
47#define XTENSA_CP_EXTRA_SIZE \
48 XTOFS(XTENSA_CPE_CP7_OFFSET, XCHAL_CP7_SA_SIZE, 16)
49
50#if XCHAL_CP_NUM > 0
51# ifndef __ASSEMBLY__
52/* 74/*
53 * Tasks that own contents of (last user) each coprocessor. 75 * XTENSA_HAVE_COPROCESSOR(x) returns 1 if coprocessor x is configured.
54 * Entries are 0 for not-owned or non-existent coprocessors. 76 *
55 * Note: The size of this structure is fixed to 8 bytes in entry.S 77 * XTENSA_HAVE_IO_PORT(x) returns 1 if io-port x is configured.
78 *
56 */ 79 */
57typedef struct {
58 struct task_struct *owner; /* owner */
59 int offset; /* offset in cpextra space. */
60} coprocessor_info_t;
61# else
62# define COPROCESSOR_INFO_OWNER 0
63# define COPROCESSOR_INFO_OFFSET 4
64# define COPROCESSOR_INFO_SIZE 8
65# endif
66#endif
67#endif /* XCHAL_HAVE_CP */
68 80
81#define XTENSA_HAVE_COPROCESSOR(x) \
82 ((XCHAL_CP_MASK ^ XCHAL_CP_PORT_MASK) & (1 << (x)))
83#define XTENSA_HAVE_COPROCESSORS \
84 (XCHAL_CP_MASK ^ XCHAL_CP_PORT_MASK)
85#define XTENSA_HAVE_IO_PORT(x) \
86 (XCHAL_CP_PORT_MASK & (1 << (x)))
87#define XTENSA_HAVE_IO_PORTS \
88 XCHAL_CP_PORT_MASK
69 89
70#ifndef __ASSEMBLY__ 90#ifndef __ASSEMBLY__
71# if XCHAL_CP_NUM > 0
72struct task_struct;
73extern void release_coprocessors (struct task_struct*);
74extern void save_coprocessor_registers(void*, int);
75# else
76# define release_coprocessors(task)
77# endif
78 91
79typedef unsigned char cp_state_t[XTENSA_CP_EXTRA_SIZE]
80 __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
81 92
82#endif /* !__ASSEMBLY__ */ 93#if XCHAL_HAVE_CP
83 94
95#define RSR_CPENABLE(x) do { \
96 __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \
97 } while(0);
98#define WSR_CPENABLE(x) do { \
99 __asm__ __volatile__("wsr %0," __stringify(CPENABLE) "; rsync" \
100 :: "a" (x)); \
101 } while(0);
84 102
103#endif /* XCHAL_HAVE_CP */
104
105
106/*
107 * Additional registers.
108 * We define three types of additional registers:
109 * ext: extra registers that are used by the compiler
110 * cpn: optional registers that can be used by a user application
111 * cpX: coprocessor registers that can only be used if the corresponding
112 * CPENABLE bit is set.
113 */
114
115#define XCHAL_SA_REG(list,compiler,x,type,y,name,z,align,size,...) \
116 __REG ## list (compiler, type, name, size, align)
117
118#define __REG0(compiler,t,name,s,a) __REG0_ ## compiler (name)
119#define __REG1(compiler,t,name,s,a) __REG1_ ## compiler (name)
120#define __REG2(c,type,...) __REG2_ ## type (__VA_ARGS__)
121
122#define __REG0_0(name)
123#define __REG0_1(name) __u32 name;
124#define __REG1_0(name) __u32 name;
125#define __REG1_1(name)
126#define __REG2_0(n,s,a) __u32 name;
127#define __REG2_1(n,s,a) unsigned char n[s] __attribute__ ((aligned(a)));
128#define __REG2_2(n,s,a) unsigned char n[s] __attribute__ ((aligned(a)));
129
130typedef struct { XCHAL_NCP_SA_LIST(0) } xtregs_opt_t
131 __attribute__ ((aligned (XCHAL_NCP_SA_ALIGN)));
132typedef struct { XCHAL_NCP_SA_LIST(1) } xtregs_user_t
133 __attribute__ ((aligned (XCHAL_NCP_SA_ALIGN)));
134
135#if XTENSA_HAVE_COPROCESSORS
136
137typedef struct { XCHAL_CP0_SA_LIST(2) } xtregs_cp0_t
138 __attribute__ ((aligned (XCHAL_CP0_SA_ALIGN)));
139typedef struct { XCHAL_CP1_SA_LIST(2) } xtregs_cp1_t
140 __attribute__ ((aligned (XCHAL_CP1_SA_ALIGN)));
141typedef struct { XCHAL_CP2_SA_LIST(2) } xtregs_cp2_t
142 __attribute__ ((aligned (XCHAL_CP2_SA_ALIGN)));
143typedef struct { XCHAL_CP3_SA_LIST(2) } xtregs_cp3_t
144 __attribute__ ((aligned (XCHAL_CP3_SA_ALIGN)));
145typedef struct { XCHAL_CP4_SA_LIST(2) } xtregs_cp4_t
146 __attribute__ ((aligned (XCHAL_CP4_SA_ALIGN)));
147typedef struct { XCHAL_CP5_SA_LIST(2) } xtregs_cp5_t
148 __attribute__ ((aligned (XCHAL_CP5_SA_ALIGN)));
149typedef struct { XCHAL_CP6_SA_LIST(2) } xtregs_cp6_t
150 __attribute__ ((aligned (XCHAL_CP6_SA_ALIGN)));
151typedef struct { XCHAL_CP7_SA_LIST(2) } xtregs_cp7_t
152 __attribute__ ((aligned (XCHAL_CP7_SA_ALIGN)));
153
154extern struct thread_info* coprocessor_owner[XCHAL_CP_MAX];
155extern void coprocessor_save(void*, int);
156extern void coprocessor_load(void*, int);
157extern void coprocessor_flush(struct thread_info*, int);
158extern void coprocessor_restore(struct thread_info*, int);
159
160extern void coprocessor_release_all(struct thread_info*);
161extern void coprocessor_flush_all(struct thread_info*);
162
163static inline void coprocessor_clear_cpenable(void)
164{
165 unsigned long i = 0;
166 WSR_CPENABLE(i);
167}
168
169#endif /* XTENSA_HAVE_COPROCESSORS */
170
171#endif /* !__ASSEMBLY__ */
85#endif /* _XTENSA_COPROCESSOR_H */ 172#endif /* _XTENSA_COPROCESSOR_H */