第一阶段:ArceOS in Qemu 验证(4.24-5.1)

任务零:Ubuntu 22.04 开发环境搭建

  1. 在 Windows 上安装 WSL
  2. 安装 Ubuntu-22.04。
    • 安装过程详见 1.1 中链接。以下是可安装的有效分发的列表:
NAMEFRIENDLY NAME
UbuntuUbuntu
DebianDebian GNU/Linux
kali-linuxKali Linux Rolling
Ubuntu-18.04Ubuntu 18.04 LTS
Ubuntu-20.04Ubuntu 20.04 LTS
Ubuntu-22.04Ubuntu 22.04 LTS
OracleLinux_8_5Oracle Linux 8.5
OracleLinux_7_9Oracle Linux 7.9
SUSE-Linux-Enterprise-Server-15-SP4SUSE Linux Enterprise Server 15 SP4
openSUSE-Leap-15.4openSUSE Leap 15.4
openSUSE-TumbleweedopenSUSE Tumbleweed
  1. 安装 rust

    • rust 官网:https://www.rust-lang.org/

    • 安装 rust:

      curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
      
    • 获取 rust 的最新版本:

      rustup update
      
    • 配置环境变量:

      vim ~/.bashrc
      
    • 按 i 键进入编辑模式,在文件最后加入:

      export PATH=~/.cargo/bin:$PATH
      
    • 按 Esc 键退出编辑模式,按 : 键并输入 wq,保存并退出。

    • 加载修改后的配置:

      source ~/.bashrc
      
    • 检查 cargo 是否能正常使用(查看版本):

      cargo --version
      
    • 更多关于 rust 的安装可参考:https://www.rust-lang.org/tools/install

  2. 安装 git

    sudo apt update
    
    sudo apt install git
    
  3. 安装 make

    sudo apt install make
    

第一阶段:ArceOS in Qemu 验证(4.24-5.1)

任务零:Ubuntu 22.04 开发环境搭建

  1. 在 Windows 上安装 WSL
  2. 安装 Ubuntu-22.04。
    • 安装过程详见 1.1 中链接。以下是可安装的有效分发的列表:
NAMEFRIENDLY NAME
UbuntuUbuntu
DebianDebian GNU/Linux
kali-linuxKali Linux Rolling
Ubuntu-18.04Ubuntu 18.04 LTS
Ubuntu-20.04Ubuntu 20.04 LTS
Ubuntu-22.04Ubuntu 22.04 LTS
OracleLinux_8_5Oracle Linux 8.5
OracleLinux_7_9Oracle Linux 7.9
SUSE-Linux-Enterprise-Server-15-SP4SUSE Linux Enterprise Server 15 SP4
openSUSE-Leap-15.4openSUSE Leap 15.4
openSUSE-TumbleweedopenSUSE Tumbleweed
  1. 安装 rust

    • rust 官网:https://www.rust-lang.org/

    • 安装 rust:

      curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
      
    • 获取 rust 的最新版本:

      rustup update
      
    • 配置环境变量:

      vim ~/.bashrc
      
    • 按 i 键进入编辑模式,在文件最后加入:

      export PATH=~/.cargo/bin:$PATH
      
    • 按 Esc 键退出编辑模式,按 : 键并输入 wq,保存并退出。

    • 加载修改后的配置:

      source ~/.bashrc
      
    • 检查 cargo 是否能正常使用(查看版本):

      cargo --version
      
    • 更多关于 rust 的安装可参考:https://www.rust-lang.org/tools/install

  2. 安装 git

    sudo apt update
    
    sudo apt install git
    
  3. 安装 make

    sudo apt install make
    

任务一:Qemu 开发环境搭建

  1. 安装 qemu:

    git clone https://git.qemu.org/git/qemu.git --depth 1
    
  2. 安装依赖:

    sudo apt install ninja-build
    sudo apt install build-essential
    sudo apt install pkg-config
    sudo apt-get install libglib2.0-dev
    sudo apt-get install libpixman-1-dev
    
  3. 将 Qemu 目录下 build 目录加入进PATH环境变量

    export PATH=(your path/qemu/build):$PATH
    
  4. 设置 Qemu 编译生成的目标为 RISC-V,AArch64,X86

    ./configure --target-list=aarch64-softmmu
    
    • 如果需要配置多个目标,可在 target-list=后面添加,并以逗号分隔,例如:
    ./configure --target-list=aarch64-softmmu,riscv64-softmmu,x86_64-softmmu
    

    result

    • 其他可生成的目标:

      set target list (default: build all)
      Available targets: aarch64-softmmu alpha-softmmu
      arm-softmmu avr-softmmu cris-softmmu hppa-softmmu
      loongarch64-softmmu m68k-softmmu
      microblaze-softmmu microblazeel-softmmu mips-softmmu
      mips64-softmmu mips64el-softmmu mipsel-softmmu
      nios2-softmmu or1k-softmmu ppc-softmmu ppc64-softmmu
      riscv32-softmmu riscv64-softmmu rx-softmmu
      s390x-softmmu sh4-softmmu sh4eb-softmmu
      sparc-softmmu sparc64-softmmu tricore-softmmu
      x86_64-softmmu xtensa-softmmu xtensaeb-softmmu
      
  5. 编译

    make
    

result

  • Qemu for RISC-V
  • Qemu for AArch64
  • Qemu for X86

任务二:ArceOS 下载、编译和运行

ArceOS GitHub 网址:https://github.com/rcore-os/arceos ArceOS 介绍 PPT:https://learningos.github.io/os-lectures/oslabs/biglabs.html

  1. 克隆仓库

    git clone https://github.com/rcore-os/arceos.git
    
  2. 编译

    1. 安装依赖:

      cargo install cargo-binutils
      
    2. 编译:(默认 ARCH = x86_64)

      # arceos目录下
      make
      

    result

  3. 运行

    1. Hello World:(默认 ARCH = x86_64)

      make justrun
      
    2. 运行特定 APP:

任务三:ArceOS in Qemu for AArch64/RISC-V 验证

  1. AArch64 验证

确保任务二中步骤 3.运行的例子中以下命令执行无误

# arceos目录下
make A=apps/helloworld ARCH=aarch64 LOG=info NET=N SMP=4 run

程序正常运行出现预期结果,即完成 AArch64 验证

  1. RISC-V 验证
# arceos目录下
make A=apps/helloworld ARCH=riscv64 LOG=info NET=N SMP=4 run

程序正常运行出现预期结果,即完成 RISC-V 验证

任务四:ArceOS + virtio-net 网卡驱动 in Qemu for AArch64/RISC-V 验证

  1. 配置

    # qemu目录下
    sudo apt-get install libslirp-dev
    sudo apt install flex
    sudo apt install bison
    ./configure --target-list=aarch64-softmmu --enable-slirp    # 用于 AArch64 架构
    ./configure --target-list=riscv64-softmmu --enable-slirp    # 用于 RISC-V 架构
    

picture

  1. 编译
    # qemu目录下
    make
    

picture

  1. 运行

    # arceos目录下
    make A=apps/net/httpserver ARCH=aarch64 LOG=info NET=y SMP=4 run  # 用于 AArch64 架构
    make A=apps/net/httpserver ARCH=riscv64 LOG=info NET=y SMP=4 run  # 用于 RISC-V 架构
    

picture

成功后显示得到的网址

picture

访问 localhost:(端口号),得到:

picture

同时查看终端中更新的 Log:

picture

任务五:ArceOS + virtio-net 网卡驱动 + UDP 发包应用程序 验证

