2022-02-02 16:38:57

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 00/21] 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.17-rc2, 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_v5 linux
$ cd linux
$ echo "CONFIG_STRICT_KERNEL_RWX=n" >> arch/riscv/configs/defconfig
$ echo "CONFIG_STRICT_MODULE_RWX=n" >> arch/riscv/configs/defconfig
$ 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 [email protected]:alistair23/qemu.git -b riscv-to-apply.for-upstream linux
$ cd qemu
$ ./configure --target-list="riscv64-softmmu riscv32-softmmu"
$ make

Now let's compare rv32-compat with rv32-native memory footprint. Kernel with rv32 = rv64
defconfig, rootfs, opensbi, Qemu are the same.

- 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-00017-g750f87086bdd-dirty (guoren@guoren-Z87-HD3) (riscv64-unknown-linux-gnu-gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.37) #96 SMP Tue Dec 28 21:01:55 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: 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: 52788K/63488K available (6184K kernel code, 888K rwdata, 1917K rodata, 294K init, 297K bss, 10700K 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
# ca[ 78.386630] random: fast init done
# cat /proc/meminfo
MemTotal: 53076 kB
MemFree: 40264 kB
MemAvailable: 40244 kB
Buffers: 236 kB
Cached: 1560 kB
SwapCached: 0 kB
Active: 1700 kB
Inactive: 516 kB
Active(anon): 40 kB
Inactive(anon): 424 kB
Active(file): 1660 kB
Inactive(file): 92 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 444 kB
Mapped: 1188 kB
Shmem: 44 kB
KReclaimable: 952 kB
Slab: 5744 kB
SReclaimable: 952 kB
SUnreclaim: 4792 kB
KernelStack: 624 kB
PageTables: 156 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 26536 kB
Committed_AS: 1748 kB
VmallocTotal: 67108863 kB
VmallocUsed: 652 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-00017-g750f87086bdd-dirty (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) #7 SMP Tue Dec 28 21:02:21 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: 51924K/61440K available (6117K kernel code, 695K rwdata, 1594K rodata, 255K init, 241K bss, 9516K 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
[ 79.320589] random: fast init done
# cat /proc/meminfo
MemTotal: 52176 kB
MemFree: 41012 kB
MemAvailable: 42176 kB
Buffers: 644 kB
Cached: 2724 kB
SwapCached: 0 kB
Active: 3128 kB
Inactive: 752 kB
Active(anon): 40 kB
Inactive(anon): 516 kB
Active(file): 3088 kB
Inactive(file): 236 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 4 kB
Writeback: 0 kB
AnonPages: 556 kB
Mapped: 2172 kB
Shmem: 44 kB
KReclaimable: 656 kB
Slab: 3684 kB
SReclaimable: 656 kB
SUnreclaim: 3028 kB
KernelStack: 312 kB
PageTables: 88 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 26088 kB
Committed_AS: 2088 kB
VmallocTotal: 524287 kB
VmallocUsed: 12 kB
VmallocChunk: 0 kB
Percpu: 60 kB
#

Some conclusions:
- kernel statics:
64: Memory: 52788K/63488K available (6184K kernel code, 888K rwdata, 1917K rodata, 294K init, 297K bss, 10700K reserved)
32: Memory: 51924K/61440K available (6117K kernel code, 695K rwdata, 1594K rodata, 255K init, 241K bss, 9516K reserved)
rv32 better than rv64: 1% 22% 17% 13% 19% 11%
The code size is very similar, but data size rv32 would be better.

- rv32 kernel runtime KernelStack, Slab... are smaller,
rv64: MemTotal: 53076 kB, MemFree: 40264 kB
rv32: MemTotal: 52176 + 2048 kB, MemFree: 41012 + 2048 kB
rv32 better than rv64: 2% 6%

(Because opensbi problem, we could add another 2MB for rv32.)
Overall in 64MB memory situation, rv64-compat is 6% worse than rv32-full
at memory footprint. If the user space memory usage increases, I think
the gap will be further reduced.

Changes in v5:
- Rebase on linux-5.17-rc2
- Include consolidate the fcntl patches by Christoph Hellwig
- Remove F_GETLK64/F_SETLK64/F_SETLKW64 from asm/compat.h
- Change COMPAT_RLIM_INFINITY from 0x7fffffff to 0xffffffff
- Bring back "Add hw-cap detect in setup_arch patch" in v1

Changes in v4:
- Rebase on linux-5.17-rc1
- Optimize compat_sys_call_table implementation with Arnd's advice
- Add reviewed-by for Arnd. Thx :)
- Remove FIXME comment in elf.h
- Optimize Cleanup duplicate definitions in compat.h with Arnd's advice

Changes in v3:
- Rebase on newest master (pre linux-5.17-rc1)
- Using newest qemu version v7 for test
- Remove fcntl common modification
- Fixup SET_PERSONALITY in elf.h by Arnd
- Fixup KVM Kconfig
- Update Acked-by & Reviewed-by

Changes in v2:
- Add __ARCH_WANT_COMPAT_STAT suggested
- Cleanup fcntl compatduplicate definitions
- Cleanup compat.h
- Move rv32_defconfig into Makefile
- Fixup rv64 rootfs boot failed, remove hw_compat_mode_detect
- Move SYSVIPC_COMPAT into init/Kconfig
- Simplify compat_elf_check


Christoph Hellwig (3):
uapi: simplify __ARCH_FLOCK{,64}_PAD a little
uapi: always define F_GETLK64/F_SETLK64/F_SETLKW64 in fcntl.h
compat: consolidate the compat_flock{,64} definition

Guo Ren (18):
kconfig: Add SYSVIPC_COMPAT for all architectures
fs: stat: compat: Add __ARCH_WANT_COMPAT_STAT
asm-generic: compat: Cleanup duplicate definitions
syscalls: compat: Fix the missing part for __SYSCALL_COMPAT
riscv: Fixup difference with defconfig
riscv: compat: Add basic compat data 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: process: Add UXL_32 support in start_thread
riscv: compat: Add elf.h implementation
riscv: compat: Add hw capability check for elf
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
riscv: compat: Add COMPAT Kbuild skeletal support
KVM: compat: riscv: Prevent KVM_COMPAT from being selected

