2021-12-21 16:35:50

by Guo Ren

[permalink] [raw]
Subject: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

From: Guo Ren <[email protected]>

Currently, most 64-bit architectures (x86, parisc, powerpc, arm64,
s390, mips, sparc) have supported COMPAT mode. But they all have
history issues and can't use standard linux unistd.h. RISC-V would
be first standard __SYSCALL_COMPAT user of include/uapi/asm-generic
/unistd.h.

The patchset are based on v5.16-rc6, you can compare rv64-compat32
v.s. rv32-whole in qemu with following step:

- Prepare rv32 rootfs & fw_jump.bin by buildroot.org
$ git clone git://git.busybox.net/buildroot
$ cd buildroot
$ make qemu_riscv32_virt_defconfig O=qemu_riscv32_virt_defconfig
$ make -C qemu_riscv32_virt_defconfig
$ make qemu_riscv64_virt_defconfig O=qemu_riscv64_virt_defconfig
$ make -C qemu_riscv64_virt_defconfig
(Got fw_jump.bin & rootfs.ext2 in qemu_riscvXX_virt_defconfig/images)

- Prepare Linux rv32 & rv64 Image
$ git clone [email protected]:c-sky/csky-linux.git -b riscv_compat_v1 linux
$ cd linux
$ make ARCH=riscv CROSS_COMPILE=riscv32-buildroot-linux-gnu- O=../build-rv32/ rv32_defconfig
$ make ARCH=riscv CROSS_COMPILE=riscv32-buildroot-linux-gnu- O=../build-rv32/ Image
$ make ARCH=riscv CROSS_COMPILE=riscv64-buildroot-linux-gnu- O=../build-rv64/ defconfig
$ make ARCH=riscv CROSS_COMPILE=riscv64-buildroot-linux-gnu- O=../build-rv64/ Image

- Prepare Qemu: (made by LIU Zhiwei <[email protected]>)
$ git clone https://github.com/romanheros/qemu.git -b riscv-upstream-uxl-v5
$ cd qemu
$ ./configure --target-list="riscv64-softmmu riscv32-softmmu"
$ make

- Run rv64 with rv32 rootfs in compat mode:
$ ./build/qemu-system-riscv64 -cpu rv64,x-h=true -M virt -m 64m -nographic -bios qemu_riscv64_virt_defconfig/images/fw_jump.bin -kernel build-rv64/Image -drive file qemu_riscv32_virt_defconfig/images/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

