xref: /linux/Documentation/translations/zh_TW/arch/arm/kernel_user_helpers.txt (revision a23e1966932464e1c5226cb9ac4ce1d5fc10ba22)
1f949cb75SHu HaowenChinese translated version of Documentation/arch/arm/kernel_user_helpers.rst
2f949cb75SHu Haowen
3f949cb75SHu HaowenIf you have any comment or update to the content, please contact the
4f949cb75SHu Haowenoriginal document maintainer directly.  However, if you have a problem
5f949cb75SHu Haowencommunicating in English you can also ask the Chinese maintainer for
6f949cb75SHu Haowenhelp.  Contact the Chinese maintainer if this translation is outdated
7f949cb75SHu Haowenor if there is a problem with the translation.
8f949cb75SHu Haowen
9f949cb75SHu HaowenMaintainer: Nicolas Pitre <nicolas.pitre@linaro.org>
10f949cb75SHu Haowen		Dave Martin <dave.martin@linaro.org>
11f949cb75SHu HaowenChinese maintainer: Fu Wei <tekkamanninja@gmail.com>
12f949cb75SHu Haowen---------------------------------------------------------------------
13f949cb75SHu HaowenDocumentation/arch/arm/kernel_user_helpers.rst 的中文翻譯
14f949cb75SHu Haowen
15f949cb75SHu Haowen如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
16f949cb75SHu Haowen交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
17f949cb75SHu Haowen譯存在問題,請聯繫中文版維護者。
18f949cb75SHu Haowen英文版維護者: Nicolas Pitre <nicolas.pitre@linaro.org>
19f949cb75SHu Haowen		Dave Martin <dave.martin@linaro.org>
20f949cb75SHu Haowen中文版維護者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
21f949cb75SHu Haowen中文版翻譯者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
22f949cb75SHu Haowen中文版校譯者: 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
23f949cb75SHu Haowen		傅煒 Fu Wei <tekkamanninja@gmail.com>
24f949cb75SHu Haowen
25f949cb75SHu Haowen
26f949cb75SHu Haowen以下爲正文
27f949cb75SHu Haowen---------------------------------------------------------------------
28f949cb75SHu Haowen內核提供的用戶空間輔助代碼
29f949cb75SHu Haowen=========================
30f949cb75SHu Haowen
31f949cb75SHu Haowen在內核內存空間的固定地址處,有一個由內核提供並可從用戶空間訪問的代碼
32f949cb75SHu Haowen段。它用於向用戶空間提供因在許多 ARM CPU 中未實現的特性和/或指令而需
33f949cb75SHu Haowen內核提供幫助的某些操作。這些代碼直接在用戶模式下執行的想法是爲了獲得
34f949cb75SHu Haowen最佳效率,但那些與內核計數器聯繫過於緊密的部分,則被留給了用戶庫實現。
35f949cb75SHu Haowen事實上,此代碼甚至可能因不同的 CPU 而異,這取決於其可用的指令集或它
36f949cb75SHu Haowen是否爲 SMP 系統。換句話說,內核保留在不作出警告的情況下根據需要更改
37f949cb75SHu Haowen這些代碼的權利。只有本文檔描述的入口及其結果是保證穩定的。
38f949cb75SHu Haowen
39f949cb75SHu Haowen這與完全成熟的 VDSO 實現不同(但兩者並不衝突),儘管如此,VDSO 可阻止
40f949cb75SHu Haowen某些通過常量高效跳轉到那些代碼段的彙編技巧。且由於那些代碼段在返回用戶
41f949cb75SHu Haowen代碼前僅使用少量的代碼週期,則一個 VDSO 間接遠程調用將會在這些簡單的
42f949cb75SHu Haowen操作上增加一個可測量的開銷。
43f949cb75SHu Haowen
44f949cb75SHu Haowen在對那些擁有原生支持的新型處理器進行代碼優化時,僅在已爲其他操作使用
45f949cb75SHu Haowen了類似的新增指令,而導致二進制結果已與早期 ARM 處理器不兼容的情況下,
46f949cb75SHu Haowen用戶空間才應繞過這些輔助代碼,並在內聯函數中實現這些操作(無論是通過
47f949cb75SHu Haowen編譯器在代碼中直接放置,還是作爲庫函數調用實現的一部分)。也就是說,
48f949cb75SHu Haowen如果你編譯的代碼不會爲了其他目的使用新指令,則不要僅爲了避免使用這些
49f949cb75SHu Haowen內核輔助代碼,導致二進制程序無法在早期處理器上運行。
50f949cb75SHu Haowen
51f949cb75SHu Haowen新的輔助代碼可能隨着時間的推移而增加,所以新內核中的某些輔助代碼在舊
52f949cb75SHu Haowen內核中可能不存在。因此,程序必須在對任何輔助代碼調用假設是安全之前,
53f949cb75SHu Haowen檢測 __kuser_helper_version 的值(見下文)。理想情況下,這種檢測應該
54f949cb75SHu Haowen只在進程啓動時執行一次;如果內核版本不支持所需輔助代碼,則該進程可儘早
55f949cb75SHu Haowen中止執行。
56f949cb75SHu Haowen
57f949cb75SHu Haowenkuser_helper_version
58f949cb75SHu Haowen--------------------
59f949cb75SHu Haowen
60f949cb75SHu Haowen位置:	0xffff0ffc
61f949cb75SHu Haowen
62f949cb75SHu Haowen參考聲明:
63f949cb75SHu Haowen
64f949cb75SHu Haowen  extern int32_t __kuser_helper_version;
65f949cb75SHu Haowen
66f949cb75SHu Haowen定義:
67f949cb75SHu Haowen
68f949cb75SHu Haowen  這個區域包含了當前運行內核實現的輔助代碼版本號。用戶空間可以通過讀
69f949cb75SHu Haowen  取此版本號以確定特定的輔助代碼是否存在。
70f949cb75SHu Haowen
71f949cb75SHu Haowen使用範例:
72f949cb75SHu Haowen
73f949cb75SHu Haowen#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
74f949cb75SHu Haowen
75f949cb75SHu Haowenvoid check_kuser_version(void)
76f949cb75SHu Haowen{
77f949cb75SHu Haowen	if (__kuser_helper_version < 2) {
78f949cb75SHu Haowen		fprintf(stderr, "can't do atomic operations, kernel too old\n");
79f949cb75SHu Haowen		abort();
80f949cb75SHu Haowen	}
81f949cb75SHu Haowen}
82f949cb75SHu Haowen
83f949cb75SHu Haowen注意:
84f949cb75SHu Haowen
85f949cb75SHu Haowen  用戶空間可以假設這個域的值不會在任何單個進程的生存期內改變。也就
86f949cb75SHu Haowen  是說,這個域可以僅在庫的初始化階段或進程啓動階段讀取一次。
87f949cb75SHu Haowen
88f949cb75SHu Haowenkuser_get_tls
89f949cb75SHu Haowen-------------
90f949cb75SHu Haowen
91f949cb75SHu Haowen位置:	0xffff0fe0
92f949cb75SHu Haowen
93f949cb75SHu Haowen參考原型:
94f949cb75SHu Haowen
95f949cb75SHu Haowen  void * __kuser_get_tls(void);
96f949cb75SHu Haowen
97f949cb75SHu Haowen輸入:
98f949cb75SHu Haowen
99f949cb75SHu Haowen  lr = 返回地址
100f949cb75SHu Haowen
101f949cb75SHu Haowen輸出:
102f949cb75SHu Haowen
103f949cb75SHu Haowen  r0 = TLS 值
104f949cb75SHu Haowen
105f949cb75SHu Haowen被篡改的寄存器:
106f949cb75SHu Haowen
107f949cb75SHu Haowen108f949cb75SHu Haowen
109f949cb75SHu Haowen定義:
110f949cb75SHu Haowen
111f949cb75SHu Haowen  獲取之前通過 __ARM_NR_set_tls 系統調用設置的 TLS 值。
112f949cb75SHu Haowen
113f949cb75SHu Haowen使用範例:
114f949cb75SHu Haowen
115f949cb75SHu Haowentypedef void * (__kuser_get_tls_t)(void);
116f949cb75SHu Haowen#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
117f949cb75SHu Haowen
118f949cb75SHu Haowenvoid foo()
119f949cb75SHu Haowen{
120f949cb75SHu Haowen	void *tls = __kuser_get_tls();
121f949cb75SHu Haowen	printf("TLS = %p\n", tls);
122f949cb75SHu Haowen}
123f949cb75SHu Haowen
124f949cb75SHu Haowen注意:
125f949cb75SHu Haowen
126f949cb75SHu Haowen  - 僅在 __kuser_helper_version >= 1 時,此輔助代碼存在
127f949cb75SHu Haowen    (從內核版本 2.6.12 開始)。
128f949cb75SHu Haowen
129f949cb75SHu Haowenkuser_cmpxchg
130f949cb75SHu Haowen-------------
131f949cb75SHu Haowen
132f949cb75SHu Haowen位置:	0xffff0fc0
133f949cb75SHu Haowen
134f949cb75SHu Haowen參考原型:
135f949cb75SHu Haowen
136f949cb75SHu Haowen  int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
137f949cb75SHu Haowen
138f949cb75SHu Haowen輸入:
139f949cb75SHu Haowen
140f949cb75SHu Haowen  r0 = oldval
141f949cb75SHu Haowen  r1 = newval
142f949cb75SHu Haowen  r2 = ptr
143f949cb75SHu Haowen  lr = 返回地址
144f949cb75SHu Haowen
145f949cb75SHu Haowen輸出:
146f949cb75SHu Haowen
147f949cb75SHu Haowen  r0 = 成功代碼 (零或非零)
148f949cb75SHu Haowen  C flag = 如果 r0 == 0 則置 1,如果 r0 != 0 則清零。
149f949cb75SHu Haowen
150f949cb75SHu Haowen被篡改的寄存器:
151f949cb75SHu Haowen
152f949cb75SHu Haowen  r3, ip, flags
153f949cb75SHu Haowen
154f949cb75SHu Haowen定義:
155f949cb75SHu Haowen
156f949cb75SHu Haowen  僅在 *ptr 爲 oldval 時原子保存 newval 於 *ptr 中。
157f949cb75SHu Haowen  如果 *ptr 被改變,則返回值爲零,否則爲非零值。
158f949cb75SHu Haowen  如果 *ptr 被改變,則 C flag 也會被置 1,以實現調用代碼中的彙編
159f949cb75SHu Haowen  優化。
160f949cb75SHu Haowen
161f949cb75SHu Haowen使用範例:
162f949cb75SHu Haowen
163f949cb75SHu Haowentypedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
164f949cb75SHu Haowen#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
165f949cb75SHu Haowen
166f949cb75SHu Haowenint atomic_add(volatile int *ptr, int val)
167f949cb75SHu Haowen{
168f949cb75SHu Haowen	int old, new;
169f949cb75SHu Haowen
170f949cb75SHu Haowen	do {
171f949cb75SHu Haowen		old = *ptr;
172f949cb75SHu Haowen		new = old + val;
173f949cb75SHu Haowen	} while(__kuser_cmpxchg(old, new, ptr));
174f949cb75SHu Haowen
175f949cb75SHu Haowen	return new;
176f949cb75SHu Haowen}
177f949cb75SHu Haowen
178f949cb75SHu Haowen注意:
179f949cb75SHu Haowen
180f949cb75SHu Haowen  - 這個例程已根據需要包含了內存屏障。
181f949cb75SHu Haowen
182f949cb75SHu Haowen  - 僅在 __kuser_helper_version >= 2 時,此輔助代碼存在
183f949cb75SHu Haowen    (從內核版本 2.6.12 開始)。
184f949cb75SHu Haowen
185f949cb75SHu Haowenkuser_memory_barrier
186f949cb75SHu Haowen--------------------
187f949cb75SHu Haowen
188f949cb75SHu Haowen位置:	0xffff0fa0
189f949cb75SHu Haowen
190f949cb75SHu Haowen參考原型:
191f949cb75SHu Haowen
192f949cb75SHu Haowen  void __kuser_memory_barrier(void);
193f949cb75SHu Haowen
194f949cb75SHu Haowen輸入:
195f949cb75SHu Haowen
196f949cb75SHu Haowen  lr = 返回地址
197f949cb75SHu Haowen
198f949cb75SHu Haowen輸出:
199f949cb75SHu Haowen
200f949cb75SHu Haowen201f949cb75SHu Haowen
202f949cb75SHu Haowen被篡改的寄存器:
203f949cb75SHu Haowen
204f949cb75SHu Haowen205f949cb75SHu Haowen
206f949cb75SHu Haowen定義:
207f949cb75SHu Haowen
208f949cb75SHu Haowen  應用於任何需要內存屏障以防止手動數據修改帶來的一致性問題,以及
209f949cb75SHu Haowen  __kuser_cmpxchg 中。
210f949cb75SHu Haowen
211f949cb75SHu Haowen使用範例:
212f949cb75SHu Haowen
213f949cb75SHu Haowentypedef void (__kuser_dmb_t)(void);
214f949cb75SHu Haowen#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
215f949cb75SHu Haowen
216f949cb75SHu Haowen注意:
217f949cb75SHu Haowen
218f949cb75SHu Haowen  - 僅在 __kuser_helper_version >= 3 時,此輔助代碼存在
219f949cb75SHu Haowen    (從內核版本 2.6.15 開始)。
220f949cb75SHu Haowen
221f949cb75SHu Haowenkuser_cmpxchg64
222f949cb75SHu Haowen---------------
223f949cb75SHu Haowen
224f949cb75SHu Haowen位置:	0xffff0f60
225f949cb75SHu Haowen
226f949cb75SHu Haowen參考原型:
227f949cb75SHu Haowen
228f949cb75SHu Haowen  int __kuser_cmpxchg64(const int64_t *oldval,
229f949cb75SHu Haowen                        const int64_t *newval,
230f949cb75SHu Haowen                        volatile int64_t *ptr);
231f949cb75SHu Haowen
232f949cb75SHu Haowen輸入:
233f949cb75SHu Haowen
234f949cb75SHu Haowen  r0 = 指向 oldval
235f949cb75SHu Haowen  r1 = 指向 newval
236f949cb75SHu Haowen  r2 = 指向目標值
237f949cb75SHu Haowen  lr = 返回地址
238f949cb75SHu Haowen
239f949cb75SHu Haowen輸出:
240f949cb75SHu Haowen
241f949cb75SHu Haowen  r0 = 成功代碼 (零或非零)
242f949cb75SHu Haowen  C flag = 如果 r0 == 0 則置 1,如果 r0 != 0 則清零。
243f949cb75SHu Haowen
244f949cb75SHu Haowen被篡改的寄存器:
245f949cb75SHu Haowen
246f949cb75SHu Haowen  r3, lr, flags
247f949cb75SHu Haowen
248f949cb75SHu Haowen定義:
249f949cb75SHu Haowen
250f949cb75SHu Haowen  僅在 *ptr 等於 *oldval 指向的 64 位值時,原子保存 *newval
251f949cb75SHu Haowen  指向的 64 位值於 *ptr 中。如果 *ptr 被改變,則返回值爲零,
252f949cb75SHu Haowen  否則爲非零值。
253f949cb75SHu Haowen
254f949cb75SHu Haowen  如果 *ptr 被改變,則 C flag 也會被置 1,以實現調用代碼中的彙編
255f949cb75SHu Haowen  優化。
256f949cb75SHu Haowen
257f949cb75SHu Haowen使用範例:
258f949cb75SHu Haowen
259f949cb75SHu Haowentypedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
260f949cb75SHu Haowen                                  const int64_t *newval,
261f949cb75SHu Haowen                                  volatile int64_t *ptr);
262f949cb75SHu Haowen#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
263f949cb75SHu Haowen
264f949cb75SHu Haowenint64_t atomic_add64(volatile int64_t *ptr, int64_t val)
265f949cb75SHu Haowen{
266f949cb75SHu Haowen	int64_t old, new;
267f949cb75SHu Haowen
268f949cb75SHu Haowen	do {
269f949cb75SHu Haowen		old = *ptr;
270f949cb75SHu Haowen		new = old + val;
271f949cb75SHu Haowen	} while(__kuser_cmpxchg64(&old, &new, ptr));
272f949cb75SHu Haowen
273f949cb75SHu Haowen	return new;
274f949cb75SHu Haowen}
275f949cb75SHu Haowen
276f949cb75SHu Haowen注意:
277f949cb75SHu Haowen
278f949cb75SHu Haowen  - 這個例程已根據需要包含了內存屏障。
279f949cb75SHu Haowen
280f949cb75SHu Haowen  - 由於這個過程的代碼長度(此輔助代碼跨越 2 個常規的 kuser “槽”),
281f949cb75SHu Haowen    因此 0xffff0f80 不被作爲有效的入口點。
282f949cb75SHu Haowen
283f949cb75SHu Haowen  - 僅在 __kuser_helper_version >= 5 時,此輔助代碼存在
284f949cb75SHu Haowen    (從內核版本 3.1 開始)。
285f949cb75SHu Haowen
286