arch/arm64/Kconfig | 4 -
arch/arm64/include/asm/compat.h | 91 +------
arch/arm64/include/asm/unistd.h | 1 +
arch/mips/Kconfig | 5 -
arch/mips/include/asm/compat.h | 41 +--
arch/mips/include/asm/unistd.h | 2 +
arch/mips/include/uapi/asm/fcntl.h | 30 +--
arch/parisc/Kconfig | 4 -
arch/parisc/include/asm/compat.h | 45 +---
arch/parisc/include/asm/unistd.h | 1 +
arch/powerpc/Kconfig | 5 -
arch/powerpc/include/asm/compat.h | 50 +---
arch/powerpc/include/asm/unistd.h | 1 +
arch/riscv/Kconfig | 19 ++
arch/riscv/Makefile | 9 +
arch/riscv/configs/rv32_defconfig | 135 ----------
arch/riscv/include/asm/compat.h | 129 ++++++++++
arch/riscv/include/asm/csr.h | 7 +
arch/riscv/include/asm/elf.h | 52 +++-
arch/riscv/include/asm/mmu.h | 1 +
arch/riscv/include/asm/pgtable.h | 13 +-
arch/riscv/include/asm/syscall.h | 1 +
arch/riscv/include/asm/thread_info.h | 1 +
arch/riscv/include/asm/unistd.h | 11 +
arch/riscv/include/asm/vdso.h | 9 +
arch/riscv/include/uapi/asm/unistd.h | 2 +-
arch/riscv/kernel/Makefile | 3 +
arch/riscv/kernel/compat_signal.c | 243 ++++++++++++++++++
arch/riscv/kernel/compat_syscall_table.c | 19 ++
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 | 36 +++
arch/riscv/kernel/ptrace.c | 87 ++++++-
arch/riscv/kernel/signal.c | 13 +-
arch/riscv/kernel/sys_riscv.c | 6 +-
arch/riscv/kernel/vdso.c | 104 +++++---
arch/riscv/kernel/vdso/vdso.S | 6 +-
arch/s390/Kconfig | 3 -
arch/s390/include/asm/compat.h | 99 +------
arch/s390/include/asm/unistd.h | 1 +
arch/sparc/Kconfig | 5 -
arch/sparc/include/asm/compat.h | 61 ++---
arch/sparc/include/asm/unistd.h | 1 +
arch/x86/Kconfig | 4 -
arch/x86/include/asm/compat.h | 104 ++------
arch/x86/include/asm/unistd.h | 1 +
fs/open.c | 24 ++
fs/read_write.c | 16 ++
fs/stat.c | 2 +-
fs/sync.c | 9 +
include/asm-generic/compat.h | 113 ++++++++
include/linux/compat.h | 68 +++++
include/uapi/asm-generic/fcntl.h | 23 +-
include/uapi/asm-generic/unistd.h | 4 +-
init/Kconfig | 4 +
mm/fadvise.c | 11 +
mm/readahead.c | 7 +
tools/include/uapi/asm-generic/fcntl.h | 21 +-
tools/include/uapi/asm-generic/unistd.h | 4 +-
virt/kvm/Kconfig | 2 +-
68 files changed, 1198 insertions(+), 691 deletions(-)
delete mode 100644 arch/riscv/configs/rv32_defconfig
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


2022-02-02 17:59:56

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 18/21] 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]>
Signed-off-by: Guo Ren <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Palmer Dabbelt <[email protected]>
---
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/compat_signal.c | 243 ++++++++++++++++++++++++++++++
arch/riscv/kernel/signal.c | 13 +-
3 files changed, 256 insertions(+), 1 deletion(-)
create mode 100644 arch/riscv/kernel/compat_signal.c

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 88e79f481c21..a46f9807c59e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -67,4 +67,5 @@ 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_signal.c b/arch/riscv/kernel/compat_signal.c
new file mode 100644
index 000000000000..7041742ded08
--- /dev/null
+++ b/arch/riscv/kernel/compat_signal.c
@@ -0,0 +1,243 @@
+// 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>
+
+#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

2022-02-02 20:31:27

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 02/21] uapi: always define F_GETLK64/F_SETLK64/F_SETLKW64 in fcntl.h

From: Christoph Hellwig <[email protected]>

The F_GETLK64/F_SETLK64/F_SETLKW64 fcntl opcodes are only implemented
for the 32-bit syscall APIs, but are also needed for compat handling
on 64-bit kernels.

Consolidate them in unistd.h instead of definining the internal compat
definitions in compat.h, which is rather error prone (e.g. parisc
gets the values wrong currently).

Note that before this change they were never visible to userspace due
to the fact that CONFIG_64BIT is only set for kernel builds.

Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Guo Ren <[email protected]>
Reviewed-by: Arnd Bergmann <[email protected]>
---
arch/arm64/include/asm/compat.h | 4 ----
arch/mips/include/asm/compat.h | 4 ----
arch/mips/include/uapi/asm/fcntl.h | 4 ++--
arch/powerpc/include/asm/compat.h | 4 ----
arch/s390/include/asm/compat.h | 4 ----
arch/sparc/include/asm/compat.h | 4 ----
arch/x86/include/asm/compat.h | 4 ----
include/uapi/asm-generic/fcntl.h | 4 ++--
tools/include/uapi/asm-generic/fcntl.h | 2 --
9 files changed, 4 insertions(+), 30 deletions(-)

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index eaa6ca062d89..276328765408 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -73,10 +73,6 @@ struct compat_flock {
compat_pid_t l_pid;
};

