以前关于虚拟地址和物理地址的学习只是在书本上,今天在实际的开发板上实践了一下
代码:
#include
#include
#include
#include
int g=0x100;
static int __init tarzan_init(void)
{
int idx;
pr_info(“tarzan_init\n”);
int x=0x10;
int pint = NULL;
printk(“PHYS_OFFSET=0x%lx\r\n” , PHYS_OFFSET);
printk(“max_mapnr:%d\r\n” , max_mapnr);
printk(“high memory:0x%lx\r\n” , high_memory); //0xF000_0000 0xF000_0000- 0xC000_0000=0x3000_0000=768M
printk(“high memory(768M) -> phy addr:0x%lx\r\n” , __pa(high_memory));
pint = kmalloc(1024sizeof(int),GFP_KERNEL);
if(!pint)
{
return -1;
}
else
{
printk(“virtual addr is :0x%lx , phy addr:0x%x\r\n” , pint , __pa(pint));
}
pr_info(“g -> VA=%lx , PA=%lx\r\n” , &g , __pa(&g));
pr_info(“x -> VA=%lx , PA=%lx\r\n” , &x , __pa(&x));
pr_info(“PAGE_OFFSET => %lx” , PAGE_OFFSET);
return 0;
}
static void __exit tarzan_exit(void)
{
pr_info(“tarzan_exit\n”);
}
module_init(tarzan_init);
module_exit(tarzan_exit);
MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“ZTE-liukai”);
Makefile:
ifneq ($(KERNELRELEASE),)
obj-m := tarzan.o
else
KDIR := /home/zte/work/hisi/hi3519/Hi3519AV100R001C02SPC020_NEW/Hi3519AV100R001C02SPC020/Hi3519AV100R001C02SPC020/01.software/board/Hi3519AV100_SDK_V2.0.2.0/osdrv/opensource/kernel/linux-4.9.y
all:
make -C
(
K
D
I
R
)
M
=
(KDIR) M=
(KDIR)M=(PWD) modules ARCH=arm CROSS_COMPILE=arm-himix200-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c .symvers modul
endif

从这张图里可以看出DDR给到Linux OS的地址是从0x2200_0000偏移开始的。
tarzan_init
PHYS_OFFSET=0x80000000
max_mapnr:131072
high memory:0xe0000000
high memory(768M) -> phy addr:0xa0000000
virtual addr is :0xde7de000 , phy addr:0x9e7de000g -> VA=bf55221c , PA=7f55221c
x -> VA=de711dc0 , PA=9e711dc0
PAGE_OFFSET => c0000000
Phy addr of 0xc0000000 is -> 0x80000000
Phy addr of 0xc0000001 is -> 0x80000001
Phy addr of 0xc0000002 is -> 0x80000002
Phy addr of 0xc0000003 is -> 0x80000003
Phy addr of 0xc0000004 is -> 0x80000004
Phy addr of 0xc0000005 is -> 0x80000005
Phy addr of 0xc0000006 is -> 0x80000006
Phy addr of 0xc0000007 is -> 0x80000007
Phy addr of 0xc0000008 is -> 0x80000008
Phy addr of 0xc0000009 is -> 0x80000009
Vir addr 0f 0x0 is -> 0x40000000
Vir addr 0f 0x1 is -> 0x40000001
Vir addr 0f 0x2 is -> 0x40000002
Vir addr 0f 0x3 is -> 0x40000003
Vir addr 0f 0x4 is -> 0x40000004
Vir addr 0f 0x5 is -> 0x40000005
Vir addr 0f 0x6 is -> 0x40000006
Vir addr 0f 0x7 is -> 0x40000007
Vir addr 0f 0x8 is -> 0x40000008
Vir addr 0f 0x9 is -> 0x40000009
/-----------------------------------------------/
~ #
~ #

可见,Hi3516DV300的 DDR起始地址为0x8000_0000
3.3 飞思卡尔i.max6平台
/mnt # insmod tarzan.ko
tarzan_init
PHYS_OFFSET=0x80000000
max_mapnr:131072
high memory:0xa0000000
high memory(768M) -> phy addr:0xa0000000
virtual addr is :0x88429000 , phy addr:0x88429000
g -> VA=7f00021c , PA=7f00021c
x -> VA=887fbdf0 , PA=887fbdf0
PAGE_OFFSET => 80000000
Phy addr of 0xc0000000 is -> 0xc0000000
Phy addr of 0xc0000001 is -> 0xc0000001
Phy addr of 0xc0000002 is -> 0xc0000002
Phy addr of 0xc0000003 is -> 0xc0000003
Phy addr of 0xc0000004 is -> 0xc0000004
Phy addr of 0xc0000005 is -> 0xc0000005
Phy addr of 0xc0000006 is -> 0xc0000006
Phy addr of 0xc0000007 is -> 0xc0000007
Phy addr of 0xc0000008 is -> 0xc0000008
Phy addr of 0xc0000009 is -> 0xc0000009
Vir addr 0f 0x0 is -> 0x0
Vir addr 0f 0x1 is -> 0x1
Vir addr 0f 0x2 is -> 0x2
Vir addr 0f 0x3 is -> 0x3
Vir addr 0f 0x4 is -> 0x4
Vir addr 0f 0x5 is -> 0x5
Vir addr 0f 0x6 is -> 0x6
Vir addr 0f 0x7 is -> 0x7
Vir addr 0f 0x8 is -> 0x8
Vir addr 0f 0x9 is -> 0x9

飞思卡尔的该芯片使用的是1:1 (user:kernel)模型,即用户态和内核态地址范围均为2GB。

该平台为1:1的使用模型,PAGE_OFFSET=80000000(2GB), PHYS_OFFSET=0x80000000,最后的结果为物理地址=虚拟地址
4. 结论
i.max地址映射范围可知,DDR的起始地址为0x8000_0000 , 故PHYS_OFFSET=0x80000000
这个参数Kernel是怎么知道的?答案是通过单板的DTS传给内核的,起始地址为0x8000_0000,大小为512MB

i.max6 dts 内存配置

hi3519 dts 内存配置

hi3516 dts内存配置
在低端内存的虚实地址换算的方法如下,为线性映射,两者之间差一个固定偏移,这个偏移不一定是0xC000_0000,还和DDR内存地址在系统中的起始地址有关系,具体计算方法如下:
虚拟地址=物理地址 - PHYS_OFFSET + PAGE_OFFSET
物理地址=虚拟地址 - PAGE_OFFSET + PHYS_OFFSET