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 Haowen 無 108f949cb75SHu 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 Haowen 無 201f949cb75SHu Haowen 202f949cb75SHu Haowen被篡改的寄存器: 203f949cb75SHu Haowen 204f949cb75SHu Haowen 無 205f949cb75SHu 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