diff options
author | Fu Wei <tekkamanninja@gmail.com> | 2012-11-15 12:01:56 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-15 20:46:42 -0500 |
commit | 83ca897d170919035acfe5c472479941847e93cc (patch) | |
tree | 1a51420993caf9849ae05a1a7296ad85aadf6fff /Documentation/zh_CN | |
parent | 7dd2517c39c1334c9431c0732487e16f752ca09a (diff) |
Documentation: Chinese translation of Documentation/arm/kernel_user_helpers.txt
This is a Chinese translated version of
Documentation/arm/kernel_user_helpers.txt
Signed-off-by: Fu Wei <tekkamanninja@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'Documentation/zh_CN')
-rw-r--r-- | Documentation/zh_CN/arm/kernel_user_helpers.txt | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/Documentation/zh_CN/arm/kernel_user_helpers.txt b/Documentation/zh_CN/arm/kernel_user_helpers.txt new file mode 100644 index 000000000000..cd7fc8f34cf9 --- /dev/null +++ b/Documentation/zh_CN/arm/kernel_user_helpers.txt | |||
@@ -0,0 +1,284 @@ | |||
1 | Chinese translated version of Documentation/arm/kernel_user_helpers.txt | ||
2 | |||
3 | If you have any comment or update to the content, please contact the | ||
4 | original document maintainer directly. However, if you have a problem | ||
5 | communicating in English you can also ask the Chinese maintainer for | ||
6 | help. Contact the Chinese maintainer if this translation is outdated | ||
7 | or if there is a problem with the translation. | ||
8 | |||
9 | Maintainer: Nicolas Pitre <nicolas.pitre@linaro.org> | ||
10 | Dave Martin <dave.martin@linaro.org> | ||
11 | Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> | ||
12 | --------------------------------------------------------------------- | ||
13 | Documentation/arm/kernel_user_helpers.txt 的中文翻译 | ||
14 | |||
15 | 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 | ||
16 | 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 | ||
17 | 译存在问题,请联系中文版维护者。 | ||
18 | 英文版维护者: Nicolas Pitre <nicolas.pitre@linaro.org> | ||
19 | Dave Martin <dave.martin@linaro.org> | ||
20 | 中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> | ||
21 | 中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> | ||
22 | 中文版校译者: 宋冬生 Dongsheng Song <dongshneg.song@gmail.com> | ||
23 | 傅炜 Fu Wei <tekkamanninja@gmail.com> | ||
24 | |||
25 | |||
26 | 以下为正文 | ||
27 | --------------------------------------------------------------------- | ||
28 | 内核提供的用户空间辅助代码 | ||
29 | ========================= | ||
30 | |||
31 | 在内核内存空间的固定地址处,有一个由内核提供并可从用户空间访问的代码 | ||
32 | 段。它用于向用户空间提供因在许多 ARM CPU 中未实现的特性和/或指令而需 | ||
33 | 内核提供帮助的某些操作。这些代码直接在用户模式下执行的想法是为了获得 | ||
34 | 最佳效率,但那些与内核计数器联系过于紧密的部分,则被留给了用户库实现。 | ||
35 | 事实上,此代码甚至可能因不同的 CPU 而异,这取决于其可用的指令集或它 | ||
36 | 是否为 SMP 系统。换句话说,内核保留在不作出警告的情况下根据需要更改 | ||
37 | 这些代码的权利。只有本文档描述的入口及其结果是保证稳定的。 | ||
38 | |||
39 | 这与完全成熟的 VDSO 实现不同(但两者并不冲突),尽管如此,VDSO 可阻止 | ||
40 | 某些通过常量高效跳转到那些代码段的汇编技巧。且由于那些代码段在返回用户 | ||
41 | 代码前仅使用少量的代码周期,则一个 VDSO 间接远程调用将会在这些简单的 | ||
42 | 操作上增加一个可测量的开销。 | ||
43 | |||
44 | 在对那些拥有原生支持的新型处理器进行代码优化时,仅在已为其他操作使用 | ||
45 | 了类似的新增指令,而导致二进制结果已与早期 ARM 处理器不兼容的情况下, | ||
46 | 用户空间才应绕过这些辅助代码,并在内联函数中实现这些操作(无论是通过 | ||
47 | 编译器在代码中直接放置,还是作为库函数调用实现的一部分)。也就是说, | ||
48 | 如果你编译的代码不会为了其他目的使用新指令,则不要仅为了避免使用这些 | ||
49 | 内核辅助代码,导致二进制程序无法在早期处理器上运行。 | ||
50 | |||
51 | 新的辅助代码可能随着时间的推移而增加,所以新内核中的某些辅助代码在旧 | ||
52 | 内核中可能不存在。因此,程序必须在对任何辅助代码调用假设是安全之前, | ||
53 | 检测 __kuser_helper_version 的值(见下文)。理想情况下,这种检测应该 | ||
54 | 只在进程启动时执行一次;如果内核版本不支持所需辅助代码,则该进程可尽早 | ||
55 | 中止执行。 | ||
56 | |||
57 | kuser_helper_version | ||
58 | -------------------- | ||
59 | |||
60 | 位置: 0xffff0ffc | ||
61 | |||
62 | 参考声明: | ||
63 | |||
64 | extern int32_t __kuser_helper_version; | ||
65 | |||
66 | 定义: | ||
67 | |||
68 | 这个区域包含了当前运行内核实现的辅助代码版本号。用户空间可以通过读 | ||
69 | 取此版本号以确定特定的辅助代码是否存在。 | ||
70 | |||
71 | 使用范例: | ||
72 | |||
73 | #define __kuser_helper_version (*(int32_t *)0xffff0ffc) | ||
74 | |||
75 | void check_kuser_version(void) | ||
76 | { | ||
77 | if (__kuser_helper_version < 2) { | ||
78 | fprintf(stderr, "can't do atomic operations, kernel too old\n"); | ||
79 | abort(); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | 注意: | ||
84 | |||
85 | 用户空间可以假设这个域的值不会在任何单个进程的生存期内改变。也就 | ||
86 | 是说,这个域可以仅在库的初始化阶段或进程启动阶段读取一次。 | ||
87 | |||
88 | kuser_get_tls | ||
89 | ------------- | ||
90 | |||
91 | 位置: 0xffff0fe0 | ||
92 | |||
93 | 参考原型: | ||
94 | |||
95 | void * __kuser_get_tls(void); | ||
96 | |||
97 | 输入: | ||
98 | |||
99 | lr = 返回地址 | ||
100 | |||
101 | 输出: | ||
102 | |||
103 | r0 = TLS 值 | ||
104 | |||
105 | 被篡改的寄存器: | ||
106 | |||
107 | 无 | ||
108 | |||
109 | 定义: | ||
110 | |||
111 | 获取之前通过 __ARM_NR_set_tls 系统调用设置的 TLS 值。 | ||
112 | |||
113 | 使用范例: | ||
114 | |||
115 | typedef void * (__kuser_get_tls_t)(void); | ||
116 | #define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0) | ||
117 | |||
118 | void foo() | ||
119 | { | ||
120 | void *tls = __kuser_get_tls(); | ||
121 | printf("TLS = %p\n", tls); | ||
122 | } | ||
123 | |||
124 | 注意: | ||
125 | |||
126 | - 仅在 __kuser_helper_version >= 1 时,此辅助代码存在 | ||
127 | (从内核版本 2.6.12 开始)。 | ||
128 | |||
129 | kuser_cmpxchg | ||
130 | ------------- | ||
131 | |||
132 | 位置: 0xffff0fc0 | ||
133 | |||
134 | 参考原型: | ||
135 | |||
136 | int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr); | ||
137 | |||
138 | 输入: | ||
139 | |||
140 | r0 = oldval | ||
141 | r1 = newval | ||
142 | r2 = ptr | ||
143 | lr = 返回地址 | ||
144 | |||
145 | 输出: | ||
146 | |||
147 | r0 = 成功代码 (零或非零) | ||
148 | C flag = 如果 r0 == 0 则置 1,如果 r0 != 0 则清零。 | ||
149 | |||
150 | 被篡改的寄存器: | ||
151 | |||
152 | r3, ip, flags | ||
153 | |||
154 | 定义: | ||
155 | |||
156 | 仅在 *ptr 为 oldval 时原子保存 newval 于 *ptr 中。 | ||
157 | 如果 *ptr 被改变,则返回值为零,否则为非零值。 | ||
158 | 如果 *ptr 被改变,则 C flag 也会被置 1,以实现调用代码中的汇编 | ||
159 | 优化。 | ||
160 | |||
161 | 使用范例: | ||
162 | |||
163 | typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr); | ||
164 | #define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0) | ||
165 | |||
166 | int atomic_add(volatile int *ptr, int val) | ||
167 | { | ||
168 | int old, new; | ||
169 | |||
170 | do { | ||
171 | old = *ptr; | ||
172 | new = old + val; | ||
173 | } while(__kuser_cmpxchg(old, new, ptr)); | ||
174 | |||
175 | return new; | ||
176 | } | ||
177 | |||
178 | 注意: | ||
179 | |||
180 | - 这个例程已根据需要包含了内存屏障。 | ||
181 | |||
182 | - 仅在 __kuser_helper_version >= 2 时,此辅助代码存在 | ||
183 | (从内核版本 2.6.12 开始)。 | ||
184 | |||
185 | kuser_memory_barrier | ||
186 | -------------------- | ||
187 | |||
188 | 位置: 0xffff0fa0 | ||
189 | |||
190 | 参考原型: | ||
191 | |||
192 | void __kuser_memory_barrier(void); | ||
193 | |||
194 | 输入: | ||
195 | |||
196 | lr = 返回地址 | ||
197 | |||
198 | 输出: | ||
199 | |||
200 | 无 | ||
201 | |||
202 | 被篡改的寄存器: | ||
203 | |||
204 | 无 | ||
205 | |||
206 | 定义: | ||
207 | |||
208 | 应用于任何需要内存屏障以防止手动数据修改带来的一致性问题,以及 | ||
209 | __kuser_cmpxchg 中。 | ||
210 | |||
211 | 使用范例: | ||
212 | |||
213 | typedef void (__kuser_dmb_t)(void); | ||
214 | #define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0) | ||
215 | |||
216 | 注意: | ||
217 | |||
218 | - 仅在 __kuser_helper_version >= 3 时,此辅助代码存在 | ||
219 | (从内核版本 2.6.15 开始)。 | ||
220 | |||
221 | kuser_cmpxchg64 | ||
222 | --------------- | ||
223 | |||
224 | 位置: 0xffff0f60 | ||
225 | |||
226 | 参考原型: | ||
227 | |||
228 | int __kuser_cmpxchg64(const int64_t *oldval, | ||
229 | const int64_t *newval, | ||
230 | volatile int64_t *ptr); | ||
231 | |||
232 | 输入: | ||
233 | |||
234 | r0 = 指向 oldval | ||
235 | r1 = 指向 newval | ||
236 | r2 = 指向目标值 | ||
237 | lr = 返回地址 | ||
238 | |||
239 | 输出: | ||
240 | |||
241 | r0 = 成功代码 (零或非零) | ||
242 | C flag = 如果 r0 == 0 则置 1,如果 r0 != 0 则清零。 | ||
243 | |||
244 | 被篡改的寄存器: | ||
245 | |||
246 | r3, lr, flags | ||
247 | |||
248 | 定义: | ||
249 | |||
250 | 仅在 *ptr 等于 *oldval 指向的 64 位值时,原子保存 *newval | ||
251 | 指向的 64 位值于 *ptr 中。如果 *ptr 被改变,则返回值为零, | ||
252 | 否则为非零值。 | ||
253 | |||
254 | 如果 *ptr 被改变,则 C flag 也会被置 1,以实现调用代码中的汇编 | ||
255 | 优化。 | ||
256 | |||
257 | 使用范例: | ||
258 | |||
259 | typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval, | ||
260 | const int64_t *newval, | ||
261 | volatile int64_t *ptr); | ||
262 | #define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60) | ||
263 | |||
264 | int64_t atomic_add64(volatile int64_t *ptr, int64_t val) | ||
265 | { | ||
266 | int64_t old, new; | ||
267 | |||
268 | do { | ||
269 | old = *ptr; | ||
270 | new = old + val; | ||
271 | } while(__kuser_cmpxchg64(&old, &new, ptr)); | ||
272 | |||
273 | return new; | ||
274 | } | ||
275 | |||
276 | 注意: | ||
277 | |||
278 | - 这个例程已根据需要包含了内存屏障。 | ||
279 | |||
280 | - 由于这个过程的代码长度(此辅助代码跨越 2 个常规的 kuser “槽”), | ||
281 | 因此 0xffff0f80 不被作为有效的入口点。 | ||
282 | |||
283 | - 仅在 __kuser_helper_version >= 5 时,此辅助代码存在 | ||
284 | (从内核版本 3.1 开始)。 | ||