-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
struct compat_flock64 {
short l_type;
short l_whence;
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index bbb3bc5a42fd..6a350c1f70d7 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -65,10 +65,6 @@ struct compat_flock {
s32 pad[4];
};

-#define F_GETLK64 33
-#define F_SETLK64 34
-#define F_SETLKW64 35
-
struct compat_flock64 {
short l_type;
short l_whence;
diff --git a/arch/mips/include/uapi/asm/fcntl.h b/arch/mips/include/uapi/asm/fcntl.h
index 9e44ac810db9..0369a38e3d4f 100644
--- a/arch/mips/include/uapi/asm/fcntl.h
+++ b/arch/mips/include/uapi/asm/fcntl.h
@@ -44,11 +44,11 @@
#define F_SETOWN 24 /* for sockets. */
#define F_GETOWN 23 /* for sockets. */

-#ifndef __mips64
+#if __BITS_PER_LONG == 32 || defined(__KERNEL__)
#define F_GETLK64 33 /* using 'struct flock64' */
#define F_SETLK64 34
#define F_SETLKW64 35
-#endif
+#endif /* __BITS_PER_LONG == 32 || defined(__KERNEL__) */

#if _MIPS_SIM != _MIPS_SIM_ABI64
#define __ARCH_FLOCK_EXTRA_SYSID long l_sysid;
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 7afc96fb6524..83d8f70779cb 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -52,10 +52,6 @@ struct compat_flock {
compat_pid_t l_pid;
};

-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
struct compat_flock64 {
short l_type;
short l_whence;
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index cdc7ae72529d..0f14b3188b1b 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -110,10 +110,6 @@ struct compat_flock {
compat_pid_t l_pid;
};

-#define F_GETLK64 12
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
struct compat_flock64 {
short l_type;
short l_whence;
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index bd949fcf9d63..108078751bb5 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -84,10 +84,6 @@ struct compat_flock {
short __unused;
};

-#define F_GETLK64 12
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
struct compat_flock64 {
short l_type;
short l_whence;
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 7516e4199b3c..8d19a212f4f2 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -58,10 +58,6 @@ struct compat_flock {
compat_pid_t l_pid;
};

-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
/*
* IA32 uses 4 byte alignment for 64 bit quantities,
* so we need to pack this structure.
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index 77aa9f2ff98d..f13d37b60775 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -116,13 +116,13 @@
#define F_GETSIG 11 /* for sockets. */
#endif

-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG == 32 || defined(__KERNEL__)
#ifndef F_GETLK64
#define F_GETLK64 12 /* using 'struct flock64' */
#define F_SETLK64 13
#define F_SETLKW64 14
#endif
-#endif
+#endif /* __BITS_PER_LONG == 32 || defined(__KERNEL__) */

#ifndef F_SETOWN_EX
#define F_SETOWN_EX 15
diff --git a/tools/include/uapi/asm-generic/fcntl.h b/tools/include/uapi/asm-generic/fcntl.h
index 99bc9b15ce2b..0197042b7dfb 100644
--- a/tools/include/uapi/asm-generic/fcntl.h
+++ b/tools/include/uapi/asm-generic/fcntl.h
@@ -115,13 +115,11 @@
#define F_GETSIG 11 /* for sockets. */
#endif

-#ifndef CONFIG_64BIT
#ifndef F_GETLK64
#define F_GETLK64 12 /* using 'struct flock64' */
#define F_SETLK64 13
#define F_SETLKW64 14
#endif
-#endif

#ifndef F_SETOWN_EX
#define F_SETOWN_EX 15
--
2.25.1

2022-02-02 22:36:38

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 21/21] KVM: compat: riscv: Prevent KVM_COMPAT from being selected

From: Guo Ren <[email protected]>

Current riscv doesn't support the 32bit KVM API. Let's make it
clear by not selecting KVM_COMPAT.

Signed-off-by: Guo Ren <[email protected]>
Signed-off-by: Guo Ren <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Anup Patel <[email protected]>
---
virt/kvm/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index f4834c20e4a6..a8c5c9f06b3c 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -53,7 +53,7 @@ config KVM_GENERIC_DIRTYLOG_READ_PROTECT

config KVM_COMPAT
def_bool y
- depends on KVM && COMPAT && !(S390 || ARM64)
+ depends on KVM && COMPAT && !(S390 || ARM64 || RISCV)

config HAVE_KVM_IRQ_BYPASS
bool
--
2.25.1

2022-02-03 01:25:52

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 19/21] 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]>
Signed-off-by: Guo Ren <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Palmer Dabbelt <[email protected]>
---
arch/riscv/kernel/ptrace.c | 87 +++++++++++++++++++++++++++++++++++---
1 file changed, 82 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index a89243730153..bb387593a121 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>
@@ -111,11 +112,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;
@@ -273,3 +269,84 @@ __visible void do_syscall_trace_exit(struct pt_regs *regs)
trace_sys_exit(regs, regs_return_value(regs));
#endif
}
+
+#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)
+{
+ 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

2022-02-03 03:32:01

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 16/21] 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]>
Signed-off-by: Guo Ren <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Palmer Dabbelt <[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 a02e588c4947..f73d50552e09 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 954dc7043ad2..88e79f481c21 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_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

2022-02-03 09:26:23

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 15/21] riscv: compat: Add hw capability check for elf

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]>
Signed-off-by: Guo Ren <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Christoph Hellwig <[email protected]>
---
arch/riscv/include/asm/elf.h | 3 ++-
arch/riscv/kernel/process.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
index aee40040917b..3a4293dc7229 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -40,7 +40,8 @@
* elf64_hdr e_machine's offset are different. The checker is
* a little bit simple compare to other architectures.
*/
-#define compat_elf_check_arch(x) ((x)->e_machine == EM_RISCV)
+extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
+#define compat_elf_check_arch compat_elf_check_arch

#define CORE_DUMP_USE_REGSET
#define ELF_EXEC_PAGESIZE (PAGE_SIZE)
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 1a666ad299b4..758847cba391 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,6 +83,38 @@ void show_regs(struct pt_regs *regs)
dump_backtrace(regs, NULL, KERN_DEFAULT);
}

+#ifdef CONFIG_COMPAT
+static bool compat_mode_support __read_mostly;
+
+bool compat_elf_check_arch(Elf32_Ehdr *hdr)
+{
+ if (compat_mode_support && (hdr->e_machine == EM_RISCV))
+ return true;
+ else
+ return false;
+}
+
+static int compat_mode_detect(void)
+{
+ unsigned long tmp = csr_read(CSR_STATUS);
+
+ csr_write(CSR_STATUS, (tmp & ~SR_UXL) | SR_UXL_32);
+
+ if ((csr_read(CSR_STATUS) & SR_UXL) != SR_UXL_32) {
+ pr_info("riscv: 32bit compat mode detect failed\n");
+ compat_mode_support = false;
+ } else {
+ compat_mode_support = true;
+ pr_info("riscv: 32bit compat mode detected\n");
+ }
+
+ csr_write(CSR_STATUS, tmp);
+
+ return 0;
+}
+arch_initcall(compat_mode_detect);
+#endif
+
void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
--
2.25.1

2022-02-03 23:44:07

by Guo Ren

