From Fedora Project Wiki
No edit summary
No edit summary
Line 14: Line 14:
* s32ilp32 - Linux version 6.3.0-rc1 (124MB) rv32_defconfig:  
* s32ilp32 - Linux version 6.3.0-rc1 (124MB) rv32_defconfig:  
<pre>
<pre>
           $(Q)$(MAKE) -f $(srctree)/Makefile defconfig 32-bit.config
           $(Q)$(MAKE) -f $(srctree)/Makefile defconfig
</pre>
</pre>


Line 34: Line 34:


[[File:64ilp32.png|center|1024px]]
[[File:64ilp32.png|center|1024px]]
这是基于当前默认配置(未做任何修改)的大致测量结果,32位(s32ilp32、s64ilp32)比64位(s64lp64)节省了超过16%的内存。
但s32ilp32和s64ilp32的内存占用相似(大约只有0.33%的差异),这意味着s64ilp32很有可能在64位机器上替代s32ilp32。
== 为什么选择s64ilp32? ==
当前的RISC-V具有RVA20S64、RVA22S64和 RVA23S64 配置文件,但不存在RVA**S32配置文件,也没有进行中的计划。这意味着当供应商想要生产一个32位的s模式RISC-V应用处理器时,他们没有可遵循的模型。因此,许多便宜的riscv芯片已经出现,但遵循RVA2xS64配置文件,例如全志D1/D1s/F133、SOPHGO CV1800B/SG2000、嘉楠科技Kendryte K230 和Bouffalo Lab BL808,这些通常对标cortex a7/a35/a53产品场景。D1、CV1800B和BL808不支持UXL=32(32位U模式),因此它们需要一个新的u64ilp32用户空间ABI,目前还没有软件生态系统。因此,s64ilp32的首次登陆将是在嘉楠科技Kendryte k230上,该芯片具有c908,支持rv64gcv和兼容用户模式(sstatus.uxl=32/64),能够支持现有的rv32用户空间软件生态系统。
发明s64ilp32的另一个原因是性能好处和简化64位CPU硬件设计(与s32ilp32相比)。
== 为什么s64ilp32性能更好? ==
一般来说,我们应该在64位处理器上构建一个32位硬件s模式来运行32位Linux(例如在cortex-a53上运行Linux-arm32)。
或者只在64位机器上使用旧的32ilp32-abi(例如mips SYS_SUPPORTS_32BIT_KERNEL)。这些不能重用64位硬件的性能相关特性和指令,例如64位ALU、AMO和LD/SD,这会在许多Linux功能上造成显著的性能差距:
- memcpy/memset/strcmp(s64ilp32的指令计数是s32ilp32的一半,加载/存储指令的带宽是s32ilp32的两倍。)
- ebpf JIT是一个64位虚拟ISA,不适合映射到s32ilp32。
- Atomic64(s64ilp32具有与s64lp64完全相同的原生指令映射,但s32ilp32只使用generic_atomic64,这是一个折衷和有限的软件解决方案。)
- 支持"long long"类型的64位原生算术指令
- 支持slub的cmxchg_double(第二个支持该功能的32位Linux,第一个是i386。)
...
与用户空间生态系统相比,32位Linux内核更迫切地需要64ilp32来提高性能,因为Linux内核不能利用ISA的浮点/向量特性。
让我们从另一个角度看性能(s64ilp32对比s64lp64)。如前所述,ilp32的指针大小是lp64的一半,它减小了关键数据结构(例如,页面、列表等)的大小。这意味着使用ilp32的缓存可以在相同的缓存容量下包含lp64的两倍数据,这是32位的天生优势。
== 为什么 s64ilp32 可以简化 CPU 设计? ==
s64ilp32简化了CPU设计的原因主要有两个方面。首先,与传统的32位模式相比,s64ilp32模式允许RISC-V硬件在64位机器模式(MXL=SXL=64)下运行,同时支持32位用户空间(UXL=32)。这样,CPU厂商就无需实现专门的32位机器模式和管理模式,从而简化了硬件的设计和实现。传统上,例如在ARM架构中,为了支持32位Linux,需要实现32位的EL1/EL2/EL3硬件模式,这增加了设计和验证的复杂度。
其次,s64ilp32模式利用了64位硬件的性能优势,同时保持了与现有的32位软件生态系统的兼容性。这种模式下,虽然处理器在硬件层面上运行在64位模式,但是通过支持32位的用户空间ABI(应用程序二进制接口),使得现有的基于RV32的软件能够无缝运行。这种方法避免了混合32位CSR(控制和状态寄存器)功能到64位硬件中的复杂性,同时也保留了64位处理器的性能优势。
== s64ilp32如何工作? ==
s64ilp32模式从硬件角度看与s64lp64兼容模式相同,即MXL=SXL=64加上UXL=32。由于s64ilp32使用Linux的CONFIG_32BIT配置,它仅支持u32ilp32 abi用户空间,即当前标准的rv32软件生态系统,目前还不能与u64lp64 abi兼容(这被认为是复杂且无用的)。但是,未来可能支持u64ilp32;现在,s64ilp32依赖于硬件的UXL=32特性。
对于地址变量的生成,64ilp32 gcc仍然使用带符号扩展的lw和auipc指令,因为插入用于屏蔽最高32位的零扩展指令会导致代码大小和性能问题。因此,通过操作系统方法来解决这个问题:
- 当satp=bare且启动物理地址小于2GB时,不存在带符号扩展的地址问题。
- 当satp=bare且启动物理地址大于2GB时,需要类似zjpm的硬件扩展来屏蔽高32位。(幸运的是,所有现有的SoC(D1/D1s/F133, CV1800B, k230, BL808)的启动物理地址都小于2GB。)
- 当satp=sv39时,通过双重映射使带符号扩展的虚拟地址与零扩展的虚拟地址相同,解决了地址扩展问题。
这种方法简化了对64位硬件的设计和实现,同时为32位软件提供了在64位硬件上运行的能力,无需牺牲性能。
== 如何运行 s64ilp32? ==
=== GNU 工具链 ===
请使用Fedora中的 riscv64-linux-gnu- 工具链
=== Opensbi ===
<pre>
git clone https://github.com/riscv-software-src/opensbi.git
CROSS_COMPILE=riscv64-linux-gnu- make PLATFORM=generic
</pre>
=== Linux kernel ===
<pre>
git clone https://github.com/guoren83/linux.git -b s64ilp32
cd linux
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- rv64ilp32_defconfig
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- menuconfig
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- all
</pre>
=== Fedora Rootfs ===
WIP
=== Qemu ===
<pre>
git clone https://github.com/plctlab/plct-qemu.git -b plct-s64ilp32-dev
cd plct-qemu
mkdir build
cd build
../qemu/configure --target-list="riscv64-softmmu riscv32-softmmu"
make
</pre>
=== 运行 ===
<pre>
./qemu-system-riscv64 -cpu rv64 -M virt -m 128m -nographic -bios fw_dynamic.bin -kernel Image -drive file=rootfs.ext2,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -append "rootwait root=/dev/vda ro console=ttyS0 earlycon=sbi" -netdev user,id=net0 -device virtio-net-device,netdev=net0
</pre>

