线性地址转换成物理地址

本文详细解释了内核4-levelpaging模式下,如何通过CR3寄存器、页目录索引和页表查找,将线性地址0xffffffff8220a000和0xffff88800220a000转换成物理地址0x220a000的过程,并揭示了转换规则和Intel手册中的关键细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇文章介绍了如何查看内核使用的分页模式,笔者电脑上内核使用的分页模式是 4-level paging,这篇文章讲解 4-level paging分页模式如何将线性地址转换成物理地址.

先思考2个问题:

  1. 内核初始化时,线性地址0xffffffff8220a000转换成物理地址是多少?
  2. 内核初始化时,线性地址0xffff88800220a000转换成物理地址是多少?

1. 4-level paging 转换过程

先看一张intel手册上的4-level paging 4KB大小的页的转换图
在这里插入图片描述
下面介绍这张图表达的内容:

2. cr3寄存器介绍

CR3寄存器又叫页目录基址寄存器(Page Directory Base Register, PDGR), CR3中存放着当前任务页表目录的物理地址.

3. 内核中线性地址和物理地址转换宏

下面代码使用内核中定义的宏打印物理地址,代码中的宏选自linux5.4.34 arch/x86/include/asm/page.h arch/x86/include/asm/page_64.h

#include <stdio.h>

#define __AC(X,Y)	(X##Y)
#define _AC(X,Y)	__AC(X,Y)
#define __PAGE_OFFSET_BASE_L4	_AC(0xffff888000000000, UL)
#define __PAGE_OFFSET           __PAGE_OFFSET_BASE_L4
#define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
#define __START_KERNEL_map	_AC(0xffffffff80000000, UL)
// __va宏是将物理地址转换成线性地址,直接等于物理地址 + 0xffff888000000000
#define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
static inline unsigned long __phys_addr_nodebug(unsigned long x)
{
   
	unsigned long y = x - __START_KERNEL_map;

	/* use the carry flag to determine if x was < __START_KERNEL_map */
	// 笔者电脑上phys_base为0
	x = y + ((x > y) ? 0 /* phys_base */ : (__START_KERNEL_map - PAGE_OFFSET));

	return x;
}
#define __phys_addr(x)		__phys_addr_nodebug(x)
#define __phys_addr_symbol(x) \
	((unsigned long)(x) - __START_KERNEL_map + 0 /* phys_base */) // phys_base为0
#define __phys_reloc_hide(x)	(x)
// __pa宏是将线性地址转换成物理地址
#define __pa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值