[permalink] [raw]
Subject: [PATCH V5 10/21] 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]>
Signed-off-by: Guo Ren <[email protected]>
Reviewed-by: Arnd Bergmann <[email protected]>
---
arch/riscv/include/asm/pgtable.h | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 7e949f25c933..f0d125ea3ceb 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -704,8 +704,17 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
* 63–48 all equal to bit 47, or else a page-fault exception will occur."
*/
#ifdef CONFIG_64BIT
-#define TASK_SIZE (PGDIR_SIZE * PTRS_PER_PGD / 2)
-#define TASK_SIZE_MIN (PGDIR_SIZE_L3 * PTRS_PER_PGD / 2)
+#define TASK_SIZE_64 (PGDIR_SIZE * PTRS_PER_PGD / 2)
+#define TASK_SIZE_MIN (PGDIR_SIZE_L3 * 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
#define TASK_SIZE_MIN TASK_SIZE
--
2.25.1

2022-02-08 18:49:19

by Guo Ren

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

On Tue, Feb 1, 2022 at 11:06 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.17-rc2, 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_v5 linux
> $ cd linux
> $ echo "CONFIG_STRICT_KERNEL_RWX=n" >> arch/riscv/configs/defconfig
> $ echo "CONFIG_STRICT_MODULE_RWX=n" >> arch/riscv/configs/defconfig
> $ 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 [email protected]:alistair23/qemu.git -b riscv-to-apply.for-upstream linux
> $ cd qemu
> $ ./configure --target-list="riscv64-softmmu riscv32-softmmu"
> $ make
>
> Now let's compare rv32-compat with rv32-native memory footprint. Kernel with rv32 = rv64
> defconfig, rootfs, opensbi, Qemu are the same.
>
> - 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

Fixup qemu cmdline (Remove x-h=true):
$ ./build/qemu-system-riscv64 -cpu rv64 -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-00017-g750f87086bdd-dirty (guoren@guoren-Z87-HD3) (riscv64-unknown-linux-gnu-gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.37) #96 SMP Tue Dec 28 21:01:55 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: 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: 52788K/63488K available (6184K kernel code, 888K rwdata, 1917K rodata, 294K init, 297K bss, 10700K 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
> # ca[ 78.386630] random: fast init done
> # cat /proc/meminfo
> MemTotal: 53076 kB
> MemFree: 40264 kB
> MemAvailable: 40244 kB
> Buffers: 236 kB
> Cached: 1560 kB
> SwapCached: 0 kB
> Active: 1700 kB
> Inactive: 516 kB
> Active(anon): 40 kB
> Inactive(anon): 424 kB
> Active(file): 1660 kB
> Inactive(file): 92 kB
> Unevictable: 0 kB
> Mlocked: 0 kB
> SwapTotal: 0 kB
> SwapFree: 0 kB
> Dirty: 0 kB
> Writeback: 0 kB
> AnonPages: 444 kB
> Mapped: 1188 kB
> Shmem: 44 kB
> KReclaimable: 952 kB
> Slab: 5744 kB
> SReclaimable: 952 kB
> SUnreclaim: 4792 kB
> KernelStack: 624 kB
> PageTables: 156 kB
> NFS_Unstable: 0 kB
> Bounce: 0 kB
> WritebackTmp: 0 kB
> CommitLimit: 26536 kB
> Committed_AS: 1748 kB
> VmallocTotal: 67108863 kB
> VmallocUsed: 652 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