Revision as of 15:31, 4 March 2024

为什么使用32位Linux?

使用32位Linux内核的目的是为了减少内存占用并满足小容量DDR和缓存的要求(例如,64/128MB SIP SoC)。

ilp32的long和指针大小仅为lp64的一半(rv64默认的abi - long和指针都是64位)。 这种数据类型上的显著差异导致了不同的内存和缓存占用成本。 在相同的128MB qemu系统环境中,这里是s32ilp32、s64ilp32和s64lp64之间的比较测量:

根文件系统:

  • u32ilp32 - 使用相同的32位用户空间rootfs.ext2(UXL=32)二进制文件,来自buildroot 2023.02-rc3,qemu_riscv32_virt_defconfig。

Linux:

  • s32ilp32 - Linux version 6.3.0-rc1 (124MB) rv32_defconfig:
           $(Q)$(MAKE) -f $(srctree)/Makefile defconfig
  • s64lp64 - Linux version 6.3.0-rc1 (126MB) defconfig:
           $(Q)$(MAKE) -f $(srctree)/Makefile defconfig
  • s64ilp32 - Linux version 6.3.0-rc1 (126MB) rv64ilp32_defconfig:
          $(Q)$(MAKE) -f $(srctree)/Makefile defconfig 64ilp32.config

Opensbi:

  • m64lp64 - (2MB) OpenSBI v1.2-80-g4b28afc98bbe
  • m32ilp32 - (4MB) OpenSBI v1.2-80-g4b28afc98bbe


64ilp32.png

这是基于当前默认配置(未做任何修改)的大致测量结果,32位(s32ilp32、s64ilp32)比64位(s64lp64)节省了超过16%的内存。 但s32ilp32和s64ilp32的内存占用相似(大约只有0.33%的差异),这意味着s64ilp32很有可能在64位机器上替代s32ilp32。

为什么选择s64ilp32?

当前的RISC-V具有RVA20S64、RVA22S64和 RVA23S64 配置文件,但不存在RVA**S32配置文件,也没有进行中的计划。这意味着当供应商想要生产一个32位的s模式RISC-V应用处理器时,他们没有可遵循的模型。因此,许多便宜的riscv芯片已经出现,但遵循RVA2xS64配置文件,例如全志D1/D1s/F133、SOPHGO CV1800B/SG2000、嘉楠科技Kendryte K230 和Bouffalo Lab BL808,这些通常对标cortex a7/a35/a53产品场景。D1、CV1800B和BL808不支持UXL=32(32位U模式),因此它们需要一个新的u64ilp32用户空间ABI,目前还没有软件生态系统。因此,s64ilp32的首次登陆将是在嘉楠科技Kendryte k230上,该芯片具有c908,支持rv64gcv和兼容用户模式(sstatus.uxl=32/64),能够支持现有的rv32用户空间软件生态系统。

