1. 程式人生 > >linux iotable_init 靜態對映與核心頁表的建立

linux iotable_init 靜態對映與核心頁表的建立

arm32 linux3.18 mach-vexpress

常用的ioremap或者of_iomap都是動態對映,靜態對映的介面是iotable_init

void __init iotable_init(struct map_desc *io_desc, int nr)
struct map_desc {
	unsigned long virtual;
	unsigned long pfn;
	unsigned long length;
	unsigned int type;
};

如map_desc所示通過例項化這個結構體我們可以建立對某個實體地址的固定的虛擬地址對映

iotable_init 一般是在machine desc 的map_io的call函式裡具體的call stack如下

start_kernel-->setup_arch-->paging_init-->devicemaps_init-->mdesc->map_io()

iotable_init會呼叫函式create_mapping來建立核心頁表和對映關係,不只是iotable_init 包括核心頁表的建立都是通過該函式

盜一張3+1的32bit linux 的memeory layout 對比kernel啟動過程中的LOG幫助後面理解

/*
 * Create the page directory entries and any necessary
 * page tables for the mapping specified by `md'.  We
 * are able to cope here with varying sizes and address
 * offsets, and we take full advantage of sections and
 * supersections.
 */
static void __init create_mapping(struct map_desc *md)
{
	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
		pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
		return;
	}
//vectors_base是中斷向量表的位置0xffff0000  TASK_SIZE是userspace的空間大小為0x7f000000 
//iotable_init 是從vmalloc區域拿地址空間,或者說low memory區,所以先判斷所申請的虛擬地址是否在此範圍內
	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
	}
//PAGE_OFFSET是kernel space虛擬地址的起始0x80000000 是2+2的memory分佈,跟TASK_SIZE gap 了16M
//FIXADDR_START 是kernel space的永久對映區 0xffc00000
//vmalloc_start 0xa0800000 vmaloc_end 0xff000000 大概1.5G 
//vmalloc區域大小也會有boot cmdline vmalloc=  決定
	
	type = &mem_types[md->type];

	addr = md->virtual & PAGE_MASK;
//分配的地址以page為offset
	phys = __pfn_to_phys(md->pfn);
//從頁框號獲得要對映的實體地址
	length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
//分配的size也是以page為offset
	if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
		printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not "
		       "be mapped using pages, ignoring.\n",
		       (long long)__pfn_to_phys(md->pfn), addr);
		return;
	}

	pgd = pgd_offset_k(addr);
//根據虛擬地址去查詢kernel頁表swapper_pg_dir找到對應的pgd(虛擬地址在text段的前0x4000,16k)
	end = addr + length;
	do {
		unsigned long next = pgd_addr_end(addr, end);

		alloc_init_pud(pgd, addr, next, phys, type);

		phys += next - addr;
		addr = next;
	} while (pgd++, addr != end);
}

/* to find an entry in a kernel page-table-directory */
#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
/* to find an entry in a page-table-directory */
#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)

相關推薦

linux iotable_init 靜態對映核心建立

arm32 linux3.18 mach-vexpress 常用的ioremap或者of_iomap都是動態對映,靜態對映的介面是iotable_init void __init iotable_init(struct map_desc *io_desc, int nr) struct

linux iotable_init 靜態對映核心建立

arm32 linux3.18 mach-vexpress 常用的ioremap或者of_iomap都是動態對映,靜態對映的介面是iotable_init void __init iotable_init(struct map_desc *io_desc, int nr)

程序核心的初始化

摘要:linux剛剛加電啟動時,如何從真實模式進入保護模式?啟動分頁機制的前提是什麼?如何保證分頁機制之前和之後通過實地址和虛擬地址都能訪問到同一個實體地址呢?核心頁表是如何進行初始化的?使用者程序不能訪問核心的資料是在初始化的哪個階段決定的?這些內容,都牽扯到linu的程

深入淺出記憶體管理-Linux核心

核心頁表實現 新版本的Linux核心程式碼中支援4級對映,那麼一個虛擬地址是包含有如下幾個部分: PGD:Page Global Directory,L0級別頁表 PUD:Page Upper Directory,L1級別頁表 PMD : Page Middle Direc

Linux靜態動態庫

Linux 靜態庫 動態庫 靜態庫 先說說我們為什麽需要庫?當有些代碼我們大量會在程序中使用比如(scanf,printf等)這些函數我們需要在程序中頻繁使用,於是我們就把這些代碼編譯為庫文件,在需要使用時我們直接鏈接即可。 定義: ?程序在編譯時把靜態庫的代碼鏈接到可執行程序中,在代碼運行時不再

Linux靜態動態庫(.a、.so)

