95 Star 262 Fork 91

泰晓科技 / RISCV-Linux

 / 详情

【老师提案】TinyLinux for RISC-V

进行中
拥有者
创建于  
2023-02-19 10:40

TinyLinux 是泰晓科技 Linux 技术社区创始人发起的项目,已经有 10 多年的历史,该项目致力于 Linux 内核裁剪,以便应用到存储和内存极端有限的硬件平台,该提案的目标是把 TinyLinux 移植到最新的 RISC-V Linux 内核,研究应用新型的 Linux 裁剪技术,并在极小存储和内存的目标系统上运行(可以直接用 QEMU 模拟)。

该项目曾经把 MIPS 内核优化到 386k 左右:

Now, we get:

$ ls -lh vmlinuz
-rwxr-xr-x 1 root root 386K 2011-01-30 03:27 vmlinuz

除了早期 TinyLinux 的工作,还有一些新兴的技术可以应用:

  1. Nolibc

    一个以头文件方式提供的,已经内置到内核源码的 C 库,本身很小,也很方便分析调用到的内核资源(特别是系统调用)。

  2. M-Mode Linux

    内核中的 nonMMU 配置选项,如何开启后支持运行 Nolibc 库,完全避免系统调用运行?见 RISC-V NoMMU Linux 相关支持调研与分析

  3. Unikernel

    更进一步地,把应用直接编译进内核,

    更多相关:https://github.com/cetic/unikernels

  4. Kexec bootloader

    基于上述功能开发具体的应用案例,验证可行性:

  5. Linux Kernel Library

    • LKL (Linux Kernel Library) is aiming to allow reusing the Linux kernel code as extensively as possible with minimal effort and reduced maintenance overhead.

有些工作虽然不一定能 Upstream,但是绝对可以值得尝试,比如:

未来可能用到的硬件平台,rv32,小内存,小ROM:

  • BL602,BL604,BL616,BL618,BL702
  • ESP32-C2/C3/C6

更多资料:

  1. https://elinux.org/Kernel_Size_Reduction_Work
  2. https://elinux.org/System_Size

评论 (12)

falcon 创建了任务
falcon 修改了描述
falcon 修改了描述
展开全部操作日志

已经开展的工作:

  1. 一个极小的内核配置文件,所有工作的基础
  2. 一个极小的用户态,基于 Nolibc 构建的 initrd
  3. gc-sections for RISC-V,需要进一步优化,可参考早期 TinyLinux 的 gc-sections 分支和论文
  4. dead syscalls elimination for RISC-V,需要进一步优化,可参考 syscall_eliminationauto-reduce

目前成果:

By enabling CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION and setting
CONFIG_SYSCALLS_USED, It is able to remove the left 'dead' syscalls.

For example, if setting CONFIG_SYSCALLS_USED="write exit reboot", a
'used' variant of the *syscall_table.c will be generated.

Here is a test result on qemu with a small rv64 config.

                    | rv64            | config
    ----------------|-----------------|-------------------
            vmlinux | 4893488         | https://pastebin.com/crz82T0s
      + gc-sections | 4376400 (-10.5%)| CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
    + syscalls_used | 4172112 (-4.67%)| CONFIG_SYSCALLS_USED="pselect6"
    + syscalls_used | 4172848 (-4.65%)| CONFIG_SYSCALLS_USED="write exit reboot"

A even smaller config is tested:

                    | rv64            | config
    ----------------|-----------------|-------------------
            vmlinux | 1698960         | https://pastebin.com/C3LR4UbT
      + gc-sections | 1319400 (-22.3%)| CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
    + syscalls_used | 1233392 (-6.52%)| CONFIG_SYSCALLS_USED="write exit reboot"

notes:

- The shrink ratios of the syscalls_used lines are based on the
  gc-sections line.

- "write exit reboot" are used by a hello.c to simply print "Hello,
   World!", exit and shutdown qemu.

- "pselect6" is used by rcutorture to do a long-time sleep.

做完 strip 后的 Image 已经可以小于 1M,还是很大:

ubuntu@linux-lab:/labs/linux-lab$ ls -l build/riscv64/virt/linux/v6.2-rc8/vmlinux
-rwxr-xr-x 1 ubuntu ubuntu 1319400 2月  19 11:00 build/riscv64/virt/linux/v6.2-rc8/vmlinux
ubuntu@linux-lab:/labs/linux-lab$ ls -l build/riscv64/virt/linux/v6.2-rc8/arch/riscv/boot/Image 
-rwxr-xr-x 1 ubuntu ubuntu 947792 2月  19 11:09 build/riscv64/virt/linux/v6.2-rc8/arch/riscv/boot/Image
ubuntu@linux-lab:/labs/linux-lab$ ls -lh build/riscv64/virt/linux/v6.2-rc8/arch/riscv/boot/Image 
-rwxr-xr-x 1 ubuntu ubuntu 926K 2月  19 11:09 build/riscv64/virt/linux/v6.2-rc8/arch/riscv/boot/Image

最近几天的一些进展:

$ pwd
/labs/linux-lab/build/riscv64/virt/linux/v6.2-rc8/arch/riscv/boot
$ ls -lh Image*
-rwxr-xr-x 1 ubuntu ubuntu 762K 2月  22 00:31 Image
-rw-r--r-- 1 ubuntu ubuntu 396K 2月  22 00:59 Image.bz2
-rw-r--r-- 1 ubuntu ubuntu 419K 2月  22 00:59 Image.gz
-rw-r--r-- 1 ubuntu ubuntu 455K 2月  22 01:01 Image.lz4
-rw-r--r-- 1 ubuntu ubuntu 368K 2月  22 00:57 Image.lzma
-rw-r--r-- 1 ubuntu ubuntu 449K 2月  22 00:58 Image.lzo
-rw-r--r-- 1 ubuntu ubuntu 392K 2月  22 00:57 Image.zst

