Linux 内核 OpenRISC 架构移植指南:从工具链搭建、内核编译到 FPGA 与 QEMU 运行
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
导读
本指南围绕 Linux 内核仓库中的 OpenRISC 架构移植(Port)展开,系统讲解这一将 Linux 移植到 OpenRISC 类微处理器(以 32 位 OpenRISC 1000 家族、即 or1k 为初始目标)的架构移植工作的全貌。文章以 Documentation/arch/openrisc/openrisc_port.rst 为骨架,结合 arch/openrisc 下的源码、Kconfig 配置与各平台 defconfig,完整覆盖工具链准备、内核交叉编译、initramfs 嵌入、FPGA 板级运行(FuseSoC + OpenOCD)以及 QEMU 模拟运行等实战流程。读完本文,你将掌握从零构建并运行 OpenRISC Linux 内核的完整操作链路,并理解 or1k 移植在配置、指令集与设备树层面的工程细节。
一、OpenRISC 移植概览
OpenRISC 是一个开源的精简指令集(RISC)处理器架构,而 Linux 内核对其的支持是一个完整的架构移植(port)。该移植的初始目标是32 位的 OpenRISC 1000 家族(or1k),其核心实现集中在仓库的 arch/openrisc 目录下,涵盖:
- 内核启动与异常/陷阱处理:
head.S、entry.S、traps.c - 进程与信号管理:
process.c、signal.c、ptrace.c - 内存管理(MMU、TLB、ioremap):
mm/子目录 - 中断控制器(OR1K PIC)与定时器:
irq.c、sync-timer.c - 设备树(Device Tree)启动与平台初始化:
prom.c、setup.c - 对称多处理(SMP)支持:
smp.c
从 arch/openrisc/Kconfig 可以看到,该移植是一套相当完整的架构配置:定义了OPENRISC架构入口,并选中了OF(Device Tree)、IRQ_DOMAIN、GENERIC_IRQ_CHIP、HAVE_ARCH_JUMP_LABEL、HAVE_PCI、MMU、SMP(可配)以及PCI_MSI if PCI等一系列基础设施,说明该移植已深度接入主线内核的通用框架。
术语表:openrisc / or1k / or1200
原文档明确指出,在代码中以下三个前缀用于限定符号的作用范围,避免混淆不同层级的处理器实现:
| 代码中的称谓 | 含义 |
|---|---|
openrisc | OpenRISC 类处理器(架构大类) |
or1k | OpenRISC 1000 家族处理器 |
or1200 | OpenRISC 1200 处理器(具体实现) |
这一约定在源码中随处可见:例如 arch/openrisc/Kconfig 中的子架构选项OR1K_1200(对应 OR1200 通用架构),以及设备树节点中出现的compatible = "opencores,or1200-rtlsvn481"。理解这三个层次的差异,是阅读 OpenRISC 相关代码的前提。
二、第一步:搭建 OpenRISC 工具链
要编译 Linux 内核,首先需要一个针对 OpenRISC 目标的交叉编译工具链。原文档给出的途径包括:
- 直接获取预编译二进制工具链:可从 openrisc.io 软件页面或社区维护者的工具链构建发布页获取现成的
or1k-linux-系列工具链二进制。 - 自行构建工具链:社区维护者(Stafford)提供了工具链构建与发布脚本(or1k-toolchain-build),按其中说明即可从源码构建完整工具链。
无论采用哪种方式,最终目的是获得前缀为or1k-linux-的交叉编译工具(gcc、binutils、glibc 等)。内核编译时通过CROSS_COMPILE="or1k-linux-"指定该前缀。
提示:原文档中的链接均为社区外部资源,此处仅说明获取途径。对内核侧而言,只要
or1k-linux-gcc等工具位于PATH中即可正常编译。
三、编译 OpenRISC Linux 内核
3.1 最小构建命令
原文档给出的标准构建流程非常简洁,只需两条命令:
make ARCH=openrisc CROSS_COMPILE="or1k-linux-" defconfig make ARCH=openrisc CROSS_COMPILE="or1k-linux-"第一条命令生成默认配置。这里的defconfig会读取 arch/openrisc/Makefile 中声明的默认配置目标:
KBUILD_DEFCONFIG := or1ksim_defconfig即默认采用 arch/openrisc/configs/or1ksim_defconfig(面向 OpenRISC 模拟器平台)。第二条命令执行完整的内核编译。
值得注意的是,arch/openrisc/Makefile 还定义了两个与其它架构不同的行为:
KBUILD_CFLAGS += -pipe -ffixed-r10 -D__linux__以及-msfimm -mshftimm,对编译选项做了架构定制;all: vmlinux.bin—— 默认目标除了生成vmlinuxELF 外,还会通过 arch/openrisc/boot/Makefile 用 objcopy 生成纯二进制镜像vmlinux.bin(-O binary),便于直接烧写进 FPGA 或加载到模拟器。
3.2 可选:嵌入 initramfs
如果希望在编译阶段就把根文件系统直接嵌入内核镜像,需要额外传递CONFIG_INITRAMFS_SOURCE,例如:
make ARCH=openrisc CROSS_COMPILE="or1k-linux-" \ CONFIG_INITRAMFS_SOURCE="path/to/rootfs path/to/devnodes"该选项的值是一个或多个路径(目录、cpio 归档等),内核构建系统会将其打包为 initramfs 嵌入镜像。更多细节可参考仓库中的 Documentation/filesystems/ramfs-rootfs-initramfs.rst。
从 defconfig 可以看出,无论是 or1ksim_defconfig 还是 de0_nano_defconfig 都开启了CONFIG_BLK_DEV_INITRD=y,说明 initramfs 是 OpenRISC 平台常见的根文件系统方案。
3.3 针对不同平台的配置目标
除了模拟器平台,仓库还提供了面向其它硬件平台的 defconfig(全部位于 arch/openrisc/configs):
| 配置文件 | 目标平台 |
|---|---|
or1ksim_defconfig | OpenRISC 模拟器(默认) |
de0_nano_defconfig | Terasic De0 Nano FPGA 开发板(单核) |
de0_nano_multicore_defconfig | De0 Nano 多核(SMP)配置 |
or1klitex_defconfig | OR1K LiteX 平台 |
simple_smp_defconfig | 通用 SMP 平台 |
virt_defconfig | 虚拟化平台 |
使用方式与标准流程一致,例如:
make ARCH=openrisc CROSS_COMPILE="or1k-linux-" de0_nano_defconfig make ARCH=openrisc CROSS_COMPILE="or1k-linux-"以 or1ksim_defconfig 为例,可以看到针对模拟器环境的精简配置:启用CONFIG_NO_HZ、CONFIG_HZ_100、CONFIG_JUMP_LABEL、CONFIG_MODULES、CONFIG_DEVTMPFS(自动挂载)、以太网驱动CONFIG_ETHOC(OpenCores 以太网控制器)、CONFIG_SERIAL_8250及其控制台支持,并指定CONFIG_BUILTIN_DTB_NAME="or1ksim"将设备树编入内核。而 de0_nano_defconfig 则额外开启了CONFIG_GPIO_SYSFS、CONFIG_NEW_LEDS与一系列 LED 触发器(heartbeat、cpu、netdev 等),以匹配 De0 Nano 板上的 GPIO/LED 外设。
四、内核配置要点:从 Kconfig 看 or1k 移植细节
arch/openrisc/Kconfig 是理解该移植能力边界的最佳入口,原文档虽未展开,但其背后的配置选项直接决定内核能否在目标处理器上正确运行。
4.1 子架构与缓存
OR1K_1200:当前唯一的子架构选择,即 OR1200 通用架构(默认选中)。DCACHE_WRITETHROUGH:如果你的实现采用写透(write-through)数据缓存,应开启此项;关闭时内核会在必要时强制冲刷数据缓存。大多数 OpenRISC 实现支持写透缓存,拿不准时选 N。
4.2 Class II 指令集开关
OpenRISC 1000 定义了可选的 Class II 指令。Kconfig 提供一组开关,让内核针对具体处理器实现启用(或不启用)这些指令。启用后 GCC 可生成对应指令,通常会提升性能并减小二进制体积:
| 配置项 | 对应指令 | 默认值 |
|---|---|---|
OPENRISC_HAVE_INST_FF1 | l.ff1(前导一计数) | y |
OPENRISC_HAVE_INST_FL1 | l.fl1 | y |
OPENRISC_HAVE_INST_MUL | l.mul(硬件乘法) | y |
OPENRISC_HAVE_INST_DIV | l.div(硬件除法) | y |
OPENRISC_HAVE_INST_CMOV | l.cmov(条件移动) | n |
OPENRISC_HAVE_INST_ROR | l.ror(循环右移) | n |
OPENRISC_HAVE_INST_RORI | l.rori(立即数循环右移) | n |
OPENRISC_HAVE_INST_SEXT | l.ext*(符号/零扩展系列) | n |
这些开关会直接反映到内核编译选项上:arch/openrisc/Makefile 中根据对应配置追加-mhard-mul/-msoft-mul、-mhard-div/-msoft-div、-mcmov、-mror、-mrori、-msext等 GCC 选项,实现硬件指令与软件模拟的自动切换。
4.3 多核、FPU 与异常行为
SMP与NR_CPUS(范围 2–32):启用对称多处理,NR_CPUS默认 2。SMP 场景下必须依赖影子寄存器组(见下)。FPU(默认 y):关闭可剔除内核中所有浮点相关处理过程以减小体积。OPENRISC_NO_SPR_SR_DSX(默认 y,仅 OR1K_1200):SPR_SR_DSX是状态寄存器中指示“上一次异常是否发生在延迟槽(delay slot)”的位。OpenRISC 架构允许硬件不实现该位,而 OR1200 恰好没有实现,因此内核默认用软件方式模拟该语义;只有确认你的处理器实现了该位才可关闭。OPENRISC_HAVE_SHADOW_GPRS:处理器是否具备影子寄存器组(shadow register file)。启用后,异常入口可将通用寄存器暂存到影子寄存器中,避免额外的保存开销;在 SMP 系统上该特性是必需的。CMDLINE:对没有 bootloader 传递参数的平台,可在编译期内置默认内核命令行。
4.4 调试选项
JUMP_UPON_UNHANDLED_EXCEPTION(默认 y):首次 oops 后让内核进入死循环,便于定位问题。OPENRISC_ESR_EXCEPTION_BUG_CHECK(默认 n):开启一些可能暴露内核潜在问题的检查。
五、在 FPGA 上运行(可选)
OpenRISC 社区通常借助FuseSoC来管理 SoC 的构建与烧写流程:FuseSoC 在构建时从 IP 核仓库下载 FPGA RTL 代码,再调用 FPGA 厂商工具完成综合与布局布线,最后通过OpenOCD将二进制加载到开发板。
原文档以 Terasic De0 Nano 开发板为例给出完整流程:
# 1) 安装 FuseSoC(Python 包,以可编辑模式安装) git clone <fusesoc-repo> cd fusesoc sudo pip install -e . # 2) 初始化并构建/烧写 De0 Nano 的 OpenRISC SoC fusesoc init fusesoc build de0_nano fusesoc pgm de0_nano # 3) 启动 OpenOCD,连接板载 Altera USB-Blaster 调试器与 or1k 目标 openocd -f interface/altera-usb-blaster.cfg \ -f board/or1k_generic.cfg # 4) 通过 telnet 进入 OpenOCD 命令界面,加载内核镜像并复位运行 telnet localhost 4444 > init > halt; load_image vmlinux ; reset上述de0_nano目标与内核侧 arch/openrisc/configs/de0_nano_defconfig 一一对应,其板级设备树描述位于 arch/openrisc/boot/dts/de0-nano.dts(与de0-nano-common.dtsi配合)。内核编译产物vmlinux(ELF)正是 OpenOCDload_image直接加载的镜像;若烧写裸二进制,则使用默认目标生成的vmlinux.bin。
六、在 QEMU 上运行(可选)
对于没有硬件或 FPGA 开发板的开发者,QEMU是官方推荐的 OpenRISC 平台模拟器。原文档建议两种方式:
- 自行编译 QEMU,启用 OpenRISC 目标支持;
- 使用发行版提供的二进制包——多数主流 Linux 发行版都带有支持 OpenRISC 的 QEMU 包,这是最快的方式。
在 QEMU 中运行 Linux 的具体步骤以 QEMU 官方 OpenRISC 平台文档为准。仓库侧与之配套的默认配置正是 or1ksim_defconfig 与设备树 arch/openrisc/boot/dts/or1ksim.dts。
从 or1ksim.dts 可以看出模拟器平台的外设布局:compatible = "opencores,or1ksim",内存起始于 0x0 且大小为 32 MiB(reg = <0x00000000 0x02000000>),CPU 为opencores,or1200(20 MHz 时钟),串口为兼容ns16550a的 OpenCores UART(serial@90000000),以太网为 OpenCoresethoc(enet0@92000000),中断控制器为 CPU 内置的opencores,or1k-pic(通过特殊功能寄存器访问,无地址空间)。chosen节点中bootargs = "earlycon"、stdout-path = "uart0:115200"指定了早期控制台输出。编译该平台时,CONFIG_BUILTIN_DTB_NAME="or1ksim"会把这棵设备树直接内嵌进内核镜像,免去外部传递 DTB 的步骤。
七、移植现状与 TODO
Documentation/arch/openrisc/todo.rst 对该移植的现状做了补充说明:OpenRISC Linux 移植已完全可用,并且自 Linux 2.6.35 起持续跟随主线演进。剩余的工作项包括:
- 补齐 DMA API 的其余部分(如
dma_map_sg等); - 完成命名清理:代码中仍残留
or32引用——这是该架构的旧名,现已统一为or1k,改名工作正在逐步推进;目前or32与or1k等价。
此外,Documentation/arch/openrisc/index.rst 将openrisc_port、todo与features三份文档组织为 OpenRISC 架构文档集;其中 features.rst 通过kernel-feat指令自动从内核特性列表生成,可作为查询该架构功能支持矩阵的入口。
八、历史沿革
原文档保留了该移植的完整历史记录,反映了 Linux/OpenRISC 移植从早期原型到上游化的演进脉络:
| 日期 | 作者 | 里程碑 |
|---|---|---|
| 2003-11-18 | Matjaz Breskvar | 将 Linux 初始移植到 OpenRISC/or32 架构,核心功能可用 |
| 2003-12-08 | Matjaz Breskvar | 完全重写 TLB miss 处理与异常处理;默认 initrd 中可运行完整的 sash-3.6 shell |
| 2004-04-10 | Matjaz Breskvar | 大量缺陷修复;加入以太网支持,可运行 HTTP 与 telnet 服务器,可跑众多标准 Linux 应用 |
| 2004-06-26 | Matjaz Breskvar | 移植到 2.6.x 内核 |
| 2004-11-30 | Matjaz Breskvar | 大量缺陷修复与增强;加入 OpenCores framebuffer 驱动 |
| 2010-10-09 | Jonas Bonn | 大规模重写,使其与上游 Linux 2.6.36 保持一致 |
这段历史解释了代码中or32/or1k名称并存的由来,也与 todo.rst 中“or32 是 or1k 的旧名”的说明相互印证。
总结
围绕 openrisc_port.rst 这篇官方移植文档,本文完整还原了 OpenRISC Linux 的构建与运行链路:从获取or1k-linux-交叉工具链,到make ARCH=openrisc完成内核与vmlinux.bin的构建,再到通过CONFIG_INITRAMFS_SOURCE嵌入根文件系统;随后分别给出了 FPGA(FuseSoC + OpenOCD)与 QEMU 两条运行路径,并结合 arch/openrisc/Kconfig 与各平台 defconfig 深入剖析了 Class II 指令开关、缓存策略、SMP/FPU 及异常行为等配置要点。对于希望深入该移植的开发者,arch/openrisc 目录下的启动代码(head.S、entry.S)、内存管理(mm/)与平台初始化(prom.c、setup.c)是继续阅读的首选入口。
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考