当前位置:   article > 正文

arm32 linux boot 常见的宏 与 符号_arch_must_set_this

arch_must_set_this

简述

boot 地址侧
uboot 通过 tftp 下载 uImage 到 ddr 到 地址 A
uboot 根据 uImage 的要求 搬运 zImage 到 地址 B
zImage boot
zImage 根据 是否会覆盖Image 搬运 自身 到 地址 C
zImage 跳转到 地址C处的 zImage
zImage 解压 出 Image 到某地址 到 地址 D
Image boot
过程中涉及到 4个boot 地址(ABCD)

地址A : tftp 0x60003000 uImage; bootm 0x60003000 中的 0x60003000 
地址B : ZTEXTADDR // 值于 Load Address 相同  // Entry Point 一般也和 Load Address 一致
地址C : TODO
地址D : ZRELADDR

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
虚拟内存
uboot 在 加载 内核最后一步, MMU 肯定是关的 // 不太关心 uboot 过程中会不会开MMU
zImage 运行过程中 , MMU 全程关闭
Image  运行过程中 , MMU 会在 start_kernel 前 打开 
	开了 MMU 之后
		物理地址  	: 	虚拟地址
		ZRELADDR 	: 	TEXTADDR
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

实例

smdk 2410
Image启动的虚拟地址 TEXTADDR  = 0xC0008000
Image启动的物理地址 ZRELADDR  = 0x30008000
  • 1
  • 2
qemu virt arm32 板
地址
$ ls -l arch/arm/boot/Image  //25.2M
-rwxrwxr-x 1 suweishuai suweishuai 26430588 May 27 21:19 arch/arm/boot/Image
$ ls -l arch/arm/boot/zImage //9.55M
-rwxrwxr-x 1 suweishuai suweishuai 10019328 May 27 21:20 arch/arm/boot/zImage

$ ls arch/arm/boot/Image  -l      
-rwxrwxr-x 1 suweishuai suweishuai 26430588 May 27 21:19 arch/arm/boot/Image
$ file arch/arm/boot/Image
arch/arm/boot/Image: data


地址A 			: 没有研究 qemu virt arm32 的 u-boot
地址B 			: 0x40010000 // 即 ZTEXTADDR
地址C 			: 0x41B3C460
地址D 			: 0x40208000 // 即 ZRELADDR
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
PHYS_OFFSET 	: 0x40000000
  • 1
PAGE_OFFSET 	: 0xc0000000
TEXT_OFFSET		: 0x00208000
TEXTADDR		: 0xc0208000
swapper_pg_dir 	: 0xc0204000
  • 1
  • 2
  • 3
  • 4
ZBSSADDR    := ALIGN(8)
  • 1
c1b9ee68 B _end
c0208000 T _text

  • 1
  • 2
  • 3
页表
  • 页表描述
页表描述
	arm32 两级映射,对于section 映射,只有1级别
	下面所有的表项都是PGD表项(即PMD表项)
	每个表项4字节,寻址1M空间
  • 1
  • 2
  • 3
  • 4
  • for mmu_on
// mmu_on 4030 0000 - 4040 0000
// __turn_mmu_on - __turn_mmu_on_end : 0x40300000 - 0x40300020
0xc0205000: 0x00000000  0x00000000  0x00000000  0x40311c0e
  • 1
  • 2
  • 3
  • for kernel(Image临时内核页表)

// Image+Image前的地址页表 4000 0000 - 40b0 0000
0xc0207000: 0x40011c0e  0x40111c0e  0x40211c0e  0x40311c0e // 0x40011c0e  0x40111c0e Image前的地址
0xc0207010: 0x40411c0e  0x40511c0e  0x40611c0e  0x40711c0e 
0xc0207020: 0x40811c0e  0x40911c0e  0x40a11c0e  0x40b11c0e 
0xc0207030: 0x40c11c0e  0x40d11c0e  0x40e11c0e  0x40f11c0e 
0xc0207040: 0x41011c0e  0x41111c0e  0x41211c0e  0x41311c0e 
0xc0207050: 0x41411c0e  0x41511c0e  0x41611c0e  0x41711c0e 
0xc0207060: 0x41811c0e  0x41911c0e  0x41a11c0e  0x41b11c0e
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • for dtb
// fdt 页表 4800 0000 - 48100000
0xc0207fe0: 0x48011c0e  0x48111c0e  0x00000000  0x00000000
  • 1
  • 2
  • 其他问题
arm32 40000000 - 40204000是干啥的?为啥virt板要预留这么多
arm32为什么要从 40000000  创建映射, arm64 为啥不用?
arm32 只有一个pgd(里面有mmu_on,Image,dtb) , 而 arm64 为什么创建两个 pgd(分别是mmu_on,Image)
  • 1
  • 2
  • 3



硬件相关