Fixup qemu cmdline (Remove x-h=true):
$ ./build/qemu-system-riscv32 -cpu rv32 -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-00017-g750f87086bdd-dirty (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) #7 SMP Tue Dec 28 21:02:21 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: 51924K/61440K available (6117K kernel code, 695K rwdata, 1594K rodata, 255K init, 241K bss, 9516K 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
> [ 79.320589] random: fast init done
> # cat /proc/meminfo
> MemTotal: 52176 kB
> MemFree: 41012 kB
> MemAvailable: 42176 kB
> Buffers: 644 kB
> Cached: 2724 kB
> SwapCached: 0 kB
> Active: 3128 kB
> Inactive: 752 kB
> Active(anon): 40 kB
> Inactive(anon): 516 kB
> Active(file): 3088 kB
> Inactive(file): 236 kB
> Unevictable: 0 kB
> Mlocked: 0 kB
> SwapTotal: 0 kB
> SwapFree: 0 kB
> Dirty: 4 kB
> Writeback: 0 kB
> AnonPages: 556 kB
> Mapped: 2172 kB
> Shmem: 44 kB
> KReclaimable: 656 kB
> Slab: 3684 kB
> SReclaimable: 656 kB
> SUnreclaim: 3028 kB
> KernelStack: 312 kB
> PageTables: 88 kB
> NFS_Unstable: 0 kB
> Bounce: 0 kB
> WritebackTmp: 0 kB
> CommitLimit: 26088 kB
> Committed_AS: 2088 kB
> VmallocTotal: 524287 kB
> VmallocUsed: 12 kB
> VmallocChunk: 0 kB
> Percpu: 60 kB
> #
>
> Some conclusions:
> - kernel statics:
> 64: Memory: 52788K/63488K available (6184K kernel code, 888K rwdata, 1917K rodata, 294K init, 297K bss, 10700K reserved)
> 32: Memory: 51924K/61440K available (6117K kernel code, 695K rwdata, 1594K rodata, 255K init, 241K bss, 9516K reserved)
> rv32 better than rv64: 1% 22% 17% 13% 19% 11%
> The code size is very similar, but data size rv32 would be better.
>
> - rv32 kernel runtime KernelStack, Slab... are smaller,
> rv64: MemTotal: 53076 kB, MemFree: 40264 kB
> rv32: MemTotal: 52176 + 2048 kB, MemFree: 41012 + 2048 kB
> rv32 better than rv64: 2% 6%
>
> (Because opensbi problem, we could add another 2MB for rv32.)
> Overall in 64MB memory situation, rv64-compat is 6% worse than rv32-full
> at memory footprint. If the user space memory usage increases, I think
> the gap will be further reduced.
>
> Changes in v5:
> - Rebase on linux-5.17-rc2
> - Include consolidate the fcntl patches by Christoph Hellwig
> - Remove F_GETLK64/F_SETLK64/F_SETLKW64 from asm/compat.h
> - Change COMPAT_RLIM_INFINITY from 0x7fffffff to 0xffffffff
> - Bring back "Add hw-cap detect in setup_arch patch" in v1
>
> Changes in v4:
> - Rebase on linux-5.17-rc1
> - Optimize compat_sys_call_table implementation with Arnd's advice
> - Add reviewed-by for Arnd. Thx :)
> - Remove FIXME comment in elf.h
> - Optimize Cleanup duplicate definitions in compat.h with Arnd's advice
>
> Changes in v3:
> - Rebase on newest master (pre linux-5.17-rc1)
> - Using newest qemu version v7 for test
> - Remove fcntl common modification
> - Fixup SET_PERSONALITY in elf.h by Arnd
> - Fixup KVM Kconfig
> - Update Acked-by & Reviewed-by
>
> Changes in v2:
> - Add __ARCH_WANT_COMPAT_STAT suggested
> - Cleanup fcntl compatduplicate definitions
> - Cleanup compat.h
> - Move rv32_defconfig into Makefile
> - Fixup rv64 rootfs boot failed, remove hw_compat_mode_detect
> - Move SYSVIPC_COMPAT into init/Kconfig
> - Simplify compat_elf_check
>
>
> Christoph Hellwig (3):
> uapi: simplify __ARCH_FLOCK{,64}_PAD a little
> uapi: always define F_GETLK64/F_SETLK64/F_SETLKW64 in fcntl.h
> compat: consolidate the compat_flock{,64} definition
>
> Guo Ren (18):
> kconfig: Add SYSVIPC_COMPAT for all architectures
> fs: stat: compat: Add __ARCH_WANT_COMPAT_STAT
> asm-generic: compat: Cleanup duplicate definitions
> syscalls: compat: Fix the missing part for __SYSCALL_COMPAT
> riscv: Fixup difference with defconfig
> riscv: compat: Add basic compat data 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: process: Add UXL_32 support in start_thread
> riscv: compat: Add elf.h implementation
> riscv: compat: Add hw capability check for elf
> 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
> riscv: compat: Add COMPAT Kbuild skeletal support
> KVM: compat: riscv: Prevent KVM_COMPAT from being selected
>
> arch/arm64/Kconfig | 4 -
> arch/arm64/include/asm/compat.h | 91 +------
> arch/arm64/include/asm/unistd.h | 1 +
> arch/mips/Kconfig | 5 -
> arch/mips/include/asm/compat.h | 41 +--
> arch/mips/include/asm/unistd.h | 2 +
> arch/mips/include/uapi/asm/fcntl.h | 30 +--
> arch/parisc/Kconfig | 4 -
> arch/parisc/include/asm/compat.h | 45 +---
> arch/parisc/include/asm/unistd.h | 1 +
> arch/powerpc/Kconfig | 5 -
> arch/powerpc/include/asm/compat.h | 50 +---
> arch/powerpc/include/asm/unistd.h | 1 +
> arch/riscv/Kconfig | 19 ++
> arch/riscv/Makefile | 9 +
> arch/riscv/configs/rv32_defconfig | 135 ----------
> arch/riscv/include/asm/compat.h | 129 ++++++++++
> arch/riscv/include/asm/csr.h | 7 +
> arch/riscv/include/asm/elf.h | 52 +++-
> arch/riscv/include/asm/mmu.h | 1 +
> arch/riscv/include/asm/pgtable.h | 13 +-
> arch/riscv/include/asm/syscall.h | 1 +
> arch/riscv/include/asm/thread_info.h | 1 +
> arch/riscv/include/asm/unistd.h | 11 +
> arch/riscv/include/asm/vdso.h | 9 +
> arch/riscv/include/uapi/asm/unistd.h | 2 +-
> arch/riscv/kernel/Makefile | 3 +
> arch/riscv/kernel/compat_signal.c | 243 ++++++++++++++++++
> arch/riscv/kernel/compat_syscall_table.c | 19 ++
> 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 | 36 +++
> arch/riscv/kernel/ptrace.c | 87 ++++++-
> arch/riscv/kernel/signal.c | 13 +-
> arch/riscv/kernel/sys_riscv.c | 6 +-
> arch/riscv/kernel/vdso.c | 104 +++++---
> arch/riscv/kernel/vdso/vdso.S | 6 +-
> arch/s390/Kconfig | 3 -
> arch/s390/include/asm/compat.h | 99 +------
> arch/s390/include/asm/unistd.h | 1 +
> arch/sparc/Kconfig | 5 -
> arch/sparc/include/asm/compat.h | 61 ++---
> arch/sparc/include/asm/unistd.h | 1 +
> arch/x86/Kconfig | 4 -
> arch/x86/include/asm/compat.h | 104 ++------
> arch/x86/include/asm/unistd.h | 1 +
> fs/open.c | 24 ++
> fs/read_write.c | 16 ++
> fs/stat.c | 2 +-
> fs/sync.c | 9 +
> include/asm-generic/compat.h | 113 ++++++++
> include/linux/compat.h | 68 +++++
> include/uapi/asm-generic/fcntl.h | 23 +-
> include/uapi/asm-generic/unistd.h | 4 +-
> init/Kconfig | 4 +
> mm/fadvise.c | 11 +
> mm/readahead.c | 7 +
> tools/include/uapi/asm-generic/fcntl.h | 21 +-
> tools/include/uapi/asm-generic/unistd.h | 4 +-
> virt/kvm/Kconfig | 2 +-
> 68 files changed, 1198 insertions(+), 691 deletions(-)
> delete mode 100644 arch/riscv/configs/rv32_defconfig
> 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/

2022-02-23 02:32:38

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH V5 19/21] riscv: compat: ptrace: Add compat_arch_ptrace implement

On Tue, 01 Feb 2022 07:05:43 PST (-0800), [email protected] wrote:
> 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]>
> Signed-off-by: Guo Ren <[email protected]>
> Cc: Arnd Bergmann <[email protected]>
> Cc: Palmer Dabbelt <[email protected]>
> ---
> arch/riscv/kernel/ptrace.c | 87 +++++++++++++++++++++++++++++++++++---
> 1 file changed, 82 insertions(+), 5 deletions(-)
>
> diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
> index a89243730153..bb387593a121 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>
> @@ -111,11 +112,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;
> @@ -273,3 +269,84 @@ __visible void do_syscall_trace_exit(struct pt_regs *regs)
> trace_sys_exit(regs, regs_return_value(regs));
> #endif
> }
> +
> +#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)
> +{
> + 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;
> +}

Reviewed-by: Palmer Dabbelt <[email protected]>

2022-02-23 02:44:37

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH V5 18/21] riscv: compat: signal: Add rt_frame implementation

On Tue, 01 Feb 2022 07:05:42 PST (-0800), [email protected] wrote:
> 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.