ref:http://niefei.blog.ccidnet.com/blog/ccid/do_showone/tid_42855.html 1. 介紹   使用GNU的工具我們如何在Linux下建立自己的程式函式庫?一個“程式函式庫”簡單的說就是一個檔案包含了一些編譯好的程式碼和資料,這些編譯好的程式碼和資

linux根檔案系統核心合二為一

《ARM Linux開發-warewin 2G/3G無線傳輸(DTU)和路由器—筆記》 硬體平臺 :AT91SAM9260 核心版本:Linux-2.6.36 核心檔案和根檔案系統在Flash中一起壓縮放置可節省大量的Flash儲存空間,也便於韌體的存檔和升級,把根檔案系

arm linux 建立

本文對arm linux頁表建立函式進行說明。在http://blog.csdn.net/flaoter/article/details/73381695中對MMU使能之前的臨時頁表進行了說明,此文是對kernel中正式頁表建立過程進行說明。文中使用的kerne

arm-linux記憶體建立

linux的記憶體(正式)頁表是在核心程式碼執行到start_kernel函式後執行paging _init函式建立的,這裡要注意一個事情就是說,這裡paging_init函式可以正常建立記憶體頁表的條件有兩個: 1、              meminfo已

核心和程序

初學核心時,經常被“核心頁表”和“程序頁表”搞暈,不知道這到底是個啥東東,跟我們平時理解的頁表有和關係。。 核心頁表:即書上說的主核心頁表,在核心中其實就是一段記憶體,存放在主核心頁全域性目錄init_mm.pgd(swapper_pg_dir)中,硬體並不直接使用。 程序

Linux檔案系統---使用者核心的互動介面

從磁碟到資料,從資料到檔案,從檔案到目錄,從目錄到檔案系統,從檔案系統到作業系統。構成了計算機中的IO讀寫機制。 整個磁碟可以分為1個MBR(Master Boot Record)和4個partitions。一個分割槽,其實就是一個檔案系統,檔案系統就是

[kernel 啟動流程] (第五章)第一階段之——臨時核心建立

本文是基於arm平臺。例子都是以tiny210(s5pv210 armv7)為基礎的。 [kernel 啟動流程]系列: 建議參考文件: ================================================ 零、說明

Linux靜態庫、動態庫的建立和使用

Linux下靜態庫、動態庫的建立和使用 Linux庫檔名由:字首lib、庫名和字尾3部分組成,靜態庫通常以.a作為字尾,動態庫以.so作為字尾, Linux下把動態庫叫做共享庫,so即shared object的縮寫。 靜態庫是程式編譯連結時使用,動態庫是程式執行時使用。

C++靜態動態庫、建立及呼叫方法

1 什麼是庫 庫是寫好的現有的,成熟的,可以複用的程式碼。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的程式碼都從零開始,因此庫的存在意義非同尋常。本質上來說庫是一種可執行程式碼的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態

Linux核心追蹤[4.14] X86的5級管理

        X86的4級頁表已經能夠管理48bit(256TB)的VA,以及64TB的PA。不過由於某些供應商釋出了超過64T的超大實體記憶體,因此需要實現了一個5級頁表特性來進行支援。       &

Linux核心4級的演進

Linux記憶體管理中core VM程式碼中,關於頁表(page tables)管理的程式碼是個重點,是虛擬記憶體(Virtual Memory, VM)的基石,本文探討Linux的頁表實現及發展過程。 頁表概覽 在虛擬記憶體中,頁表是個對映表的概念, 即從程序能理解的

Linux使用者空間核心空間記憶體對映

Linux 作業系統和驅動程式執行在核心空間,應用程式執行在使用者空間,兩者不能簡單地使用指標傳遞資料,因為Linux使用的虛擬記憶體機制,使用者空間的資料可能被換出,當核心空間使用使用者空間指標時,對應的資料可能不在記憶體中。 Linux核心地址對映模型 x86 C

例說linux核心應用資料通訊(四):對映裝置核心空間到使用者態

#include <linux/module.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/mm.h> #incl

Linux啟動時的對映

核心啟動時進行記憶體對映, map_mem()->create_mapping() 核心支援4級對映(PGD->PUD->PMD->PTE) ,支援的level由巨集CONFIG_PGTABLE_LEVELS定義,目前為3級對映,也即PGD->

arm的2級Linux核心建立過程解析

系統DDR的基地址為0x0,記憶體為1GB,所以TTB的基地址為0x4000。下面要建立虛擬地址0xfe700000到實體地址0xffff0000之間的對映,對映大小為64KB,即16頁。由於實體地址不是1MB位元組對齊,所以必須建立兩級對映。   使用者空間/核心空間