PHYS_OFFSET
PHYS_OFFSET
	Physical start address of the first bank of RAM.
	RAM第一个bank的物理起始地址,即物理内存的起始地址。
	ram的起始地址 : 例如 qemu virt arm 的 0x40000000

  • 1
  • 2
  • 3
  • 4
  • 5

uImage 相关

Load Address
https://blog.csdn.net/u011011827/article/details/82995261
Load Address 是 zImage 的住宿地址	// 和 bootm的参数没有关系

make LOADADDR=0x60004000 uImage    // 指定      LOADADDR

//arch/arm/boot/Makefile // 关注 : UIMAGE_LOADADDR
ifneq ($(LOADADDR),)           // 可通过     make LOADADDR=0x60004000 uImage    指定      LOADADDR
  UIMAGE_LOADADDR=$(LOADADDR)                                                       
else                                                                                
  ifeq ($(CONFIG_ZBOOT_ROM),y)                                                      
    UIMAGE_LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT)                                        
  else                                                                              
    UIMAGE_LOADADDR=$(ZRELADDR)                                                     
  endif                                                                             
endif
————————————————
版权声明:本文为CSDN博主「__pop_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011011827/article/details/82995261
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
Entry Point
https://blog.csdn.net/u011011827/article/details/82995261
Entry Point 是 zImage 的控制地址,(从这个地址接收控制权)

// scripts/Makefile.lib // 关注 : UIMAGE_ENTRYADDR
UIMAGE_LOADADDR ?= arch_must_set_this                                            
UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR)
...
      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \          
            -C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \                             
            -T $(UIMAGE_TYPE) \                                                     
            -a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \                          
            -n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT)
————————————————
版权声明:本文为CSDN博主「__pop_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011011827/article/details/82995261
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

zImage 相关

zImage 的代码是位置无关码,随意扔到哪里都可以
  • 1
ZTEXTADDR
ZTEXTADDR
	Start address of decompressor.  There's no point in talking about
	virtual or physical addresses here, since the MMU will be off at
	the time when you call the decompressor code.  You normally call
	the kernel at this address to start it booting.  This doesn't have
	to be located in RAM, it can be in flash or other read-only or
	read-write addressable medium.
	解压代码(zImage)运行的开始地址。
	没有虚拟地址的概念,因为此时MMU处于关闭状态。
	这个地址不一定时RAM的地址,可以是支持读写寻址的flash等存储中介。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
ZBSSADDR

ZBSSADDR
	Start address of zero-initialised work area for the decompressor.
	This must be pointing at RAM.  The decompressor will zero initialise
	this for you.  Again, the MMU will be off.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
INITRD_VIRT

INITRD_VIRT
	Virtual address of the initial RAM disk.  The following  constraint
	must be valid:

		__virt_to_phys(INITRD_VIRT) == INITRD_PHYS
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Image 相关

虚拟地址

PAGE_OFFSET
PAGE_OFFSET
	Virtual start address of the first bank of RAM.  During the kernel
	boot phase, virtual address PAGE_OFFSET will be mapped to physical
	address PHYS_OFFSET, along with any other mappings you supply.
	This should be the same value as TASK_SIZE.
	RAM第一个bank的虚拟起始地址,即内核虚拟地址空间的起始地址。
	
	#define PAGE_OFFSET     UL(CONFIG_PAGE_OFFSET)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
TEXT_OFFSET
TEXT_OFFSET
内核偏移地址,即内核起始位置相对于内存起始位置的偏移,
对于相对于物理内存还是相对于虚拟内存都是一样的结果。
在arch/arm/makefile中设定。
TEXT_OFFSET := $(textofs-y)
140 # Text offset. This list is sorted numerically by address in order to            
141 # provide a means to avoid/resolve conflicts in multi-arch kernels.              
142 # Note: the 32kB below this value is reserved for use by the kernel              
143 # during boot, and this offset is critical to the functioning of                 
144 # kexec-tools.                                                                   
145 textofs-y   := 0x00008000
可取范围
0x008000
0x208000
0x408000
...

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
TEXTADDR
// 目前好像没有这个宏了?
TEXTADDR
内核启动的虚拟地址,与ZRELADDR相对应。一般内核启动的虚拟地址为RAM的第一个bank地址加上0x8000。
       TEXTADDR = PAGE_OFFSET + TEXT_OFFSET
Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.This is where the kernel image ends up. With the latest kernels, it must be located at 32768 bytes into a 128MB region. Previous kernels placed a restriction of 256MB here.

TEXTADDR
	Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.
	This is where the kernel image ends up.  With the latest kernels,
	it must be located at 32768 bytes into a 128MB region.  Previous
	kernels placed a restriction of 256MB here.

相应地,内核启动的虚拟地址被设定为TEXTADDR,满足如下条件:

TEXTADDR = PAGE_OFFSET + TEXT_OFFSET