It's kind of ugly to have two copies of essentially exactly the same
code, just targeted at different structures. The other ports have
sufficiently different 32-bit and 64-bit ABIs that it makes sense there,
but we should be able to share pretty much everything. That said, all
that would probably only ever benefit RISC-V so I'm not sure it'd be
worth doing.

Reviewed-by: Palmer Dabbelt <[email protected]>

Happy to see someone clean this up later, but it seems good enough for
now.

Thanks!

> Signed-off-by: Guo Ren <[email protected]>
> Signed-off-by: Guo Ren <[email protected]>
> Cc: Arnd Bergmann <[email protected]>
> Cc: Palmer Dabbelt <[email protected]>
> ---
> arch/riscv/kernel/Makefile | 1 +
> arch/riscv/kernel/compat_signal.c | 243 ++++++++++++++++++++++++++++++
> arch/riscv/kernel/signal.c | 13 +-
> 3 files changed, 256 insertions(+), 1 deletion(-)
> create mode 100644 arch/riscv/kernel/compat_signal.c
>
> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> index 88e79f481c21..a46f9807c59e 100644
> --- a/arch/riscv/kernel/Makefile
> +++ b/arch/riscv/kernel/Makefile
> @@ -67,4 +67,5 @@ 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_signal.c b/arch/riscv/kernel/compat_signal.c
> new file mode 100644
> index 000000000000..7041742ded08
> --- /dev/null
> +++ b/arch/riscv/kernel/compat_signal.c
> @@ -0,0 +1,243 @@
> +// 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>
> +
> +#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);
> }

2022-02-23 04:35:30

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH V5 16/21] riscv: compat: vdso: Add rv32 VDSO base code implementation

On Tue, 01 Feb 2022 07:05:40 PST (-0800), [email protected] wrote:
> 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.

IMO this is the wrong way to go, as there's some subtle differences
between elf32 and elf64 (the .gnu.hash layout, for example). I'm kind
of surprised userspace tolerates this sort of thing at all, but given
how easy it is to target rv32 from all toolchains (we don't need
libraries here, so just -march should do it) I don't think it's worth
chasing around the likely long-tail issues that will arise.

