Linux内存 -- 内核空间物理与虚拟地址转换

目录

        内核空间物理与虚拟地址转换逻辑

        内核段物理地址与虚拟地址的转换函数


        内核启动过程中完成临时的内核空间页表创建后,就可以实现内核空间物理地址与对应虚拟地址间的相互转化,该转化过程可以通过__phys_to_kimg 、__kimg_to_phys实现。

        内核空间物理与虚拟地址转换逻辑

        从页表创建过程看,一段连续物理内存空间连续映射到虚拟空间时,其对应的虚拟空间、页表均是连续空间。如下图A  Phy Region物理空间映射连续映射到虚拟空间A Virtual Region,A Region 在虚拟空间中保持了在物理空间时的地址顺序性,唯独虚拟空间与物理空间对应的地址不同;故A Region中的内容的物理地址和虚拟地址差值固定,且等于 A va_addr start -  A phy_add start 。

        连续物理内存空间连续映射到虚拟空间时,连续物理内存地址与其对应虚拟内存地址差值固定。这是物理地址和虚拟地址相互转换的逻辑基础。

        内核段物理地址与虚拟地址的转换函数

 #define __phys_to_kimg(x)    ((unsigned long)((x) + kimage_voffset))

        __phys_to_kimg 实现内核段物理地址转为虚拟地址,从函数实现看内核物理地址与虚拟地址的差值为kimage_voffset。

        kimage_voffset赋值过程,需要看如下几段代码:

        代码段1,取__PHYS_OFFSET的物理页地址(内核在内存中的起始页地址)赋给x0寄存器,然后跳转执行__primary_switched函数。

        代码段2,定义 kimage_vaddr = _text - TEXT_OFFSET,kimage_vaddr为内核在虚拟空间中的起始地址

        代码段3, (取自__primary_switched函数中的一段)将内核在虚拟空间的起始地址与物理空间的起始地址做差值后赋给kimage_voffset;即 内核空间虚拟地址 =  kimage_voffset  + 内核空间物理地址。

代码段1

    ldr	x8, =__primary_switched
	
	/* 获取内核在内存中的起始物理地址*/
	adrp	x0, __PHYS_OFFSET

    /* 跳转到__primary_switched函数执行*/  
	br	x8



代码段2

ENTRY(kimage_vaddr)
	.quad		_text - TEXT_OFFSET



代码段3

__primary_switched:
	...

    /* Save the offset between, 
     * kimage_vaddr = _text - TEXT_OFFSET = __PHYS_OFFSET
	 * 加载内核起始虚拟地址到X4
	 */
	ldr_l	x4, kimage_vaddr

	/*
	 * X4 内核在虚拟内存中起始地址
	 * X0 内核在物理内存中起始地址
	 */
	sub	x4, x4, x0			

	/* 
	 * 将X4 内核虚拟地址与物理的地址的差值赋给kimage_voffset
	 * 故内核空间 虚拟地址 = 物理地址 + kimage_voffset
	 */
	str_l	x4, kimage_voffset, x5		// physical mappings
    
    ...
#define __kimg_to_phys(addr)	((addr) - kimage_voffset)

        __kimg_to_phys 与__phys_to_kimg相反,__kimg_to_phys实现的内核空间虚拟地址到物理地址的转化。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值