移植

选自邮件列表归档:http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html

初始定义

以下符号定义依赖于您了解 __virt_to_phys() 在您的机器上执行的地址转换。此宏将传入的虚拟地址转换为物理地址。通常,它很简单:

phys = virt - PAGE_OFFSET + PHYS_OFFSET

解压器符号

ZTEXTADDR

解压器的起始地址。在这里讨论虚拟地址或物理地址毫无意义,因为在你调用解压器代码时 MMU 是关闭的。通常你会在这个地址调用内核来启动它。它不必位于 RAM 中,可以位于 flash 或其他只读或可读写的可寻址介质中。

ZBSSADDR

解压器零初始化工作区的起始地址。这必须指向 RAM。解压器会为你将其初始化为零。同样,MMU 也是关闭的。

ZRELADDR

这是解压后的内核将被写入并最终执行的地址。必须满足以下约束:

__virt_to_phys(TEXTADDR) == ZRELADDR

内核的初始部分经过精心编写,具备位置无关性。

INITRD_PHYS

放置初始 RAM 盘的物理地址。仅在使用 bootpImage 相关内容时适用(该内容仅适用于旧的 struct param_struct)。

INITRD_VIRT

初始 RAM 盘的虚拟地址。必须满足以下约束:

__virt_to_phys(INITRD_VIRT) == INITRD_PHYS

PARAMS_PHYS

struct param_struct 或标签列表(tag list)的物理地址,用于向内核提供其执行环境的各种参数。

内核符号

PHYS_OFFSET

第一块 RAM 的物理起始地址。

PAGE_OFFSET

第一块 RAM 的虚拟起始地址。在内核引导阶段,虚拟地址 PAGE_OFFSET 将连同您提供的任何其他映射一起,被映射到物理地址 PHYS_OFFSET。该值应该与 TASK_SIZE 相同。

TASK_SIZE

用户进程的最大大小(以字节为单位)。由于用户空间总是从零开始,因此这是用户进程可以访问的最大地址 + 1。用户空间栈从该地址向下增长。

TASK_SIZE 以下的任何虚拟地址都被视为用户进程区域,因此由内核按进程进行动态管理。我将其称为用户段。

TASK_SIZE 以上的所有内容对所有进程而言都是公共的。我将其称为内核段。

(换句话说,您不能将 IO 映射放在 TASK_SIZE 之下,从而也不能放在 PAGE_OFFSET 之下)。

TEXTADDR

内核的虚拟起始地址,通常为 PAGE_OFFSET + 0x8000。这是内核镜像最终存放的位置。对于最新内核,它必须位于 128MB 区域内从起始处偏移 32768 字节的地方。先前的内核对此处施加了 256MB 的限制。

DATAADDR

内核数据段的虚拟地址。使用解压器时不得定义此项。

VMALLOC_START / VMALLOC_END

界定 vmalloc() 区域的虚拟地址边界。该区域中绝不能有任何静态映射;vmalloc 会覆盖它们。这些地址也必须位于内核段中(见上文)。通常,vmalloc() 区域从最后一个虚拟 RAM 地址(通过变量 high_memory 获得)上方 VMALLOC_OFFSET 字节处开始。

VMALLOC_OFFSET

通常合并到 VMALLOC_START 中的偏移量,用于在虚拟 RAM 和 vmalloc 区域之间留出一个空洞。我们这样做是为了能够捕获越界内存访问(例如,有代码写入了已映射内存映射的末尾之外)。通常设置为 8MB。

体系结构特定宏

BOOT_MEM(pram,pio,vio)

pram 指定了 RAM 的物理起始地址。必须始终存在,且应与 PHYS_OFFSET 相同。

pio 是一个 8MB 区域的物理地址,该区域包含用于 arch/arm/kernel/debug-armv.S 中调试宏的 IO。

vio 是该 8MB 调试区域的虚拟地址。

预计该调试区域稍后会由体系结构特定的代码(通过 MAPIO 函数)重新初始化。

BOOT_PARAMS

与 PARAMS_PHYS 相同,请参见 PARAMS_PHYS。

FIXUP(func)

机器特定的修复,在内存子系统初始化之前运行。

MAPIO(func)

用于映射 IO 区域的机器特定函数(包括上述调试区域)。

INITIRQ(func)

用于初始化中断的机器特定函数。