吴大帅在 ArceOS 上做的 UDP 开发工作:

  1. 仓库: https://github.com/reflyable/arceos-udp(main 分支)
  2. 报告: https://github.com/reflyable/arceos-udp/tree/report/report

  1. 编译运行

    # arceos目录下
    make A=apps/net/udpserver ARCH=aarch64 LOG=info NET=y SMP=4 run
    

    运行成功出现如下结果

    picture

  2. 打开新的终端,输入

    nc -uv 0.0.0.0  (port number)
    

    其中port number为步骤一结果图中最后一行显示的端口号,在本例中此处输入

    nc -uv 0.0.0.0 5555
    

    若上述命令成功执行,则客户端输出如下

    picture

    服务器端输出如下

    picture

    此时在客户端键入任何文本,都会收到回复,例如输入hi后换行

    客户端显示输出如下

    picture

    服务器端输出如下

    picture

任务六:ArceOS + e1000 网卡驱动 + lwip 网络应用程序 验证

第二阶段:Linux 6.1 in Qemu 验证(5.8-5.20)

此阶段重点放在 Linux 6.1 内核的编译,不需要引入 rust4linux,尽量配置为 AArch64。

Qemu 支持的树莓派板子: https://www.qemu.org/docs/master/system/arm/raspi.html

raspi0 and raspi1ap ARM1176JZF-S core, 512 MiB of RAM

raspi2b Cortex-A7 (4 cores), 1 GiB of RAM

raspi3ap Cortex-A53 (4 cores), 512 MiB of RAM

raspi3b Cortex-A53 (4 cores), 1 GiB of RAM

树莓派 6.1 内核源码: https://github.com/raspberrypi/linux/tree/rpi-6.1.y

任务一:Linux 6.1 in x86/AArch64 编译

  1. 克隆仓库

    # 全部文件总计约为3.40GiB
    git clone https://github.com/raspberrypi/linux.git
    

    依据 linux/changes.rst at rpi-6.1.y · raspberrypi/linux (github.com) 安装或更新所需的软件

  2. 安装交叉编译所需的依赖:

    sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev libelf-dev
    
  3. 安装交叉编译器

    sudo apt install crossbuild-essential-arm64
    
  4. 配置编译目标

    cd linux
    KERNEL=kernel7
    make menuconfig # 进入之后按照菜单栏顶部说明移动选项至SAVE保存生成.config文件
    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig
    

    编译配置的默认参数 bcmrpi3_defconfig 文件可以参考 https://github.com/raspberrypi/linux/blob/rpi-6.1.y/arch/arm64/configs/bcmrpi3_defconfig

  5. 编译

    make -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs
    

    编译结束后应显示:

    picture

  6. 查看镜像位置

    picture

    上一步编译结束后,输入如下命令

    # linux目录下
    ls ./arch/arm64/boot
    

    可以看到对应目录下出现了Image镜像文件

    参考:15 分钟教你搞懂树莓派的 Linux 内核编译 - 知乎 (zhihu.com)

任务二:Linux 6.1 在 Qemu for x86/AArch64 中运行

Qemu 模拟器硬件支持

Qemu 模拟器支持的 virt machine 包含的模拟硬件(串口模拟用 One PL011 UART) https://www.qemu.org/docs/master/system/arm/virt.html

Qemu 模拟器支持的 raspi3b machine 包含的模拟硬件 https://www.qemu.org/docs/master/system/arm/raspi.html https://www.qemu.org/docs/master/system/arm/raspi.html#implemented-devices

树莓派 3B+的串口使用(有两个内建串口,一个是 PL011 Uart,一个是 Mini Uart) https://zhuanlan.zhihu.com/p/497002318

