Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,176 @@
Chinese translated version of Documentation/arch/arm/booting.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help. Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.
Maintainer: Russell King <linux@arm.linux.org.uk>
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
---------------------------------------------------------------------
Documentation/arch/arm/booting.rst 的中文翻譯
如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
譯存在問題,請聯繫中文版維護者。
英文版維護者: Russell King <linux@arm.linux.org.uk>
中文版維護者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
中文版翻譯者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
中文版校譯者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
以下爲正文
---------------------------------------------------------------------
啓動 ARM Linux
==============
作者:Russell King
日期:2002年5月18日
以下文檔適用於 2.4.18-rmk6 及以上版本。
爲了啓動 ARM Linux,你需要一個引導裝載程序(boot loader),
它是一個在主內核啓動前運行的一個小程序。引導裝載程序需要初始化各種
設備,並最終調用 Linux 內核,將信息傳遞給內核。
從本質上講,引導裝載程序應提供(至少)以下功能:
1、設置和初始化 RAM。
2、初始化一個串口。
3、檢測機器的類型(machine type)。
4、設置內核標籤列表(tagged list)。
5、調用內核映像。
1、設置和初始化 RAM
-------------------
現有的引導加載程序: 強制
新開發的引導加載程序: 強制
引導裝載程序應該找到並初始化系統中所有內核用於保持系統變量數據的 RAM。
這個操作的執行是設備依賴的。(它可能使用內部算法來自動定位和計算所有
RAM,或可能使用對這個設備已知的 RAM 信息,還可能使用任何引導裝載程序
設計者想到的匹配方法。)
2、初始化一個串口
-----------------------------
現有的引導加載程序: 可選、建議
新開發的引導加載程序: 可選、建議
引導加載程序應該初始化並使能一個目標板上的串口。這允許內核串口驅動
自動檢測哪個串口用於內核控制檯。(一般用於調試或與目標板通信。)
作爲替代方案,引導加載程序也可以通過標籤列表傳遞相關的'console='
選項給內核以指定某個串口,而串口數據格式的選項在以下文檔中描述:
Documentation/admin-guide/kernel-parameters.rst。
3、檢測機器類型
--------------------------
現有的引導加載程序: 可選
新開發的引導加載程序: 強制
引導加載程序應該通過某些方式檢測自身所處的機器類型。這是一個硬件
代碼或通過查看所連接的硬件用某些算法得到,這些超出了本文檔的範圍。
引導加載程序最終必須能提供一個 MACH_TYPE_xxx 值給內核。
(詳見 linux/arch/arm/tools/mach-types )。
4、設置啓動數據
------------------
現有的引導加載程序: 可選、強烈建議
新開發的引導加載程序: 強制
引導加載程序必須提供標籤列表或者 dtb 映像以傳遞配置數據給內核。啓動
數據的物理地址通過寄存器 r2 傳遞給內核。
4a、設置內核標籤列表
--------------------------------
bootloader 必須創建和初始化內核標籤列表。一個有效的標籤列表以
ATAG_CORE 標籤開始,並以 ATAG_NONE 標籤結束。ATAG_CORE 標籤可以是
空的,也可以是非空。一個空 ATAG_CORE 標籤其 size 域設置爲
‘2’(0x00000002)。ATAG_NONE 標籤的 size 域必須設置爲零。
在列表中可以保存任意數量的標籤。對於一個重複的標籤是追加到之前標籤
所攜帶的信息之後,還是會覆蓋原來的信息,是未定義的。某些標籤的行爲
是前者,其他是後者。
bootloader 必須傳遞一個系統內存的位置和最小值,以及根文件系統位置。
因此,最小的標籤列表如下所示:
+-----------+
基地址 -> | ATAG_CORE | |
+-----------+ |
| ATAG_MEM | | 地址增長方向
+-----------+ |
| ATAG_NONE | |
+-----------+ v
標籤列表應該保存在系統的 RAM 中。
標籤列表必須置於內核自解壓和 initrd'bootp' 程序都不會覆蓋的內存區。
建議放在 RAM 的頭 16KiB 中。
4b、設置設備樹
-------------------------
bootloader 必須以 64bit 地址對齊的形式加載一個設備樹映像(dtb)到系統
RAM 中,並用啓動數據初始化它。dtb 格式在文檔
https://www.devicetree.org/specifications/ 中。內核將會在
dtb 物理地址處查找 dtb 魔數值(0xd00dfeed),以確定 dtb 是否已經代替
標籤列表被傳遞進來。
bootloader 必須傳遞一個系統內存的位置和最小值,以及根文件系統位置。
dtb 必須置於內核自解壓不會覆蓋的內存區。建議將其放置於 RAM 的頭 16KiB
中。但是不可將其放置於“0”物理地址處,因爲內核認爲:r2 中爲 0,意味着
沒有標籤列表和 dtb 傳遞過來。
5、調用內核映像
---------------------------
現有的引導加載程序: 強制
新開發的引導加載程序: 強制
調用內核映像 zImage 有兩個選擇。如果 zImge 保存在 flash 中,且是爲了
在 flash 中直接運行而被正確鏈接的。這樣引導加載程序就可以在 flash 中
直接調用 zImage。
zImage 也可以被放在系統 RAM(任意位置)中被調用。注意:內核使用映像
基地址的前 16KB RAM 空間來保存頁表。建議將映像置於 RAM 的 32KB 處。
對於以上任意一種情況,都必須符合以下啓動狀態:
- 停止所有 DMA 設備,這樣內存數據就不會因爲虛假網絡包或磁盤數據而被破壞。
這可能可以節省你許多的調試時間。
- CPU 寄存器配置
r0 = 0,
r1 = (在上面 3 中獲取的)機器類型碼。
r2 = 標籤列表在系統 RAM 中的物理地址,或
設備樹塊(dtb)在系統 RAM 中的物理地址
- CPU 模式
所有形式的中斷必須被禁止 (IRQs 和 FIQs)
CPU 必須處於 SVC 模式。(對於 Angel 調試有特例存在)
- 緩存,MMUs
MMU 必須關閉。
指令緩存開啓或關閉都可以。
數據緩存必須關閉。
- 引導加載程序應該通過直接跳轉到內核映像的第一條指令來調用內核映像。
對於支持 ARM 指令集的 CPU,跳入內核入口時必須處在 ARM 狀態,即使
對於 Thumb-2 內核也是如此。
對於僅支持 Thumb 指令集的 CPU,比如 Cortex-M 系列的 CPU,跳入
內核入口時必須處於 Thumb 狀態。
@@ -0,0 +1,285 @@
Chinese translated version of Documentation/arch/arm/kernel_user_helpers.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help. Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.
Maintainer: Nicolas Pitre <nicolas.pitre@linaro.org>
Dave Martin <dave.martin@linaro.org>
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
---------------------------------------------------------------------
Documentation/arch/arm/kernel_user_helpers.rst 的中文翻譯
如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
譯存在問題,請聯繫中文版維護者。
英文版維護者: Nicolas Pitre <nicolas.pitre@linaro.org>
Dave Martin <dave.martin@linaro.org>
中文版維護者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
中文版翻譯者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
中文版校譯者: 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
傅煒 Fu Wei <tekkamanninja@gmail.com>
以下爲正文
---------------------------------------------------------------------
內核提供的用戶空間輔助代碼
=========================
在內核內存空間的固定地址處,有一個由內核提供並可從用戶空間訪問的代碼
段。它用於向用戶空間提供因在許多 ARM CPU 中未實現的特性和/或指令而需
內核提供幫助的某些操作。這些代碼直接在用戶模式下執行的想法是爲了獲得
最佳效率,但那些與內核計數器聯繫過於緊密的部分,則被留給了用戶庫實現。
事實上,此代碼甚至可能因不同的 CPU 而異,這取決於其可用的指令集或它
是否爲 SMP 系統。換句話說,內核保留在不作出警告的情況下根據需要更改
這些代碼的權利。只有本文檔描述的入口及其結果是保證穩定的。
這與完全成熟的 VDSO 實現不同(但兩者並不衝突),儘管如此,VDSO 可阻止
某些通過常量高效跳轉到那些代碼段的彙編技巧。且由於那些代碼段在返回用戶
代碼前僅使用少量的代碼週期,則一個 VDSO 間接遠程調用將會在這些簡單的
操作上增加一個可測量的開銷。
在對那些擁有原生支持的新型處理器進行代碼優化時,僅在已爲其他操作使用
了類似的新增指令,而導致二進制結果已與早期 ARM 處理器不兼容的情況下,
用戶空間才應繞過這些輔助代碼,並在內聯函數中實現這些操作(無論是通過
編譯器在代碼中直接放置,還是作爲庫函數調用實現的一部分)。也就是說,
如果你編譯的代碼不會爲了其他目的使用新指令,則不要僅爲了避免使用這些
內核輔助代碼,導致二進制程序無法在早期處理器上運行。
新的輔助代碼可能隨着時間的推移而增加,所以新內核中的某些輔助代碼在舊
內核中可能不存在。因此,程序必須在對任何輔助代碼調用假設是安全之前,
檢測 __kuser_helper_version 的值(見下文)。理想情況下,這種檢測應該
只在進程啓動時執行一次;如果內核版本不支持所需輔助代碼,則該進程可儘早
中止執行。
kuser_helper_version
--------------------
位置: 0xffff0ffc
參考聲明:
extern int32_t __kuser_helper_version;
定義:
這個區域包含了當前運行內核實現的輔助代碼版本號。用戶空間可以通過讀
取此版本號以確定特定的輔助代碼是否存在。
使用範例:
#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
void check_kuser_version(void)
{
if (__kuser_helper_version < 2) {
fprintf(stderr, "can't do atomic operations, kernel too old\n");
abort();
}
}
注意:
用戶空間可以假設這個域的值不會在任何單個進程的生存期內改變。也就
是說,這個域可以僅在庫的初始化階段或進程啓動階段讀取一次。
kuser_get_tls
-------------
位置: 0xffff0fe0
參考原型:
void * __kuser_get_tls(void);
輸入:
lr = 返回地址
輸出:
r0 = TLS 值
被篡改的寄存器:
無
定義:
獲取之前通過 __ARM_NR_set_tls 系統調用設置的 TLS 值。
使用範例:
typedef void * (__kuser_get_tls_t)(void);
#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
void foo()
{
void *tls = __kuser_get_tls();
printf("TLS = %p\n", tls);
}
注意:
- 僅在 __kuser_helper_version >= 1 時,此輔助代碼存在
(從內核版本 2.6.12 開始)。
kuser_cmpxchg
-------------
位置: 0xffff0fc0
參考原型:
int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
輸入:
r0 = oldval
r1 = newval
r2 = ptr
lr = 返回地址
輸出:
r0 = 成功代碼 (零或非零)
C flag = 如果 r0 == 0 則置 1,如果 r0 != 0 則清零。
被篡改的寄存器:
r3, ip, flags
定義:
僅在 *ptr 爲 oldval 時原子保存 newval 於 *ptr 中。
如果 *ptr 被改變,則返回值爲零,否則爲非零值。
如果 *ptr 被改變,則 C flag 也會被置 1,以實現調用代碼中的彙編
優化。
使用範例:
typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
int atomic_add(volatile int *ptr, int val)
{
int old, new;
do {
old = *ptr;
new = old + val;
} while(__kuser_cmpxchg(old, new, ptr));
return new;
}
注意:
- 這個例程已根據需要包含了內存屏障。
- 僅在 __kuser_helper_version >= 2 時,此輔助代碼存在
(從內核版本 2.6.12 開始)。
kuser_memory_barrier
--------------------
位置: 0xffff0fa0
參考原型:
void __kuser_memory_barrier(void);
輸入:
lr = 返回地址
輸出:
無
被篡改的寄存器:
無
定義:
應用於任何需要內存屏障以防止手動數據修改帶來的一致性問題,以及
__kuser_cmpxchg 中。
使用範例:
typedef void (__kuser_dmb_t)(void);
#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
注意:
- 僅在 __kuser_helper_version >= 3 時,此輔助代碼存在
(從內核版本 2.6.15 開始)。
kuser_cmpxchg64
---------------
位置: 0xffff0f60
參考原型:
int __kuser_cmpxchg64(const int64_t *oldval,
const int64_t *newval,
volatile int64_t *ptr);
輸入:
r0 = 指向 oldval
r1 = 指向 newval
r2 = 指向目標值
lr = 返回地址
輸出:
r0 = 成功代碼 (零或非零)
C flag = 如果 r0 == 0 則置 1,如果 r0 != 0 則清零。
被篡改的寄存器:
r3, lr, flags
定義:
僅在 *ptr 等於 *oldval 指向的 64 位值時,原子保存 *newval
指向的 64 位值於 *ptr 中。如果 *ptr 被改變,則返回值爲零,
否則爲非零值。
如果 *ptr 被改變,則 C flag 也會被置 1,以實現調用代碼中的彙編
優化。
使用範例:
typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
const int64_t *newval,
volatile int64_t *ptr);
#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
{
int64_t old, new;
do {
old = *ptr;
new = old + val;
} while(__kuser_cmpxchg64(&old, &new, ptr));
return new;
}
注意:
- 這個例程已根據需要包含了內存屏障。
- 由於這個過程的代碼長度(此輔助代碼跨越 2 個常規的 kuser “槽”),
因此 0xffff0f80 不被作爲有效的入口點。
- 僅在 __kuser_helper_version >= 5 時,此輔助代碼存在
(從內核版本 3.1 開始)。