发明s64ilp32的另一个原因是性能好处和简化64位CPU硬件设计(与s32ilp32相比)。

为什么s64ilp32性能更好?

一般来说,我们应该在64位处理器上构建一个32位硬件s模式来运行32位Linux(例如在cortex-a53上运行Linux-arm32)。 或者只在64位机器上使用旧的32ilp32-abi(例如mips SYS_SUPPORTS_32BIT_KERNEL)。这些不能重用64位硬件的性能相关特性和指令,例如64位ALU、AMO和LD/SD,这会在许多Linux功能上造成显著的性能差距:

- memcpy/memset/strcmp(s64ilp32的指令计数是s32ilp32的一半,加载/存储指令的带宽是s32ilp32的两倍。)
- ebpf JIT是一个64位虚拟ISA,不适合映射到s32ilp32。
- Atomic64(s64ilp32具有与s64lp64完全相同的原生指令映射,但s32ilp32只使用generic_atomic64,这是一个折衷和有限的软件解决方案。)
- 支持"long long"类型的64位原生算术指令
- 支持slub的cmxchg_double(第二个支持该功能的32位Linux,第一个是i386。)

... 与用户空间生态系统相比,32位Linux内核更迫切地需要64ilp32来提高性能,因为Linux内核不能利用ISA的浮点/向量特性。

让我们从另一个角度看性能(s64ilp32对比s64lp64)。如前所述,ilp32的指针大小是lp64的一半,它减小了关键数据结构(例如,页面、列表等)的大小。这意味着使用ilp32的缓存可以在相同的缓存容量下包含lp64的两倍数据,这是32位的天生优势。

为什么 s64ilp32 可以简化 CPU 设计?

s64ilp32简化了CPU设计的原因主要有两个方面。首先,与传统的32位模式相比,s64ilp32模式允许RISC-V硬件在64位机器模式(MXL=SXL=64)下运行,同时支持32位用户空间(UXL=32)。这样,CPU厂商就无需实现专门的32位机器模式和管理模式,从而简化了硬件的设计和实现。传统上,例如在ARM架构中,为了支持32位Linux,需要实现32位的EL1/EL2/EL3硬件模式,这增加了设计和验证的复杂度。

其次,s64ilp32模式利用了64位硬件的性能优势,同时保持了与现有的32位软件生态系统的兼容性。这种模式下,虽然处理器在硬件层面上运行在64位模式,但是通过支持32位的用户空间ABI(应用程序二进制接口),使得现有的基于RV32的软件能够无缝运行。这种方法避免了混合32位CSR(控制和状态寄存器)功能到64位硬件中的复杂性,同时也保留了64位处理器的性能优势。

s64ilp32如何工作?

s64ilp32模式从硬件角度看与s64lp64兼容模式相同,即MXL=SXL=64加上UXL=32。由于s64ilp32使用Linux的CONFIG_32BIT配置,它仅支持u32ilp32 abi用户空间,即当前标准的rv32软件生态系统,目前还不能与u64lp64 abi兼容(这被认为是复杂且无用的)。但是,未来可能支持u64ilp32;现在,s64ilp32依赖于硬件的UXL=32特性。

对于地址变量的生成,64ilp32 gcc仍然使用带符号扩展的lw和auipc指令,因为插入用于屏蔽最高32位的零扩展指令会导致代码大小和性能问题。因此,通过操作系统方法来解决这个问题:

- 当satp=bare且启动物理地址小于2GB时,不存在带符号扩展的地址问题。
- 当satp=bare且启动物理地址大于2GB时,需要类似zjpm的硬件扩展来屏蔽高32位。(幸运的是,所有现有的SoC(D1/D1s/F133, CV1800B, k230, BL808)的启动物理地址都小于2GB。)
- 当satp=sv39时,通过双重映射使带符号扩展的虚拟地址与零扩展的虚拟地址相同,解决了地址扩展问题。

这种方法简化了对64位硬件的设计和实现,同时为32位软件提供了在64位硬件上运行的能力,无需牺牲性能。


如何运行 s64ilp32?

GNU 工具链

请使用Fedora中的 riscv64-linux-gnu- 工具链 

Opensbi

git clone https://github.com/riscv-software-src/opensbi.git
CROSS_COMPILE=riscv64-linux-gnu- make PLATFORM=generic

Linux kernel

git clone https://github.com/guoren83/linux.git -b s64ilp32
cd linux
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- rv64ilp32_defconfig
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- menuconfig
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- all

Fedora Rootfs

WIP


Qemu

git clone https://github.com/plctlab/plct-qemu.git -b plct-s64ilp32-dev
cd plct-qemu
mkdir build
cd build
../qemu/configure --target-list="riscv64-softmmu riscv32-softmmu"
make

运行

./qemu-system-riscv64 -cpu rv64 -M virt -m 128m -nographic -bios fw_dynamic.bin -kernel Image -drive file=rootfs.ext2,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -append "rootwait root=/dev/vda ro console=ttyS0 earlycon=sbi" -netdev user,id=net0 -device virtio-net-device,netdev=net0