> 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]>
> Signed-off-by: Guo Ren <[email protected]>
> Cc: Arnd Bergmann <[email protected]>
> Cc: Palmer Dabbelt <[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 a02e588c4947..f73d50552e09 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 954dc7043ad2..88e79f481c21 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_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:

2022-02-23 11:40:48

by Guo Ren

[permalink] [raw]
Subject: Re: [PATCH V5 16/21] riscv: compat: vdso: Add rv32 VDSO base code implementation

On Wed, Feb 23, 2022 at 9:42 AM Palmer Dabbelt <[email protected]> wrote:
>
> On Tue, 01 Feb 2022 07:05:40 PST (-0800), [email protected] wrote:
> > 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.
>
> IMO this is the wrong way to go, as there's some subtle differences
> between elf32 and elf64 (the .gnu.hash layout, for example). I'm kind
> of surprised userspace tolerates this sort of thing at all, but given
> how easy it is to target rv32 from all toolchains (we don't need
> libraries here, so just -march should do it) I don't think it's worth
> chasing around the likely long-tail issues that will arise.
I would keep the patch in next version. When "multi-arch toolchain" or
"rv32 HAVE_GENERIC_VDSO" isready in the future, let's switch to the
rv32 compiler.

>
> > 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]>
> > Signed-off-by: Guo Ren <[email protected]>
> > Cc: Arnd Bergmann <[email protected]>
> > Cc: Palmer Dabbelt <[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 a02e588c4947..f73d50552e09 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 954dc7043ad2..88e79f481c21 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_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:



--
Best Regards
Guo Ren

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

2022-02-23 13:47:34

by Palmer Dabbelt

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

On Tue, 01 Feb 2022 07:05:24 PST (-0800), [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.

TBH, I'd always sort of hoped we wouldn't have to do this: it's a lot of
ABI surface to keep around for a use case I'm not really sure is ever
going to get any traction (it's not like we have legacy 32-bit
userspaces floating around, the 32-bit userspace is newer than the
64-bit userspace). My assumption is that users who actually wanted the
memory savings (likely a very small number) would be better served with
rv64/ilp32, as that'll allow the larger registers that the hardware
supports. From some earlier discussions it looks like rv64/ilp32 isn't
going to be allowed, though, so this seems like the only way to go.

I've left some minor comments, and I saw some unresolved ones as well.
I'm going to assume there'll be a v6, but LMK if you want me to deal
with cleaning things up.

I'm OK targeting this for 5.18, assuming the cleanups can be resolved in
the next week or two: generally with a lot of ABI surface I'd prefer to
let things sit on for-next for a whole cycle, but I don't think it's a
stretch to say that the actual ABI here is the rv32 port and that
rv64/COMPAT=y is just our best attempt at matching it.

It's probably worth running at least the glibc test suite, just to see
if there's anything obvious that's failing.

> The patchset are based on v5.17-rc2, 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_v5 linux
> $ cd linux
> $ echo "CONFIG_STRICT_KERNEL_RWX=n" >> arch/riscv/configs/defconfig
> $ echo "CONFIG_STRICT_MODULE_RWX=n" >> arch/riscv/configs/defconfig
> $ 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 [email protected]:alistair23/qemu.git -b riscv-to-apply.for-upstream linux
> $ cd qemu
> $ ./configure --target-list="riscv64-softmmu riscv32-softmmu"
> $ make
>
> Now let's compare rv32-compat with rv32-native memory footprint. Kernel with rv32 = rv64
> defconfig, rootfs, opensbi, Qemu are the same.
>
> - 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-00017-g750f87086bdd-dirty (guoren@guoren-Z87-HD3) (riscv64-unknown-linux-gnu-gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.37) #96 SMP Tue Dec 28 21:01:55 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: 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: 52788K/63488K available (6184K kernel code, 888K rwdata, 1917K rodata, 294K init, 297K bss, 10700K 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
> # ca[ 78.386630] random: fast init done
> # cat /proc/meminfo
> MemTotal: 53076 kB
> MemFree: 40264 kB
> MemAvailable: 40244 kB
> Buffers: 236 kB
> Cached: 1560 kB
> SwapCached: 0 kB
> Active: 1700 kB
> Inactive: 516 kB
> Active(anon): 40 kB
> Inactive(anon): 424 kB
> Active(file): 1660 kB
> Inactive(file): 92 kB
> Unevictable: 0 kB
> Mlocked: 0 kB
> SwapTotal: 0 kB
> SwapFree: 0 kB
> Dirty: 0 kB
> Writeback: 0 kB
> AnonPages: 444 kB
> Mapped: 1188 kB
> Shmem: 44 kB
> KReclaimable: 952 kB
> Slab: 5744 kB
> SReclaimable: 952 kB
> SUnreclaim: 4792 kB
> KernelStack: 624 kB
> PageTables: 156 kB
> NFS_Unstable: 0 kB
> Bounce: 0 kB
> WritebackTmp: 0 kB
> CommitLimit: 26536 kB
> Committed_AS: 1748 kB
> VmallocTotal: 67108863 kB
> VmallocUsed: 652 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-00017-g750f87086bdd-dirty (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) #7 SMP Tue Dec 28 21:02:21 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: 51924K/61440K available (6117K kernel code, 695K rwdata, 1594K rodata, 255K init, 241K bss, 9516K 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
> [ 79.320589] random: fast init done
> # cat /proc/meminfo
> MemTotal: 52176 kB
> MemFree: 41012 kB
> MemAvailable: 42176 kB
> Buffers: 644 kB
> Cached: 2724 kB
> SwapCached: 0 kB
> Active: 3128 kB
> Inactive: 752 kB
> Active(anon): 40 kB
> Inactive(anon): 516 kB
> Active(file): 3088 kB
> Inactive(file): 236 kB
> Unevictable: 0 kB
> Mlocked: 0 kB
> SwapTotal: 0 kB
> SwapFree: 0 kB
> Dirty: 4 kB
> Writeback: 0 kB
> AnonPages: 556 kB
> Mapped: 2172 kB
> Shmem: 44 kB
> KReclaimable: 656 kB
> Slab: 3684 kB
> SReclaimable: 656 kB
> SUnreclaim: 3028 kB
> KernelStack: 312 kB
> PageTables: 88 kB
> NFS_Unstable: 0 kB
> Bounce: 0 kB
> WritebackTmp: 0 kB
> CommitLimit: 26088 kB
> Committed_AS: 2088 kB
> VmallocTotal: 524287 kB
> VmallocUsed: 12 kB
> VmallocChunk: 0 kB
> Percpu: 60 kB
> #
>
> Some conclusions:
> - kernel statics:
> 64: Memory: 52788K/63488K available (6184K kernel code, 888K rwdata, 1917K rodata, 294K init, 297K bss, 10700K reserved)
> 32: Memory: 51924K/61440K available (6117K kernel code, 695K rwdata, 1594K rodata, 255K init, 241K bss, 9516K reserved)
> rv32 better than rv64: 1% 22% 17% 13% 19% 11%
> The code size is very similar, but data size rv32 would be better.
>
> - rv32 kernel runtime KernelStack, Slab... are smaller,
> rv64: MemTotal: 53076 kB, MemFree: 40264 kB
> rv32: MemTotal: 52176 + 2048 kB, MemFree: 41012 + 2048 kB
> rv32 better than rv64: 2% 6%
>
> (Because opensbi problem, we could add another 2MB for rv32.)
> Overall in 64MB memory situation, rv64-compat is 6% worse than rv32-full
> at memory footprint. If the user space memory usage increases, I think
> the gap will be further reduced.
>
> Changes in v5:
> - Rebase on linux-5.17-rc2
> - Include consolidate the fcntl patches by Christoph Hellwig
> - Remove F_GETLK64/F_SETLK64/F_SETLKW64 from asm/compat.h
> - Change COMPAT_RLIM_INFINITY from 0x7fffffff to 0xffffffff
> - Bring back "Add hw-cap detect in setup_arch patch" in v1
>
> Changes in v4:
> - Rebase on linux-5.17-rc1
> - Optimize compat_sys_call_table implementation with Arnd's advice
> - Add reviewed-by for Arnd. Thx :)
> - Remove FIXME comment in elf.h
> - Optimize Cleanup duplicate definitions in compat.h with Arnd's advice
>
> Changes in v3:
> - Rebase on newest master (pre linux-5.17-rc1)
> - Using newest qemu version v7 for test
> - Remove fcntl common modification
> - Fixup SET_PERSONALITY in elf.h by Arnd
> - Fixup KVM Kconfig
> - Update Acked-by & Reviewed-by
>
> Changes in v2:
> - Add __ARCH_WANT_COMPAT_STAT suggested
> - Cleanup fcntl compatduplicate definitions
> - Cleanup compat.h
> - Move rv32_defconfig into Makefile
> - Fixup rv64 rootfs boot failed, remove hw_compat_mode_detect
> - Move SYSVIPC_COMPAT into init/Kconfig
> - Simplify compat_elf_check
>
>
> Christoph Hellwig (3):
> uapi: simplify __ARCH_FLOCK{,64}_PAD a little
> uapi: always define F_GETLK64/F_SETLK64/F_SETLKW64 in fcntl.h
> compat: consolidate the compat_flock{,64} definition
>
> Guo Ren (18):
> kconfig: Add SYSVIPC_COMPAT for all architectures
> fs: stat: compat: Add __ARCH_WANT_COMPAT_STAT
> asm-generic: compat: Cleanup duplicate definitions
> syscalls: compat: Fix the missing part for __SYSCALL_COMPAT
> riscv: Fixup difference with defconfig
> riscv: compat: Add basic compat data 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: process: Add UXL_32 support in start_thread
> riscv: compat: Add elf.h implementation
> riscv: compat: Add hw capability check for elf
> 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
> riscv: compat: Add COMPAT Kbuild skeletal support
> KVM: compat: riscv: Prevent KVM_COMPAT from being selected
>
> arch/arm64/Kconfig | 4 -
> arch/arm64/include/asm/compat.h | 91 +------
> arch/arm64/include/asm/unistd.h | 1 +
> arch/mips/Kconfig | 5 -
> arch/mips/include/asm/compat.h | 41 +--
> arch/mips/include/asm/unistd.h | 2 +
> arch/mips/include/uapi/asm/fcntl.h | 30 +--
> arch/parisc/Kconfig | 4 -
> arch/parisc/include/asm/compat.h | 45 +---
> arch/parisc/include/asm/unistd.h | 1 +
> arch/powerpc/Kconfig | 5 -
> arch/powerpc/include/asm/compat.h | 50 +---
> arch/powerpc/include/asm/unistd.h | 1 +
> arch/riscv/Kconfig | 19 ++
> arch/riscv/Makefile | 9 +
> arch/riscv/configs/rv32_defconfig | 135 ----------
> arch/riscv/include/asm/compat.h | 129 ++++++++++
> arch/riscv/include/asm/csr.h | 7 +
> arch/riscv/include/asm/elf.h | 52 +++-
> arch/riscv/include/asm/mmu.h | 1 +
> arch/riscv/include/asm/pgtable.h | 13 +-
> arch/riscv/include/asm/syscall.h | 1 +
> arch/riscv/include/asm/thread_info.h | 1 +
> arch/riscv/include/asm/unistd.h | 11 +
> arch/riscv/include/asm/vdso.h | 9 +
> arch/riscv/include/uapi/asm/unistd.h | 2 +-
> arch/riscv/kernel/Makefile | 3 +
> arch/riscv/kernel/compat_signal.c | 243 ++++++++++++++++++
> arch/riscv/kernel/compat_syscall_table.c | 19 ++
> 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 | 36 +++
> arch/riscv/kernel/ptrace.c | 87 ++++++-
> arch/riscv/kernel/signal.c | 13 +-
> arch/riscv/kernel/sys_riscv.c | 6 +-
> arch/riscv/kernel/vdso.c | 104 +++++---
> arch/riscv/kernel/vdso/vdso.S | 6 +-
> arch/s390/Kconfig | 3 -
> arch/s390/include/asm/compat.h | 99 +------
> arch/s390/include/asm/unistd.h | 1 +
> arch/sparc/Kconfig | 5 -
> arch/sparc/include/asm/compat.h | 61 ++---
> arch/sparc/include/asm/unistd.h | 1 +
> arch/x86/Kconfig | 4 -
> arch/x86/include/asm/compat.h | 104 ++------
> arch/x86/include/asm/unistd.h | 1 +
> fs/open.c | 24 ++
> fs/read_write.c | 16 ++
> fs/stat.c | 2 +-
> fs/sync.c | 9 +
> include/asm-generic/compat.h | 113 ++++++++
> include/linux/compat.h | 68 +++++
> include/uapi/asm-generic/fcntl.h | 23 +-
> include/uapi/asm-generic/unistd.h | 4 +-
> init/Kconfig | 4 +
> mm/fadvise.c | 11 +
> mm/readahead.c | 7 +
> tools/include/uapi/asm-generic/fcntl.h | 21 +-
> tools/include/uapi/asm-generic/unistd.h | 4 +-
> virt/kvm/Kconfig | 2 +-
> 68 files changed, 1198 insertions(+), 691 deletions(-)
> delete mode 100644 arch/riscv/configs/rv32_defconfig
> 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

2022-02-23 16:24:04

by Arnd Bergmann

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

On Wed, Feb 23, 2022 at 2:43 AM Palmer Dabbelt <[email protected]> wrote:
>
> On Tue, 01 Feb 2022 07:05:24 PST (-0800), [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.
>
> TBH, I'd always sort of hoped we wouldn't have to do this: it's a lot of
> ABI surface to keep around for a use case I'm not really sure is ever
> going to get any traction (it's not like we have legacy 32-bit
> userspaces floating around, the 32-bit userspace is newer than the
> 64-bit userspace).

The low-end embedded market isn't usually that newsworthy, but the
machines ship in huge quantities, and they all run 32-bit user
space for good reasons:

The cheapest Linux systems at the moment use a low-end MIPS or
Arm core with a single DDR2 (32MB to 128MB) or DDR3 (128MB
to 512MB) memory chip that for now is a bit cheaper than a larger
LP-DDR4 (256MB+). The smaller configurations will go away over
time as they get outpriced by systems with LP-DDR4, but a 32-bit
system with 256MB will keep beating a 64-bit-only system with
512MB on price, and will run most workloads better than a 64-bit
system with the same amount of RAM.

On the Arm side, I hope that these systems will migrate to Armv8
based designs (Cortex-A53/A35 or newer) running 64-bit kernel
with 32-bit user space to replace the currently dominant but aging
32-bit Cortex-A7 cores. As you say, RISC-V is at a disadvantage
here because there is no existing 32-bit ecosystem, but it may take
a chunk of that market anyway based on licensing cost. Between
doing this using pure 32-bit cores or on mixed 32/64-bit cores,
I found Guo Ren's explanation very sensible, it lets you use the
same chip both as a low-end embedded version with SiP
memory, or using an external DDR3/LPDDR4 chip with enough
capacity to run a generic 64-bit distro.

> My assumption is that users who actually wanted the
> memory savings (likely a very small number) would be better served with
> rv64/ilp32, as that'll allow the larger registers that the hardware
> supports. From some earlier discussions it looks like rv64/ilp32 isn't
> going to be allowed, though, so this seems like the only way to go.

Right, between rv32 user space and a hypothetical rv64-ilp32 target,
I think it's clear that the former is better because it means introducing
only one fringe ABI rather than two incompatible ones with minor
performance differences.

Arnd

2022-02-24 01:17:14

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH V5 21/21] KVM: compat: riscv: Prevent KVM_COMPAT from being selected

On Tue, 01 Feb 2022 07:05:45 PST (-0800), [email protected] wrote:
> From: Guo Ren <[email protected]>
>
> Current riscv doesn't support the 32bit KVM API. Let's make it
> clear by not selecting KVM_COMPAT.
>
> Signed-off-by: Guo Ren <[email protected]>
> Signed-off-by: Guo Ren <[email protected]>
> Cc: Arnd Bergmann <[email protected]>
> Cc: Anup Patel <[email protected]>
> ---
> virt/kvm/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
> index f4834c20e4a6..a8c5c9f06b3c 100644
> --- a/virt/kvm/Kconfig
> +++ b/virt/kvm/Kconfig
> @@ -53,7 +53,7 @@ config KVM_GENERIC_DIRTYLOG_READ_PROTECT
>
> config KVM_COMPAT
> def_bool y
> - depends on KVM && COMPAT && !(S390 || ARM64)
> + depends on KVM && COMPAT && !(S390 || ARM64 || RISCV)
>
> config HAVE_KVM_IRQ_BYPASS
> bool

Reviewed-by: Palmer Dabbelt <[email protected]>
Acked-by: Palmer Dabbelt <[email protected]>

I'm assuming Anup is going to take this as per the discussion, but LMK
if you want me to take it along with the rest of the series. There's
some minor comments outstanding on the other patches.