QEMU emulator version 6.2.50 (v6.2.0-29-g196d7182c8)
OpenSBI v0.9
[ 0.000000] Linux version 5.16.0-rc6-00013-g60f122c486d0 (guoren@guoren-Z87-HD3) (riscv64-unknown-linux-gnu-gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.37) #62 SMP Tue Dec 21 22:54:05 CST 2021
[ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
[ 0.000000] Machine model: riscv-virtio,qemu
[ 0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
[ 0.000000] printk: bootconsole [sbi0] enabled
[ 0.000000] efi: UEFI not found.
[ 0.000000] Zone ranges:
[ 0.000000] DMA32 [mem 0x0000000080200000-0x0000000083ffffff]
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000080200000-0x0000000083ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x0000000083ffffff]
[ 0.000000] SBI specification v0.2 detected
[ 0.000000] SBI implementation ID=0x1 Version=0x9
[ 0.000000] SBI TIME extension detected
[ 0.000000] SBI IPI extension detected
[ 0.000000] SBI RFENCE extension detected
[ 0.000000] SBI v0.2 HSM extension detected
[ 0.000000] riscv: compat: 32bit U-mode applications support
[ 0.000000] riscv: ISA extensions acdfhimsu
[ 0.000000] riscv: ELF capabilities acdfim
[ 0.000000] percpu: Embedded 17 pages/cpu s30696 r8192 d30744 u69632
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 15655
[ 0.000000] Kernel command line: rootwait root=/dev/vda ro console=ttyS0 earlycon=sbi
[ 0.000000] Dentry cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] fixmap : 0xffffffcefee00000 - 0xffffffceff000000 (2048 kB)
[ 0.000000] pci io : 0xffffffceff000000 - 0xffffffcf00000000 ( 16 MB)
[ 0.000000] vmemmap : 0xffffffcf00000000 - 0xffffffcfffffffff (4095 MB)
[ 0.000000] vmalloc : 0xffffffd000000000 - 0xffffffdfffffffff (65535 MB)
[ 0.000000] lowmem : 0xffffffe000000000 - 0xffffffe003e00000 ( 62 MB)
[ 0.000000] kernel : 0xffffffff80000000 - 0xffffffffffffffff (2047 MB)
[ 0.000000] Memory: 43952K/63488K available (6180K kernel code, 4873K rwdata, 2048K rodata, 2146K init, 297K bss, 19536K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] rcu: Hierarchical RCU implementation.
[ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
[ 0.000000] rcu: RCU debug extended QS entry/exit.
[ 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=1
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] riscv-intc: 64 local interrupts mapped
[ 0.000000] plic: plic@c000000: mapped 53 interrupts with 1 handlers for 2 contexts.
...
Welcome to Buildroot
buildroot login: root
# cat /proc/cpuinfo
processor : 0
hart : 0
isa : rv64imafdcsuh
mmu : sv48

# file /bin/busybox
/bin/busybox: setuid ELF 32-bit LSB shared object, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv32-ilp32d.so.1, for GNU/Linux 5.15.0, stripped
# cat /proc/meminfo
MemTotal: 46096 kB
MemFree: 30116 kB
MemAvailable: 32824 kB
Buffers: 664 kB
Cached: 3900 kB
SwapCached: 0 kB
Active: 3164 kB
Inactive: 1920 kB
Active(anon): 40 kB
Inactive(anon): 524 kB
Active(file): 3124 kB
Inactive(file): 1396 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 8 kB
Writeback: 0 kB
AnonPages: 556 kB
Mapped: 2084 kB
Shmem: 44 kB
KReclaimable: 964 kB
Slab: 5760 kB
SReclaimable: 964 kB
SUnreclaim: 4796 kB
KernelStack: 624 kB
PageTables: 132 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 23048 kB
Committed_AS: 2088 kB
VmallocTotal: 67108863 kB
VmallocUsed: 636 kB
VmallocChunk: 0 kB
Percpu: 80 kB
#

- Run rv32 with rv32 rootfs:
$ ./build/qemu-system-riscv32 -cpu rv32,x-h=true -M virt -m 64m -nographic -bios qemu_riscv32_virt_defconfig/images/fw_jump.bin -kernel build-rv32/Image -drive file qemu_riscv32_virt_defconfig/images/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

QEMU emulator version 6.2.50 (v6.2.0-29-g196d7182c8)
OpenSBI v0.9
[ 0.000000] Linux version 5.16.0-rc6-00013-g60f122c486d0 (guoren@guoren-Z87-HD3) (riscv32-buildroot-linux-gnu-gcc.br_real (Buildroot 2021.11-201-g7600ca7960-dirty) 10.3.0, GNU ld (GNU Binutils) 2.36.1) #4 SMP Tue Dec 21 22:54:43 CST 2021
[ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80400000
[ 0.000000] Machine model: riscv-virtio,qemu
[ 0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
[ 0.000000] printk: bootconsole [sbi0] enabled
[ 0.000000] efi: UEFI not found.
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000080400000-0x0000000083ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000080400000-0x0000000083ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000080400000-0x0000000083ffffff]
[ 0.000000] SBI specification v0.2 detected
[ 0.000000] SBI implementation ID=0x1 Version=0x9
[ 0.000000] SBI TIME extension detected
[ 0.000000] SBI IPI extension detected
[ 0.000000] SBI RFENCE extension detected
[ 0.000000] SBI v0.2 HSM extension detected
[ 0.000000] riscv: ISA extensions acdfhimsu
[ 0.000000] riscv: ELF capabilities acdfim
[ 0.000000] percpu: Embedded 12 pages/cpu s16600 r8192 d24360 u49152
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 15240
[ 0.000000] Kernel command line: rootwait root=/dev/vda ro console=ttyS0 earlycon=sbi
[ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] fixmap : 0x9dc00000 - 0x9e000000 (4096 kB)
[ 0.000000] pci io : 0x9e000000 - 0x9f000000 ( 16 MB)
[ 0.000000] vmemmap : 0x9f000000 - 0x9fffffff ( 15 MB)
[ 0.000000] vmalloc : 0xa0000000 - 0xbfffffff ( 511 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xc3c00000 ( 60 MB)
[ 0.000000] Memory: 35332K/61440K available (6073K kernel code, 8814K rwdata, 4096K rodata, 4160K init, 241K bss, 26108K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] rcu: Hierarchical RCU implementation.
[ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
[ 0.000000] rcu: RCU debug extended QS entry/exit.
[ 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=1
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] riscv-intc: 32 local interrupts mapped
[ 0.000000] plic: plic@c000000: mapped 53 interrupts with 1 handlers for 2 contexts.
...
Welcome to Buildroot
buildroot login: root
# cat /proc/cpuinfo
processor : 0
hart : 0
isa : rv32imafdcsuh
mmu : sv32

# file /bin/busybox
/bin/busybox: setuid ELF 32-bit LSB shared object, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv32-ilp32d.so.1, for GNU/Linux 5.15.0, stripped
# cat /proc/meminfo
MemTotal: 39492 kB
MemFree: 26756 kB
MemAvailable: 29552 kB
Buffers: 668 kB
Cached: 3908 kB
SwapCached: 0 kB
Active: 3156 kB
Inactive: 1936 kB
Active(anon): 40 kB
Inactive(anon): 520 kB
Active(file): 3116 kB
Inactive(file): 1416 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 552 kB
Mapped: 2144 kB
Shmem: 44 kB
KReclaimable: 624 kB
Slab: 3660 kB
SReclaimable: 624 kB
SUnreclaim: 3036 kB
KernelStack: 312 kB
PageTables: 92 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 19744 kB
Committed_AS: 2088 kB
VmallocTotal: 524287 kB
VmallocUsed: 12 kB
VmallocChunk: 0 kB
Percpu: 60 kB
#

Some conclusions:
- rv32 linux kernel code, data sizes are larger than rv64.
(complier's issue?)
- rv32 kernel runtime KernelStack, Slab... are smaller,
but not so much for memory footprint saving.
- Totally rv64 kernel is much better than rv32.
- Qemu, kernel, rv32 = rv64 defconfig, rootfs, opensbi
are the same in this comparison.

Guo Ren (13):
syscalls: compat: Fix the missing part for __SYSCALL_COMPAT
riscv: Fixup difference with defconfig
riscv: compat: Add basic compat date type implementation
riscv: compat: Re-implement TASK_SIZE for COMPAT_32BIT
riscv: compat: syscall: Add compat_sys_call_table implementation
riscv: compat: syscall: Add entry.S implementation
riscv: compat: Add elf.h implementation
riscv: compat: Add COMPAT Kbuild skeletal support
riscv: compat: init: Add hw-cap detect in setup_arch
riscv: compat: vdso: Add rv32 VDSO base code implementation
riscv: compat: vdso: Add setup additional pages implementation
riscv: compat: signal: Add rt_frame implementation
riscv: compat: ptrace: Add compat_arch_ptrace implement

arch/riscv/Kconfig | 22 ++
arch/riscv/Makefile | 5 +
arch/riscv/configs/rv32_defconfig | 20 +-
arch/riscv/include/asm/compat.h | 259 ++++++++++++++++++
arch/riscv/include/asm/csr.h | 7 +
arch/riscv/include/asm/elf.h | 53 +++-
arch/riscv/include/asm/mmu.h | 1 +
arch/riscv/include/asm/pgtable.h | 11 +-
arch/riscv/include/asm/processor.h | 10 +
arch/riscv/include/asm/syscall.h | 3 +
arch/riscv/include/asm/thread_info.h | 1 +
arch/riscv/include/asm/vdso.h | 9 +
arch/riscv/kernel/Makefile | 3 +
arch/riscv/kernel/compat_signal.c | 243 ++++++++++++++++
arch/riscv/kernel/compat_syscall_table.c | 84 ++++++
arch/riscv/kernel/compat_vdso/.gitignore | 2 +
arch/riscv/kernel/compat_vdso/Makefile | 68 +++++
arch/riscv/kernel/compat_vdso/compat_vdso.S | 8 +
.../kernel/compat_vdso/compat_vdso.lds.S | 3 +
arch/riscv/kernel/compat_vdso/flush_icache.S | 3 +
.../compat_vdso/gen_compat_vdso_offsets.sh | 5 +
arch/riscv/kernel/compat_vdso/getcpu.S | 3 +
arch/riscv/kernel/compat_vdso/note.S | 3 +
arch/riscv/kernel/compat_vdso/rt_sigreturn.S | 3 +
arch/riscv/kernel/entry.S | 18 +-
arch/riscv/kernel/process.c | 32 +++
arch/riscv/kernel/ptrace.c | 87 +++++-
arch/riscv/kernel/setup.c | 5 +
arch/riscv/kernel/signal.c | 13 +-
arch/riscv/kernel/vdso.c | 104 +++++--
arch/riscv/kernel/vdso/vdso.S | 6 +-
drivers/firmware/efi/libstub/efi-stub.c | 2 +-
include/uapi/asm-generic/unistd.h | 4 +-
tools/include/uapi/asm-generic/unistd.h | 4 +-
34 files changed, 1055 insertions(+), 49 deletions(-)
create mode 100644 arch/riscv/include/asm/compat.h
create mode 100644 arch/riscv/kernel/compat_signal.c
create mode 100644 arch/riscv/kernel/compat_syscall_table.c
create mode 100644 arch/riscv/kernel/compat_vdso/.gitignore
create mode 100644 arch/riscv/kernel/compat_vdso/Makefile
create mode 100644 arch/riscv/kernel/compat_vdso/compat_vdso.S
create mode 100644 arch/riscv/kernel/compat_vdso/compat_vdso.lds.S
create mode 100644 arch/riscv/kernel/compat_vdso/flush_icache.S
create mode 100755 arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh
create mode 100644 arch/riscv/kernel/compat_vdso/getcpu.S
create mode 100644 arch/riscv/kernel/compat_vdso/note.S
create mode 100644 arch/riscv/kernel/compat_vdso/rt_sigreturn.S

--
2.25.1



2021-12-21 16:35:56

by Guo Ren

[permalink] [raw]
Subject: [PATCH 01/13] syscalls: compat: Fix the missing part for __SYSCALL_COMPAT

From: Guo Ren <[email protected]>

Make "uapi asm unistd.h" could be used for architectures' COMPAT
mode. The __SYSCALL_COMPAT is first used in riscv.

Signed-off-by: Guo Ren <[email protected]>
---
include/uapi/asm-generic/unistd.h | 4 ++--
tools/include/uapi/asm-generic/unistd.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 4557a8b6086f..aafe5cfeb27c 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -383,7 +383,7 @@ __SYSCALL(__NR_syslog, sys_syslog)

/* kernel/ptrace.c */
#define __NR_ptrace 117
-__SYSCALL(__NR_ptrace, sys_ptrace)
+__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace)

/* kernel/sched/core.c */
#define __NR_sched_setparam 118
@@ -779,7 +779,7 @@ __SYSCALL(__NR_rseq, sys_rseq)
#define __NR_kexec_file_load 294
__SYSCALL(__NR_kexec_file_load, sys_kexec_file_load)
/* 295 through 402 are unassigned to sync up with generic numbers, don't use */
-#if __BITS_PER_LONG == 32
+#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32
#define __NR_clock_gettime64 403
__SYSCALL(__NR_clock_gettime64, sys_clock_gettime)
#define __NR_clock_settime64 404
diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h
index 4557a8b6086f..aafe5cfeb27c 100644
--- a/tools/include/uapi/asm-generic/unistd.h
+++ b/tools/include/uapi/asm-generic/unistd.h
@@ -383,7 +383,7 @@ __SYSCALL(__NR_syslog, sys_syslog)

/* kernel/ptrace.c */
#define __NR_ptrace 117
-__SYSCALL(__NR_ptrace, sys_ptrace)
+__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace)

/* kernel/sched/core.c */
#define __NR_sched_setparam 118
@@ -779,7 +779,7 @@ __SYSCALL(__NR_rseq, sys_rseq)
#define __NR_kexec_file_load 294
__SYSCALL(__NR_kexec_file_load, sys_kexec_file_load)
/* 295 through 402 are unassigned to sync up with generic numbers, don't use */
-#if __BITS_PER_LONG == 32
+#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32
#define __NR_clock_gettime64 403
__SYSCALL(__NR_clock_gettime64, sys_clock_gettime)
#define __NR_clock_settime64 404
--
2.25.1


2021-12-21 16:36:02

by Guo Ren

[permalink] [raw]
Subject: [PATCH 02/13] riscv: Fixup difference with defconfig

From: Guo Ren <[email protected]>

Let's follow the origin patch's spirit.

The only difference between rv32_defconfig and defconfig is that
rv32_defconfig has CONFIG_ARCH_RV32I=y.

This is helpful to compare rv64-compat-rv32 v.s. rv32-linux.

Fixes: 1b937e8faa87ccfb ("RISC-V: Add separate defconfig for 32bit systems")
Signed-off-by: Guo Ren <[email protected]>
Cc: Anup Patel <[email protected]>
Cc: Palmer Dabbelt <[email protected]>
---
arch/riscv/configs/rv32_defconfig | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/configs/rv32_defconfig b/arch/riscv/configs/rv32_defconfig
index 6e9f12ff968a..d858906cff2d 100644
--- a/arch/riscv/configs/rv32_defconfig
+++ b/arch/riscv/configs/rv32_defconfig
@@ -1,3 +1,4 @@
+CONFIG_ARCH_RV32I=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ_IDLE=y
@@ -16,7 +17,7 @@ CONFIG_EXPERT=y
CONFIG_BPF_SYSCALL=y
CONFIG_SOC_SIFIVE=y
CONFIG_SOC_VIRT=y
-CONFIG_ARCH_RV32I=y
+CONFIG_SOC_MICROCHIP_POLARFIRE=y
CONFIG_SMP=y
CONFIG_HOTPLUG_CPU=y
CONFIG_VIRTUALIZATION=y
@@ -41,10 +42,12 @@ CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCIE_XILINX=y
+CONFIG_PCIE_FU740=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
+CONFIG_BLK_DEV_NVME=m
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_SCSI_VIRTIO=y
@@ -68,11 +71,14 @@ CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_SPI=y
CONFIG_SPI_SIFIVE=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SIFIVE=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_POWER_RESET=y
-CONFIG_DRM=y
-CONFIG_DRM_RADEON=y
-CONFIG_DRM_VIRTIO_GPU=y
+CONFIG_DRM=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_VIRTIO_GPU=m
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
@@ -83,6 +89,9 @@ CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC=y
CONFIG_MMC_SPI=y
CONFIG_RTC_CLASS=y
@@ -105,6 +114,8 @@ CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_9P_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=m
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_PRINTK_TIME=y
@@ -133,3 +144,4 @@ CONFIG_RCU_EQS_DEBUG=y
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_MEMTEST=y
# CONFIG_SYSFS_SYSCALL is not set
+CONFIG_EFI=y
--
2.25.1


2021-12-21 16:36:04

by Guo Ren

[permalink] [raw]
Subject: [PATCH 03/13] riscv: compat: Add basic compat date type implementation

From: Guo Ren <[email protected]>

Implement asm/compat.h for struct compat_xxx, RLIM_INFINITY,
OFF_T_MAX, is_compat_task, compat_user_regset, regset convert.

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/include/asm/compat.h | 259 +++++++++++++++++++++++++++
arch/riscv/include/asm/thread_info.h | 1 +
2 files changed, 260 insertions(+)
create mode 100644 arch/riscv/include/asm/compat.h

diff --git a/arch/riscv/include/asm/compat.h b/arch/riscv/include/asm/compat.h
new file mode 100644
index 000000000000..8e9777811f3b
--- /dev/null
+++ b/arch/riscv/include/asm/compat.h
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_COMPAT_H
+#define __ASM_COMPAT_H
+
+#define compat_mode_t compat_mode_t
+typedef u16 compat_mode_t;
+
+/*
+ * Architecture specific compatibility types
+ */
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/sched/task_stack.h>
+#include <asm-generic/compat.h>
+
+#define COMPAT_USER_HZ 100
+#define COMPAT_UTS_MACHINE "riscv\0\0"
+
+typedef compat_uint_t __compat_uid_t;
+typedef compat_uint_t __compat_gid_t;
+typedef compat_uint_t compat_dev_t;
+typedef compat_int_t compat_ipc_pid_t;
+
+struct compat_stat {
+ compat_ulong_t st_dev;
+ compat_ulong_t st_ino;
+ compat_uint_t st_mode;
+ compat_uint_t st_nlink;
+ compat_uint_t st_uid;
+ compat_uint_t st_gid;
+ compat_ulong_t st_rdev;
+ compat_ulong_t __pad1;
+ compat_long_t st_size;
+ compat_int_t st_blksize;
+ compat_int_t __pad2;
+ compat_long_t st_blocks;
+ compat_long_t st_atime;
+ compat_ulong_t st_atime_nsec;
+ compat_long_t st_mtime;
+ compat_ulong_t st_mtime_nsec;
+ compat_long_t st_ctime;
+ compat_ulong_t st_ctime_nsec;
+ compat_uint_t __unused4;
+ compat_uint_t __unused5;
+};
+
+struct compat_flock {
+ compat_short_t l_type;
+ compat_short_t l_whence;
+ compat_off_t l_start;
+ compat_off_t l_len;
+ compat_pid_t l_pid;
+ /* No __ARCH_FLOCK_PAD in riscv */
+};
+
+#define F_GETLK64 12
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
+struct compat_flock64 {
+ compat_short_t l_type;
+ compat_short_t l_whence;
+ compat_loff_t l_start;
+ compat_loff_t l_len;
+ compat_pid_t l_pid;
+ /* No __ARCH_FLOCK64_PAD in riscv */
+};
+
+struct compat_statfs {
+ compat_uint_t f_type;
+ compat_uint_t f_bsize;
+ compat_uint_t f_blocks;
+ compat_uint_t f_bfree;
+ compat_uint_t f_bavail;
+ compat_uint_t f_files;
+ compat_uint_t f_ffree;
+ __kernel_fsid_t f_fsid;
+ compat_uint_t f_namelen;
+ compat_uint_t f_frsize;
+ compat_uint_t f_flags;
+ compat_uint_t f_spare[4];
+};
+
+#define COMPAT_RLIM_INFINITY 0x7fffffff
+#define COMPAT_OFF_T_MAX COMPAT_RLIM_INFINITY
+
+struct compat_ipc64_perm {
+ compat_key_t key;
+ __compat_uid32_t uid;
+ __compat_gid32_t gid;
+ __compat_uid32_t cuid;
+ __compat_gid32_t cgid;
+ compat_mode_t mode;
+ unsigned char __pad1[4 - sizeof(compat_mode_t)];
+ compat_ushort_t seq;
+ compat_ushort_t __pad2;
+ compat_ulong_t unused1;
+ compat_ulong_t unused2;
+};
+
+struct compat_semid64_ds {
+ struct compat_ipc64_perm sem_perm;
+ compat_ulong_t sem_otime;
+ compat_ulong_t sem_otime_high;
+ compat_ulong_t sem_ctime;
+ compat_ulong_t sem_ctime_high;
+ compat_ulong_t sem_nsems;
+ compat_ulong_t __unused3;
+ compat_ulong_t __unused4;
+};
+
+struct compat_msqid64_ds {
+ struct compat_ipc64_perm msg_perm;
+ compat_ulong_t msg_stime;
+ compat_ulong_t msg_stime_high;
+ compat_ulong_t msg_rtime;
+ compat_ulong_t msg_rtime_high;
+ compat_ulong_t msg_ctime;
+ compat_ulong_t msg_ctime_high;
+ compat_ulong_t msg_cbytes;
+ compat_ulong_t msg_qnum;
+ compat_ulong_t msg_qbytes;
+ compat_pid_t msg_lspid;
+ compat_pid_t msg_lrpid;
+ compat_ulong_t __unused4;
+ compat_ulong_t __unused5;
+};
+
+struct compat_shmid64_ds {
+ struct compat_ipc64_perm shm_perm;
+ compat_size_t shm_segsz;
+ compat_ulong_t shm_atime;
+ compat_ulong_t shm_atime_high;
+ compat_ulong_t shm_dtime;
+ compat_ulong_t shm_dtime_high;
+ compat_ulong_t shm_ctime;
+ compat_ulong_t shm_ctime_high;
+ compat_pid_t shm_cpid;
+ compat_pid_t shm_lpid;
+ compat_ulong_t shm_nattch;
+ compat_ulong_t __unused4;
+ compat_ulong_t __unused5;
+};
+
+static inline int is_compat_task(void)
+{
+ return test_thread_flag(TIF_32BIT);
+}
+
+struct compat_user_regs_struct {
+ compat_ulong_t pc;
+ compat_ulong_t ra;
+ compat_ulong_t sp;
+ compat_ulong_t gp;
+ compat_ulong_t tp;
+ compat_ulong_t t0;
+ compat_ulong_t t1;
+ compat_ulong_t t2;
+ compat_ulong_t s0;
+ compat_ulong_t s1;
+ compat_ulong_t a0;
+ compat_ulong_t a1;
+ compat_ulong_t a2;
+ compat_ulong_t a3;
+ compat_ulong_t a4;
+ compat_ulong_t a5;
+ compat_ulong_t a6;
+ compat_ulong_t a7;
+ compat_ulong_t s2;
+ compat_ulong_t s3;
+ compat_ulong_t s4;
+ compat_ulong_t s5;
+ compat_ulong_t s6;
+ compat_ulong_t s7;
+ compat_ulong_t s8;
+ compat_ulong_t s9;
+ compat_ulong_t s10;
+ compat_ulong_t s11;
+ compat_ulong_t t3;
+ compat_ulong_t t4;
+ compat_ulong_t t5;
+ compat_ulong_t t6;
+};
+
+static inline void regs_to_cregs(struct compat_user_regs_struct *cregs,
+ struct pt_regs *regs)
+{
+ cregs->pc = (compat_ulong_t) regs->epc;
+ cregs->ra = (compat_ulong_t) regs->ra;
+ cregs->sp = (compat_ulong_t) regs->sp;
+ cregs->gp = (compat_ulong_t) regs->gp;
+ cregs->tp = (compat_ulong_t) regs->tp;
+ cregs->t0 = (compat_ulong_t) regs->t0;
+ cregs->t1 = (compat_ulong_t) regs->t1;
+ cregs->t2 = (compat_ulong_t) regs->t2;
+ cregs->s0 = (compat_ulong_t) regs->s0;
+ cregs->s1 = (compat_ulong_t) regs->s1;
+ cregs->a0 = (compat_ulong_t) regs->a0;
+ cregs->a1 = (compat_ulong_t) regs->a1;
+ cregs->a2 = (compat_ulong_t) regs->a2;
+ cregs->a3 = (compat_ulong_t) regs->a3;
+ cregs->a4 = (compat_ulong_t) regs->a4;
+ cregs->a5 = (compat_ulong_t) regs->a5;
+ cregs->a6 = (compat_ulong_t) regs->a6;
+ cregs->a7 = (compat_ulong_t) regs->a7;
+ cregs->s2 = (compat_ulong_t) regs->s2;
+ cregs->s3 = (compat_ulong_t) regs->s3;
+ cregs->s4 = (compat_ulong_t) regs->s4;
+ cregs->s5 = (compat_ulong_t) regs->s5;
+ cregs->s6 = (compat_ulong_t) regs->s6;
+ cregs->s7 = (compat_ulong_t) regs->s7;
+ cregs->s8 = (compat_ulong_t) regs->s8;
+ cregs->s9 = (compat_ulong_t) regs->s9;
+ cregs->s10 = (compat_ulong_t) regs->s10;
+ cregs->s11 = (compat_ulong_t) regs->s11;
+ cregs->t3 = (compat_ulong_t) regs->t3;
+ cregs->t4 = (compat_ulong_t) regs->t4;
+ cregs->t5 = (compat_ulong_t) regs->t5;
+ cregs->t6 = (compat_ulong_t) regs->t6;
+};
+
+static inline void cregs_to_regs(struct compat_user_regs_struct *cregs,
+ struct pt_regs *regs)
+{
+ regs->epc = (unsigned long) cregs->pc;
+ regs->ra = (unsigned long) cregs->ra;
+ regs->sp = (unsigned long) cregs->sp;
+ regs->gp = (unsigned long) cregs->gp;
+ regs->tp = (unsigned long) cregs->tp;
+ regs->t0 = (unsigned long) cregs->t0;
+ regs->t1 = (unsigned long) cregs->t1;
+ regs->t2 = (unsigned long) cregs->t2;
+ regs->s0 = (unsigned long) cregs->s0;
+ regs->s1 = (unsigned long) cregs->s1;
+ regs->a0 = (unsigned long) cregs->a0;
+ regs->a1 = (unsigned long) cregs->a1;
+ regs->a2 = (unsigned long) cregs->a2;
+ regs->a3 = (unsigned long) cregs->a3;
+ regs->a4 = (unsigned long) cregs->a4;
+ regs->a5 = (unsigned long) cregs->a5;
+ regs->a6 = (unsigned long) cregs->a6;
+ regs->a7 = (unsigned long) cregs->a7;
+ regs->s2 = (unsigned long) cregs->s2;
+ regs->s3 = (unsigned long) cregs->s3;
+ regs->s4 = (unsigned long) cregs->s4;
+ regs->s5 = (unsigned long) cregs->s5;
+ regs->s6 = (unsigned long) cregs->s6;
+ regs->s7 = (unsigned long) cregs->s7;
+ regs->s8 = (unsigned long) cregs->s8;
+ regs->s9 = (unsigned long) cregs->s9;
+ regs->s10 = (unsigned long) cregs->s10;
+ regs->s11 = (unsigned long) cregs->s11;
+ regs->t3 = (unsigned long) cregs->t3;
+ regs->t4 = (unsigned long) cregs->t4;
+ regs->t5 = (unsigned long) cregs->t5;
+ regs->t6 = (unsigned long) cregs->t6;
+};
+
+#endif /* __ASM_COMPAT_H */
diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h
index 60da0dcacf14..9392e35c689d 100644
--- a/arch/riscv/include/asm/thread_info.h
+++ b/arch/riscv/include/asm/thread_info.h
@@ -91,6 +91,7 @@ struct thread_info {
#define TIF_SECCOMP 8 /* syscall secure computing */
#define TIF_NOTIFY_SIGNAL 9 /* signal notifications exist */
#define TIF_UPROBE 10 /* uprobe breakpoint or singlestep */
+#define TIF_32BIT 11 /* 32bit process */

#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
--
2.25.1


2021-12-21 16:36:09

by Guo Ren

[permalink] [raw]
Subject: [PATCH 04/13] riscv: compat: Re-implement TASK_SIZE for COMPAT_32BIT

From: Guo Ren <[email protected]>

Make TASK_SIZE from const to dynamic detect TIF_32BIT flag
function. Refer to arm64 to implement DEFAULT_MAP_WINDOW_64 for
efi-stub.

Limit 32-bit compatible process in 0-2GB virtual address range
(which is enough for real scenarios), because it could avoid
address sign extend problem when 32-bit enter 64-bit and ease
software design.

The standard 32-bit TASK_SIZE is 0x9dc00000:FIXADDR_START, and
compared to a compatible 32-bit, it increases 476MB for the
application's virtual address.

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/include/asm/pgtable.h | 11 ++++++++++-
arch/riscv/include/asm/processor.h | 6 ++++++
drivers/firmware/efi/libstub/efi-stub.c | 2 +-
3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index bf204e7c1f74..2dd5b8674380 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -663,7 +663,16 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
* Note that PGDIR_SIZE must evenly divide TASK_SIZE.
*/
#ifdef CONFIG_64BIT
-#define TASK_SIZE (PGDIR_SIZE * PTRS_PER_PGD / 2)
+#define TASK_SIZE_64 (PGDIR_SIZE * PTRS_PER_PGD / 2)
+
+#ifdef CONFIG_COMPAT
+#define TASK_SIZE_32 (_AC(0x80000000, UL) - PAGE_SIZE)
+#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
+ TASK_SIZE_32 : TASK_SIZE_64)
+#else
+#define TASK_SIZE TASK_SIZE_64
+#endif
+
#else
#define TASK_SIZE FIXADDR_START
#endif
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 0749924d9e55..8649436b8fcf 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -61,6 +61,12 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
extern void start_thread(struct pt_regs *regs,
unsigned long pc, unsigned long sp);

+#ifdef CONFIG_COMPAT
+#define DEFAULT_MAP_WINDOW_64 TASK_SIZE_64
+#else
+#define DEFAULT_MAP_WINDOW_64 TASK_SIZE
+#endif
+
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 26e69788f27a..4075fd19d219 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -38,7 +38,7 @@
#define EFI_RT_VIRTUAL_BASE SZ_512M
#define EFI_RT_VIRTUAL_SIZE SZ_512M

-#ifdef CONFIG_ARM64
+#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
# define EFI_RT_VIRTUAL_LIMIT DEFAULT_MAP_WINDOW_64
#else
# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE
--
2.25.1


2021-12-21 16:36:12

by Guo Ren

[permalink] [raw]
Subject: [PATCH 05/13] riscv: compat: syscall: Add compat_sys_call_table implementation

From: Guo Ren <[email protected]>

Implement compat_syscall_table.c with compat_sys_call_table & fixup
system call such as truncate64,pread64,fallocate which need two
regs to indicate 64bit-arg (copied from arm64).

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/include/asm/syscall.h | 3 +
arch/riscv/kernel/compat_syscall_table.c | 84 ++++++++++++++++++++++++
2 files changed, 87 insertions(+)
create mode 100644 arch/riscv/kernel/compat_syscall_table.c

diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h
index 7ac6a0e275f2..4ff98a22ef24 100644
--- a/arch/riscv/include/asm/syscall.h
+++ b/arch/riscv/include/asm/syscall.h
@@ -16,6 +16,9 @@

/* The array of function pointers for syscalls. */
extern void * const sys_call_table[];
+#ifdef CONFIG_COMPAT
+extern void * const compat_sys_call_table[];
+#endif

/*
* Only the low 32 bits of orig_r0 are meaningful, so we return int.
diff --git a/arch/riscv/kernel/compat_syscall_table.c b/arch/riscv/kernel/compat_syscall_table.c
new file mode 100644
index 000000000000..9b81fb9a8683
--- /dev/null
+++ b/arch/riscv/kernel/compat_syscall_table.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define __SYSCALL_COMPAT
+#undef __LP64__
+
+#include <linux/compat.h>
+#include <linux/syscalls.h>
+#include <asm-generic/mman-common.h>
+#include <asm-generic/syscalls.h>
+#include <asm/syscall.h>
+
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+ unsigned long, prot, unsigned long, flags,
+ unsigned long, fd, unsigned long, offset)
+{
+ if ((prot & PROT_WRITE) && (prot & PROT_EXEC))
+ if (unlikely(!(prot & PROT_READ)))
+ return -EINVAL;
+
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd, offset);
+}
+
+#define arg_u32p(name) u32, name##_lo, u32, name##_hi
+
+#define arg_u64(name) (((u64)name##_hi << 32) | \
+ ((u64)name##_lo & 0xffffffff))
+
+COMPAT_SYSCALL_DEFINE3(truncate64, const char __user *, pathname,
+ arg_u32p(length))
+{
+ return ksys_truncate(pathname, arg_u64(length));
+}
+
+COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd, arg_u32p(length))
+{
+ return ksys_ftruncate(fd, arg_u64(length));
+}
+
+COMPAT_SYSCALL_DEFINE6(fallocate, int, fd, int, mode,
+ arg_u32p(offset), arg_u32p(len))
+{
+ return ksys_fallocate(fd, mode, arg_u64(offset), arg_u64(len));
+}
+
+COMPAT_SYSCALL_DEFINE5(pread64, unsigned int, fd, char __user *, buf,
+ size_t, count, arg_u32p(pos))
+{
+ return ksys_pread64(fd, buf, count, arg_u64(pos));
+}
+
+COMPAT_SYSCALL_DEFINE5(pwrite64, unsigned int, fd,
+ const char __user *, buf, size_t, count, arg_u32p(pos))
+{
+ return ksys_pwrite64(fd, buf, count, arg_u64(pos));
+}
+
+COMPAT_SYSCALL_DEFINE6(sync_file_range, int, fd, arg_u32p(offset),
+ arg_u32p(nbytes), unsigned int, flags)
+{
+ return ksys_sync_file_range(fd, arg_u64(offset), arg_u64(nbytes),
+ flags);
+}
+
+COMPAT_SYSCALL_DEFINE4(readahead, int, fd, arg_u32p(offset),
+ size_t, count)
+{
+ return ksys_readahead(fd, arg_u64(offset), count);
+}
+
+COMPAT_SYSCALL_DEFINE6(fadvise64_64, int, fd, int, advice, arg_u32p(offset),
+ arg_u32p(len))
+{
+ return ksys_fadvise64_64(fd, arg_u64(offset), arg_u64(len), advice);
+}
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+asmlinkage long compat_sys_rt_sigreturn(void);
+
+void * const compat_sys_call_table[__NR_syscalls] = {
+ [0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
--
2.25.1


2021-12-21 16:36:15

by Guo Ren

[permalink] [raw]
Subject: [PATCH 06/13] riscv: compat: syscall: Add entry.S implementation

From: Guo Ren <[email protected]>

Implement the entry of compat_sys_call_table[] in asm. Ref to
riscv-privileged spec 4.1.1 Supervisor Status Register (sstatus):

BIT[32:33] = UXL[1:0]:
- 1:32
- 2:64
- 3:128

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/include/asm/csr.h | 7 +++++++
arch/riscv/kernel/entry.S | 18 ++++++++++++++++--
2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 5046f431645c..7dac12366833 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -36,6 +36,13 @@
#define SR_SD _AC(0x8000000000000000, UL) /* FS/XS dirty */
#endif

+#ifdef CONFIG_COMPAT
+#define SR_UXL _AC(0x300000000, UL) /* XLEN mask for U-mode */
+#define SR_UXL_32 _AC(0x100000000, UL) /* XLEN = 32 for U-mode */
+#define SR_UXL_64 _AC(0x200000000, UL) /* XLEN = 64 for U-mode */
+#define SR_UXL_SHIFT 32
+#endif
+
/* SATP flags */
#ifndef CONFIG_64BIT
#define SATP_PPN _AC(0x003FFFFF, UL)
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index ed29e9c8f660..1951743f09b3 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -207,13 +207,27 @@ check_syscall_nr:
* Syscall number held in a7.
* If syscall number is above allowed value, redirect to ni_syscall.
*/
- bgeu a7, t0, 1f
+ bgeu a7, t0, 3f
+#ifdef CONFIG_COMPAT
+ REG_L s0, PT_STATUS(sp)
+ srli s0, s0, SR_UXL_SHIFT
+ andi s0, s0, (SR_UXL >> SR_UXL_SHIFT)
+ li t0, (SR_UXL_32 >> SR_UXL_SHIFT)
+ sub t0, s0, t0
+ bnez t0, 1f
+
+ /* Call compat_syscall */
+ la s0, compat_sys_call_table
+ j 2f
+1:
+#endif
/* Call syscall */
la s0, sys_call_table
+2:
slli t0, a7, RISCV_LGPTR
add s0, s0, t0
REG_L s0, 0(s0)
-1:
+3:
jalr s0

ret_from_syscall:
--
2.25.1


2021-12-21 16:36:22

by Guo Ren

[permalink] [raw]
Subject: [PATCH 07/13] riscv: compat: Add elf.h implementation

From: Guo Ren <[email protected]>

Implement necessary type and macro for compat elf. See the code
comment for detail.

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/include/asm/elf.h | 42 +++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
index f53c40026c7a..48c116f3c12d 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -8,6 +8,8 @@
#ifndef _ASM_RISCV_ELF_H
#define _ASM_RISCV_ELF_H

+#include <uapi/linux/elf.h>
+#include <linux/compat.h>
#include <uapi/asm/elf.h>
#include <asm/auxvec.h>
#include <asm/byteorder.h>
@@ -18,11 +20,13 @@
*/
#define ELF_ARCH EM_RISCV

+#ifndef ELF_CLASS
#ifdef CONFIG_64BIT
#define ELF_CLASS ELFCLASS64
#else
#define ELF_CLASS ELFCLASS32
#endif
+#endif

#define ELF_DATA ELFDATA2LSB

@@ -31,6 +35,8 @@
*/
#define elf_check_arch(x) ((x)->e_machine == EM_RISCV)

+#define compat_elf_check_arch(x) ((x)->e_machine == EM_RISCV)
+
#define CORE_DUMP_USE_REGSET
#define ELF_EXEC_PAGESIZE (PAGE_SIZE)

@@ -43,8 +49,14 @@
#define ELF_ET_DYN_BASE ((TASK_SIZE / 3) * 2)

#ifdef CONFIG_64BIT
+#ifdef CONFIG_COMPAT
+#define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \
+ 0x7ff >> (PAGE_SHIFT - 12) : \
+ 0x3ffff >> (PAGE_SHIFT - 12))
+#else
#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12))
#endif
+#endif
/*
* This yields a mask that user programs can use to figure out what
* instruction set this CPU supports. This could be done in user space,
@@ -60,11 +72,19 @@ extern unsigned long elf_hwcap;
*/
#define ELF_PLATFORM (NULL)

+#define COMPAT_ELF_PLATFORM (NULL)
+
#ifdef CONFIG_MMU
#define ARCH_DLINFO \
do { \
+ /* \
+ * Note that we add ulong after elf_addr_t because \
+ * casting current->mm->context.vdso triggers a cast \
+ * warning of cast from pointer to integer for \
+ * COMPAT ELFCLASS32. \
+ */ \
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
- (elf_addr_t)current->mm->context.vdso); \
+ (elf_addr_t)(ulong)current->mm->context.vdso); \
NEW_AUX_ENT(AT_L1I_CACHESIZE, \
get_cache_size(1, CACHE_TYPE_INST)); \
NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, \
@@ -90,4 +110,24 @@ do { \
*(struct user_regs_struct *)regs; \
} while (0);

+#ifdef CONFIG_COMPAT
+
+/*
+ * FIXME: not sure SET_PERSONALITY for compat process is right!
+ */
+#define SET_PERSONALITY(ex) \
+do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+ set_thread_flag(TIF_32BIT); \
+ else \
+ clear_thread_flag(TIF_32BIT); \
+ set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \
+} while (0)
+
+#define COMPAT_ELF_ET_DYN_BASE ((TASK_SIZE_32 / 3) * 2)
+
+/* rv32 registers */
+typedef compat_ulong_t compat_elf_greg_t;
+typedef compat_elf_greg_t compat_elf_gregset_t[ELF_NGREG];
+
+#endif /* CONFIG_COMPAT */
#endif /* _ASM_RISCV_ELF_H */
--
2.25.1