使用 busybox 制作内存文件系统 initramfs:

  1. 下载解压 busybox 并配置环境变量

    wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2
    tar -xf busybox-1.35.0.tar.bz2
    cd busybox-1.35.0
    # 配置环境变量
    export ARCH=arm64
    export CROSS_COMPILE=aarch64-linux-gnu-
    
  2. 配置编译内核的参数

    # busybox-1.35.0目录下
    make menuconfig
    # 修改配置,选中如下项目,静态编译
    # Settings -> Build Options -> [*] Build static binary (no share libs)
    
    # 反选如下项目,否则后续qemu执行会提示 /bin/sh:can't access tty;job control turned off
    # Shells -> [] Job control
    

    保存退出后,终端显示

    picture

  3. 编译

    make -j `nproc`
    

    编译结束后出现如下提示可以忽略

    Trying libraries: m resolv rt
    Library m is needed, can't exclude it (yet)
    Library resolv is needed, can't exclude it (yet)
    Library rt is not needed, excluding it
    Library m is needed, can't exclude it (yet)
    Library resolv is needed, can't exclude it (yet)
    Final link with: m resolv
    
  4. 安装

    安装前 busybox-1.35.0 目录下的文件如下图所示

    picture

    输入如下命令

    make install
    

    编译后 busybox-1.35.0 目录下的文件如下图所示

    picture

    安装后目录下生成了_install 目录

  5. 在_install 目录下创建后续所需的文件和目录

    cd _install
    mkdir proc sys dev tmp
    touch init
    chmod +x init
    
  6. 用任意的文本编辑器编辑 init 文件内容如下

    #!/bin/sh
    
    # 挂载一些必要的文件系统
    mount -t proc none /proc
    mount -t sysfs none /sys
    mount -t tmpfs none /tmp
    mount -t devtmpfs none /dev
    
    echo
    echo "Hello 64-bit ARM Linux"
    
    # 显示开机消耗时间
    echo "This boot took $(cut -d' ' -f1 /proc/uptime) seconds"
    echo
    
    # 停留在控制台
    exec /bin/sh
    
  7. 用 busybox 制作 initramfs 文件

    # _install目录
    find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
    

    执行成功后可在 busybox-1.35.0 目录下找到 initramfs.cpio.gz 文件

  8. 进入 qemu 目录下,执行如下命令

    qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 8 -m 128M -kernel (your Image path) -initrd (your initramfs.cpio.gz path) -nographic -append "init=/init console=ttyAMA0"
    

    其中(your Image path)为上一个任务中最后的Image镜像文件所在的目录,(your initramfs.cpio.gz)为步骤 7 中执行成功后得到的 initramfs.cpio.gz 的目录,例如

    qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 8 -m 128M -kernel /home/jun/maodou/linux/arch/arm64/boot/Image -initrd /home/jun/maodou/busybox-1.35.0/initramfs.cpio.gz -nographic -append "init=/init console=ttyAMA0"
    

    可使用相对路径

    其中,qemu 启动参数的意义如下:

    -M:指定模拟的开发板,可通过qemu-system-aarch64 M help查看
    -cpu:指定模拟的cpu,可通过qemu-system-aarch64 -M virt --cpu help查看,这里选择cortex-a72。
    -smp:指定cpu核数量,启动后可以使用nproc命令核对。
    -m:指定内存大小,virt 可支持超大内存,启动后可以使用free -h命令核对。
    -kernel:指定启动的内核镜像;
    -initrd:指定启动的内存文件系统;
    -append:传递给内核的启动参数;启动后可使用cat /proc/cmdline命令核对。
    -nographic:启动字符界面(不启动图形界面),输出重定向到宿主机命令行,与参数 console=ttyAMA0 组合使用
    

    运行结果如下所示

    [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
    [    0.000000] Linux version 6.1.25-v8+ (jun@DESKTOP-L2BA3J3) (aarch64-linux-gnu-gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #3 SMP PREEMPT Thu Apr 27 02:28:49 CST 2023
    [    0.000000] Machine model: linux,dummy-virt
    [    0.000000] efi: UEFI not found.
    [    0.000000] Zone ranges:
    [    0.000000]   DMA      [mem 0x0000000040000000-0x0000000047ffffff]
    [    0.000000]   DMA32    empty
    [    0.000000]   Normal   empty
    [    0.000000] Movable zone start for each node
    [    0.000000] Early memory node ranges
    [    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
    [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000047ffffff]
    [    0.000000] cma: Reserved 8 MiB at 0x0000000047400000
    [    0.000000] psci: probing for conduit method from DT.
    [    0.000000] psci: PSCIv0.2 detected in firmware.
    [    0.000000] psci: Using standard PSCI v0.2 function IDs
    [    0.000000] psci: Trusted OS migration not required
    [    0.000000] Number of cores (8) exceeds configured maximum of 4 - clipping
    [    0.000000] percpu: Embedded 28 pages/cpu s74152 r8192 d32344 u114688
    [    0.000000] Detected PIPT I-cache on CPU0
    [    0.000000] CPU features: detected: Spectre-v2
    [    0.000000] CPU features: detected: Spectre-v3a
    [    0.000000] CPU features: detected: Spectre-v4
    [    0.000000] CPU features: detected: Spectre-BHB
    [    0.000000] CPU features: kernel page table isolation forced ON by KASLR
    [    0.000000] CPU features: detected: Kernel page table isolation (KPTI)
    [    0.000000] CPU features: detected: ARM erratum 1742098
    [    0.000000] CPU features: detected: ARM errata 1165522, 1319367, or 1530923
    [    0.000000] alternatives: applying boot alternatives
    [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32256
    [    0.000000] Kernel command line: init=/init console=ttyAMA0
    [    0.000000] Dentry cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
    [    0.000000] Inode-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
    [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
    [    0.000000] Memory: 96388K/131072K available (11008K kernel code, 1978K rwdata, 3336K rodata, 3840K init, 1000K bss, 26492K reserved, 8192K cma-reserved)
    [    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
    [    0.000000] ftrace: allocating 35500 entries in 139 pages
    [    0.000000] ftrace: allocated 139 pages with 4 groups
    [    0.000000] trace event string verifier disabled
    [    0.000000] rcu: Preemptible hierarchical RCU implementation.
    [    0.000000] rcu:     RCU event tracing is enabled.
    [    0.000000]  Trampoline variant of Tasks RCU enabled.
    [    0.000000]  Rude variant of Tasks RCU enabled.
    [    0.000000]  Tracing variant of Tasks RCU enabled.
    [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 100 jiffies.
    [    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
    [    0.000000] Root IRQ handler: gic_handle_irq
    [    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
    [    0.000000] arch_timer: cp15 timer(s) running at 62.50MHz (virt).
    [    0.000000] clocksource: arch_sys_counter: mask: 0x1ffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
    [    0.000091] sched_clock: 57 bits at 63MHz, resolution 16ns, wraps every 4398046511096ns
    [    0.012917] Console: colour dummy device 80x25
    [    0.014715] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=62500)
    [    0.015162] pid_max: default: 32768 minimum: 301
    [    0.016408] LSM: Security Framework initializing
    [    0.022676] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
    [    0.022759] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
    [    0.072277] cgroup: Disabling memory control group subsystem
    [    0.097326] CPU node for /cpus/cpu@4 exist but the possible cpu range is :0-3
    [    0.098235] CPU node for /cpus/cpu@5 exist but the possible cpu range is :0-3
    [    0.098604] CPU node for /cpus/cpu@6 exist but the possible cpu range is :0-3
    [    0.098910] CPU node for /cpus/cpu@7 exist but the possible cpu range is :0-3
    [    0.100953] cacheinfo: Unable to detect cache hierarchy for CPU 0
    [    0.111760] cblist_init_generic: Setting adjustable number of callback queues.
    [    0.111947] cblist_init_generic: Setting shift to 2 and lim to 1.
    [    0.112516] cblist_init_generic: Setting shift to 2 and lim to 1.
    [    0.113354] cblist_init_generic: Setting shift to 2 and lim to 1.
    [    0.115810] rcu: Hierarchical SRCU implementation.
    [    0.115866] rcu:     Max phase no-delay instances is 400.
    [    0.123961] EFI services will not be available.
    [    0.128069] smp: Bringing up secondary CPUs ...
    [    0.132605] Detected PIPT I-cache on CPU1
    [    0.133404] cacheinfo: Unable to detect cache hierarchy for CPU 1
    [    0.133823] CPU1: Booted secondary processor 0x0000000001 [0x410fd083]
    [    0.141740] Detected PIPT I-cache on CPU2
    [    0.142124] cacheinfo: Unable to detect cache hierarchy for CPU 2
    [    0.142532] CPU2: Booted secondary processor 0x0000000002 [0x410fd083]
    [    0.146704] Detected PIPT I-cache on CPU3
    [    0.146999] cacheinfo: Unable to detect cache hierarchy for CPU 3
    [    0.147248] CPU3: Booted secondary processor 0x0000000003 [0x410fd083]
    [    0.147948] smp: Brought up 1 node, 4 CPUs
    [    0.148001] SMP: Total of 4 processors activated.
    [    0.148167] CPU features: detected: 32-bit EL0 Support
    [    0.148277] CPU features: detected: CRC32 instructions
    [    0.152631] CPU: All CPU(s) started at EL1
    [    0.152688] alternatives: applying system-wide alternatives
    [    0.188730] devtmpfs: initialized
    [    0.208840] Enabled cp15_barrier support
    [    0.209365] Enabled setend support
    [    0.212216] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns
    [    0.212512] futex hash table entries: 1024 (order: 4, 65536 bytes, linear)
    [    0.218927] pinctrl core: initialized pinctrl subsystem
    [    0.236330] DMI not present or invalid.
    [    0.249155] NET: Registered PF_NETLINK/PF_ROUTE protocol family
    [    0.276325] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
    [    0.279163] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
    [    0.280715] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
    [    0.281140] audit: initializing netlink subsys (disabled)
    [    0.285650] audit: type=2000 audit(0.222:1): state=initialized audit_enabled=0 res=1
    [    0.290581] thermal_sys: Registered thermal governor 'step_wise'
    [    0.291520] cpuidle: using governor menu
    [    0.293196] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
    [    0.295702] ASID allocator initialised with 32768 entries
    [    0.297182] Serial: AMBA PL011 UART driver
    [    0.351451] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1
    [    0.603658] printk: console [ttyAMA0] enabled
    [    0.620728] KASLR enabled
    [    0.712628] SCSI subsystem initialized
    [    0.716920] usbcore: registered new interface driver usbfs
    [    0.718003] usbcore: registered new interface driver hub
    [    0.718612] usbcore: registered new device driver usb
    [    0.721550] pps_core: LinuxPPS API ver. 1 registered
    [    0.721983] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
    [    0.724501] PTP clock support registered
    [    0.750721] clocksource: Switched to clocksource arch_sys_counter
    [    0.764408] VFS: Disk quotas dquot_6.6.0
    [    0.766205] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
    [    0.769411] FS-Cache: Loaded
    [    0.772236] CacheFiles: Loaded
    [    0.845061] NET: Registered PF_INET protocol family
    [    0.849606] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
    [    0.866793] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear)
    [    0.868451] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
    [    0.869340] TCP established hash table entries: 1024 (order: 1, 8192 bytes, linear)
    [    0.871024] TCP bind hash table entries: 1024 (order: 3, 32768 bytes, linear)
    [    0.872885] TCP: Hash tables configured (established 1024 bind 1024)
    [    0.876938] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
    [    0.878683] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
    [    0.883045] NET: Registered PF_UNIX/PF_LOCAL protocol family
    [    0.895783] RPC: Registered named UNIX socket transport module.
    [    0.896190] RPC: Registered udp transport module.
    [    0.896414] RPC: Registered tcp transport module.
    [    0.897470] RPC: Registered tcp NFSv4.1 backchannel transport module.
    [    0.912912] hw perfevents: enabled with armv8_pmuv3 PMU driver, 5 counters available
    [    0.915441] Trying to unpack rootfs image as initramfs...
    [    1.179258] Freeing initrd memory: 1140K
    [    2.287308] Initialise system trusted keyrings
    [    2.297304] workingset: timestamp_bits=46 max_order=15 bucket_order=0
    [    2.324224] zbud: loaded
    [    2.341364] NFS: Registering the id_resolver key type
    [    2.343083] Key type id_resolver registered
    [    2.343402] Key type id_legacy registered
    [    2.345689] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
    [    2.346213] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
    [    2.357375] Key type asymmetric registered
    [    2.358373] Asymmetric key parser 'x509' registered
    [    2.360307] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 247)
    [    2.362114] io scheduler mq-deadline registered
    [    2.363186] io scheduler kyber registered
    [    2.421284] vc-mem: phys_addr:0x00000000 mem_base=0x00000000 mem_size:0x00000000(0 MiB)
    [    2.428120] cacheinfo: Unable to detect cache hierarchy for CPU 0
    [    2.503885] brd: module loaded
    [    2.547578] loop: module loaded
    [    2.553900] Loading iSCSI transport class v2.0-870.
    [    2.564699] usbcore: registered new interface driver lan78xx
    [    2.565208] usbcore: registered new interface driver smsc95xx
    [    2.566010] dwc_otg: version 3.00a 10-AUG-2012 (platform bus)
    [    2.570927] usbcore: registered new interface driver usb-storage
    [    2.579958] sdhci: Secure Digital Host Controller Interface driver
    [    2.580349] sdhci: Copyright(c) Pierre Ossman
    [    2.582803] sdhci-pltfm: SDHCI platform and OF driver helper
    [    2.586599] ledtrig-cpu: registered to indicate activity on CPUs
    [    2.589870] hid: raw HID events driver (C) Jiri Kosina
    [    2.591268] usbcore: registered new interface driver usbhid
    [    2.591876] usbhid: USB HID core driver
    [    2.597777] Initializing XFRM netlink socket
    [    2.598860] NET: Registered PF_PACKET protocol family
    [    2.600248] Key type dns_resolver registered
    [    2.606225] registered taskstats version 1
    [    2.606980] Loading compiled-in X.509 certificates
    [    2.616060] Key type .fscrypt registered
    [    2.616320] Key type fscrypt-provisioning registered
    [    2.728236] of_cfs_init
    [    2.738597] of_cfs_init: OK
    [    2.765467] uart-pl011 9000000.pl011: no DMA platform data
    [    2.837268] Freeing unused kernel memory: 3840K
    [    2.843935] Run /init as init process
    
    Hello 64-bit ARM Linux
    This boot took 10732.04 seconds
    
    / #
    
  9. 在启动的 linux 内核中的终端输入ls命令查看当前目录下文件列表,如下图所示

    picture

    可以看到文件列表与_install 目录下的文件保持一致

参考资料:QEMU 启动 ARM64 Linux 内核linux 启动 qemu许振坪的博客-CSDN 博客

任务三:Linux 6.1 + 网卡驱动 在 Qemu for x86/AArch64 中运行

背景知识

Linux 镜像如何添加驱动,安装 virtio 驱动(Linux)

PCI:接口 -netdev 设置接口 NIC:网卡 -device 设置网卡

参考配置

Qemu 模拟 E1000 网卡

Boot options

Here is a simple setup with one e1000e NIC :

$ qemu-system-ppc64 -m 2G -machine powernv9 -smp 2,cores=2,threads=1 \
-accel tcg,thread=single \
-device e1000e,netdev=net0,mac=C0:FF:EE:00:00:02,bus=pcie.0,addr=0x0 \
-netdev user,id=net0,hostfwd=::20022-:22,hostname=pnv \
-kernel ./zImage.epapr  \
-initrd ./rootfs.cpio.xz \
-nographic

zCore 里面模拟了 e1000 网卡,qemu_opts 需要增加 2 行以指定 e1000

qemu_opts += \
	-netdev user,id=net1,hostfwd=tcp::8000-:80,hostfwd=tcp::2222-:2222,hostfwd=udp::6969-:6969 \
	-device e1000e,netdev=net1

参考:Documentation/Networking - QEMU

  • 编译内核

    make clean
    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
    make -j4  ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs
    
  • 运行

    qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 8 -m 128M -kernel (your Image path) -initrd (your initramfs.cpio.gz path) -nographic -netdev user,id=net0 -device e1000e,netdev=net0,mac=C0:FF:EE:00:00:02
    

    例如:

    qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 8 -m 128M -kernel (your Image path) -initrd (your initramfs.cpio.gz path) -nographic -netdev user,id=net0 -device e1000e,netdev=net0,mac=C0:FF:EE:00:00:02
    

    -netdev user是设置网络接口为 user,-device是指定网卡,此处是使用 e1000e

    下面是运行结果:

    qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 8 -m 128M -kernel /home/jun/maodou/linux/arch/arm64/boot/Image -initrd /home/jun/maodou/busybox-1.35.0/initramfs.cpio.gz -nographic -netdev user,id=net0 -device e1000e,netdev=net0,mac=C0:FF:EE:00:00:02
    [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
    [    0.000000] Linux version 6.1.25-gfc30a915ea61-dirty (jun@DESKTOP-L2BA3J3) (aarch64-linux-gnu-gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #6 SMP PREEMPT Sun Apr 30 13:48:59 CST 2023
    [    0.000000] Machine model: linux,dummy-virt
    [    0.000000] efi: UEFI not found.
    [    0.000000] NUMA: No NUMA configuration found
    [    0.000000] NUMA: Faking a node at [mem 0x0000000040000000-0x0000000047ffffff]
    [    0.000000] NUMA: NODE_DATA [mem 0x47fafa00-0x47fb1fff]
    [    0.000000] Zone ranges:
    [    0.000000]   DMA      [mem 0x0000000040000000-0x0000000047ffffff]
    [    0.000000]   DMA32    empty
    [    0.000000]   Normal   empty
    [    0.000000] Movable zone start for each node
    [    0.000000] Early memory node ranges
    [    0.000000]   node   0: [mem 0x0000000040000000-0x0000000047ffffff]
    [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000047ffffff]
    [    0.000000] cma: Reserved 32 MiB at 0x0000000045c00000
    [    0.000000] psci: probing for conduit method from DT.
    [    0.000000] psci: PSCIv0.2 detected in firmware.
    [    0.000000] psci: Using standard PSCI v0.2 function IDs
    [    0.000000] psci: Trusted OS migration not required
    [    0.000000] percpu: Embedded 20 pages/cpu s44840 r8192 d28888 u81920
    [    0.000000] Detected PIPT I-cache on CPU0
    [    0.000000] CPU features: detected: Spectre-v2
    [    0.000000] CPU features: detected: Spectre-v3a
    [    0.000000] CPU features: detected: Spectre-v4
    [    0.000000] CPU features: detected: Spectre-BHB
    [    0.000000] CPU features: kernel page table isolation forced ON by KASLR
    [    0.000000] CPU features: detected: Kernel page table isolation (KPTI)
    [    0.000000] CPU features: detected: ARM erratum 1742098
    [    0.000000] CPU features: detected: ARM errata 1165522, 1319367, or 1530923
    [    0.000000] alternatives: applying boot alternatives
    [    0.000000] Fallback order for Node 0: 0
    [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32256
    [    0.000000] Policy zone: DMA
    [    0.000000] Kernel command line:
    [    0.000000] Dentry cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
    [    0.000000] Inode-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
    [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
    [    0.000000] Memory: 56008K/131072K available (16064K kernel code, 3706K rwdata, 8836K rodata, 7552K init, 609K bss, 42296K reserved, 32768K cma-reserved)
    [    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1
    [    0.000000] rcu: Preemptible hierarchical RCU implementation.
    [    0.000000] rcu:     RCU event tracing is enabled.
    [    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=8.
    [    0.000000]  Trampoline variant of Tasks RCU enabled.
    [    0.000000]  Tracing variant of Tasks RCU enabled.
    [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
    [    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=8
    [    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
    [    0.000000] Root IRQ handler: gic_handle_irq
    [    0.000000] GICv2m: range[mem 0x08020000-0x08020fff], SPI[80:143]
    [    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
    [    0.000000] arch_timer: cp15 timer(s) running at 62.50MHz (virt).
    [    0.000000] clocksource: arch_sys_counter: mask: 0x1ffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
    [    0.000076] sched_clock: 57 bits at 63MHz, resolution 16ns, wraps every 4398046511096ns
    [    0.007920] Console: colour dummy device 80x25
    [    0.010044] printk: console [tty0] enabled
    [    0.012330] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=250000)
    [    0.012500] pid_max: default: 32768 minimum: 301
    [    0.013262] LSM: Security Framework initializing
    [    0.016003] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
    [    0.016065] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
    [    0.047451] cgroup: Disabling memory control group subsystem
    [    0.063952] cacheinfo: Unable to detect cache hierarchy for CPU 0
    [    0.070942] cblist_init_generic: Setting adjustable number of callback queues.
    [    0.071145] cblist_init_generic: Setting shift to 3 and lim to 1.
    [    0.071441] cblist_init_generic: Setting shift to 3 and lim to 1.
    [    0.072850] rcu: Hierarchical SRCU implementation.
    [    0.072904] rcu:     Max phase no-delay instances is 1000.
    [    0.078647] EFI services will not be available.
    [    0.080163] smp: Bringing up secondary CPUs ...
    [    0.083812] Detected PIPT I-cache on CPU1
    [    0.084409] cacheinfo: Unable to detect cache hierarchy for CPU 1
    [    0.084815] CPU1: Booted secondary processor 0x0000000001 [0x410fd083]
    [    0.089347] Detected PIPT I-cache on CPU2
    [    0.089523] cacheinfo: Unable to detect cache hierarchy for CPU 2
    [    0.089738] CPU2: Booted secondary processor 0x0000000002 [0x410fd083]
    [    0.091006] Detected PIPT I-cache on CPU3
    [    0.091154] cacheinfo: Unable to detect cache hierarchy for CPU 3
    [    0.091279] CPU3: Booted secondary processor 0x0000000003 [0x410fd083]
    [    0.092569] Detected PIPT I-cache on CPU4
    [    0.092704] cacheinfo: Unable to detect cache hierarchy for CPU 4
    [    0.092838] CPU4: Booted secondary processor 0x0000000004 [0x410fd083]
    [    0.094313] Detected PIPT I-cache on CPU5
    [    0.094455] cacheinfo: Unable to detect cache hierarchy for CPU 5
    [    0.094612] CPU5: Booted secondary processor 0x0000000005 [0x410fd083]
    [    0.096838] Detected PIPT I-cache on CPU6
    [    0.097059] cacheinfo: Unable to detect cache hierarchy for CPU 6
    [    0.097407] CPU6: Booted secondary processor 0x0000000006 [0x410fd083]
    [    0.098799] Detected PIPT I-cache on CPU7
    [    0.098941] cacheinfo: Unable to detect cache hierarchy for CPU 7
    [    0.099114] CPU7: Booted secondary processor 0x0000000007 [0x410fd083]
    [    0.099976] smp: Brought up 1 node, 8 CPUs
    [    0.100270] SMP: Total of 8 processors activated.
    [    0.100373] CPU features: detected: 32-bit EL0 Support
    [    0.100415] CPU features: detected: 32-bit EL1 Support
    [    0.100493] CPU features: detected: CRC32 instructions
    [    0.104523] CPU: All CPU(s) started at EL1
    [    0.104766] alternatives: applying system-wide alternatives
    [    0.134654] devtmpfs: initialized
    [    0.151198] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
    [    0.151670] futex hash table entries: 2048 (order: 5, 131072 bytes, linear)
    [    0.156256] pinctrl core: initialized pinctrl subsystem
    [    0.167152] DMI not present or invalid.
    [    0.178729] NET: Registered PF_NETLINK/PF_ROUTE protocol family
    [    0.191012] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
    [    0.192709] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
    [    0.193016] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
    [    0.193311] audit: initializing netlink subsys (disabled)
    [    0.195980] audit: type=2000 audit(0.176:1): state=initialized audit_enabled=0 res=1
    [    0.201001] thermal_sys: Registered thermal governor 'step_wise'
    [    0.201119] thermal_sys: Registered thermal governor 'power_allocator'
    [    0.201591] cpuidle: using governor menu
    [    0.202702] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
    [    0.204553] ASID allocator initialised with 32768 entries
    [    0.210462] Serial: AMBA PL011 UART driver
    [    0.250626] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1
    [    0.412612] printk: console [ttyAMA0] enabled
    [    0.432545] KASLR enabled
    [    0.465245] HugeTLB: registered 1.00 GiB page size, pre-allocated 0 pages
    [    0.468073] HugeTLB: 0 KiB vmemmap can be freed for a 1.00 GiB page
    [    0.469774] HugeTLB: registered 32.0 MiB page size, pre-allocated 0 pages
    [    0.473402] HugeTLB: 0 KiB vmemmap can be freed for a 32.0 MiB page
    [    0.474257] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
    [    0.478495] HugeTLB: 0 KiB vmemmap can be freed for a 2.00 MiB page
    [    0.479951] HugeTLB: registered 64.0 KiB page size, pre-allocated 0 pages
    [    0.481171] HugeTLB: 0 KiB vmemmap can be freed for a 64.0 KiB page
    [    0.497351] ACPI: Interpreter disabled.
    [    0.506097] iommu: Default domain type: Translated
    [    0.507213] iommu: DMA domain TLB invalidation policy: strict mode
    [    0.512840] SCSI subsystem initialized
    [    0.517128] usbcore: registered new interface driver usbfs
    [    0.517968] usbcore: registered new interface driver hub
    [    0.518780] usbcore: registered new device driver usb
    [    0.526644] pps_core: LinuxPPS API ver. 1 registered
    [    0.527189] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
    [    0.529573] PTP clock support registered
    [    0.530874] EDAC MC: Ver: 3.0.0
    [    0.540321] FPGA manager framework
    [    0.543878] Advanced Linux Sound Architecture Driver Initialized.
    [    0.561118] vgaarb: loaded
    [    0.574033] clocksource: Switched to clocksource arch_sys_counter
    [    0.577531] VFS: Disk quotas dquot_6.6.0
    [    0.579154] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
    [    0.589008] pnp: PnP ACPI: disabled
    [    0.633693] NET: Registered PF_INET protocol family
    [    0.636445] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
    [    0.648946] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear)
    [    0.649690] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
    [    0.650529] TCP established hash table entries: 1024 (order: 1, 8192 bytes, linear)
    [    0.651585] TCP bind hash table entries: 1024 (order: 3, 32768 bytes, linear)
    [    0.652841] TCP: Hash tables configured (established 1024 bind 1024)
    [    0.655092] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
    [    0.655707] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
    [    0.660727] NET: Registered PF_UNIX/PF_LOCAL protocol family
    [    0.666423] RPC: Registered named UNIX socket transport module.
    [    0.667081] RPC: Registered udp transport module.
    [    0.668086] RPC: Registered tcp transport module.
    [    0.668547] RPC: Registered tcp NFSv4.1 backchannel transport module.
    [    0.669484] PCI: CLS 0 bytes, default 64
    [    0.678630] Unpacking initramfs...
    [    0.682946] hw perfevents: enabled with armv8_pmuv3 PMU driver, 5 counters available
    [    0.689163] kvm [1]: HYP mode not available
    [    0.698184] Initialise system trusted keyrings
    [    0.705175] workingset: timestamp_bits=42 max_order=15 bucket_order=0
    [    0.730389] squashfs: version 4.0 (2009/01/31) Phillip Lougher
    [    0.736416] NFS: Registering the id_resolver key type
    [    0.740411] Key type id_resolver registered
    [    0.743369] Key type id_legacy registered
    [    0.745312] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
    [    0.749096] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
    [    0.753622] 9p: Installing v9fs 9p2000 file system support
    [    0.800839] Key type asymmetric registered
    [    0.801297] Asymmetric key parser 'x509' registered
    [    0.802532] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
    [    0.803498] io scheduler mq-deadline registered
    [    0.804339] io scheduler kyber registered
    [    0.850819] Freeing initrd memory: 1140K
    [    0.853844] pl061_gpio 9030000.pl061: PL061 GPIO chip registered
    [    0.862556] pci-host-generic 4010000000.pcie: host bridge /pcie@10000000 ranges:
    [    0.864113] pci-host-generic 4010000000.pcie:       IO 0x003eff0000..0x003effffff -> 0x0000000000
    [    0.865492] pci-host-generic 4010000000.pcie:      MEM 0x0010000000..0x003efeffff -> 0x0010000000
    [    0.865949] pci-host-generic 4010000000.pcie:      MEM 0x8000000000..0xffffffffff -> 0x8000000000
    [    0.867194] pci-host-generic 4010000000.pcie: Memory resource size exceeds max for 32 bits
    [    0.869698] pci-host-generic 4010000000.pcie: ECAM at [mem 0x4010000000-0x401fffffff] for [bus 00-ff]
    [    0.872749] pci-host-generic 4010000000.pcie: PCI host bridge to bus 0000:00
    [    0.873662] pci_bus 0000:00: root bus resource [bus 00-ff]
    [    0.874127] pci_bus 0000:00: root bus resource [io  0x0000-0xffff]
    [    0.874910] pci_bus 0000:00: root bus resource [mem 0x10000000-0x3efeffff]
    [    0.875453] pci_bus 0000:00: root bus resource [mem 0x8000000000-0xffffffffff]
    [    0.878873] pci 0000:00:00.0: [1b36:0008] type 00 class 0x060000
    [    0.885660] pci 0000:00:01.0: [8086:10d3] type 00 class 0x020000
    [    0.886295] pci 0000:00:01.0: reg 0x10: [mem 0x00000000-0x0001ffff]
    [    0.886750] pci 0000:00:01.0: reg 0x14: [mem 0x00000000-0x0001ffff]
    [    0.887329] pci 0000:00:01.0: reg 0x18: [io  0x0000-0x001f]
    [    0.888488] pci 0000:00:01.0: reg 0x1c: [mem 0x00000000-0x00003fff]
    [    0.888783] pci 0000:00:01.0: reg 0x30: [mem 0x00000000-0x0007ffff pref]
    [    0.894141] pci 0000:00:01.0: BAR 6: assigned [mem 0x10000000-0x1007ffff pref]
    [    0.894784] pci 0000:00:01.0: BAR 0: assigned [mem 0x10080000-0x1009ffff]
    [    0.895135] pci 0000:00:01.0: BAR 1: assigned [mem 0x100a0000-0x100bffff]
    [    0.895491] pci 0000:00:01.0: BAR 3: assigned [mem 0x100c0000-0x100c3fff]
    [    0.895865] pci 0000:00:01.0: BAR 2: assigned [io  0x1000-0x101f]
    [    0.903785] EINJ: ACPI disabled.
    [    0.973656] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
    [    0.982418] SuperH (H)SCI(F) driver initialized
    [    0.983837] msm_serial: driver initialized
    [    0.988656] cacheinfo: Unable to detect cache hierarchy for CPU 0
    [    1.015481] loop: module loaded
    [    1.018467] megasas: 07.719.03.00-rc1
    [    1.026907] physmap-flash 0.flash: physmap platform flash device: [mem 0x00000000-0x03ffffff]
    [    1.029881] 0.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
    [    1.032254] Intel/Sharp Extended Query Table at 0x0031
    [    1.033856] Using buffer write method
    [    1.034612] physmap-flash 0.flash: physmap platform flash device: [mem 0x04000000-0x07ffffff]
    [    1.035784] 0.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
    [    1.036668] Intel/Sharp Extended Query Table at 0x0031
    [    1.037892] Using buffer write method
    [    1.042241] Concatenating MTD devices:
    [    1.043181] (0): "0.flash"
    [    1.043340] (1): "0.flash"
    [    1.043475] into device "0.flash"
    [    1.135325] tun: Universal TUN/TAP device driver, 1.6
    [    1.139309] thunder_xcv, ver 1.0
    [    1.140468] thunder_bgx, ver 1.0
    [    1.141381] nicpf, ver 1.0
    [    1.145694] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
    [    1.146002] hns3: Copyright (c) 2017 Huawei Corporation.
    [    1.146554] hclge is initializing
    [    1.146788] e1000: Intel(R) PRO/1000 Network Driver
    [    1.146926] e1000: Copyright (c) 1999-2006 Intel Corporation.
    [    1.147300] e1000e: Intel(R) PRO/1000 Network Driver
    [    1.147497] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
    [    1.149866] e1000e 0000:00:01.0: enabling device (0000 -> 0002)
    [    1.153859] e1000e 0000:00:01.0: Interrupt Throttling Rate (ints/sec) set to dynamic conservative mode
    [    1.210632] e1000e 0000:00:01.0 0000:00:01.0 (uninitialized): registered PHC clock
    [    1.267834] e1000e 0000:00:01.0 eth0: (PCI Express:2.5GT/s:Width x1) c0:ff:ee:00:00:02
    [    1.269040] e1000e 0000:00:01.0 eth0: Intel(R) PRO/1000 Network Connection
    [    1.269793] e1000e 0000:00:01.0 eth0: MAC: 3, PHY: 8, PBA No: 000000-000
    [    1.270558] igb: Intel(R) Gigabit Ethernet Network Driver
    [    1.270842] igb: Copyright (c) 2007-2014 Intel Corporation.
    [    1.271492] igbvf: Intel(R) Gigabit Virtual Function Network Driver
    [    1.272275] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
    [    1.273745] sky2: driver version 1.30
    [    1.277125] VFIO - User Level meta-driver version: 0.3
    [    1.287749] usbcore: registered new interface driver usb-storage
    [    1.301808] rtc-pl031 9010000.pl031: registered as rtc0
    [    1.302825] rtc-pl031 9010000.pl031: setting system clock to 2023-04-30T06:10:30 UTC (1682835030)
    [    1.305806] i2c_dev: i2c /dev entries driver
    [    1.323678] sdhci: Secure Digital Host Controller Interface driver
    [    1.324345] sdhci: Copyright(c) Pierre Ossman
    [    1.327161] Synopsys Designware Multimedia Card Interface Driver
    [    1.329910] sdhci-pltfm: SDHCI platform and OF driver helper
    [    1.338273] ledtrig-cpu: registered to indicate activity on CPUs
    [    1.346070] usbcore: registered new interface driver usbhid
    [    1.346365] usbhid: USB HID core driver
    [    1.366689] NET: Registered PF_PACKET protocol family
    [    1.368545] 9pnet: Installing 9P2000 support
    [    1.369227] Key type dns_resolver registered
    [    1.371120] registered taskstats version 1
    [    1.371594] Loading compiled-in X.509 certificates
    [    1.452939] input: gpio-keys as /devices/platform/gpio-keys/input/input0
    [    1.466718] ALSA device list:
    [    1.466984]   No soundcards found.
    [    1.474464] uart-pl011 9000000.pl011: no DMA platform data
    [    1.532887] Freeing unused kernel memory: 7552K
    [    1.536640] Run /init as init process
    
    Hello 64-bit ARM Linux
    This boot took 10732.04 seconds
    
    / # ls
    bin      init     proc     sbin     tmp
    dev      linuxrc  root     sys      usr
    / # ifconfig
    / # ifconfig -a
    eth0      Link encap:Ethernet  HWaddr C0:FF:EE:00:00:02
            BROADCAST MULTICAST  MTU:1500  Metric:1
            RX packets:0 errors:0 dropped:0 overruns:0 frame:0
            TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000
            RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
            Interrupt:16 Memory:10080000-100a0000
    
    lo        Link encap:Local Loopback
            LOOPBACK  MTU:65536  Metric:1
            RX packets:0 errors:0 dropped:0 overruns:0 frame:0
            TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000
            RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    
    / # ifconfig lo up
    / # ping 127.0.0.1
    PING 127.0.0.1 (127.0.0.1): 56 data bytes
    64 bytes from 127.0.0.1: seq=0 ttl=64 time=12.804 ms
    64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.570 ms
    64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.492 ms
    

    picture

    注意 ifconfig 命令只能显示已经激活的网卡,要想看到本地已有的网卡需要使用 ifconfig -a

    另外,不管是模拟 e1000 还是 virtio_net,如果成功都将以 eth0 的形式出现。可以看到 eth0 网卡的 mac 地址,与运行 qemu 时所用的参数:

    -device e1000e,netdev=net0,mac=C0:FF:EE:00:00:02
    

    中设置的 mac 地址是一致的。 从运行结果可以看出,当网络接口为 user 的时候,在使用命令 ifconfig lo up ,激活 lo (回环接口)之后,能够成功 ping 127.0.0.1(本地 ip)。

    picture

    但是,激活 eth0 网卡之后,并不能 ping 任何 ip ,包括本地 ip :

    picture

    依据 qemu 官方文档https://wiki.qemu.org/Documentation/Networking,若想要 ping 得其他 ip,需要将网络接口设置为 tap 。 将 -netdev user 改为 -netdev tap ,执行:

    sudo qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 8 -m 128M -kernel /home/jun/maodou/linux/arch/arm64/boot/Image -initrd /home/jun/maodou/busybox-1.35.0/initramfs.cpio.gz -nographic -netdev tap,id=net0 -device e1000e,netdev=net0,mac=C0:FF:EE:00:00:02
    

    picture

    可以成功运行,但是在 eth0 被激活的状态下,

    picture

    sudo qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 8 -m 128M -kernel /home/jun/maodou/linux/arch/arm64/boot/Image -initrd /home/jun/maodou/busybox-1.35.0/initramfs.cpio.gz -nographic -netdev tap,id=net0,ifname=tap0 -device e1000e,netdev=net0,mac=C0:FF:EE:00:00:02
    

    无法 ping 外网。

    如果使用 ifconfig eth0 arbitrary_ip 命令设置 eth0 的 ip,此处是 123.123.12.13:

    picture

    可以看到如果只激活 eth0,无法 ping eth0 网卡的 ip。

    picture

    但是在激活 lo 网卡之后,是可以 ping eth0 网卡的 ip 的。

任务四:Linux 6.1 + 网卡驱动 + UDP 发包在 Qemu 中运行

任务五:Linux 6.1 UDP 发包 + ArceOS UDP 收包在 Qemu 中运行

第三阶段:Rust for Linux 驱动验证(5.22-6.1)

此阶段重点放在跑通 rust for linux 的驱动代码编译,可不考虑 AArch64,先基于 x86 跑通。

  • M1: R4L 编译 e1000 网卡内核模块,解决编译环境和编译错误,生成 .ko 驱动模块 当前进展:米明恒已经完成,成功生成 .ko 驱动模块 ✅,还有待验证
  • M2: 基于 Qemu e1000 模拟器,在 Linux 6.1 加载 .ko 驱动,测试跑通 ping 工作计划:由米明恒,向毅恺负责验证,争取 5.8 跑通
  • M3: R4L 编译 dw 网卡内核模块,解决编译环境和编译错误,生成 .ko 驱动模块 工作计划:由何家胜,朱懿一起用 C 写一个简单版的 dw 驱动,争取 5.22 之前上板子跑通 由米明恒,唐洪雨一起用 R4L 写 dw 驱动,争取 5.22 之前生成 .ko 驱动模块
  • M4: 基于黑芝麻 evb 板子 或 hw204 开发板,在 Linux 6.1 加载 .ko 驱动,测试跑通 ping 工作计划:朱懿(evb),向毅恺(hw204) 一起争取 5.29 之前上板子跑通
  • M5: 编写整理有关技术文档,总结 R4L 开发工程经验 工作计划:由米明恒负责 5.29 在训练营第三阶段进行为期一周的 LDD in Rust 课程

任务零:环境搭建 C 语言内核模块的编译和测试

参考唐洪雨的最简驱动体验

环境搭建

Docker 安装

为了统一开发环境,同时于其它开发环境做隔离,选择在 Docker 中做开发。

卸载旧版本

sudo apt remove docker docker-engine docker.io containerd runc

其中:

  • docker-engine 在 Debian 仓库中已不存在,所以可能会报错,删除后重新执行即可。

使用仓库安装

Docker 支持多种安装方式,这里选择通过 apt 仓库的形式安装。

设置仓库

更新 apt 包索引,并允许 apt 通过 HTTPS 使用仓库:

sudo apt update
sudo apt install ca-certificates curl gnupg

安装一些必要的软件包:

sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

添加 Docker 的官方 GPG 密钥:

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

使用以下命令设置仓库:

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

添加 Docker 的仓库:

对于 Ubuntu 20.04 (Focal Fossa) 和更高版本:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

对于 Ubuntu 18.04 (Bionic Beaver):

oslab@oslab-virtual-machine:~$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

安装 Docker Engine

更新 apt 包索引:

sudo apt-get update

安装 Docker Engine, containerd 和 Docker Compose

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

通过运行 hello-world 镜像来确认 Docker Engine 安装成功:

sudo docker run hello-world

成功输出:

picture

Docter 配置

Qemu

apt install qemu-utils qemu-system-x86 qemu-system-gui

Busybox

apt install cpio

编译依赖

apt -y install \
  binutils build-essential libtool texinfo \
  gzip zip unzip patchutils curl git \
  make cmake ninja-build automake bison flex gperf \
  grep sed gawk bc \
  zlib1g-dev libexpat1-dev libmpc-dev \
  libglib2.0-dev libfdt-dev libpixman-1-dev

Clang

apt install clang-format clang-tidy clang-tools clang clangd libc++-dev libc++1 libc++abi-dev libc++abi1 libclang-dev libclang1 liblldb-dev libllvm-ocaml-dev libomp-dev libomp5 lld lldb llvm-dev llvm-runtime llvm python3-clang

编译器

根据开发环境,下载的是 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz。

解压后将 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin 添加进环境变量,便于后续使用。

C 驱动开发

首先编写模块的必要代码

// file name: hellomodule.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

static int __init hello_init(void) {
    printk("[ default ] Hello Module Init\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk("[ default ] Hello Module Exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL2");
MODULE_AUTHOR("THY");
MODULE_DESCRIPTION("hello module");
MODULE_ALIAS("test_module");

其中:

  • module_init(hello_init) 用来指定模块的初始化函数,在 insmod 时被调用
  • module_init(hello_exit) 用来指定模块的初始化函数,在 rmmod 时被调用
  • MODULE_* 用来指定模块的相关信息,在 modinfo 时被调用

编译

# file name: Makefile

KERNRL_DIR = /path/to/src/linux-6.1.21

ARCH := arm64
CROSS_COMPILE := aarch64-linux-gnu-
PATH := $(PATH):/path/to/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
export ARCH CROSS_COMPILE PATH

obj-m := hellomodule.o

all:
    $(MAKE) -C $(KERNRL_DIR) M=$(CURDIR) modules

.PHONE: clean

clean:
    $(MAKE) -C $(KERNRL_DIR) M=$(CURDIR) clean

运行 make 后得到 hellomodule.ko 文件,将之放入根文件系统中。

测试模块

启动虚拟机,加载模块:

/ # insmod hellomodule.ko
hellomodule: loading out-of-tree module taints kernel.
hellomodule: module license 'GPL2' taints kernel.
Disabling lock debugging due to kernel taint
[ default ] Hello Module Init

可以看到有 hello_init() 中的输出内容,表明初始化函数被执行。 卸载模块:

/ # rmmod hellomodule.ko
[ default ] Hello Module Exit

可以看到有 hello_exit() 中的输出内容,表明卸载函数被执行。

查看模块信息:

/ # modinfo hellomodule.ko
filename:       hellomodule.ko
author:         THY
description:    hello module
license:        GPL2
alias:          test_module
depends:
vermagic:       6.1.21 SMP mod_unload ARMv7 p2v8

任务一:R4L e10000 网卡驱动代码内核模块编译

linux 内核下载

代码地址: https://github.com/os2edu/rust-for-linux-6.1 (目前驱动可以在这个内核运行)

下载、解压后进入,查看 Documentation/rust/quick-start.rst 可以看到开启内核里 Rust 支持的一些先决条件

# 1. 指定 rustc 版本:
rustup override set $(scripts/min-tool-version.sh rustc)

# 2. 添加 rust 源码
rustup component add rust-src

# 3. libclang:从 https://releases.llvm.org/download.html 下载最新编译好的内容,将 bin 文件夹加入环境变量

# 4. 指定 binggen 版本:
cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen

# 5. 其余内容在安装 rust 时都已自动安装

# 6. 检查依赖是否满足
make LLVM=1 rustavailable

内核配置

# 1. 选择基本环境,当前版本内核支持的并不宽泛,x86_64 和 arm64(aarch64)的限制少:
make x86_64_defconfig
# 2.1 General setup ->
#       [*] Rust support
# 2.2 Kernel hacking ->
#       [*] Sample kernel code ->
#           [*] Rust samples ->
#               [*] Minimal
# 2.3 Device Driver ->
#   Network device support ->
#     Ethernet driver suppart ->
#      Intel devices ->
#        <*> Intel(R) PRO/100+ support
#        <M> Intel(R) PRO/100 Gigabit Ethernet support
#        <*> Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support
make LLVM=1 menuconfig
# 3. 编译
make LLVM=1

为了保证顺利加载驱动模块需要将 busybox 重新编译与内核架构一致

进入 BusyBox 源代码所在的目录

make clean

生成默认的 .config 文件:

make defconfig

运行 make menuconfig

make menuconfig

在菜单界面中,找到以下选项:

Busybox Settings  --->
    Build Options  --->

选中 Build BusyBox as a static binary (no shared libs),然后按 Y 键。这将确保 BusyBox 静态链接,使其在不同系统上更容易运行。

保存配置并退出 menuconfig。

编译 BusyBox:

make

安装 BusyBox:

make install

这将在 _install 子目录中创建一个包含 BusyBox 可执行文件和符号链接的文件系统。然后将 BusyBox 的二进制文件复制到适当的目录,以便在您的环境中使用。

r4l e1000 驱动模块下载

git clone https://github.com/myrfy001/r4l-e1000.git

注意 build_image 脚本,需要根据你的电脑更改相应的路径。

例如:

set -e

# Build the kernel module
make -C ~/rust-for-linux-6.1 M=$PWD LLVM=1 CLIPPY=1

# Copy the build kernel module to the rootfs folder, there should be a usable busybox at `rootfs` folder
cp ./r4l_e1000_demo.ko ../rootfs

# Build the rootfs image
pushd ../rootfs && \
find . | cpio -o --format=newc > ../rootfs.img && \
popd


# Run QEMU to test the kernel, the network traffic will be dumped to `dump.dat` and you can use wireshark to explore the result.
qemu-system-x86_64 \
-netdev "user,id=eth0" \
-device "e1000,netdev=eth0" \
-object "filter-dump,id=eth0,netdev=eth0,file=dump.dat" \
-kernel ../rust-for-linux-6.1/arch/x86/boot/bzImage \
-append "root=/dev/ram rdinit=sbin/init ip=10.0.2.15::10.0.2.1:255.255.255.0 console=ttyS0" \
-nographic \
-initrd ../rootfs.img

任务二:Linux 6.1 + R4L e10000 网卡驱动 在 Qemu 中运行

配置完成后,在 r4l-e1000 文件目录下,执行:

bash ./build_image.sh

内核启动时,键入以下命令以安装驱动程序并配置网络接口:

insmod r4l_e1000_demo.ko
ip link set eth0 up
ip addr add broadcast 10.0.2.255 dev eth0
ip addr add 10.0.2.15/255.255.255.0 dev eth0
ip route add default via 10.0.2.1

然后,ping 主机以查看最终结果:

ping 10.0.2.2

可以看到成功 ping 通:

picture

结束后返回结果:

picture

任务三:R4L virtio-net 网卡驱动代码内核模块编译

任务四:Linux 6.1 + R4L virtio-net 网卡驱动 在 Qemu 中运行