内核启动的物理地址和虚拟地址满足入下条件:
ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)= virt_to_phys(TEXTADDR)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
swapper_pg_dir
swapper_pg_dir 的 值 为 "TEXTADDR - 0x4000"
boot时 用来存储 临时页表
运行时 用来存储 内核页表

/*
 * swapper_pg_dir is the virtual address of the initial page table.
 * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
 * make sure that KERNEL_RAM_VADDR is correctly set.  Currently, we expect
 * the least significant 16 bits to be 0x8000, but we could probably
 * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000.
 */

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
VMALLOC
VMALLOC_START
	arch/arm/include/asm/pgtable.h
	#define VMALLOC_START       (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))

VMALLOC_END
	Virtual addresses bounding the vmalloc() area.  There must not be
	any static mappings in this area; vmalloc will overwrite them.
	The addresses must also be in the kernel segment (see above).
	Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the
	last virtual RAM address (found using variable high_memory).
	
	#define VMALLOC_END     0xff800000UL

VMALLOC_OFFSET
	Offset normally incorporated into VMALLOC_START to provide a hole
	between virtual RAM and the vmalloc area.  We do this to allow
	out of bounds memory accesses (eg, something writing off the end
	of the mapped memory map) to be caught.  Normally set to 8MB.

	#define VMALLOC_OFFSET      (8*1024*1024)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
DATAADDR
DATAADDR
	// 没有这个宏
	Virtual address for the kernel data segment.  Must not be defined
	when using the decompressor.
  • 1
  • 2
  • 3
  • 4

物理地址

ZRELADDR
// 就是 Load Address 中的那个 ZRELADDR , 如果实在没办法了, 就将 ZRELADDR 的值 赋值给 UIMAGE_LOADADDR
ZRELADDR
	内核启动在RAM中的物理地址。压缩的内核映像被解压到这个地址,然后执行。
	This is the address where the decompressed kernel will be written, and eventually executed. The following constraint must be valid:
	              __virt_to_phys(TEXTADDR) == ZRELADDR
	The initial part of the kernel is carefully coded to be position independent.


	值有要求,= PHYS_OFFSET + TEXT_OFFSET


 20 # Note: the following conditions must always be true:                            
 21 #   ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)                          
 22 #   PARAMS_PHYS must be within 4MB of ZRELADDR                                   
 23 #   INITRD_PHYS must be in RAM                                                   
 24 ZRELADDR    := $(zreladdr-y)                                                     
 25 PARAMS_PHYS := $(params_phys-y)                                                  
 26 INITRD_PHYS := $(initrd_phys-y)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
INITRD_PHYS
INITRD_PHYS
	Physical address to place the initial RAM disk.  Only relevant if
	you are using the bootpImage stuff (which only works on the old
	struct param_struct).
  • 1
  • 2
  • 3
  • 4
PARAMS_PHYS
PARAMS_PHYS
	Physical address of the struct param_struct or tag list, giving the
	kernel various parameters about its execution environment.
  • 1
  • 2
  • 3

线性映射中 物理地址和虚拟地址的转换

Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html

Initial definitions
-------------------

The following symbol definitions rely on you knowing the translation that
__virt_to_phys() does for your machine.  This macro converts the passed
virtual address to a physical address.  Normally, it is simply:

		phys = virt - PAGE_OFFSET + PHYS_OFFSET
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

其他

TASK_SIZE

TASK_SIZE
	The maximum size of a user process in bytes.  Since user space
	always starts at zero, this is the maximum address that a user
	process can access+1.  The user space stack grows down from this
	address.

	Any virtual address below TASK_SIZE is deemed to be user process
	area, and therefore managed dynamically on a process by process
	basis by the kernel.  I'll call this the user segment.

	Anything above TASK_SIZE is common to all processes.  I'll call
	this the kernel segment.

	(In other words, you can't put IO mappings below TASK_SIZE, and
	hence PAGE_OFFSET).

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
Architecture Specific Macros
----------------------------

BOOT_MEM(pram,pio,vio)
	`pram' specifies the physical start address of RAM.  Must always
	be present, and should be the same as PHYS_OFFSET.

	`pio' is the physical address of an 8MB region containing IO for
	use with the debugging macros in arch/arm/kernel/debug-armv.S.

	`vio' is the virtual address of the 8MB debugging region.

	It is expected that the debugging region will be re-initialised
	by the architecture specific code later in the code (via the
	MAPIO function).

BOOT_PARAMS
	Same as, and see PARAMS_PHYS.

FIXUP(func)
	Machine specific fixups, run before memory subsystems have been
	initialised.

MAPIO(func)
	Machine specific function to map IO areas (including the debug
	region above).

INITIRQ(func)
	Machine specific function to initialise interrupts.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/67569
推荐阅读
相关标签
  

闽ICP备14008679号