2021-12-21 16:36:24

by Guo Ren

[permalink] [raw]
Subject: [PATCH 08/13] riscv: compat: Add COMPAT Kbuild skeletal support

From: Guo Ren <[email protected]>

Adds initial skeletal COMPAT Kbuild (Runing 32bit U-mode on 64bit
S-mode) support.
- Setup kconfig & dummy functions for compiling.
- Implement compat_start_thread by the way.

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/Kconfig | 22 ++++++++++++++++++++++
arch/riscv/include/asm/elf.h | 8 ++++++++
arch/riscv/include/asm/processor.h | 3 +++
arch/riscv/kernel/Makefile | 2 ++
arch/riscv/kernel/compat_signal.c | 18 ++++++++++++++++++
arch/riscv/kernel/process.c | 10 ++++++++++
arch/riscv/kernel/ptrace.c | 9 +++++++++
arch/riscv/kernel/vdso.c | 8 ++++++++
8 files changed, 80 insertions(+)
create mode 100644 arch/riscv/kernel/compat_signal.c

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 821252b65f89..6c3515a492a8 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -72,6 +72,7 @@ config RISCV
select HAVE_ARCH_KGDB if !XIP_KERNEL
select HAVE_ARCH_KGDB_QXFER_PKT
select HAVE_ARCH_MMAP_RND_BITS if MMU
+ select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU
@@ -122,12 +123,18 @@ config ARCH_MMAP_RND_BITS_MIN
default 18 if 64BIT
default 8

+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+ default 8
+
# max bits determined by the following formula:
# VA_BITS - PAGE_SHIFT - 3
config ARCH_MMAP_RND_BITS_MAX
default 24 if 64BIT # SV39 based
default 17

+config ARCH_MMAP_RND_COMPAT_BITS_MAX
+ default 17
+
# set if we run in machine mode, cleared if we run in supervisor mode
config RISCV_M_MODE
bool
@@ -427,6 +434,21 @@ config CRASH_DUMP

For more details see Documentation/admin-guide/kdump/kdump.rst

+config COMPAT
+ bool "Kernel support for 32-bit U-mode"
+ depends on 64BIT && MMU
+ help
+ This option enables support for a 32-bit U-mode running under a 64-bit
+ kernel at S-mode. riscv32-specific components such as system calls,
+ the user helper functions (vdso), signal rt_frame functions and the
+ ptrace interface are handled appropriately by the kernel.
+
+ If you want to execute 32-bit userspace applications, say Y.
+
+config SYSVIPC_COMPAT
+ def_bool y
+ depends on COMPAT && SYSVIPC
+
endmenu

menu "Boot options"
diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
index 48c116f3c12d..37f1cbdaa242 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -129,5 +129,13 @@ do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
typedef compat_ulong_t compat_elf_greg_t;
typedef compat_elf_greg_t compat_elf_gregset_t[ELF_NGREG];

+#define compat_start_thread compat_start_thread
+
+
+extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+#define compat_arch_setup_additional_pages \
+ compat_arch_setup_additional_pages
+
#endif /* CONFIG_COMPAT */
#endif /* _ASM_RISCV_ELF_H */
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 8649436b8fcf..9544c138d9ce 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -62,6 +62,9 @@ extern void start_thread(struct pt_regs *regs,
unsigned long pc, unsigned long sp);

#ifdef CONFIG_COMPAT
+extern void compat_start_thread(struct pt_regs *regs,
+ unsigned long pc, unsigned long sp);
+
#define DEFAULT_MAP_WINDOW_64 TASK_SIZE_64
#else
#define DEFAULT_MAP_WINDOW_64 TASK_SIZE
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 3397ddac1a30..f83e22affd5f 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -65,3 +65,5 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o

obj-$(CONFIG_EFI) += efi.o
+obj-$(CONFIG_COMPAT) += compat_syscall_table.o
+obj-$(CONFIG_COMPAT) += compat_signal.o
diff --git a/arch/riscv/kernel/compat_signal.c b/arch/riscv/kernel/compat_signal.c
new file mode 100644
index 000000000000..1ad3d348f37c
--- /dev/null
+++ b/arch/riscv/kernel/compat_signal.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+#include <linux/syscalls.h>
+#include <linux/tracehook.h>
+#include <linux/linkage.h>
+
+#include <asm/ucontext.h>
+#include <asm/vdso.h>
+#include <asm/switch_to.h>
+#include <asm/csr.h>
+
+COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
+{
+ return 0;
+}
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 03ac3aa611f5..9ebf9a95e5ea 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -15,6 +15,7 @@
#include <linux/tick.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
+#include <uapi/linux/elf.h>

#include <asm/unistd.h>
#include <asm/processor.h>
@@ -99,6 +100,15 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
regs->sp = sp;
}

+#ifdef CONFIG_COMPAT
+void compat_start_thread(struct pt_regs *regs, unsigned long pc,
+ unsigned long sp)
+{
+ start_thread(regs, pc, sp);
+ regs->status |= SR_UXL_32;
+}
+#endif
+
void flush_thread(void)
{
#ifdef CONFIG_FPU
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index 9c0511119bad..55dd50f8a5cc 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -12,6 +12,7 @@
#include <asm/thread_info.h>
#include <asm/switch_to.h>
#include <linux/audit.h>
+#include <linux/compat.h>
#include <linux/ptrace.h>
#include <linux/elf.h>
#include <linux/regset.h>
@@ -275,3 +276,11 @@ __visible void do_syscall_trace_exit(struct pt_regs *regs)
trace_sys_exit(regs, regs_return_value(regs));
#endif
}
+
+#ifdef CONFIG_COMPAT
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t caddr, compat_ulong_t cdata)
+{
+ return 0;
+}
+#endif
diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
index a9436a65161a..4f523a23a5d1 100644
--- a/arch/riscv/kernel/vdso.c
+++ b/arch/riscv/kernel/vdso.c
@@ -253,6 +253,14 @@ static int __setup_additional_pages(struct mm_struct *mm,
return PTR_ERR(ret);
}

+#ifdef CONFIG_COMPAT
+int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp)
+{
+ return 0;
+}
+#endif
+
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
struct mm_struct *mm = current->mm;
--
2.25.1


2021-12-21 16:36:32

by Guo Ren

[permalink] [raw]
Subject: [PATCH 09/13] riscv: compat: init: Add hw-cap detect in setup_arch

From: Guo Ren <[email protected]>

Detect hardware COMPAT (32bit U-mode) capability in rv64. If not
support COMPAT mode in hw, compat_elf_check_arch would return
false by compat_binfmt_elf.c

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/include/asm/elf.h | 5 ++++-
arch/riscv/include/asm/processor.h | 1 +
arch/riscv/kernel/process.c | 22 ++++++++++++++++++++++
arch/riscv/kernel/setup.c | 5 +++++
4 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
index 37f1cbdaa242..6baa49c4fba1 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -35,7 +35,10 @@
*/
#define elf_check_arch(x) ((x)->e_machine == EM_RISCV)

-#define compat_elf_check_arch(x) ((x)->e_machine == EM_RISCV)
+#ifdef CONFIG_COMPAT
+extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
+#define compat_elf_check_arch compat_elf_check_arch
+#endif

#define CORE_DUMP_USE_REGSET
#define ELF_EXEC_PAGESIZE (PAGE_SIZE)
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 9544c138d9ce..8b288ac0d704 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -64,6 +64,7 @@ extern void start_thread(struct pt_regs *regs,
#ifdef CONFIG_COMPAT
extern void compat_start_thread(struct pt_regs *regs,
unsigned long pc, unsigned long sp);
+extern void compat_mode_detect(void);

#define DEFAULT_MAP_WINDOW_64 TASK_SIZE_64
#else
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 9ebf9a95e5ea..496d09c5d384 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -101,6 +101,28 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
}

#ifdef CONFIG_COMPAT
+static bool compat_mode_support __read_mostly = false;
+
+bool compat_elf_check_arch(Elf32_Ehdr *hdr)
+{
+ if (compat_mode_support && (hdr->e_machine == EM_RISCV))
+ return true;
+
+ return false;
+}
+
+void compat_mode_detect(void)
+{
+ csr_write(CSR_STATUS, (csr_read(CSR_STATUS) & ~SR_UXL) | SR_UXL_32);
+
+ if ((csr_read(CSR_STATUS) & SR_UXL) != SR_UXL_32)
+ return;
+
+ compat_mode_support = true;
+
+ pr_info("riscv: compat: 32bit U-mode applications support\n");
+}
+
void compat_start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index b42bfdc67482..be131219d549 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -12,6 +12,7 @@
#include <linux/mm.h>
#include <linux/memblock.h>
#include <linux/sched.h>
+#include <linux/compat.h>
#include <linux/console.h>
#include <linux/screen_info.h>
#include <linux/of_fdt.h>
@@ -294,6 +295,10 @@ void __init setup_arch(char **cmdline_p)
setup_smp();
#endif

+#ifdef CONFIG_COMPAT
+ compat_mode_detect();
+#endif
+
riscv_fill_hwcap();
}

--
2.25.1


2021-12-21 16:36:34

by Guo Ren

[permalink] [raw]
Subject: [PATCH 10/13] riscv: compat: vdso: Add rv32 VDSO base code implementation

From: Guo Ren <[email protected]>

There is no vgettimeofday supported in rv32 that makes simple to
generate rv32 vdso code which only needs riscv64 compiler. Other
architectures need change compiler or -m (machine parameter) to
support vdso32 compiling. If rv32 support vgettimeofday (which
cause C compile) in future, we would add CROSS_COMPILE to support
that makes more requirement on compiler enviornment.

linux-rv64/arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg:
file format elf64-littleriscv

Disassembly of section .text:

0000000000000800 <__vdso_rt_sigreturn>:
800: 08b00893 li a7,139
804: 00000073 ecall
808: 0000 unimp
...

000000000000080c <__vdso_getcpu>:
80c: 0a800893 li a7,168
810: 00000073 ecall
814: 8082 ret
...

0000000000000818 <__vdso_flush_icache>:
818: 10300893 li a7,259
81c: 00000073 ecall
820: 8082 ret

linux-rv32/arch/riscv/kernel/vdso/vdso.so.dbg:
file format elf32-littleriscv

Disassembly of section .text:

00000800 <__vdso_rt_sigreturn>:
800: 08b00893 li a7,139
804: 00000073 ecall
808: 0000 unimp
...

0000080c <__vdso_getcpu>:
80c: 0a800893 li a7,168
810: 00000073 ecall
814: 8082 ret
...

00000818 <__vdso_flush_icache>:
818: 10300893 li a7,259
81c: 00000073 ecall
820: 8082 ret

Finally, reuse all *.S from vdso in compat_vdso that makes
implementation clear and readable.

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/Makefile | 5 ++
arch/riscv/include/asm/vdso.h | 9 +++
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/compat_vdso/.gitignore | 2 +
arch/riscv/kernel/compat_vdso/Makefile | 68 +++++++++++++++++++
arch/riscv/kernel/compat_vdso/compat_vdso.S | 8 +++
.../kernel/compat_vdso/compat_vdso.lds.S | 3 +
arch/riscv/kernel/compat_vdso/flush_icache.S | 3 +
.../compat_vdso/gen_compat_vdso_offsets.sh | 5 ++
arch/riscv/kernel/compat_vdso/getcpu.S | 3 +
arch/riscv/kernel/compat_vdso/note.S | 3 +
arch/riscv/kernel/compat_vdso/rt_sigreturn.S | 3 +
arch/riscv/kernel/vdso/vdso.S | 6 +-
13 files changed, 118 insertions(+), 1 deletion(-)
create mode 100644 arch/riscv/kernel/compat_vdso/.gitignore
create mode 100644 arch/riscv/kernel/compat_vdso/Makefile
create mode 100644 arch/riscv/kernel/compat_vdso/compat_vdso.S
create mode 100644 arch/riscv/kernel/compat_vdso/compat_vdso.lds.S
create mode 100644 arch/riscv/kernel/compat_vdso/flush_icache.S
create mode 100755 arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh
create mode 100644 arch/riscv/kernel/compat_vdso/getcpu.S
create mode 100644 arch/riscv/kernel/compat_vdso/note.S
create mode 100644 arch/riscv/kernel/compat_vdso/rt_sigreturn.S

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 8a107ed18b0d..fb984b8721ef 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -106,12 +106,17 @@ libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
PHONY += vdso_install
vdso_install:
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
+ $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
+ $(build)=arch/riscv/kernel/compat_vdso $@)

ifeq ($(KBUILD_EXTMOD),)
ifeq ($(CONFIG_MMU),y)
prepare: vdso_prepare
vdso_prepare: prepare0
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
+ $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
+ $(build)=arch/riscv/kernel/compat_vdso include/generated/compat_vdso-offsets.h)
+
endif
endif

diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h
index bc6f75f3a199..af981426fe0f 100644
--- a/arch/riscv/include/asm/vdso.h
+++ b/arch/riscv/include/asm/vdso.h
@@ -21,6 +21,15 @@