新增自解压支持,采用 lzma 压缩后:

$ ls -lh build/riscv64/virt/linux/v6.2-rc8/arch/riscv/boot/compressed/vmlinuz
-rwxr-xr-x 1 ubuntu ubuntu 371K 2月  22 22:33 build/riscv64/virt/linux/v6.2-rc8/arch/riscv/boot/compressed/vmlinuz
falcon 任务状态待办的 修改为进行中
falcon 负责人设置为falcon

新增 M mode kernel 支持:

$ ls -lh build/riscv64/virt/linux/v6.2/arch/riscv/boot/compressed/vmlinuz
-rwxr-xr-x 1 ubuntu ubuntu 337K 2月  23 07:00 build/riscv64/virt/linux/v6.2/arch/riscv/boot/compressed/vmlinuz

新增 M Mode Application 支持:

$ ls -l /labs/linux-lab/build/riscv64/virt/linux/v6.2/nolibc/initramfs/init 
-rwxr--r-- 1 ubuntu ubuntu 864 3月   2 22:09 /labs/linux-lab/build/riscv64/virt/linux/v6.2/nolibc/initramfs/init

$ ls -lh build/riscv64/virt/linux/v6.2/arch/riscv/boot/compressed/vmlinuz
-rwxr-xr-x 1 ubuntu ubuntu 334K 3月   2 22:11 build/riscv64/virt/linux/v6.2/arch/riscv/boot/compressed/vmlinuz

在 Linux Lab 下编译和运行 !MMU 应用,开启内核支持的方法在 这里

$ export NOLIBC=1
$ export NOMMU=1
$ make kernel vmlinuz nolibc_src=$PWD/src/examples/assembly/riscv64/riscv64-hello.s
$ make boot
Linux version 6.2.0-00047-gf9a88b15cf5a (ubuntu@linux-lab) (riscv64-linux-gnu-gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #353 Thu Mar  2 22:20:24 CST 2023
...
Freeing unused kernel image (initmem) memory: 72K
This architecture does not have kernel memory protection.
Run /init as init process
Hello, RISC-V 64!
reboot: Power down

社区正在尝试新增 Non-MMU ELF-FDPIC 格式支持,目前只是内核部分:

rv32 nolibc 支持,已提交一组 patchset: https://lore.kernel.org/linux-riscv/cover.1684425792.git.falcon@tinylab.org/T/#t

  1. 可以编译 hello.c
    • 在做完下面的第一笔修改后,即可编译 hello.c
    • make B=riscv32/virt; export nolibc=1; make kernel; make boot
  2. 需要做几处修改
    • tools/include/nolibc/arch-riscv.h, sw/sd, lw/ld for rv32 and rv64
    • 需要 revert 掉 commit: d4c08b9776b3 或参考 glibc 新增基于 time64 syscalls 的一系列系统调用,详见:c8ce48f06503
    • 修复 sys_lseek,rv32 没有 __NR_lseek,需要基于 64 位的 __NR_llseek 新增 sys_lseek 支持
  3. 测试方法(rv64 ok, rv32 not yet)
  • 方法一:
$ make nolibc nolibc_src=src/linux-stable/tools/testing/selftests/nolibc/nolibc-test.c
$ make kernel
$ make boot
  • 方法二:
$ make run-user ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -C src/linux-stable/tools/testing/selftests/nolibc O=/labs/linux-lab/build/riscv64/virt/linux/v6.4-rc2
  • 方法三:
$ make qemu-clone QEMU_NEW=v8.0.0
$ make qemu
$ make qemu-save
$ env PATH=$PWD/boards/riscv64/virt/bsp/qemu/v8.0.0/bin/:/usr/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin BIOS=$PWD/boards/riscv64/virt/bsp/bios/opensbi/generic/fw_jump.elf make  O=/labs/linux-lab/build/riscv64/virt/linux/v6.4-rc2 -C /labs/linux-lab/src/linux-stable/tools/testing/selftests/nolibc/   ARCH=riscv LOADADDR=0x84000000 CROSS_COMPILE=riscv64-linux-gnu- run  IMAGE=../../build/riscv64/virt/linux/v6.4-rc2/arch/riscv/boot/Image

TODO:

  1. tools/testing/selftests/nolibc/Makefile 的 kernel 目标无法通过 Linux Lab 嵌套工作,怀疑是环境变量导致的,需要在子任务中清理父任务新增的环境变量,最好是用脚本来做,用 Makefile 来实现,问题比较多。
  2. 在 rv32 上,很多 time32 的 syscalls 在 v5.0.0-rc2 之后都不再提供给用户态了,需要重新基于 time64 的 syscalls 来实现,可能有 10 个左右库函数需要重新为 rv32 (以及未来的其他新架构)来专门实现。可以参考 commit: c8ce48f06503 和 glibc 或 musl, newlib, uclibc 等,需要调研看看哪些对 rv32 支持得比较好。
falcon 修改了描述
falcon 修改了描述
falcon 修改了描述
falcon 修改了描述

pure kernel deployment 后续阶段:基于 nolibc 的 shell 或者 busybox 支持。

https://github.com/ziyao233/kdsh
http://mirbsd.de/mksh
https://www.busybox.net/
https://github.com/ksh93/ksh

falcon 修改了描述

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(1)
5069540 wuzhangjin 1594531572
1
https://gitee.com/tinylab/riscv-linux.git
git@gitee.com:tinylab/riscv-linux.git
tinylab
riscv-linux
RISCV-Linux

搜索帮助