【記憶體】高階記憶體對映
阿新 • • 發佈:2018-12-16
高階記憶體含義為:線性地址空間 PAGE_OFFSET + 896M至4G的最後128M線性地址 <==對映==> 896M以上的物理頁框,非直接對映。有3種方法:非連續記憶體區對映,永久核心對映,臨時核心對映(固定對映)
從 PAGE_OFFSET開始的線性地址區域為:
PAGE_OFFSET(3G)|實體記憶體對映 --8M-- vmallot區 --4K-- vmallot區 --8K-- 永久核心對映--臨時核心對映(固定對映)|4G
1. 非連續區對映
1.1 每個非連續記憶體區都對應一個型別為 vm_struct的描述符,通過next欄位,這些描述符被插入到一個vmlist連結串列中。
1.2 三種非連續區的型別:
VM_ALLOC -- 實體記憶體(呼叫alloc_page)和線性地址同時申請,實體記憶體是 __GFP_HIGHMEM型別(分配順序是HIGH, NORMAL, DMA )
VM_MAP -- 僅申請線性區,實體記憶體另外申請,是VM_ALLOC的簡化版
VM_IOREMAP -- 僅申請線性區,實體記憶體另外申請(這裡的實體記憶體一般都是高階記憶體,大於896M的記憶體)
2. 永久核心對映
2.1 永久記憶體對映允許建立長期對映。使用主核心頁表中swapper_pg_dir的一個專門頁表。
pkmap_page_table: 專門的頁表。頁表表項數由LAST_PKMAP(512或1024)產生。
page_address_htable: 存放地址的
pkmap_count: 包含LAST_PKMAP個計數器的陣列。
PKMAP_BASE: 頁表線性地址從PKMAP_BASE開始。
2.2 如果LAST_PKMAP個項都用完,則把當前程序置為 TASK_UNINTERRUPTIBLE,並呼叫schedule()
3. 臨時記憶體對映
3.1 可以用在中斷處理函式和可延遲函式的內部,從不阻塞。因為臨時記憶體對映是固定記憶體對映的一部分,一個地址固定給一個核心成分使用。
3.2 每個CPU都有自己的一個13個視窗(一個線性地址及頁表項)的集合。
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
KM_BIO_SRC_IRQ,
KM_BIO_DST_IRQ,
KM_PTE0,
KM_PTE1,
KM_IRQ0,
KM_IRQ1,
KM_SOFTIRQ0,
KM_SOFTIRQ1,
KM_TYPE_NR
};
所有固定對映的固定線性地址
enum fixed_addresses {
FIX_HOLE,
FIX_VSYSCALL,
....
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
#endif
.......
__end_of_permanent_fixed_addresses,
/* temporary boot-time mappings, used before ioremap() is functional */
#define NR_FIX_BTMAPS 16
FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
FIX_WP_TEST,
__end_of_fixed_addresses
};
3.3 注意 fixed_addresses 的地址從上至下是倒著的,FIX_HOLE的地址等於 0xfffff000,是一個洞
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __FIXADDR_TOP 0xfffff000
從 PAGE_OFFSET開始的線性地址區域為:
PAGE_OFFSET(3G)|實體記憶體對映 --8M-- vmallot區 --4K-- vmallot區 --8K-- 永久核心對映--臨時核心對映(固定對映)|4G
1. 非連續區對映
1.1 每個非連續記憶體區都對應一個型別為 vm_struct的描述符,通過next欄位,這些描述符被插入到一個vmlist連結串列中。
1.2 三種非連續區的型別:
VM_ALLOC -- 實體記憶體(呼叫alloc_page)和線性地址同時申請,實體記憶體是 __GFP_HIGHMEM型別(分配順序是HIGH, NORMAL, DMA )
VM_MAP -- 僅申請線性區,實體記憶體另外申請,是VM_ALLOC的簡化版
VM_IOREMAP -- 僅申請線性區,實體記憶體另外申請(這裡的實體記憶體一般都是高階記憶體,大於896M的記憶體)
2. 永久核心對映
2.1 永久記憶體對映允許建立長期對映。使用主核心頁表中swapper_pg_dir的一個專門頁表。
pkmap_page_table: 專門的頁表。頁表表項數由LAST_PKMAP(512或1024)產生。
page_address_htable: 存放地址的
pkmap_count: 包含LAST_PKMAP個計數器的陣列。
PKMAP_BASE: 頁表線性地址從PKMAP_BASE開始。
2.2 如果LAST_PKMAP個項都用完,則把當前程序置為 TASK_UNINTERRUPTIBLE,並呼叫schedule()
3. 臨時記憶體對映
3.1 可以用在中斷處理函式和可延遲函式的內部,從不阻塞。因為臨時記憶體對映是固定記憶體對映的一部分,一個地址固定給一個核心成分使用。
3.2 每個CPU都有自己的一個13個視窗(一個線性地址及頁表項)的集合。
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
KM_BIO_SRC_IRQ,
KM_BIO_DST_IRQ,
KM_PTE0,
KM_PTE1,
KM_IRQ0,
KM_IRQ1,
KM_SOFTIRQ0,
KM_SOFTIRQ1,
KM_TYPE_NR
};
所有固定對映的固定線性地址
enum fixed_addresses {
FIX_HOLE,
FIX_VSYSCALL,
....
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
#endif
.......
__end_of_permanent_fixed_addresses,
/* temporary boot-time mappings, used before ioremap() is functional */
#define NR_FIX_BTMAPS 16
FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
FIX_WP_TEST,
__end_of_fixed_addresses
};
3.3 注意 fixed_addresses 的地址從上至下是倒著的,FIX_HOLE的地址等於 0xfffff000,是一個洞
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __FIXADDR_TOP 0xfffff000