#define VDSO_SYMBOL(base, name) \
(void __user *)((unsigned long)(base) + __vdso_##name##_offset)
+
+#ifdef CONFIG_COMPAT
+#include <generated/compat_vdso-offsets.h>
+
+#define COMPAT_VDSO_SYMBOL(base, name) \
+ (void __user *)((unsigned long)(base) + compat__vdso_##name##_offset)
+
+#endif /* CONFIG_COMPAT */
+
#endif /* !__ASSEMBLY__ */

#endif /* CONFIG_MMU */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index f83e22affd5f..ef47f7d5843f 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -67,3 +67,4 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_EFI) += efi.o
obj-$(CONFIG_COMPAT) += compat_syscall_table.o
obj-$(CONFIG_COMPAT) += compat_signal.o
+obj-$(CONFIG_COMPAT) += compat_vdso/
diff --git a/arch/riscv/kernel/compat_vdso/.gitignore b/arch/riscv/kernel/compat_vdso/.gitignore
new file mode 100644
index 000000000000..19d83d846c1e
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+compat_vdso.lds
diff --git a/arch/riscv/kernel/compat_vdso/Makefile b/arch/riscv/kernel/compat_vdso/Makefile
new file mode 100644
index 000000000000..7bbbbf94307f
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/Makefile
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
+# the inclusion of generic Makefile.
+ARCH_REL_TYPE_ABS := R_RISCV_32|R_RISCV_64|R_RISCV_JUMP_SLOT
+include $(srctree)/lib/vdso/Makefile
+# Symbols present in the compat_vdso
+compat_vdso-syms = rt_sigreturn
+compat_vdso-syms += getcpu
+compat_vdso-syms += flush_icache
+
+# Files to link into the compat_vdso
+obj-compat_vdso = $(patsubst %, %.o, $(compat_vdso-syms)) note.o
+
+ccflags-y := -fno-stack-protector
+
+# Build rules
+targets := $(obj-compat_vdso) compat_vdso.so compat_vdso.so.dbg compat_vdso.lds
+obj-compat_vdso := $(addprefix $(obj)/, $(obj-compat_vdso))
+
+obj-y += compat_vdso.o
+CPPFLAGS_compat_vdso.lds += -P -C -U$(ARCH)
+
+# Disable profiling and instrumentation for VDSO code
+GCOV_PROFILE := n
+KCOV_INSTRUMENT := n
+KASAN_SANITIZE := n
+UBSAN_SANITIZE := n
+
+# Force dependency
+$(obj)/compat_vdso.o: $(obj)/compat_vdso.so
+
+# link rule for the .so file, .lds has to be first
+$(obj)/compat_vdso.so.dbg: $(obj)/compat_vdso.lds $(obj-compat_vdso) FORCE
+ $(call if_changed,compat_vdsold)
+LDFLAGS_compat_vdso.so.dbg = -shared -S -soname=linux-compat_vdso.so.1 \
+ --build-id=sha1 --hash-style=both --eh-frame-hdr
+
+# strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+ $(call if_changed,objcopy)
+
+# Generate VDSO offsets using helper script
+gen-compat_vdsosym := $(srctree)/$(src)/gen_compat_vdso_offsets.sh
+quiet_cmd_compat_vdsosym = VDSOSYM $@
+ cmd_compat_vdsosym = $(NM) $< | $(gen-compat_vdsosym) | LC_ALL=C sort > $@
+
+include/generated/compat_vdso-offsets.h: $(obj)/compat_vdso.so.dbg FORCE
+ $(call if_changed,compat_vdsosym)
+
+# actual build commands
+# The DSO images are built using a special linker script
+# Make sure only to export the intended __compat_vdso_xxx symbol offsets.
+quiet_cmd_compat_vdsold = VDSOLD $@
+ cmd_compat_vdsold = $(LD) $(ld_flags) -T $(filter-out FORCE,$^) -o [email protected] && \
+ $(OBJCOPY) $(patsubst %, -G __compat_vdso_%, $(compat_vdso-syms)) [email protected] $@ && \
+ rm [email protected]
+
+# install commands for the unstripped file
+quiet_cmd_compat_vdso_install = INSTALL $@
+ cmd_compat_vdso_install = cp $(obj)/[email protected] $(MODLIB)/compat_vdso/$@
+
+compat_vdso.so: $(obj)/compat_vdso.so.dbg
+ @mkdir -p $(MODLIB)/compat_vdso
+ $(call cmd,compat_vdso_install)
+
+compat_vdso_install: compat_vdso.so
diff --git a/arch/riscv/kernel/compat_vdso/compat_vdso.S b/arch/riscv/kernel/compat_vdso/compat_vdso.S
new file mode 100644
index 000000000000..fea4a8b0c45d
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/compat_vdso.S
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#define vdso_start compat_vdso_start
+#define vdso_end compat_vdso_end
+
+#define __VDSO_PATH "arch/riscv/kernel/compat_vdso/compat_vdso.so"
+
+#include <../vdso/vdso.S>
diff --git a/arch/riscv/kernel/compat_vdso/compat_vdso.lds.S b/arch/riscv/kernel/compat_vdso/compat_vdso.lds.S
new file mode 100644
index 000000000000..02a9ec5dc7f6
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/compat_vdso.lds.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <../vdso/vdso.lds.S>
diff --git a/arch/riscv/kernel/compat_vdso/flush_icache.S b/arch/riscv/kernel/compat_vdso/flush_icache.S
new file mode 100644
index 000000000000..88e21a84a974
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/flush_icache.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <../vdso/flush_icache.S>
diff --git a/arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh b/arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh
new file mode 100755
index 000000000000..8ac070c783b3
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+LC_ALL=C
+sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define compat\2_offset\t0x\1/p'
diff --git a/arch/riscv/kernel/compat_vdso/getcpu.S b/arch/riscv/kernel/compat_vdso/getcpu.S
new file mode 100644
index 000000000000..946449a15a94
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/getcpu.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <../vdso/getcpu.S>
diff --git a/arch/riscv/kernel/compat_vdso/note.S b/arch/riscv/kernel/compat_vdso/note.S
new file mode 100644
index 000000000000..67c50898b8e5
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/note.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <../vdso/note.S>
diff --git a/arch/riscv/kernel/compat_vdso/rt_sigreturn.S b/arch/riscv/kernel/compat_vdso/rt_sigreturn.S
new file mode 100644
index 000000000000..f4c98f18c053
--- /dev/null
+++ b/arch/riscv/kernel/compat_vdso/rt_sigreturn.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <../vdso/rt_sigreturn.S>
diff --git a/arch/riscv/kernel/vdso/vdso.S b/arch/riscv/kernel/vdso/vdso.S
index df222245be05..83f1c899e8d8 100644
--- a/arch/riscv/kernel/vdso/vdso.S
+++ b/arch/riscv/kernel/vdso/vdso.S
@@ -7,12 +7,16 @@
#include <linux/linkage.h>
#include <asm/page.h>

+#ifndef __VDSO_PATH
+#define __VDSO_PATH "arch/riscv/kernel/vdso/vdso.so"
+#endif
+
__PAGE_ALIGNED_DATA

.globl vdso_start, vdso_end
.balign PAGE_SIZE
vdso_start:
- .incbin "arch/riscv/kernel/vdso/vdso.so"
+ .incbin __VDSO_PATH
.balign PAGE_SIZE
vdso_end:

--
2.25.1


2021-12-21 16:36:41

by Guo Ren

[permalink] [raw]
Subject: [PATCH 11/13] riscv: compat: vdso: Add setup additional pages implementation

From: Guo Ren <[email protected]>

Reconstruct __setup_additional_pages() by appending vdso info
pointer argument to meet compat_vdso_info requirement. And change
vm_special_mapping *dm, *cm initialization into static.

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/include/asm/mmu.h | 1 +
arch/riscv/kernel/vdso.c | 98 +++++++++++++++++++++++++-----------
2 files changed, 69 insertions(+), 30 deletions(-)

diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h
index 0099dc116168..cedcf8ea3c76 100644
--- a/arch/riscv/include/asm/mmu.h
+++ b/arch/riscv/include/asm/mmu.h
@@ -16,6 +16,7 @@ typedef struct {
atomic_long_t id;
#endif
void *vdso;
+ void *vdso_info;
#ifdef CONFIG_SMP
/* A local icache flush is needed before user execution can resume. */
cpumask_t icache_stale_mask;
diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
index 4f523a23a5d1..deca69524799 100644
--- a/arch/riscv/kernel/vdso.c
+++ b/arch/riscv/kernel/vdso.c
@@ -23,6 +23,9 @@ struct vdso_data {
#endif

extern char vdso_start[], vdso_end[];
+#ifdef CONFIG_COMPAT
+extern char compat_vdso_start[], compat_vdso_end[];
+#endif

enum vvar_pages {
VVAR_DATA_PAGE_OFFSET,
@@ -30,6 +33,11 @@ enum vvar_pages {
VVAR_NR_PAGES,
};

+enum rv_vdso_map {
+ RV_VDSO_MAP_VVAR,
+ RV_VDSO_MAP_VDSO,
+};
+
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)

/*
@@ -52,12 +60,6 @@ struct __vdso_info {
struct vm_special_mapping *cm;
};

-static struct __vdso_info vdso_info __ro_after_init = {
- .name = "vdso",
- .vdso_code_start = vdso_start,
- .vdso_code_end = vdso_end,
-};
-
static int vdso_mremap(const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
{
@@ -66,35 +68,35 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
return 0;
}

-static int __init __vdso_init(void)
+static int __init __vdso_init(struct __vdso_info *vdso_info)
{
unsigned int i;
struct page **vdso_pagelist;
unsigned long pfn;

- if (memcmp(vdso_info.vdso_code_start, "\177ELF", 4)) {
+ if (memcmp(vdso_info->vdso_code_start, "\177ELF", 4)) {
pr_err("vDSO is not a valid ELF object!\n");
return -EINVAL;
}

- vdso_info.vdso_pages = (
- vdso_info.vdso_code_end -
- vdso_info.vdso_code_start) >>
+ vdso_info->vdso_pages = (
+ vdso_info->vdso_code_end -
+ vdso_info->vdso_code_start) >>
PAGE_SHIFT;

- vdso_pagelist = kcalloc(vdso_info.vdso_pages,
+ vdso_pagelist = kcalloc(vdso_info->vdso_pages,
sizeof(struct page *),
GFP_KERNEL);
if (vdso_pagelist == NULL)
return -ENOMEM;

/* Grab the vDSO code pages. */
- pfn = sym_to_pfn(vdso_info.vdso_code_start);
+ pfn = sym_to_pfn(vdso_info->vdso_code_start);

- for (i = 0; i < vdso_info.vdso_pages; i++)
+ for (i = 0; i < vdso_info->vdso_pages; i++)
vdso_pagelist[i] = pfn_to_page(pfn + i);

- vdso_info.cm->pages = vdso_pagelist;
+ vdso_info->cm->pages = vdso_pagelist;

return 0;
}
@@ -116,13 +118,14 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
{
struct mm_struct *mm = task->mm;
struct vm_area_struct *vma;
+ struct __vdso_info *vdso_info = mm->context.vdso_info;

mmap_read_lock(mm);

for (vma = mm->mmap; vma; vma = vma->vm_next) {
unsigned long size = vma->vm_end - vma->vm_start;

- if (vma_is_special_mapping(vma, vdso_info.dm))
+ if (vma_is_special_mapping(vma, vdso_info->dm))
zap_page_range(vma, vma->vm_start, size);
}

@@ -187,11 +190,6 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
return vmf_insert_pfn(vma, vmf->address, pfn);
}

-enum rv_vdso_map {
- RV_VDSO_MAP_VVAR,
- RV_VDSO_MAP_VDSO,
-};
-
static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = {
[RV_VDSO_MAP_VVAR] = {
.name = "[vvar]",
@@ -203,25 +201,53 @@ static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = {
},
};

+static struct __vdso_info vdso_info __ro_after_init = {
+ .name = "vdso",
+ .vdso_code_start = vdso_start,
+ .vdso_code_end = vdso_end,
+ .dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR],
+ .cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO],
+};
+
+#ifdef CONFIG_COMPAT
+static struct __vdso_info compat_vdso_info __ro_after_init = {
+ .name = "compat_vdso",
+ .vdso_code_start = compat_vdso_start,
+ .vdso_code_end = compat_vdso_end,
+ .dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR],
+ .cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO],
+};
+#endif
+
static int __init vdso_init(void)
{
- vdso_info.dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR];
- vdso_info.cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO];
+ int ret;
+
+ ret = __vdso_init(&vdso_info);
+ if (ret)
+ goto out;

- return __vdso_init();
+#ifdef CONFIG_COMPAT
+ ret = __vdso_init(&compat_vdso_info);
+ if (ret)
+ goto out;
+#endif
+out:
+ return ret;
}
arch_initcall(vdso_init);

static int __setup_additional_pages(struct mm_struct *mm,
struct linux_binprm *bprm,
- int uses_interp)
+ int uses_interp,
+ struct __vdso_info *vdso_info)
{
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;

BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES);

- vdso_text_len = vdso_info.vdso_pages << PAGE_SHIFT;
+ vdso_text_len = vdso_info->vdso_pages << PAGE_SHIFT;
/* Be sure to map the data page */
vdso_mapping_len = vdso_text_len + VVAR_SIZE;

@@ -232,16 +258,18 @@ static int __setup_additional_pages(struct mm_struct *mm,
}

ret = _install_special_mapping(mm, vdso_base, VVAR_SIZE,
- (VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info.dm);
+ (VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info->dm);
if (IS_ERR(ret))
goto up_fail;

vdso_base += VVAR_SIZE;
mm->context.vdso = (void *)vdso_base;
+ mm->context.vdso_info = (void *)vdso_info;
+
ret =
_install_special_mapping(mm, vdso_base, vdso_text_len,
(VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC),
- vdso_info.cm);
+ vdso_info->cm);

if (IS_ERR(ret))
goto up_fail;
@@ -257,7 +285,17 @@ static int __setup_additional_pages(struct mm_struct *mm,
int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp)
{
- return 0;
+ struct mm_struct *mm = current->mm;
+ int ret;
+
+ if (mmap_write_lock_killable(mm))
+ return -EINTR;
+
+ ret = __setup_additional_pages(mm, bprm, uses_interp,
+ &compat_vdso_info);
+ mmap_write_unlock(mm);
+
+ return ret;
}
#endif

@@ -269,7 +307,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
if (mmap_write_lock_killable(mm))
return -EINTR;

- ret = __setup_additional_pages(mm, bprm, uses_interp);
+ ret = __setup_additional_pages(mm, bprm, uses_interp, &vdso_info);
mmap_write_unlock(mm);

return ret;
--
2.25.1


2021-12-21 16:36:47

by Guo Ren

[permalink] [raw]
Subject: [PATCH 12/13] riscv: compat: signal: Add rt_frame implementation

From: Guo Ren <[email protected]>

Implement compat_setup_rt_frame for sigcontext save & restore. The
main process is the same with signal, but the rv32 pt_regs' size
is different from rv64's, so we needs convert them.

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/kernel/compat_signal.c | 225 ++++++++++++++++++++++++++++++
arch/riscv/kernel/signal.c | 13 +-
2 files changed, 237 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/kernel/compat_signal.c b/arch/riscv/kernel/compat_signal.c
index 1ad3d348f37c..7041742ded08 100644
--- a/arch/riscv/kernel/compat_signal.c
+++ b/arch/riscv/kernel/compat_signal.c
@@ -12,7 +12,232 @@
#include <asm/switch_to.h>
#include <asm/csr.h>

+#define COMPAT_DEBUG_SIG 0
+
+struct compat_sigcontext {
+ struct compat_user_regs_struct sc_regs;
+ union __riscv_fp_state sc_fpregs;
+};
+
+struct compat_ucontext {
+ compat_ulong_t uc_flags;
+ struct compat_ucontext *uc_link;
+ compat_stack_t uc_stack;
+ sigset_t uc_sigmask;
+ /* There's some padding here to allow sigset_t to be expanded in the
+ * future. Though this is unlikely, other architectures put uc_sigmask
+ * at the end of this structure and explicitly state it can be
+ * expanded, so we didn't want to box ourselves in here. */
+ __u8 __unused[1024 / 8 - sizeof(sigset_t)];
+ /* We can't put uc_sigmask at the end of this structure because we need
+ * to be able to expand sigcontext in the future. For example, the
+ * vector ISA extension will almost certainly add ISA state. We want
+ * to ensure all user-visible ISA state can be saved and restored via a
+ * ucontext, so we're putting this at the end in order to allow for
+ * infinite extensibility. Since we know this will be extended and we
+ * assume sigset_t won't be extended an extreme amount, we're
+ * prioritizing this. */
+ struct compat_sigcontext uc_mcontext;
+};
+
+struct compat_rt_sigframe {
+ struct compat_siginfo info;
+ struct compat_ucontext uc;
+};
+
+#ifdef CONFIG_FPU
+static long compat_restore_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state __user *sc_fpregs)
+{
+ long err;
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
+ size_t i;
+
+ err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
+ if (unlikely(err))
+ return err;
+
+ fstate_restore(current, regs);
+
+ /* We support no other extension state at this time. */
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+ u32 value;
+
+ err = __get_user(value, &sc_fpregs->q.reserved[i]);
+ if (unlikely(err))
+ break;
+ if (value != 0)
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static long compat_save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state __user *sc_fpregs)
+{
+ long err;
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
+ size_t i;
+
+ fstate_save(current, regs);
+ err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
+ if (unlikely(err))
+ return err;
+
+ /* We support no other extension state at this time. */
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+ err = __put_user(0, &sc_fpregs->q.reserved[i]);
+ if (unlikely(err))
+ break;
+ }
+
+ return err;
+}
+#else
+#define compat_save_fp_state(task, regs) (0)
+#define compat_restore_fp_state(task, regs) (0)
+#endif
+
+static long compat_restore_sigcontext(struct pt_regs *regs,
+ struct compat_sigcontext __user *sc)
+{
+ long err;
+ struct compat_user_regs_struct cregs;
+
+ /* sc_regs is structured the same as the start of pt_regs */
+ err = __copy_from_user(&cregs, &sc->sc_regs, sizeof(sc->sc_regs));
+
+ cregs_to_regs(&cregs, regs);
+
+ /* Restore the floating-point state. */
+ if (has_fpu())
+ err |= compat_restore_fp_state(regs, &sc->sc_fpregs);
+ return err;
+}
+
COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
{
+ struct pt_regs *regs = current_pt_regs();
+ struct compat_rt_sigframe __user *frame;
+ struct task_struct *task;
+ sigset_t set;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current->restart_block.fn = do_no_restart_syscall;
+
+ frame = (struct compat_rt_sigframe __user *)regs->sp;
+
+ if (!access_ok(frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ set_current_blocked(&set);
+
+ if (compat_restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
+ if (compat_restore_altstack(&frame->uc.uc_stack))
+ goto badframe;
+
+ return regs->a0;
+
+badframe:
+ task = current;
+ if (show_unhandled_signals) {
+ pr_info_ratelimited(
+ "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
+ task->comm, task_pid_nr(task), __func__,
+ frame, (void *)regs->epc, (void *)regs->sp);
+ }
+ force_sig(SIGSEGV);
+ return 0;
+}
+
+static long compat_setup_sigcontext(struct compat_rt_sigframe __user *frame,
+ struct pt_regs *regs)
+{
+ struct compat_sigcontext __user *sc = &frame->uc.uc_mcontext;
+ struct compat_user_regs_struct cregs;
+ long err;
+
+ regs_to_cregs(&cregs, regs);
+
+ /* sc_regs is structured the same as the start of pt_regs */
+ err = __copy_to_user(&sc->sc_regs, &cregs, sizeof(sc->sc_regs));
+ /* Save the floating-point state. */
+ if (has_fpu())
+ err |= compat_save_fp_state(regs, &sc->sc_fpregs);
+ return err;
+}
+
+static inline void __user *compat_get_sigframe(struct ksignal *ksig,
+ struct pt_regs *regs, size_t framesize)
+{
+ unsigned long sp;
+ /* Default to using normal stack */
+ sp = regs->sp;
+
+ /*
+ * If we are on the alternate signal stack and would overflow it, don't.
+ * Return an always-bogus address instead so we will die with SIGSEGV.
+ */
+ if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
+ return (void __user __force *)(-1UL);
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ sp = sigsp(sp, ksig) - framesize;
+
+ /* Align the stack frame. */
+ sp &= ~0xfUL;
+
+ return (void __user *)sp;
+}
+
+int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
+{
+ struct compat_rt_sigframe __user *frame;
+ long err = 0;
+
+ frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
+ if (!access_ok(frame, sizeof(*frame)))
+ return -EFAULT;
+
+ err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(NULL, &frame->uc.uc_link);
+ err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
+ err |= compat_setup_sigcontext(frame, regs);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ return -EFAULT;
+
+ regs->ra = (unsigned long)COMPAT_VDSO_SYMBOL(
+ current->mm->context.vdso, rt_sigreturn);
+
+ /*
+ * Set up registers for signal handler.
+ * Registers that we don't modify keep the value they had from
+ * user-space at the time we took the signal.
+ * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
+ * since some things rely on this (e.g. glibc's debug/segfault.c).
+ */
+ regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
+ regs->sp = (unsigned long)frame;
+ regs->a0 = ksig->sig; /* a0: signal number */
+ regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
+ regs->a2 = (unsigned long)(&frame->uc); /* a2: ucontext pointer */
+
+#if COMPAT_DEBUG_SIG
+ pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
+ current->comm, task_pid_nr(current), ksig->sig,
+ (void *)regs->epc, (void *)regs->ra, frame);
+#endif
+
return 0;
}
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index c2d5ecbe5526..27d8f39228c4 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -6,6 +6,7 @@
* Copyright (C) 2012 Regents of the University of California
*/

+#include <linux/compat.h>
#include <linux/signal.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
@@ -229,6 +230,11 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
return 0;
}

+#ifdef CONFIG_COMPAT
+extern int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs);
+#endif
+
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
@@ -258,8 +264,13 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
}
}

+#ifdef CONFIG_COMPAT
/* Set up the stack frame */
- ret = setup_rt_frame(ksig, oldset, regs);
+ if (is_compat_task())
+ ret = compat_setup_rt_frame(ksig, oldset, regs);
+ else
+#endif
+ ret = setup_rt_frame(ksig, oldset, regs);

signal_setup_done(ret, ksig, 0);
}
--
2.25.1


2021-12-21 16:36:50

by Guo Ren

[permalink] [raw]
Subject: [PATCH 13/13] riscv: compat: ptrace: Add compat_arch_ptrace implement

From: Guo Ren <[email protected]>

Now, you can use native gdb on riscv64 for rv32 app debugging.

$ uname -a
Linux buildroot 5.16.0-rc4-00036-gbef6b82fdf23-dirty #53 SMP Mon Dec 20 23:06:53 CST 2021 riscv64 GNU/Linux
$ cat /proc/cpuinfo
processor : 0
hart : 0
isa : rv64imafdcsuh
mmu : sv48

$ file /bin/busybox
/bin/busybox: setuid ELF 32-bit LSB shared object, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv32-ilp32d.so.1, for GNU/Linux 5.15.0, stripped
$ file /usr/bin/gdb
/usr/bin/gdb: ELF 32-bit LSB shared object, UCB RISC-V, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-riscv32-ilp32d.so.1, for GNU/Linux 5.15.0, stripped
$ /usr/bin/gdb /bin/busybox
GNU gdb (GDB) 10.2
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
...
Reading symbols from /bin/busybox...
(No debugging symbols found in /bin/busybox)
(gdb) b main
Breakpoint 1 at 0x8ddc
(gdb) r
Starting program: /bin/busybox
Failed to read a valid object file image from memory.

Breakpoint 1, 0x555a8ddc in main ()
(gdb) i r
ra 0x77df0b74 0x77df0b74
sp 0x7fdd3d10 0x7fdd3d10
gp 0x5567e800 0x5567e800 <bb_common_bufsiz1+160>
tp 0x77f64280 0x77f64280
t0 0x0 0
t1 0x555a6fac 1431990188
t2 0x77dd8db4 2011008436
fp 0x7fdd3e34 0x7fdd3e34
s1 0x7fdd3e34 2145205812
a0 0xffffffff -1
a1 0x2000 8192
a2 0x7fdd3e3c 2145205820
a3 0x0 0
a4 0x7fdd3d30 2145205552
a5 0x555a8dc0 1431997888
a6 0x77f2c170 2012397936
a7 0x6a7c7a2f 1786542639
s2 0x0 0
s3 0x0 0
s4 0x555a8dc0 1431997888
s5 0x77f8a3a8 2012783528
s6 0x7fdd3e3c 2145205820
s7 0x5567cecc 1432866508
--Type <RET> for more, q to quit, c to continue without paging--
s8 0x1 1
s9 0x0 0
s10 0x55634448 1432568904
s11 0x0 0
t3 0x77df0bb8 2011106232
t4 0x42fc 17148
t5 0x0 0
t6 0x40 64
pc 0x555a8ddc 0x555a8ddc <main+28>
(gdb) si
0x555a78f0 in mallopt@plt ()
(gdb) c
Continuing.
BusyBox v1.34.1 (2021-12-19 22:39:48 CST) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
or: busybox --list[-full]
...
[Inferior 1 (process 107) exited normally]
(gdb) q

Signed-off-by: Guo Ren <[email protected]>
---
arch/riscv/kernel/ptrace.c | 80 +++++++++++++++++++++++++++++++++++---
1 file changed, 74 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index 55dd50f8a5cc..76042ed861a3 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -114,11 +114,6 @@ static const struct user_regset_view riscv_user_native_view = {
.n = ARRAY_SIZE(riscv_user_regset),
};

-const struct user_regset_view *task_user_regset_view(struct task_struct *task)
-{
- return &riscv_user_native_view;
-}
-
struct pt_regs_offset {
const char *name;
int offset;
@@ -278,9 +273,82 @@ __visible void do_syscall_trace_exit(struct pt_regs *regs)
}

#ifdef CONFIG_COMPAT
+static int compat_riscv_gpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ struct compat_user_regs_struct cregs;
+
+ regs_to_cregs(&cregs, task_pt_regs(target));
+
+ return membuf_write(&to, &cregs,
+ sizeof(struct compat_user_regs_struct));
+}
+
+static int compat_riscv_gpr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+ struct compat_user_regs_struct cregs;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1);
+
+ cregs_to_regs(&cregs, task_pt_regs(target));
+
+ return ret;
+}
+
+static const struct user_regset compat_riscv_user_regset[] = {
+ [REGSET_X] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(compat_elf_greg_t),
+ .align = sizeof(compat_elf_greg_t),
+ .regset_get = compat_riscv_gpr_get,
+ .set = compat_riscv_gpr_set,
+ },
+#ifdef CONFIG_FPU
+ [REGSET_F] = {
+ .core_note_type = NT_PRFPREG,
+ .n = ELF_NFPREG,
+ .size = sizeof(elf_fpreg_t),
+ .align = sizeof(elf_fpreg_t),
+ .regset_get = riscv_fpr_get,
+ .set = riscv_fpr_set,
+ },
+#endif
+};
+
+static const struct user_regset_view compat_riscv_user_native_view = {
+ .name = "riscv",
+ .e_machine = EM_RISCV,
+ .regsets = compat_riscv_user_regset,
+ .n = ARRAY_SIZE(compat_riscv_user_regset),
+};
+
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
compat_ulong_t caddr, compat_ulong_t cdata)
{
- return 0;
+ long ret = -EIO;
+
+ switch (request) {
+ default:
+ ret = compat_ptrace_request(child, request, caddr, cdata);
+ break;
+ }
+
+ return ret;
}
+#endif /* CONFIG_COMPAT */
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_COMPAT
+ if (test_tsk_thread_flag(task, TIF_32BIT))
+ return &compat_riscv_user_native_view;
+ else
#endif
+ return &riscv_user_native_view;
+}
--
2.25.1


2021-12-21 17:09:05

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 01/13] syscalls: compat: Fix the missing part for __SYSCALL_COMPAT

On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
> index 4557a8b6086f..aafe5cfeb27c 100644
> --- a/include/uapi/asm-generic/unistd.h
> +++ b/include/uapi/asm-generic/unistd.h
> @@ -383,7 +383,7 @@ __SYSCALL(__NR_syslog, sys_syslog)
>
> /* kernel/ptrace.c */
> #define __NR_ptrace 117
> -__SYSCALL(__NR_ptrace, sys_ptrace)
> +__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace)
>

Right. We could merge sys_ptrace and compat_sys_ptrace() by adding
a in_compat_syscall() check, but either way works.

> /* kernel/sched/core.c */
> #define __NR_sched_setparam 118
> @@ -779,7 +779,7 @@ __SYSCALL(__NR_rseq, sys_rseq)
> #define __NR_kexec_file_load 294
> __SYSCALL(__NR_kexec_file_load, sys_kexec_file_load)
> /* 295 through 402 are unassigned to sync up with generic numbers, don't use */
> -#if __BITS_PER_LONG == 32
> +#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32
> #define __NR_clock_gettime64 403
> __SYSCALL(__NR_clock_gettime64, sys_clock_gettime)

This part looks wrong, you expose clock_gettime64 to user space this way, both
in asm/unistd.h and in the table.

Arnd

2021-12-21 17:09:50

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 02/13] riscv: Fixup difference with defconfig

On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
>
> From: Guo Ren <[email protected]>
>
> Let's follow the origin patch's spirit.
>
> The only difference between rv32_defconfig and defconfig is that
> rv32_defconfig has CONFIG_ARCH_RV32I=y.
>
> This is helpful to compare rv64-compat-rv32 v.s. rv32-linux.
>

If the intention is to keep them in sync, maybe use a fragment for 32-bit
mode, like powerpc or mips do.

Arnd

2021-12-21 17:13:07

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 03/13] riscv: compat: Add basic compat date type implementation

On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
>
> From: Guo Ren <[email protected]>
>
> Implement asm/compat.h for struct compat_xxx, RLIM_INFINITY,
> OFF_T_MAX, is_compat_task, compat_user_regset, regset convert.
>
> Signed-off-by: Guo Ren <[email protected]>
> ---
> arch/riscv/include/asm/compat.h | 259 +++++++++++++++++++++++++++

Since both the native and compat side use the generic interface, I think this
should all be part of asm-generic/compat.h, in case other architectures want to
share this in the future. Maybe see if any other architectures use the
same definition
for some of the structures and then remove the duplicates.

> +struct compat_stat {
> + compat_ulong_t st_dev;
> + compat_ulong_t st_ino;
> + compat_uint_t st_mode;
> + compat_uint_t st_nlink;

You should not need a compat_stat, because native rv32 does not have a
stat() syscall.

> +static inline int is_compat_task(void)
> +{
> + return test_thread_flag(TIF_32BIT);
> +}
> +
> +struct compat_user_regs_struct {
> + compat_ulong_t pc;
> + compat_ulong_t ra;

These clearly need to stay in arch/riscv

Arnd

2021-12-21 17:15:57

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 05/13] riscv: compat: syscall: Add compat_sys_call_table implementation

On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
>
> From: Guo Ren <[email protected]>
>
> Implement compat_syscall_table.c with compat_sys_call_table & fixup
> system call such as truncate64,pread64,fallocate which need two
> regs to indicate 64bit-arg (copied from arm64).
>
> Signed-off-by: Guo Ren <[email protected]>
> ---
> arch/riscv/include/asm/syscall.h | 3 +
> arch/riscv/kernel/compat_syscall_table.c | 84 ++++++++++++++++++++++++

Same here, I think most of these should go next to the actual syscalls, with the
duplicates removed from other platforms,

> +#define __SYSCALL_COMPAT
> +#undef __LP64__

What is the #undef for?

> +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> + unsigned long, prot, unsigned long, flags,
> + unsigned long, fd, unsigned long, offset)
> +{
> + if ((prot & PROT_WRITE) && (prot & PROT_EXEC))
> + if (unlikely(!(prot & PROT_READ)))
> + return -EINVAL;
> +
> + return ksys_mmap_pgoff(addr, len, prot, flags, fd, offset);
> +}

This is one that we may have to deal with separately, introducing
sys_mmap_pgoff() was a mistake in my opinion, and we should just have
added a sys_mmap2() for all architectures that don't explicitly override it.

Arnd

2021-12-21 18:21:25

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 08/13] riscv: compat: Add COMPAT Kbuild skeletal support

On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> +
> +config SYSVIPC_COMPAT
> + def_bool y
> + depends on COMPAT && SYSVIPC

Can this be moved to init/Kconfig next to SYSVIPC?

> +
> +COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
> +{
> + return 0;
> +}

This confused me a bit while reviewing, would it make sense to reorder the
patches to add the three missing functions first instead of adding the
dummy and then replacing it?


Arnd

2021-12-21 18:27:45

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
>
> From: Guo Ren <[email protected]>
>
> Currently, most 64-bit architectures (x86, parisc, powerpc, arm64,
> s390, mips, sparc) have supported COMPAT mode. But they all have
> history issues and can't use standard linux unistd.h. RISC-V would
> be first standard __SYSCALL_COMPAT user of include/uapi/asm-generic
> /unistd.h.
>
> The patchset are based on v5.16-rc6, you can compare rv64-compat32
> v.s. rv32-whole in qemu with following step:

Looks good overall, see my individual replies for minor comments I had.

I think there is a bigger question to answer though, which is whether this is
actually a useful feature for rv64. In general, there are two reasons for
wanting compat mode:

a) compatibility with existing binaries and distros

b) reducing the memory footprint of user space in a memory constrained
environment, either deeply embedded or in a container.

For the other architectures, a) is clearly the main driver, but equally so
this is not the case on riscv, which does not have any legacy 32-bit
code. Without that, adding compat mode would mainly introduce a
second ABI to a lot of environments that at the moment only need to
support one, and that adds complexity to the implementation and
the extra attack surface of the second syscall ABI when an exploit
may be possible only in compat mode.

There is still some benefit in b), but it would need to be weighed
against the downsides above. Can you explain in more detail what
use cases you have in mind, and which CPU cores actually support
this mode?

Arnd

2021-12-22 11:16:27

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 01/13] syscalls: compat: Fix the missing part for __SYSCALL_COMPAT

On Wed, Dec 22, 2021 at 1:09 AM Arnd Bergmann <[email protected]> wrote:
>
> On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
> > index 4557a8b6086f..aafe5cfeb27c 100644
> > --- a/include/uapi/asm-generic/unistd.h
> > +++ b/include/uapi/asm-generic/unistd.h
> > @@ -383,7 +383,7 @@ __SYSCALL(__NR_syslog, sys_syslog)
> >
> > /* kernel/ptrace.c */
> > #define __NR_ptrace 117
> > -__SYSCALL(__NR_ptrace, sys_ptrace)
> > +__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace)
> >
>
> Right. We could merge sys_ptrace and compat_sys_ptrace() by adding
> a in_compat_syscall() check, but either way works.
>
> > /* kernel/sched/core.c */
> > #define __NR_sched_setparam 118
> > @@ -779,7 +779,7 @@ __SYSCALL(__NR_rseq, sys_rseq)
> > #define __NR_kexec_file_load 294
> > __SYSCALL(__NR_kexec_file_load, sys_kexec_file_load)
> > /* 295 through 402 are unassigned to sync up with generic numbers, don't use */
> > -#if __BITS_PER_LONG == 32
> > +#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32
> > #define __NR_clock_gettime64 403
> > __SYSCALL(__NR_clock_gettime64, sys_clock_gettime)
>
> This part looks wrong, you expose clock_gettime64 to user space this way, both
> in asm/unistd.h and in the table.
>
> Arnd

No, we only define __SYSCALL_COMPAT in compat_syscall_table.c. It
won't be expose to user space, because there is no __SYSCALL_COMPAT.

$ grep __SYSCALL_COMPAT * -r
arch/riscv/kernel/compat_syscall_table.c:#define __SYSCALL_COMPAT
^^^^^^^^^^^^^^^^^^^^^^
include/uapi/asm-generic/unistd.h:#if __BITS_PER_LONG == 32 ||
defined(__SYSCALL_COMPAT)
include/uapi/asm-generic/unistd.h:#ifdef __SYSCALL_COMPAT
include/uapi/asm-generic/unistd.h:#if defined(__SYSCALL_COMPAT) ||
__BITS_PER_LONG == 32
include/uapi/asm-generic/unistd.h:#if __BITS_PER_LONG == 64 &&
!defined(__SYSCALL_COMPAT)
tools/include/uapi/asm-generic/unistd.h:#if __BITS_PER_LONG == 32 ||
defined(__SYSCALL_COMPAT)
tools/include/uapi/asm-generic/unistd.h:#ifdef __SYSCALL_COMPAT
tools/include/uapi/asm-generic/unistd.h:#if defined(__SYSCALL_COMPAT)
|| __BITS_PER_LONG == 32
tools/include/uapi/asm-generic/unistd.h:#if __BITS_PER_LONG == 64 &&
!defined(__SYSCALL_COMPAT)

--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 11:25:12

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 01/13] syscalls: compat: Fix the missing part for __SYSCALL_COMPAT

On Wed, Dec 22, 2021 at 12:16 PM Guo Ren <[email protected]> wrote:
> On Wed, Dec 22, 2021 at 1:09 AM Arnd Bergmann <[email protected]> wrote:
> > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > > /* 295 through 402 are unassigned to sync up with generic numbers, don't use */
> > > -#if __BITS_PER_LONG == 32
> > > +#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32
> > > #define __NR_clock_gettime64 403
> > > __SYSCALL(__NR_clock_gettime64, sys_clock_gettime)
> >
> > This part looks wrong, you expose clock_gettime64 to user space this way, both
> > in asm/unistd.h and in the table.
> >
>
> No, we only define __SYSCALL_COMPAT in compat_syscall_table.c. It
> won't be expose to user space, because there is no __SYSCALL_COMPAT.

Ok, it looks good then. It feels like we should have a macro to wrap this, but
in reality what we should actually do is to convert the entire file to the
more modern syscall.tbl format, so let's just stay with your version.

Arnd

2021-12-22 11:34:33

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 02/13] riscv: Fixup difference with defconfig

On Wed, Dec 22, 2021 at 1:09 AM Arnd Bergmann <[email protected]> wrote:
>
> On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> >
> > From: Guo Ren <[email protected]>
> >
> > Let's follow the origin patch's spirit.
> >
> > The only difference between rv32_defconfig and defconfig is that
> > rv32_defconfig has CONFIG_ARCH_RV32I=y.
> >
> > This is helpful to compare rv64-compat-rv32 v.s. rv32-linux.
> >
>
> If the intention is to keep them in sync, maybe use a fragment for 32-bit
> mode, like powerpc or mips do.
>
> Arnd

Some people are familiar with "make rv32_defconfig". There has a
32-bit.config fragment config in arch/riscv/configs/.

I've tested with:

make ARCH=riscv CROSS_COMPILE=riscv32-buildroot-linux-gnu-
EXTRA_CFLAGS+=-g O=../build-rv32/ defconfig 32-bit.config

The above is tested Okay, do you mean we should delete rv32_defconfig?
I think it's another topic, I just want them the same in "compat"
patchset.

--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 11:44:37

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 02/13] riscv: Fixup difference with defconfig

On Wed, Dec 22, 2021 at 12:34 PM Guo Ren <[email protected]> wrote:
> On Wed, Dec 22, 2021 at 1:09 AM Arnd Bergmann <[email protected]> wrote:
> > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > If the intention is to keep them in sync, maybe use a fragment for 32-bit
> > mode, like powerpc or mips do.
>
> Some people are familiar with "make rv32_defconfig". There has a
> 32-bit.config fragment config in arch/riscv/configs/.
>
> I've tested with:
>
> make ARCH=riscv CROSS_COMPILE=riscv32-buildroot-linux-gnu-
> EXTRA_CFLAGS+=-g O=../build-rv32/ defconfig 32-bit.config
>
> The above is tested Okay, do you mean we should delete rv32_defconfig?
> I think it's another topic, I just want them the same in "compat"
> patchset.

I think what you can do is to add rv32_defconfig as a target in
arch/riscv/Makefile the same way as rv32_randconfig, and then
delete the other file, that will keep the existing process working
for any existing users.

Given that there are no specific rv32 SoC implementations supported
by the kernel today (other than SOC_VIRT), the number of users
would be close to zero anyway.

Arnd

2021-12-22 12:01:03

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Wed, Dec 22, 2021 at 12:35 AM <[email protected]> wrote:
>
> From: Guo Ren <[email protected]>
>
> Currently, most 64-bit architectures (x86, parisc, powerpc, arm64,
> s390, mips, sparc) have supported COMPAT mode. But they all have
> history issues and can't use standard linux unistd.h. RISC-V would
> be first standard __SYSCALL_COMPAT user of include/uapi/asm-generic
> /unistd.h.
>
> The patchset are based on v5.16-rc6, you can compare rv64-compat32
> v.s. rv32-whole in qemu with following step:
>
> - Prepare rv32 rootfs & fw_jump.bin by buildroot.org
> $ git clone git://git.busybox.net/buildroot
> $ cd buildroot
> $ make qemu_riscv32_virt_defconfig O=qemu_riscv32_virt_defconfig
> $ make -C qemu_riscv32_virt_defconfig
> $ make qemu_riscv64_virt_defconfig O=qemu_riscv64_virt_defconfig
> $ make -C qemu_riscv64_virt_defconfig
> (Got fw_jump.bin & rootfs.ext2 in qemu_riscvXX_virt_defconfig/images)
>
> - Prepare Linux rv32 & rv64 Image
> $ git clone [email protected]:c-sky/csky-linux.git -b riscv_compat_v1 linux
> $ cd linux
> $ make ARCH=riscv CROSS_COMPILE=riscv32-buildroot-linux-gnu- O=../build-rv32/ rv32_defconfig
> $ make ARCH=riscv CROSS_COMPILE=riscv32-buildroot-linux-gnu- O=../build-rv32/ Image
> $ make ARCH=riscv CROSS_COMPILE=riscv64-buildroot-linux-gnu- O=../build-rv64/ defconfig
You need menuconfig to enable CONFIG_COMPAT, here.

I forgot add CONFIG_COMPAT in defconfig or make CONFIG_COMPAT with def_bool.

> $ make ARCH=riscv CROSS_COMPILE=riscv64-buildroot-linux-gnu- O=../build-rv64/ Image
>
> - Prepare Qemu: (made by LIU Zhiwei <[email protected]>)
> $ git clone https://github.com/romanheros/qemu.git -b riscv-upstream-uxl-v5
> $ cd qemu
> $ ./configure --target-list="riscv64-softmmu riscv32-softmmu"
> $ make
>
> - Run rv64 with rv32 rootfs in compat mode:
> $ ./build/qemu-system-riscv64 -cpu rv64,x-h=true -M virt -m 64m -nographic -bios qemu_riscv64_virt_defconfig/images/fw_jump.bin -kernel build-rv64/Image -drive file qemu_riscv32_virt_defconfig/images/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
>
> QEMU emulator version 6.2.50 (v6.2.0-29-g196d7182c8)
> OpenSBI v0.9
> [ 0.000000] Linux version 5.16.0-rc6-00013-g60f122c486d0 (guoren@guoren-Z87-HD3) (riscv64-unknown-linux-gnu-gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.37) #62 SMP Tue Dec 21 22:54:05 CST 2021
> [ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
> [ 0.000000] Machine model: riscv-virtio,qemu
> [ 0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
> [ 0.000000] printk: bootconsole [sbi0] enabled
> [ 0.000000] efi: UEFI not found.
> [ 0.000000] Zone ranges:
> [ 0.000000] DMA32 [mem 0x0000000080200000-0x0000000083ffffff]
> [ 0.000000] Normal empty
> [ 0.000000] Movable zone start for each node
> [ 0.000000] Early memory node ranges
> [ 0.000000] node 0: [mem 0x0000000080200000-0x0000000083ffffff]
> [ 0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x0000000083ffffff]
> [ 0.000000] SBI specification v0.2 detected
> [ 0.000000] SBI implementation ID=0x1 Version=0x9
> [ 0.000000] SBI TIME extension detected
> [ 0.000000] SBI IPI extension detected
> [ 0.000000] SBI RFENCE extension detected
> [ 0.000000] SBI v0.2 HSM extension detected
> [ 0.000000] riscv: compat: 32bit U-mode applications support
> [ 0.000000] riscv: ISA extensions acdfhimsu
> [ 0.000000] riscv: ELF capabilities acdfim
> [ 0.000000] percpu: Embedded 17 pages/cpu s30696 r8192 d30744 u69632
> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 15655
> [ 0.000000] Kernel command line: rootwait root=/dev/vda ro console=ttyS0 earlycon=sbi
> [ 0.000000] Dentry cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
> [ 0.000000] Inode-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
> [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> [ 0.000000] Virtual kernel memory layout:
> [ 0.000000] fixmap : 0xffffffcefee00000 - 0xffffffceff000000 (2048 kB)
> [ 0.000000] pci io : 0xffffffceff000000 - 0xffffffcf00000000 ( 16 MB)
> [ 0.000000] vmemmap : 0xffffffcf00000000 - 0xffffffcfffffffff (4095 MB)
> [ 0.000000] vmalloc : 0xffffffd000000000 - 0xffffffdfffffffff (65535 MB)
> [ 0.000000] lowmem : 0xffffffe000000000 - 0xffffffe003e00000 ( 62 MB)
> [ 0.000000] kernel : 0xffffffff80000000 - 0xffffffffffffffff (2047 MB)
> [ 0.000000] Memory: 43952K/63488K available (6180K kernel code, 4873K rwdata, 2048K rodata, 2146K init, 297K bss, 19536K reserved, 0K cma-reserved)
> [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
> [ 0.000000] rcu: Hierarchical RCU implementation.
> [ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
> [ 0.000000] rcu: RCU debug extended QS entry/exit.
> [ 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=1
> [ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
> [ 0.000000] riscv-intc: 64 local interrupts mapped
> [ 0.000000] plic: plic@c000000: mapped 53 interrupts with 1 handlers for 2 contexts.
> ...
> Welcome to Buildroot
> buildroot login: root
> # cat /proc/cpuinfo
> processor : 0
> hart : 0
> isa : rv64imafdcsuh
> mmu : sv48
>
> # file /bin/busybox
> /bin/busybox: setuid ELF 32-bit LSB shared object, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv32-ilp32d.so.1, for GNU/Linux 5.15.0, stripped
> # cat /proc/meminfo
> MemTotal: 46096 kB
> MemFree: 30116 kB
> MemAvailable: 32824 kB
> Buffers: 664 kB
> Cached: 3900 kB
> SwapCached: 0 kB
> Active: 3164 kB
> Inactive: 1920 kB
> Active(anon): 40 kB
> Inactive(anon): 524 kB
> Active(file): 3124 kB
> Inactive(file): 1396 kB
> Unevictable: 0 kB
> Mlocked: 0 kB
> SwapTotal: 0 kB
> SwapFree: 0 kB
> Dirty: 8 kB
> Writeback: 0 kB
> AnonPages: 556 kB
> Mapped: 2084 kB
> Shmem: 44 kB
> KReclaimable: 964 kB
> Slab: 5760 kB
> SReclaimable: 964 kB
> SUnreclaim: 4796 kB
> KernelStack: 624 kB
> PageTables: 132 kB
> NFS_Unstable: 0 kB
> Bounce: 0 kB
> WritebackTmp: 0 kB
> CommitLimit: 23048 kB
> Committed_AS: 2088 kB
> VmallocTotal: 67108863 kB
> VmallocUsed: 636 kB
> VmallocChunk: 0 kB
> Percpu: 80 kB
> #
>
> - Run rv32 with rv32 rootfs:
> $ ./build/qemu-system-riscv32 -cpu rv32,x-h=true -M virt -m 64m -nographic -bios qemu_riscv32_virt_defconfig/images/fw_jump.bin -kernel build-rv32/Image -drive file qemu_riscv32_virt_defconfig/images/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
>
> QEMU emulator version 6.2.50 (v6.2.0-29-g196d7182c8)
> OpenSBI v0.9
> [ 0.000000] Linux version 5.16.0-rc6-00013-g60f122c486d0 (guoren@guoren-Z87-HD3) (riscv32-buildroot-linux-gnu-gcc.br_real (Buildroot 2021.11-201-g7600ca7960-dirty) 10.3.0, GNU ld (GNU Binutils) 2.36.1) #4 SMP Tue Dec 21 22:54:43 CST 2021
> [ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80400000
> [ 0.000000] Machine model: riscv-virtio,qemu
> [ 0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
> [ 0.000000] printk: bootconsole [sbi0] enabled
> [ 0.000000] efi: UEFI not found.
> [ 0.000000] Zone ranges:
> [ 0.000000] Normal [mem 0x0000000080400000-0x0000000083ffffff]
> [ 0.000000] Movable zone start for each node
> [ 0.000000] Early memory node ranges
> [ 0.000000] node 0: [mem 0x0000000080400000-0x0000000083ffffff]
> [ 0.000000] Initmem setup node 0 [mem 0x0000000080400000-0x0000000083ffffff]
> [ 0.000000] SBI specification v0.2 detected
> [ 0.000000] SBI implementation ID=0x1 Version=0x9
> [ 0.000000] SBI TIME extension detected
> [ 0.000000] SBI IPI extension detected
> [ 0.000000] SBI RFENCE extension detected
> [ 0.000000] SBI v0.2 HSM extension detected
> [ 0.000000] riscv: ISA extensions acdfhimsu
> [ 0.000000] riscv: ELF capabilities acdfim
> [ 0.000000] percpu: Embedded 12 pages/cpu s16600 r8192 d24360 u49152
> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 15240
> [ 0.000000] Kernel command line: rootwait root=/dev/vda ro console=ttyS0 earlycon=sbi
> [ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
> [ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
> [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> [ 0.000000] Virtual kernel memory layout:
> [ 0.000000] fixmap : 0x9dc00000 - 0x9e000000 (4096 kB)
> [ 0.000000] pci io : 0x9e000000 - 0x9f000000 ( 16 MB)
> [ 0.000000] vmemmap : 0x9f000000 - 0x9fffffff ( 15 MB)
> [ 0.000000] vmalloc : 0xa0000000 - 0xbfffffff ( 511 MB)
> [ 0.000000] lowmem : 0xc0000000 - 0xc3c00000 ( 60 MB)
> [ 0.000000] Memory: 35332K/61440K available (6073K kernel code, 8814K rwdata, 4096K rodata, 4160K init, 241K bss, 26108K reserved, 0K cma-reserved)
> [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
> [ 0.000000] rcu: Hierarchical RCU implementation.
> [ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
> [ 0.000000] rcu: RCU debug extended QS entry/exit.
> [ 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=1
> [ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
> [ 0.000000] riscv-intc: 32 local interrupts mapped
> [ 0.000000] plic: plic@c000000: mapped 53 interrupts with 1 handlers for 2 contexts.
> ...
> Welcome to Buildroot
> buildroot login: root
> # cat /proc/cpuinfo
> processor : 0
> hart : 0
> isa : rv32imafdcsuh
> mmu : sv32
>
> # file /bin/busybox
> /bin/busybox: setuid ELF 32-bit LSB shared object, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv32-ilp32d.so.1, for GNU/Linux 5.15.0, stripped
> # cat /proc/meminfo
> MemTotal: 39492 kB
> MemFree: 26756 kB
> MemAvailable: 29552 kB
> Buffers: 668 kB
> Cached: 3908 kB
> SwapCached: 0 kB
> Active: 3156 kB
> Inactive: 1936 kB
> Active(anon): 40 kB
> Inactive(anon): 520 kB
> Active(file): 3116 kB
> Inactive(file): 1416 kB
> Unevictable: 0 kB
> Mlocked: 0 kB
> SwapTotal: 0 kB
> SwapFree: 0 kB
> Dirty: 0 kB
> Writeback: 0 kB
> AnonPages: 552 kB
> Mapped: 2144 kB
> Shmem: 44 kB
> KReclaimable: 624 kB
> Slab: 3660 kB
> SReclaimable: 624 kB
> SUnreclaim: 3036 kB
> KernelStack: 312 kB
> PageTables: 92 kB
> NFS_Unstable: 0 kB
> Bounce: 0 kB
> WritebackTmp: 0 kB
> CommitLimit: 19744 kB
> Committed_AS: 2088 kB
> VmallocTotal: 524287 kB
> VmallocUsed: 12 kB
> VmallocChunk: 0 kB
> Percpu: 60 kB
> #
>
> Some conclusions:
> - rv32 linux kernel code, data sizes are larger than rv64.
> (complier's issue?)
> - rv32 kernel runtime KernelStack, Slab... are smaller,
> but not so much for memory footprint saving.
> - Totally rv64 kernel is much better than rv32.
> - Qemu, kernel, rv32 = rv64 defconfig, rootfs, opensbi
> are the same in this comparison.
>
> Guo Ren (13):
> syscalls: compat: Fix the missing part for __SYSCALL_COMPAT
> riscv: Fixup difference with defconfig
> riscv: compat: Add basic compat date type implementation
> riscv: compat: Re-implement TASK_SIZE for COMPAT_32BIT
> riscv: compat: syscall: Add compat_sys_call_table implementation
> riscv: compat: syscall: Add entry.S implementation
> riscv: compat: Add elf.h implementation
> riscv: compat: Add COMPAT Kbuild skeletal support
> riscv: compat: init: Add hw-cap detect in setup_arch
> riscv: compat: vdso: Add rv32 VDSO base code implementation
> riscv: compat: vdso: Add setup additional pages implementation
> riscv: compat: signal: Add rt_frame implementation
> riscv: compat: ptrace: Add compat_arch_ptrace implement
>
> arch/riscv/Kconfig | 22 ++
> arch/riscv/Makefile | 5 +
> arch/riscv/configs/rv32_defconfig | 20 +-
> arch/riscv/include/asm/compat.h | 259 ++++++++++++++++++
> arch/riscv/include/asm/csr.h | 7 +
> arch/riscv/include/asm/elf.h | 53 +++-
> arch/riscv/include/asm/mmu.h | 1 +
> arch/riscv/include/asm/pgtable.h | 11 +-
> arch/riscv/include/asm/processor.h | 10 +
> arch/riscv/include/asm/syscall.h | 3 +
> arch/riscv/include/asm/thread_info.h | 1 +
> arch/riscv/include/asm/vdso.h | 9 +
> arch/riscv/kernel/Makefile | 3 +
> arch/riscv/kernel/compat_signal.c | 243 ++++++++++++++++
> arch/riscv/kernel/compat_syscall_table.c | 84 ++++++
> arch/riscv/kernel/compat_vdso/.gitignore | 2 +
> arch/riscv/kernel/compat_vdso/Makefile | 68 +++++
> arch/riscv/kernel/compat_vdso/compat_vdso.S | 8 +
> .../kernel/compat_vdso/compat_vdso.lds.S | 3 +
> arch/riscv/kernel/compat_vdso/flush_icache.S | 3 +
> .../compat_vdso/gen_compat_vdso_offsets.sh | 5 +
> arch/riscv/kernel/compat_vdso/getcpu.S | 3 +
> arch/riscv/kernel/compat_vdso/note.S | 3 +
> arch/riscv/kernel/compat_vdso/rt_sigreturn.S | 3 +
> arch/riscv/kernel/entry.S | 18 +-
> arch/riscv/kernel/process.c | 32 +++
> arch/riscv/kernel/ptrace.c | 87 +++++-
> arch/riscv/kernel/setup.c | 5 +
> arch/riscv/kernel/signal.c | 13 +-
> arch/riscv/kernel/vdso.c | 104 +++++--
> arch/riscv/kernel/vdso/vdso.S | 6 +-
> drivers/firmware/efi/libstub/efi-stub.c | 2 +-
> include/uapi/asm-generic/unistd.h | 4 +-
> tools/include/uapi/asm-generic/unistd.h | 4 +-
> 34 files changed, 1055 insertions(+), 49 deletions(-)
> create mode 100644 arch/riscv/include/asm/compat.h
> create mode 100644 arch/riscv/kernel/compat_signal.c
> create mode 100644 arch/riscv/kernel/compat_syscall_table.c
> create mode 100644 arch/riscv/kernel/compat_vdso/.gitignore
> create mode 100644 arch/riscv/kernel/compat_vdso/Makefile
> create mode 100644 arch/riscv/kernel/compat_vdso/compat_vdso.S
> create mode 100644 arch/riscv/kernel/compat_vdso/compat_vdso.lds.S
> create mode 100644 arch/riscv/kernel/compat_vdso/flush_icache.S
> create mode 100755 arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh
> create mode 100644 arch/riscv/kernel/compat_vdso/getcpu.S
> create mode 100644 arch/riscv/kernel/compat_vdso/note.S
> create mode 100644 arch/riscv/kernel/compat_vdso/rt_sigreturn.S
>
> --
> 2.25.1
>


--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 12:04:04

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 03/13] riscv: compat: Add basic compat date type implementation

On Wed, Dec 22, 2021 at 1:13 AM Arnd Bergmann <[email protected]> wrote:
>
> On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> >
> > From: Guo Ren <[email protected]>
> >
> > Implement asm/compat.h for struct compat_xxx, RLIM_INFINITY,
> > OFF_T_MAX, is_compat_task, compat_user_regset, regset convert.
> >
> > Signed-off-by: Guo Ren <[email protected]>
> > ---
> > arch/riscv/include/asm/compat.h | 259 +++++++++++++++++++++++++++
>
> Since both the native and compat side use the generic interface, I think this
> should all be part of asm-generic/compat.h, in case other architectures want to
> share this in the future. Maybe see if any other architectures use the
> same definition
> for some of the structures and then remove the duplicates.
Agree.

>
> > +struct compat_stat {
> > + compat_ulong_t st_dev;
> > + compat_ulong_t st_ino;
> > + compat_uint_t st_mode;
> > + compat_uint_t st_nlink;
>
> You should not need a compat_stat, because native rv32 does not have a
> stat() syscall.
We need it:

$ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-
EXTRA_CFLAGS+=-g O=../build-riscv/ Image -j > /dev/null
/home/guoren/source/kernel/riscv-linux/fs/stat.c: In function 'cp_compat_stat':
/home/guoren/source/kernel/riscv-linux/fs/stat.c:645:21: error:
storage size of 'tmp' isn't known
645 | struct compat_stat tmp;
| ^~~
/home/guoren/source/kernel/riscv-linux/fs/stat.c:645:21: warning:
unused variable 'tmp' [-Wunused-variable]
/home/guoren/source/kernel/riscv-linux/fs/stat.c:674:1: error: control
reaches end of non-void function [-Werror=return-type]
674 | }
| ^
cc1: some warnings being treated as errors
make[2]: *** [/home/guoren/source/kernel/riscv-linux/scripts/Makefile.build:287:
fs/stat.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/home/guoren/source/kernel/riscv-linux/Makefile:1846: fs] Error 2

>
> > +static inline int is_compat_task(void)
> > +{
> > + return test_thread_flag(TIF_32BIT);
> > +}
> > +
> > +struct compat_user_regs_struct {
> > + compat_ulong_t pc;
> > + compat_ulong_t ra;
>
> These clearly need to stay in arch/riscv
Okay

>
> Arnd

--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 12:07:12

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 08/13] riscv: compat: Add COMPAT Kbuild skeletal support

On Wed, Dec 22, 2021 at 2:23 AM Arnd Bergmann <[email protected]> wrote:
>
> On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > +
> > +config SYSVIPC_COMPAT
> > + def_bool y
> > + depends on COMPAT && SYSVIPC
>
> Can this be moved to init/Kconfig next to SYSVIPC?

I would try another patchset, to see other architecture guys' advice.

$ grep SYSVIPC_COMPAT arch -r
arch/x86/Kconfig:config SYSVIPC_COMPAT
arch/parisc/Kconfig:config SYSVIPC_COMPAT
arch/powerpc/Kconfig:config SYSVIPC_COMPAT
arch/arm64/Kconfig:config SYSVIPC_COMPAT
arch/riscv/Kconfig:config SYSVIPC_COMPAT
arch/s390/Kconfig:config SYSVIPC_COMPAT
arch/mips/Kconfig:config SYSVIPC_COMPAT
arch/mips/Kconfig: select SYSVIPC_COMPAT if SYSVIPC
arch/mips/Kconfig: select SYSVIPC_COMPAT if SYSVIPC
arch/sparc/Kconfig:config SYSVIPC_COMPAT

>
> > +
> > +COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
> > +{
> > + return 0;
> > +}
>
> This confused me a bit while reviewing, would it make sense to reorder the
> patches to add the three missing functions first instead of adding the
> dummy and then replacing it?
Okay, I would try in the next version. Make the compile at last.

>
>
> Arnd



--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 12:43:47

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 05/13] riscv: compat: syscall: Add compat_sys_call_table implementation

On Wed, Dec 22, 2021 at 2:15 AM Arnd Bergmann <[email protected]> wrote:
>
> On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> >
> > From: Guo Ren <[email protected]>
> >
> > Implement compat_syscall_table.c with compat_sys_call_table & fixup
> > system call such as truncate64,pread64,fallocate which need two
> > regs to indicate 64bit-arg (copied from arm64).
> >
> > Signed-off-by: Guo Ren <[email protected]>
> > ---
> > arch/riscv/include/asm/syscall.h | 3 +
> > arch/riscv/kernel/compat_syscall_table.c | 84 ++++++++++++++++++++++++
>
> Same here, I think most of these should go next to the actual syscalls, with the
> duplicates removed from other platforms,
Agree, I will try that next version.

>
> > +#define __SYSCALL_COMPAT
> > +#undef __LP64__
>
> What is the #undef for?

See arch/riscv/include/uapi/asm/unistd.h:

#ifdef __LP64__
#define __ARCH_WANT_NEW_STAT
#define __ARCH_WANT_SET_GET_RLIMIT
#endif /* __LP64__ */


>
> > +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> > + unsigned long, prot, unsigned long, flags,
> > + unsigned long, fd, unsigned long, offset)
> > +{
> > + if ((prot & PROT_WRITE) && (prot & PROT_EXEC))
> > + if (unlikely(!(prot & PROT_READ)))
> > + return -EINVAL;
> > +
> > + return ksys_mmap_pgoff(addr, len, prot, flags, fd, offset);
> > +}
>
> This is one that we may have to deal with separately, introducing
> sys_mmap_pgoff() was a mistake in my opinion, and we should just have
#if __BITS_PER_LONG == 32 || defined(__SYSCALL_COMPAT)
#define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _32)
#else
#define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _64)
#endif

#define __NR3264_mmap 222
__SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)

> added a sys_mmap2() for all architectures that don't explicitly override it.
That should be another patch, right? Let's keep it here.

>
> Arnd



--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 12:47:08

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 03/13] riscv: compat: Add basic compat date type implementation

On Wed, Dec 22, 2021 at 1:03 PM Guo Ren <[email protected]> wrote:
> On Wed, Dec 22, 2021 at 1:13 AM Arnd Bergmann <[email protected]> wrote:
> > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> >
> > > +struct compat_stat {
> > > + compat_ulong_t st_dev;
> > > + compat_ulong_t st_ino;
> > > + compat_uint_t st_mode;
> > > + compat_uint_t st_nlink;
> >
> > You should not need a compat_stat, because native rv32 does not have a
> > stat() syscall.
> We need it:
>
> $ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-
> EXTRA_CFLAGS+=-g O=../build-riscv/ Image -j > /dev/null
> /home/guoren/source/kernel/riscv-linux/fs/stat.c: In function 'cp_compat_stat':
> /home/guoren/source/kernel/riscv-linux/fs/stat.c:645:21: error:
> storage size of 'tmp' isn't known
> 645 | struct compat_stat tmp;

I think that's just a bug in fs/stat.c. Every other architecture so
far needed it,
just not riscv, so we should add an appropriate #ifdef here. I would replace
#ifdef CONFIG_COMPAT around these with __ARCH_WANT_COMPAT_STAT
and then change all other compat architectures to define that depending
on the configuration.

Arnd

2021-12-22 12:59:45

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
>
> On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> >
> > From: Guo Ren <[email protected]>
> >
> > Currently, most 64-bit architectures (x86, parisc, powerpc, arm64,
> > s390, mips, sparc) have supported COMPAT mode. But they all have
> > history issues and can't use standard linux unistd.h. RISC-V would
> > be first standard __SYSCALL_COMPAT user of include/uapi/asm-generic
> > /unistd.h.
> >
> > The patchset are based on v5.16-rc6, you can compare rv64-compat32
> > v.s. rv32-whole in qemu with following step:
>
> Looks good overall, see my individual replies for minor comments I had.
Thx for the review :)

>
> I think there is a bigger question to answer though, which is whether this is
> actually a useful feature for rv64. In general, there are two reasons for
> wanting compat mode:
>
> a) compatibility with existing binaries and distros
>
> b) reducing the memory footprint of user space in a memory constrained
> environment, either deeply embedded or in a container.
>
> For the other architectures, a) is clearly the main driver, but equally so
> this is not the case on riscv, which does not have any legacy 32-bit
> code. Without that, adding compat mode would mainly introduce a
> second ABI to a lot of environments that at the moment only need to
> support one, and that adds complexity to the implementation and
> the extra attack surface of the second syscall ABI when an exploit
> may be possible only in compat mode.
>
> There is still some benefit in b), but it would need to be weighed
> against the downsides above. Can you explain in more detail what
> use cases you have in mind, and which CPU cores actually support
> this mode?
The most reason is about b), see our customer's product:
https://www.cnx-software.com/2021/10/25/allwinner-d1s-f133-risc-v-processor-64mb-ddr2/

So I think all our next generation rv64 cores should support
compat-mode. Compare to releasing rv32-full core, rv64 compat-mode is
very cheap for our CPU design.

You would get the answer when our new generation CPU is announced and it's soon.

Currently, only qemu supports rv64 compact mode, that is my colleague
(LIU Zhi Wei) contributed.

>
> Arnd



--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 13:06:54

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 02/13] riscv: Fixup difference with defconfig

On Wed, Dec 22, 2021 at 8:51 PM Arnd Bergmann <[email protected]> wrote:
>
> On Wed, Dec 22, 2021 at 12:34 PM Guo Ren <[email protected]> wrote:
> > On Wed, Dec 22, 2021 at 1:09 AM Arnd Bergmann <[email protected]> wrote:
> > > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > > If the intention is to keep them in sync, maybe use a fragment for 32-bit
> > > mode, like powerpc or mips do.
> >
> > Some people are familiar with "make rv32_defconfig". There has a
> > 32-bit.config fragment config in arch/riscv/configs/.
> >
> > I've tested with:
> >
> > make ARCH=riscv CROSS_COMPILE=riscv32-buildroot-linux-gnu-
> > EXTRA_CFLAGS+=-g O=../build-rv32/ defconfig 32-bit.config
> >
> > The above is tested Okay, do you mean we should delete rv32_defconfig?
> > I think it's another topic, I just want them the same in "compat"
> > patchset.
>
> I think what you can do is to add rv32_defconfig as a target in
> arch/riscv/Makefile the same way as rv32_randconfig, and then
> delete the other file, that will keep the existing process working
> for any existing users.
Good idea, I would try.

>
> Given that there are no specific rv32 SoC implementations supported
> by the kernel today (other than SOC_VIRT), the number of users
> would be close to zero anyway.
I really agree with you, but we still need the rv32 user mode
ecosystem for memory footprint.

>
> Arnd



--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-22 13:21:51

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 05/13] riscv: compat: syscall: Add compat_sys_call_table implementation

On Wed, Dec 22, 2021 at 1:43 PM Guo Ren <[email protected]> wrote:
>
> On Wed, Dec 22, 2021 at 2:15 AM Arnd Bergmann <[email protected]> wrote:
> >
> > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > >
> > > From: Guo Ren <[email protected]>
> > >
> > > Implement compat_syscall_table.c with compat_sys_call_table & fixup
> > > system call such as truncate64,pread64,fallocate which need two
> > > regs to indicate 64bit-arg (copied from arm64).
> > >
> > > Signed-off-by: Guo Ren <[email protected]>
> > > ---
> > > arch/riscv/include/asm/syscall.h | 3 +
> > > arch/riscv/kernel/compat_syscall_table.c | 84 ++++++++++++++++++++++++
> >
> > Same here, I think most of these should go next to the actual syscalls, with the
> > duplicates removed from other platforms,
> Agree, I will try that next version.
>
> >
> > > +#define __SYSCALL_COMPAT
> > > +#undef __LP64__
> >
> > What is the #undef for?
>
> See arch/riscv/include/uapi/asm/unistd.h:
>
> #ifdef __LP64__
> #define __ARCH_WANT_NEW_STAT
> #define __ARCH_WANT_SET_GET_RLIMIT
> #endif /* __LP64__ */

Ok, in this case I would recommend changing that #ifdef to
check for __SYSCALL_COMPAT instead, as removing the
__LP64__ define may cause other unintended changes.


> > > +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> > > + unsigned long, prot, unsigned long, flags,
> > > + unsigned long, fd, unsigned long, offset)
> > > +{
> > > + if ((prot & PROT_WRITE) && (prot & PROT_EXEC))
> > > + if (unlikely(!(prot & PROT_READ)))
> > > + return -EINVAL;
> > > +
> > > + return ksys_mmap_pgoff(addr, len, prot, flags, fd, offset);
> > > +}
> >
> > This is one that we may have to deal with separately, introducing
> > sys_mmap_pgoff() was a mistake in my opinion, and we should just have
>
> #if __BITS_PER_LONG == 32 || defined(__SYSCALL_COMPAT)
> #define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _32)
> #else
> #define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _64)
> #endif
>
> #define __NR3264_mmap 222
> __SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)
>
> > added a sys_mmap2() for all architectures that don't explicitly override it.
> That should be another patch, right? Let's keep it here.

Right, I think the patch would be a nice cleanup, but it appears that
riscv is among the few architectures that have defined their own
nonstandard mmap2() syscall after all, despite using the standard
name for the entry point. Not sure how this slipped past my original
review, but it certainly can't be changed now.

It also means that you need to change your implementation of
compat_sys_mmap2() to match the version from
arch/riscv/kernel/sys_riscv.c, rather than the version that
everyone else has. Maybe leave it there and change the
#ifdef to build mmap2 for both native rv32 and compat
mode.

FWIW, this is what a conversion from mmap_pgoff() to mmap2()
would look like, I think this is an overall win, but it's entirely
unrelated to your series now: https://pastebin.com/QtF55dn4
(I'm sure I got some details wrong, at least it needs some
#ifdef checks).

Arnd

2021-12-22 13:29:36

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Wed, Dec 22, 2021 at 1:59 PM Guo Ren <[email protected]> wrote:
> On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
> > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
>
> > There is still some benefit in b), but it would need to be weighed
> > against the downsides above. Can you explain in more detail what
> > use cases you have in mind, and which CPU cores actually support
> > this mode?
> The most reason is about b), see our customer's product:
> https://www.cnx-software.com/2021/10/25/allwinner-d1s-f133-risc-v-processor-64mb-ddr2/
>
> So I think all our next generation rv64 cores should support
> compat-mode. Compare to releasing rv32-full core, rv64 compat-mode is
> very cheap for our CPU design.
>
> You would get the answer when our new generation CPU is announced and it's soon.
>
> Currently, only qemu supports rv64 compact mode, that is my colleague
> (LIU Zhi Wei) contributed.

Right, that does make a lot of sense. I'm not sure we'll see a lot more of 64MB
DDR2 SiP implementations when a 128MB or even 256MB DDR3 configuration
has almost the same cost, but for any of those sizes I can see why you'd want to
run 32-bit user space, as well as 64-bit kernels.

Arnd

2021-12-22 13:56:37

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 02/13] riscv: Fixup difference with defconfig

On Wed, Dec 22, 2021 at 2:06 PM Guo Ren <[email protected]> wrote:
> On Wed, Dec 22, 2021 at 8:51 PM Arnd Bergmann <[email protected]> wrote:
> > On Wed, Dec 22, 2021 at 12:34 PM Guo Ren <[email protected]> wrote:
> > Given that there are no specific rv32 SoC implementations supported
> > by the kernel today (other than SOC_VIRT), the number of users
> > would be close to zero anyway.
> I really agree with you, but we still need the rv32 user mode
> ecosystem for memory footprint.

Sure, I just meant there are few users that would have to relearn typing
"make defconfig 32-bit.config" instead of "make rv32_defconfig" even
without the added Makefile target.

Arnd

2021-12-22 14:00:36

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 05/13] riscv: compat: syscall: Add compat_sys_call_table implementation

On Wed, Dec 22, 2021 at 2:21 PM Arnd Bergmann <[email protected]> wrote:
> On Wed, Dec 22, 2021 at 1:43 PM Guo Ren <[email protected]> wrote:
>
> Right, I think the patch would be a nice cleanup, but it appears that
> riscv is among the few architectures that have defined their own
> nonstandard mmap2() syscall after all, despite using the standard
> name for the entry point. Not sure how this slipped past my original
> review, but it certainly can't be changed now.

No, I misread, the calling conventions are fine after all, it's
just written in a rather odd way.

> Maybe leave it there and change the #ifdef to build mmap2 for both
> native rv32 and compat mode.

This bit still applies though, I don't think you need to add another
helper, just use the one that is already there.

Arnd

2021-12-23 02:12:52

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 02/13] riscv: Fixup difference with defconfig

On Wed, Dec 22, 2021 at 9:52 PM Arnd Bergmann <[email protected]> wrote:
>
> On Wed, Dec 22, 2021 at 2:06 PM Guo Ren <[email protected]> wrote:
> > On Wed, Dec 22, 2021 at 8:51 PM Arnd Bergmann <[email protected]> wrote:
> > > On Wed, Dec 22, 2021 at 12:34 PM Guo Ren <[email protected]> wrote:
> > > Given that there are no specific rv32 SoC implementations supported
> > > by the kernel today (other than SOC_VIRT), the number of users
> > > would be close to zero anyway.
> > I really agree with you, but we still need the rv32 user mode
> > ecosystem for memory footprint.
>
> Sure, I just meant there are few users that would have to relearn typing
> "make defconfig 32-bit.config" instead of "make rv32_defconfig" even
> without the added Makefile target.
Emm... I got you.

Next version, I would send delete rv32_defconfig patch. If Palmer
object, I would change to make rv32_defconfig target. ;)

>
> Arnd


--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-24 06:52:40

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 01/13] syscalls: compat: Fix the missing part for __SYSCALL_COMPAT

On Tue, Dec 21, 2021 at 06:08:45PM +0100, Arnd Bergmann wrote:
> > -__SYSCALL(__NR_ptrace, sys_ptrace)
> > +__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace)
> >
>
> Right. We could merge sys_ptrace and compat_sys_ptrace() by adding
> a in_compat_syscall() check, but either way works.

I think merging them would be very useful, including merging
compat_arch_ptrace into arch_ptrace. But we can leave that for
later.

2021-12-24 06:53:31

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 03/13] riscv: compat: Add basic compat date type implementation

On Wed, Dec 22, 2021 at 12:35:22AM +0800, [email protected] wrote:
> From: Guo Ren <[email protected]>
>
> Implement asm/compat.h for struct compat_xxx, RLIM_INFINITY,
> OFF_T_MAX, is_compat_task, compat_user_regset, regset convert.

Much of this really has no busines being duplicated over all the
architectures. I have an old series to consolidate a fair amount
of compat.h cruft, I'll see if I can resurrect that.

2021-12-24 06:54:44

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 08/13] riscv: compat: Add COMPAT Kbuild skeletal support

On Wed, Dec 22, 2021 at 08:06:55PM +0800, Guo Ren wrote:
> On Wed, Dec 22, 2021 at 2:23 AM Arnd Bergmann <[email protected]> wrote:
> >
> > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > > +
> > > +config SYSVIPC_COMPAT
> > > + def_bool y
> > > + depends on COMPAT && SYSVIPC
> >
> > Can this be moved to init/Kconfig next to SYSVIPC?
>
> I would try another patchset, to see other architecture guys' advice.

The existing per-arch definitions are pretty much historic cruft.

2021-12-24 09:28:40

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 03/13] riscv: compat: Add basic compat date type implementation

On Fri, Dec 24, 2021 at 2:53 PM Christoph Hellwig <[email protected]> wrote:
>
> On Wed, Dec 22, 2021 at 12:35:22AM +0800, [email protected] wrote:
> > From: Guo Ren <[email protected]>
> >
> > Implement asm/compat.h for struct compat_xxx, RLIM_INFINITY,
> > OFF_T_MAX, is_compat_task, compat_user_regset, regset convert.
>
> Much of this really has no busines being duplicated over all the
> architectures. I have an old series to consolidate a fair amount
> of compat.h cruft, I'll see if I can resurrect that.
Sounds good. I hope you could do that after my patchset merges. Thx.

--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-24 09:42:46

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 05/13] riscv: compat: syscall: Add compat_sys_call_table implementation

On Wed, Dec 22, 2021 at 10:00 PM Arnd Bergmann <[email protected]> wrote:
>
> On Wed, Dec 22, 2021 at 2:21 PM Arnd Bergmann <[email protected]> wrote:
> > On Wed, Dec 22, 2021 at 1:43 PM Guo Ren <[email protected]> wrote:
> >
> > Right, I think the patch would be a nice cleanup, but it appears that
> > riscv is among the few architectures that have defined their own
> > nonstandard mmap2() syscall after all, despite using the standard
> > name for the entry point. Not sure how this slipped past my original
> > review, but it certainly can't be changed now.
>
> No, I misread, the calling conventions are fine after all, it's
> just written in a rather odd way.
>
> > Maybe leave it there and change the #ifdef to build mmap2 for both
> > native rv32 and compat mode.
>
> This bit still applies though, I don't think you need to add another
> helper, just use the one that is already there.
Yes, I will:

diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c
index 12f8a7fce78b..9c0194f176fc 100644
--- a/arch/riscv/kernel/sys_riscv.c
+++ b/arch/riscv/kernel/sys_riscv.c
@@ -33,7 +33,9 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
{
return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 0);
}
-#else
+#endif
+
+#if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
unsigned long, fd, off_t, offset)
@@ -44,7 +46,7 @@ SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned
long, len,
*/
return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 12);
}
-#endif /* !CONFIG_64BIT */
+#endif

>
> Arnd



--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-26 08:36:53

by Jisheng Zhang

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Wed, 22 Dec 2021 20:59:30 +0800
Guo Ren <[email protected]> wrote:

> On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
> >
> > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > >
> > > From: Guo Ren <[email protected]>
> > >
> > > Currently, most 64-bit architectures (x86, parisc, powerpc, arm64,
> > > s390, mips, sparc) have supported COMPAT mode. But they all have
> > > history issues and can't use standard linux unistd.h. RISC-V would
> > > be first standard __SYSCALL_COMPAT user of include/uapi/asm-generic
> > > /unistd.h.
> > >
> > > The patchset are based on v5.16-rc6, you can compare rv64-compat32
> > > v.s. rv32-whole in qemu with following step:
> >
> > Looks good overall, see my individual replies for minor comments I had.
> Thx for the review :)
>
> >
> > I think there is a bigger question to answer though, which is whether this is
> > actually a useful feature for rv64. In general, there are two reasons for
> > wanting compat mode:
> >
> > a) compatibility with existing binaries and distros
> >
> > b) reducing the memory footprint of user space in a memory constrained
> > environment, either deeply embedded or in a container.
> >
> > For the other architectures, a) is clearly the main driver, but equally so
> > this is not the case on riscv, which does not have any legacy 32-bit
> > code. Without that, adding compat mode would mainly introduce a
> > second ABI to a lot of environments that at the moment only need to
> > support one, and that adds complexity to the implementation and
> > the extra attack surface of the second syscall ABI when an exploit
> > may be possible only in compat mode.
> >
> > There is still some benefit in b), but it would need to be weighed
> > against the downsides above. Can you explain in more detail what
> > use cases you have in mind, and which CPU cores actually support
> > this mode?
> The most reason is about b), see our customer's product:
> https://www.cnx-software.com/2021/10/25/allwinner-d1s-f133-risc-v-processor-64mb-ddr2/
>
> So I think all our next generation rv64 cores should support
> compat-mode. Compare to releasing rv32-full core, rv64 compat-mode is
> very cheap for our CPU design.
>
> You would get the answer when our new generation CPU is announced and it's soon.
>

What about adding RV64 ILP32 support instead? This don't need HW side
modifications so can benefit all RV64.

Thanks

> Currently, only qemu supports rv64 compact mode, that is my colleague
> (LIU Zhi Wei) contributed.


2021-12-26 12:38:38

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Sun, Dec 26, 2021 at 4:36 PM Jisheng Zhang <[email protected]> wrote:
>
> On Wed, 22 Dec 2021 20:59:30 +0800
> Guo Ren <[email protected]> wrote:
>
> > On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
> > >
> > > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > > >
> > > > From: Guo Ren <[email protected]>
> > > >
> > > > Currently, most 64-bit architectures (x86, parisc, powerpc, arm64,
> > > > s390, mips, sparc) have supported COMPAT mode. But they all have
> > > > history issues and can't use standard linux unistd.h. RISC-V would
> > > > be first standard __SYSCALL_COMPAT user of include/uapi/asm-generic
> > > > /unistd.h.
> > > >
> > > > The patchset are based on v5.16-rc6, you can compare rv64-compat32
> > > > v.s. rv32-whole in qemu with following step:
> > >
> > > Looks good overall, see my individual replies for minor comments I had.
> > Thx for the review :)
> >
> > >
> > > I think there is a bigger question to answer though, which is whether this is
> > > actually a useful feature for rv64. In general, there are two reasons for
> > > wanting compat mode:
> > >
> > > a) compatibility with existing binaries and distros
> > >
> > > b) reducing the memory footprint of user space in a memory constrained
> > > environment, either deeply embedded or in a container.
> > >
> > > For the other architectures, a) is clearly the main driver, but equally so
> > > this is not the case on riscv, which does not have any legacy 32-bit
> > > code. Without that, adding compat mode would mainly introduce a
> > > second ABI to a lot of environments that at the moment only need to
> > > support one, and that adds complexity to the implementation and
> > > the extra attack surface of the second syscall ABI when an exploit
> > > may be possible only in compat mode.
> > >
> > > There is still some benefit in b), but it would need to be weighed
> > > against the downsides above. Can you explain in more detail what
> > > use cases you have in mind, and which CPU cores actually support
> > > this mode?
> > The most reason is about b), see our customer's product:
> > https://www.cnx-software.com/2021/10/25/allwinner-d1s-f133-risc-v-processor-64mb-ddr2/
> >
> > So I think all our next generation rv64 cores should support
> > compat-mode. Compare to releasing rv32-full core, rv64 compat-mode is
> > very cheap for our CPU design.
> >
> > You would get the answer when our new generation CPU is announced and it's soon.
> >
>
> What about adding RV64 ILP32 support instead? This don't need HW side
> modifications so can benefit all RV64.
ILP32 is another topic in C Language Data Type Models and it couldn't
replace the standard rv32 ecosystem.
COMPAT is a common framework in Linux (7 arches have been supported),
so let rv64 support COMPAT mode is considerable.

Customers would choose ILP32 / RV32-compat by themself and that
depends on which one has a better ecosystem.

>
> Thanks
>
> > Currently, only qemu supports rv64 compact mode, that is my colleague
> > (LIU Zhi Wei) contributed.
>


--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-26 15:33:51

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 03/13] riscv: compat: Add basic compat date type implementation

On Wed, Dec 22, 2021 at 8:47 PM Arnd Bergmann <[email protected]> wrote:
>
> On Wed, Dec 22, 2021 at 1:03 PM Guo Ren <[email protected]> wrote:
> > On Wed, Dec 22, 2021 at 1:13 AM Arnd Bergmann <[email protected]> wrote:
> > > On Tue, Dec 21, 2021 at 5:35 PM <[email protected]> wrote:
> > >
> > > > +struct compat_stat {
> > > > + compat_ulong_t st_dev;
> > > > + compat_ulong_t st_ino;
> > > > + compat_uint_t st_mode;
> > > > + compat_uint_t st_nlink;
> > >
> > > You should not need a compat_stat, because native rv32 does not have a
> > > stat() syscall.
> > We need it:
> >
> > $ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-
> > EXTRA_CFLAGS+=-g O=../build-riscv/ Image -j > /dev/null
> > /home/guoren/source/kernel/riscv-linux/fs/stat.c: In function 'cp_compat_stat':
> > /home/guoren/source/kernel/riscv-linux/fs/stat.c:645:21: error:
> > storage size of 'tmp' isn't known
> > 645 | struct compat_stat tmp;
>
> I think that's just a bug in fs/stat.c. Every other architecture so
> far needed it,
> just not riscv, so we should add an appropriate #ifdef here. I would replace
> #ifdef CONFIG_COMPAT around these with __ARCH_WANT_COMPAT_STAT
> and then change all other compat architectures to define that depending
> on the configuration.
Agree, but I would keep compat_stat in the next version. You could add
__ARCH_WANT_COMPAT_STAT next.

>
> Arnd



--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-26 20:31:40

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Sun, Dec 26, 2021 at 7:38 AM Guo Ren <[email protected]> wrote:
> On Sun, Dec 26, 2021 at 4:36 PM Jisheng Zhang <[email protected]> wrote:
> > On Wed, 22 Dec 2021 20:59:30 +0800 Guo Ren <[email protected]> wrote:
> > > On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
> >
> > What about adding RV64 ILP32 support instead? This don't need HW side
> > modifications so can benefit all RV64.
>
> ILP32 is another topic in C Language Data Type Models and it couldn't
> replace the standard rv32 ecosystem.
> COMPAT is a common framework in Linux (7 arches have been supported),
> so let rv64 support COMPAT mode is considerable.
>
> Customers would choose ILP32 / RV32-compat by themself and that
> depends on which one has a better ecosystem.

From a kernel perspective, supporting both is not much more work than
supporting either of them. We had the same debate for Arm64, and ended
up never merging the ILP32 patches despite them being well written
and maintainable, to limit the number of supported user space ABIs
as well as the possible attack vectors when there is an exploitable
bug that is specific to an ABI.

arm64 does support big-endian mode, which is a similar niche, but it
can't easily be removed after it's already supported. Supporting normal
compat mode is the easiest here because it doesn't add another user
space ABI, but I'd strongly recommend not to add any other ones.

Arnd

2021-12-27 01:16:18

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Mon, Dec 27, 2021 at 4:31 AM Arnd Bergmann <[email protected]> wrote:
>
> On Sun, Dec 26, 2021 at 7:38 AM Guo Ren <[email protected]> wrote:
> > On Sun, Dec 26, 2021 at 4:36 PM Jisheng Zhang <[email protected]> wrote:
> > > On Wed, 22 Dec 2021 20:59:30 +0800 Guo Ren <[email protected]> wrote:
> > > > On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
> > >
> > > What about adding RV64 ILP32 support instead? This don't need HW side
> > > modifications so can benefit all RV64.
> >
> > ILP32 is another topic in C Language Data Type Models and it couldn't
> > replace the standard rv32 ecosystem.
> > COMPAT is a common framework in Linux (7 arches have been supported),
> > so let rv64 support COMPAT mode is considerable.
> >
> > Customers would choose ILP32 / RV32-compat by themself and that
> > depends on which one has a better ecosystem.
>
> From a kernel perspective, supporting both is not much more work than
> supporting either of them. We had the same debate for Arm64, and ended
> up never merging the ILP32 patches despite them being well written
> and maintainable, to limit the number of supported user space ABIs
> as well as the possible attack vectors when there is an exploitable
> bug that is specific to an ABI.
>
> arm64 does support big-endian mode, which is a similar niche, but it
> can't easily be removed after it's already supported. Supporting normal
> compat mode is the easiest here because it doesn't add another user
> space ABI, but I'd strongly recommend not to add any other ones.

@Palmer Dabbelt How do you think about supporting ILP32 & COMPAT both
in rv64? And let users vote by foot which is better.

>
> Arnd



--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

2021-12-27 02:29:07

by Jessica Clarke

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On 27 Dec 2021, at 01:16, Guo Ren <[email protected]> wrote:
>
> On Mon, Dec 27, 2021 at 4:31 AM Arnd Bergmann <[email protected]> wrote:
>>
>> On Sun, Dec 26, 2021 at 7:38 AM Guo Ren <[email protected]> wrote:
>>> On Sun, Dec 26, 2021 at 4:36 PM Jisheng Zhang <[email protected]> wrote:
>>>> On Wed, 22 Dec 2021 20:59:30 +0800 Guo Ren <[email protected]> wrote:
>>>>> On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
>>>>
>>>> What about adding RV64 ILP32 support instead? This don't need HW side
>>>> modifications so can benefit all RV64.
>>>
>>> ILP32 is another topic in C Language Data Type Models and it couldn't
>>> replace the standard rv32 ecosystem.
>>> COMPAT is a common framework in Linux (7 arches have been supported),
>>> so let rv64 support COMPAT mode is considerable.
>>>
>>> Customers would choose ILP32 / RV32-compat by themself and that
>>> depends on which one has a better ecosystem.
>>
>> From a kernel perspective, supporting both is not much more work than
>> supporting either of them. We had the same debate for Arm64, and ended
>> up never merging the ILP32 patches despite them being well written
>> and maintainable, to limit the number of supported user space ABIs
>> as well as the possible attack vectors when there is an exploitable
>> bug that is specific to an ABI.
>>
>> arm64 does support big-endian mode, which is a similar niche, but it
>> can't easily be removed after it's already supported. Supporting normal
>> compat mode is the easiest here because it doesn't add another user
>> space ABI, but I'd strongly recommend not to add any other ones.
>
> @Palmer Dabbelt How do you think about supporting ILP32 & COMPAT both
> in rv64? And let users vote by foot which is better.

As psABI TG co-chair I really do not want an ILP32 RV64 to exist if it
can at all be avoided. Every single attempt at an ILP32 ABI for a
64-bit architecture has failed to take off in the past, so I struggle
to see why RV64 will be any different. So, in my opinion, there is a
relatively high barrier to entry for it to be an official frozen ABI,
and without it being that I doubt upstreams will want to go near it, be
it Linux, GCC, binutils or GCC, but they can speak for themselves if
they feel otherwise.

Also, with every year that goes by, ILP32 becomes more and more limited
in what you can use it for, due to increased memory footprints...

Jess


2021-12-28 10:46:14

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH 00/13] riscv: compat: Add COMPAT mode support for rv64

On Mon, Dec 27, 2021 at 10:29 AM Jessica Clarke <[email protected]> wrote:
>
> On 27 Dec 2021, at 01:16, Guo Ren <[email protected]> wrote:
> >
> > On Mon, Dec 27, 2021 at 4:31 AM Arnd Bergmann <[email protected]> wrote:
> >>
> >> On Sun, Dec 26, 2021 at 7:38 AM Guo Ren <[email protected]> wrote:
> >>> On Sun, Dec 26, 2021 at 4:36 PM Jisheng Zhang <[email protected]> wrote:
> >>>> On Wed, 22 Dec 2021 20:59:30 +0800 Guo Ren <[email protected]> wrote:
> >>>>> On Wed, Dec 22, 2021 at 2:10 AM Arnd Bergmann <[email protected]> wrote:
> >>>>
> >>>> What about adding RV64 ILP32 support instead? This don't need HW side
> >>>> modifications so can benefit all RV64.
> >>>
> >>> ILP32 is another topic in C Language Data Type Models and it couldn't
> >>> replace the standard rv32 ecosystem.
> >>> COMPAT is a common framework in Linux (7 arches have been supported),
> >>> so let rv64 support COMPAT mode is considerable.
> >>>
> >>> Customers would choose ILP32 / RV32-compat by themself and that
> >>> depends on which one has a better ecosystem.
> >>
> >> From a kernel perspective, supporting both is not much more work than
> >> supporting either of them. We had the same debate for Arm64, and ended
> >> up never merging the ILP32 patches despite them being well written
> >> and maintainable, to limit the number of supported user space ABIs
> >> as well as the possible attack vectors when there is an exploitable
> >> bug that is specific to an ABI.
> >>
> >> arm64 does support big-endian mode, which is a similar niche, but it
> >> can't easily be removed after it's already supported. Supporting normal
> >> compat mode is the easiest here because it doesn't add another user
> >> space ABI, but I'd strongly recommend not to add any other ones.
> >
> > @Palmer Dabbelt How do you think about supporting ILP32 & COMPAT both
> > in rv64? And let users vote by foot which is better.
>
> As psABI TG co-chair I really do not want an ILP32 RV64 to exist if it
> can at all be avoided. Every single attempt at an ILP32 ABI for a
> 64-bit architecture has failed to take off in the past, so I struggle
> to see why RV64 will be any different. So, in my opinion, there is a
> relatively high barrier to entry for it to be an official frozen ABI,
> and without it being that I doubt upstreams will want to go near it, be
> it Linux, GCC, binutils or GCC, but they can speak for themselves if
> they feel otherwise.
>
> Also, with every year that goes by, ILP32 becomes more and more limited
> in what you can use it for, due to increased memory footprints...
Agree, I think we are on the right road :)

>
> Jess

>


--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/