2021-09-17 16:00:31

by Huacai Chen

[permalink] [raw]
Subject: [PATCH V3 00/22] arch: Add basic LoongArch support

LoongArch is a new RISC ISA, which is a bit like MIPS or RISC-V.
LoongArch includes a reduced 32-bit version (LA32R), a standard 32-bit
version (LA32S) and a 64-bit version (LA64). LoongArch use ACPI as its
boot protocol LoongArch-specific interrupt controllers (similar to APIC)
are already added in the next revision of ACPI Specification (current
revision is 6.4).

This patchset is adding basic LoongArch support in mainline kernel, we
can see a complete snapshot here:
https://github.com/loongson/linux/tree/loongarch-next

Cross-compile tool chain to build kernel:
https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20210812-cross-tools.tar.xz

A CLFS-based Linux distro:
https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-system-2021-08-22.tar.bz2

Open-source tool chain which is under review:
https://github.com/loongson/binutils-gdb/tree/loongarch-2_37
https://github.com/loongson/gcc/tree/loongarch-12
https://github.com/loongson/glibc/tree/loongarch_2_34_dev

Loongson and LoongArch documentations:
https://github.com/loongson/LoongArch-Documentation

LoongArch-specific interrupt controllers:
https://mantis.uefi.org/mantis/view.php?id=2203

V1 -> V2:
1, Add documentation patches;
2, Restore copyright statements;
3, Split the big header patch;
4, Cleanup signal-related headers;
5, Cleanup incomplete 32-bit support;
6, Move the major PCI work to drivers/pci;
7, Rework Loongson64 platform support;
8, Rework lpj and __udelay()/__ndelay();
9, Rework page table layout config options;
10, Rework syscall/exception/interrupt with generic entry framework;
11, Simplify the VDSO/VSYSCALL implementation;
12, Use generic I/O access macros and functions;
13, Remove unaligned access emulation at present;
14, Keep clocksource code in arch since it is the "native clocksource";
15, Some other minor fixes and improvements.

V2 -> V3:
1, Rebased on 5.15-rc1;
2, Cleanup PCI code on V2;
3, Support multiple msi domain;
4, Support cacheable ioremap();
5, Use irq stack for interrupt handling;
6, Adjust struct ucontext and rt_sigframe;
7, Some other minor fixes and improvements.

Huacai Chen(22):
Documentation: LoongArch: Add basic documentations.
Documentation/zh_CN: Add basic LoongArch documentations.
LoongArch: Add elf-related definitions.
LoongArch: Add writecombine support for drm.
LoongArch: Add build infrastructure.
LoongArch: Add CPU definition headers.
LoongArch: Add atomic/locking headers.
LoongArch: Add other common headers.
LoongArch: Add boot and setup routines.
LoongArch: Add exception/interrupt handling.
LoongArch: Add process management.
LoongArch: Add memory management.
LoongArch: Add system call support.
LoongArch: Add signal handling support.
LoongArch: Add elf and module support.
LoongArch: Add misc common routines.
LoongArch: Add some library functions.
LoongArch: Add PCI controller support.
LoongArch: Add VDSO and VSYSCALL support.
LoongArch: Add multi-processor (SMP) support.
LoongArch: Add Non-Uniform Memory Access (NUMA) support.
LoongArch: Add Loongson-3 default config file.

Signed-off-by: Huacai Chen <[email protected]>
---
Documentation/arch.rst | 1 +
Documentation/loongarch/features.rst | 3 +
Documentation/loongarch/index.rst | 21 +
Documentation/loongarch/introduction.rst | 342 +++++
Documentation/loongarch/irq-chip-model.rst | 158 ++
Documentation/translations/zh_CN/index.rst | 1 +
.../translations/zh_CN/loongarch/features.rst | 8 +
.../translations/zh_CN/loongarch/index.rst | 26 +
.../translations/zh_CN/loongarch/introduction.rst | 316 ++++
.../zh_CN/loongarch/irq-chip-model.rst | 160 +++
arch/loongarch/.gitignore | 9 +
arch/loongarch/Kbuild | 3 +
arch/loongarch/Kconfig | 436 ++++++
arch/loongarch/Kconfig.debug | 0
arch/loongarch/Makefile | 124 ++
arch/loongarch/configs/loongson3_defconfig | 724 ++++++++++
arch/loongarch/include/asm/Kbuild | 31 +
arch/loongarch/include/asm/abi.h | 27 +
arch/loongarch/include/asm/acenv.h | 17 +
arch/loongarch/include/asm/acpi.h | 37 +
arch/loongarch/include/asm/addrspace.h | 110 ++
arch/loongarch/include/asm/asm-offsets.h | 5 +
arch/loongarch/include/asm/asm-prototypes.h | 7 +
arch/loongarch/include/asm/asm.h | 212 +++
arch/loongarch/include/asm/asmmacro.h | 318 +++++
arch/loongarch/include/asm/atomic.h | 302 ++++
arch/loongarch/include/asm/barrier.h | 161 +++
arch/loongarch/include/asm/bitops.h | 220 +++
arch/loongarch/include/asm/bitrev.h | 34 +
arch/loongarch/include/asm/boot_param.h | 91 ++
arch/loongarch/include/asm/bootinfo.h | 34 +
arch/loongarch/include/asm/branch.h | 21 +
arch/loongarch/include/asm/bug.h | 23 +
arch/loongarch/include/asm/cache.h | 13 +
arch/loongarch/include/asm/cacheflush.h | 79 +
arch/loongarch/include/asm/cacheops.h | 33 +
arch/loongarch/include/asm/clocksource.h | 12 +
arch/loongarch/include/asm/cmpxchg.h | 138 ++
arch/loongarch/include/asm/compiler.h | 15 +
arch/loongarch/include/asm/cpu-features.h | 67 +
arch/loongarch/include/asm/cpu-info.h | 136 ++
arch/loongarch/include/asm/cpu.h | 123 ++
arch/loongarch/include/asm/cpufeature.h | 24 +
arch/loongarch/include/asm/delay.h | 26 +
arch/loongarch/include/asm/dma-direct.h | 11 +
arch/loongarch/include/asm/dma.h | 13 +
arch/loongarch/include/asm/dmi.h | 24 +
arch/loongarch/include/asm/efi.h | 32 +
arch/loongarch/include/asm/elf.h | 308 ++++
arch/loongarch/include/asm/entry-common.h | 13 +
arch/loongarch/include/asm/exec.h | 10 +
arch/loongarch/include/asm/fb.h | 23 +
arch/loongarch/include/asm/fixmap.h | 15 +
arch/loongarch/include/asm/fpregdef.h | 55 +
arch/loongarch/include/asm/fpu.h | 129 ++
arch/loongarch/include/asm/futex.h | 108 ++
arch/loongarch/include/asm/fw.h | 18 +
arch/loongarch/include/asm/hardirq.h | 26 +
arch/loongarch/include/asm/hugetlb.h | 79 +
arch/loongarch/include/asm/hw_irq.h | 17 +
arch/loongarch/include/asm/idle.h | 9 +
arch/loongarch/include/asm/io.h | 129 ++
arch/loongarch/include/asm/irq.h | 128 ++
arch/loongarch/include/asm/irq_regs.h | 27 +
arch/loongarch/include/asm/irqflags.h | 52 +
arch/loongarch/include/asm/kdebug.h | 23 +
arch/loongarch/include/asm/linkage.h | 36 +
arch/loongarch/include/asm/local.h | 138 ++
arch/loongarch/include/asm/loongarch.h | 1509 ++++++++++++++++++++
arch/loongarch/include/asm/loongson.h | 159 +++
arch/loongarch/include/asm/mmu.h | 16 +
arch/loongarch/include/asm/mmu_context.h | 151 ++
arch/loongarch/include/asm/mmzone.h | 18 +
arch/loongarch/include/asm/module.h | 15 +
arch/loongarch/include/asm/numa.h | 69 +
arch/loongarch/include/asm/page.h | 127 ++
arch/loongarch/include/asm/pci.h | 40 +
arch/loongarch/include/asm/percpu.h | 222 +++
arch/loongarch/include/asm/perf_event.h | 10 +
arch/loongarch/include/asm/pgalloc.h | 97 ++
arch/loongarch/include/asm/pgtable-bits.h | 139 ++
arch/loongarch/include/asm/pgtable.h | 618 ++++++++
arch/loongarch/include/asm/prefetch.h | 29 +
arch/loongarch/include/asm/processor.h | 209 +++
arch/loongarch/include/asm/ptrace.h | 140 ++
arch/loongarch/include/asm/reboot.h | 10 +
arch/loongarch/include/asm/regdef.h | 43 +
arch/loongarch/include/asm/serial.h | 11 +
arch/loongarch/include/asm/setup.h | 21 +
arch/loongarch/include/asm/shmparam.h | 12 +
arch/loongarch/include/asm/smp.h | 134 ++
arch/loongarch/include/asm/sparsemem.h | 21 +
arch/loongarch/include/asm/spinlock.h | 12 +
arch/loongarch/include/asm/spinlock_types.h | 11 +
arch/loongarch/include/asm/stackframe.h | 243 ++++
arch/loongarch/include/asm/string.h | 17 +
arch/loongarch/include/asm/switch_to.h | 37 +
arch/loongarch/include/asm/syscall.h | 74 +
arch/loongarch/include/asm/thread_info.h | 116 ++
arch/loongarch/include/asm/time.h | 50 +
arch/loongarch/include/asm/timex.h | 32 +
arch/loongarch/include/asm/tlb.h | 216 +++
arch/loongarch/include/asm/tlbflush.h | 46 +
arch/loongarch/include/asm/topology.h | 41 +
arch/loongarch/include/asm/types.h | 33 +
arch/loongarch/include/asm/uaccess.h | 327 +++++
arch/loongarch/include/asm/unistd.h | 11 +
arch/loongarch/include/asm/vdso.h | 38 +
arch/loongarch/include/asm/vdso/clocksource.h | 8 +
arch/loongarch/include/asm/vdso/gettimeofday.h | 100 ++
arch/loongarch/include/asm/vdso/processor.h | 14 +
arch/loongarch/include/asm/vdso/vdso.h | 31 +
arch/loongarch/include/asm/vdso/vsyscall.h | 27 +
arch/loongarch/include/asm/vermagic.h | 19 +
arch/loongarch/include/asm/vmalloc.h | 4 +
arch/loongarch/include/uapi/asm/Kbuild | 2 +
arch/loongarch/include/uapi/asm/abidefs.h | 21 +
arch/loongarch/include/uapi/asm/auxvec.h | 17 +
arch/loongarch/include/uapi/asm/bitfield.h | 15 +
arch/loongarch/include/uapi/asm/bitsperlong.h | 9 +
arch/loongarch/include/uapi/asm/break.h | 23 +
arch/loongarch/include/uapi/asm/byteorder.h | 13 +
arch/loongarch/include/uapi/asm/hwcap.h | 20 +
arch/loongarch/include/uapi/asm/ptrace.h | 50 +
arch/loongarch/include/uapi/asm/reg.h | 103 ++
arch/loongarch/include/uapi/asm/sigcontext.h | 40 +
arch/loongarch/include/uapi/asm/swab.h | 52 +
arch/loongarch/include/uapi/asm/ucontext.h | 35 +
arch/loongarch/include/uapi/asm/unistd.h | 6 +
arch/loongarch/kernel/Makefile | 26 +
arch/loongarch/kernel/access-helper.h | 13 +
arch/loongarch/kernel/acpi.c | 488 +++++++
arch/loongarch/kernel/asm-offsets.c | 256 ++++
arch/loongarch/kernel/cacheinfo.c | 122 ++
arch/loongarch/kernel/cmdline.c | 28 +
arch/loongarch/kernel/cmpxchg.c | 107 ++
arch/loongarch/kernel/cpu-probe.c | 301 ++++
arch/loongarch/kernel/dma.c | 58 +
arch/loongarch/kernel/efi.c | 95 ++
arch/loongarch/kernel/elf.c | 41 +
arch/loongarch/kernel/entry.S | 88 ++
arch/loongarch/kernel/env.c | 170 +++
arch/loongarch/kernel/fpu.S | 296 ++++
arch/loongarch/kernel/genex.S | 114 ++
arch/loongarch/kernel/head.S | 95 ++
arch/loongarch/kernel/idle.c | 16 +
arch/loongarch/kernel/io.c | 94 ++
arch/loongarch/kernel/irq.c | 174 +++
arch/loongarch/kernel/mem.c | 83 ++
arch/loongarch/kernel/module.c | 653 +++++++++
arch/loongarch/kernel/numa.c | 482 +++++++
arch/loongarch/kernel/proc.c | 127 ++
arch/loongarch/kernel/process.c | 273 ++++
arch/loongarch/kernel/ptrace.c | 420 ++++++
arch/loongarch/kernel/reset.c | 102 ++
arch/loongarch/kernel/rtc.c | 36 +
arch/loongarch/kernel/setup.c | 501 +++++++
arch/loongarch/kernel/signal-common.h | 38 +
arch/loongarch/kernel/signal.c | 487 +++++++
arch/loongarch/kernel/smp.c | 923 ++++++++++++
arch/loongarch/kernel/switch.S | 37 +
arch/loongarch/kernel/syscall.c | 80 ++
arch/loongarch/kernel/time.c | 237 +++
arch/loongarch/kernel/topology.c | 57 +
arch/loongarch/kernel/traps.c | 748 ++++++++++
arch/loongarch/kernel/vdso.c | 139 ++
arch/loongarch/kernel/vmlinux.lds.S | 115 ++
arch/loongarch/lib/Makefile | 7 +
arch/loongarch/lib/clear_user.S | 43 +
arch/loongarch/lib/copy_user.S | 47 +
arch/loongarch/lib/delay.c | 43 +
arch/loongarch/lib/dump_tlb.c | 111 ++
arch/loongarch/lib/memcpy.S | 32 +
arch/loongarch/lib/memmove.S | 45 +
arch/loongarch/lib/memset.S | 30 +
arch/loongarch/lib/strncpy_user.S | 51 +
arch/loongarch/lib/strnlen_user.S | 47 +
arch/loongarch/mm/Makefile | 9 +
arch/loongarch/mm/cache.c | 153 ++
arch/loongarch/mm/extable.c | 22 +
arch/loongarch/mm/fault.c | 248 ++++
arch/loongarch/mm/hugetlbpage.c | 87 ++
arch/loongarch/mm/init.c | 226 +++
arch/loongarch/mm/ioremap.c | 27 +
arch/loongarch/mm/maccess.c | 10 +
arch/loongarch/mm/mmap.c | 125 ++
arch/loongarch/mm/page.S | 84 ++
arch/loongarch/mm/pgtable.c | 132 ++
arch/loongarch/mm/tlb.c | 287 ++++
arch/loongarch/mm/tlbex.S | 537 +++++++
arch/loongarch/pci/Makefile | 7 +
arch/loongarch/pci/acpi.c | 174 +++
arch/loongarch/pci/pci.c | 123 ++
arch/loongarch/vdso/Makefile | 96 ++
arch/loongarch/vdso/elf.S | 15 +
arch/loongarch/vdso/gen_vdso_offsets.sh | 14 +
arch/loongarch/vdso/sigreturn.S | 24 +
arch/loongarch/vdso/vdso.S | 22 +
arch/loongarch/vdso/vdso.lds.S | 72 +
arch/loongarch/vdso/vgettimeofday.c | 26 +
drivers/gpu/drm/drm_vm.c | 2 +-
drivers/gpu/drm/ttm/ttm_module.c | 2 +-
include/drm/drm_cache.h | 8 +
include/linux/cpuhotplug.h | 1 +
include/uapi/linux/audit.h | 2 +
include/uapi/linux/elf-em.h | 1 +
include/uapi/linux/elf.h | 5 +
include/uapi/linux/kexec.h | 1 +
scripts/sorttable.c | 5 +
scripts/subarch.include | 2 +-
210 files changed, 22926 insertions(+), 3 deletions(-)
create mode 100644 Documentation/loongarch/features.rst
create mode 100644 Documentation/loongarch/index.rst
create mode 100644 Documentation/loongarch/introduction.rst
create mode 100644 Documentation/loongarch/irq-chip-model.rst
create mode 100644 Documentation/translations/zh_CN/loongarch/features.rst
create mode 100644 Documentation/translations/zh_CN/loongarch/index.rst
create mode 100644 Documentation/translations/zh_CN/loongarch/introduction.rst
create mode 100644 Documentation/translations/zh_CN/loongarch/irq-chip-model.rst
create mode 100644 arch/loongarch/.gitignore
create mode 100644 arch/loongarch/Kbuild
create mode 100644 arch/loongarch/Kconfig
create mode 100644 arch/loongarch/Kconfig.debug
create mode 100644 arch/loongarch/Makefile
create mode 100644 arch/loongarch/configs/loongson3_defconfig
create mode 100644 arch/loongarch/include/asm/Kbuild
create mode 100644 arch/loongarch/include/asm/abi.h
create mode 100644 arch/loongarch/include/asm/acenv.h
create mode 100644 arch/loongarch/include/asm/acpi.h
create mode 100644 arch/loongarch/include/asm/addrspace.h
create mode 100644 arch/loongarch/include/asm/asm-offsets.h
create mode 100644 arch/loongarch/include/asm/asm-prototypes.h
create mode 100644 arch/loongarch/include/asm/asm.h
create mode 100644 arch/loongarch/include/asm/asmmacro.h
create mode 100644 arch/loongarch/include/asm/atomic.h
create mode 100644 arch/loongarch/include/asm/barrier.h
create mode 100644 arch/loongarch/include/asm/bitops.h
create mode 100644 arch/loongarch/include/asm/bitrev.h
create mode 100644 arch/loongarch/include/asm/boot_param.h
create mode 100644 arch/loongarch/include/asm/bootinfo.h
create mode 100644 arch/loongarch/include/asm/branch.h
create mode 100644 arch/loongarch/include/asm/bug.h
create mode 100644 arch/loongarch/include/asm/cache.h
create mode 100644 arch/loongarch/include/asm/cacheflush.h
create mode 100644 arch/loongarch/include/asm/cacheops.h
create mode 100644 arch/loongarch/include/asm/clocksource.h
create mode 100644 arch/loongarch/include/asm/cmpxchg.h
create mode 100644 arch/loongarch/include/asm/compiler.h
create mode 100644 arch/loongarch/include/asm/cpu-features.h
create mode 100644 arch/loongarch/include/asm/cpu-info.h
create mode 100644 arch/loongarch/include/asm/cpu.h
create mode 100644 arch/loongarch/include/asm/cpufeature.h
create mode 100644 arch/loongarch/include/asm/delay.h
create mode 100644 arch/loongarch/include/asm/dma-direct.h
create mode 100644 arch/loongarch/include/asm/dma.h
create mode 100644 arch/loongarch/include/asm/dmi.h
create mode 100644 arch/loongarch/include/asm/efi.h
create mode 100644 arch/loongarch/include/asm/elf.h
create mode 100644 arch/loongarch/include/asm/entry-common.h
create mode 100644 arch/loongarch/include/asm/exec.h
create mode 100644 arch/loongarch/include/asm/fb.h
create mode 100644 arch/loongarch/include/asm/fixmap.h
create mode 100644 arch/loongarch/include/asm/fpregdef.h
create mode 100644 arch/loongarch/include/asm/fpu.h
create mode 100644 arch/loongarch/include/asm/futex.h
create mode 100644 arch/loongarch/include/asm/fw.h
create mode 100644 arch/loongarch/include/asm/hardirq.h
create mode 100644 arch/loongarch/include/asm/hugetlb.h
create mode 100644 arch/loongarch/include/asm/hw_irq.h
create mode 100644 arch/loongarch/include/asm/idle.h
create mode 100644 arch/loongarch/include/asm/io.h
create mode 100644 arch/loongarch/include/asm/irq.h
create mode 100644 arch/loongarch/include/asm/irq_regs.h
create mode 100644 arch/loongarch/include/asm/irqflags.h
create mode 100644 arch/loongarch/include/asm/kdebug.h
create mode 100644 arch/loongarch/include/asm/linkage.h
create mode 100644 arch/loongarch/include/asm/local.h
create mode 100644 arch/loongarch/include/asm/loongarch.h
create mode 100644 arch/loongarch/include/asm/loongson.h
create mode 100644 arch/loongarch/include/asm/mmu.h
create mode 100644 arch/loongarch/include/asm/mmu_context.h
create mode 100644 arch/loongarch/include/asm/mmzone.h
create mode 100644 arch/loongarch/include/asm/module.h
create mode 100644 arch/loongarch/include/asm/numa.h
create mode 100644 arch/loongarch/include/asm/page.h
create mode 100644 arch/loongarch/include/asm/pci.h
create mode 100644 arch/loongarch/include/asm/percpu.h
create mode 100644 arch/loongarch/include/asm/perf_event.h
create mode 100644 arch/loongarch/include/asm/pgalloc.h
create mode 100644 arch/loongarch/include/asm/pgtable-bits.h
create mode 100644 arch/loongarch/include/asm/pgtable.h
create mode 100644 arch/loongarch/include/asm/prefetch.h
create mode 100644 arch/loongarch/include/asm/processor.h
create mode 100644 arch/loongarch/include/asm/ptrace.h
create mode 100644 arch/loongarch/include/asm/reboot.h
create mode 100644 arch/loongarch/include/asm/regdef.h
create mode 100644 arch/loongarch/include/asm/serial.h
create mode 100644 arch/loongarch/include/asm/setup.h
create mode 100644 arch/loongarch/include/asm/shmparam.h
create mode 100644 arch/loongarch/include/asm/smp.h
create mode 100644 arch/loongarch/include/asm/sparsemem.h
create mode 100644 arch/loongarch/include/asm/spinlock.h
create mode 100644 arch/loongarch/include/asm/spinlock_types.h
create mode 100644 arch/loongarch/include/asm/stackframe.h
create mode 100644 arch/loongarch/include/asm/string.h
create mode 100644 arch/loongarch/include/asm/switch_to.h
create mode 100644 arch/loongarch/include/asm/syscall.h
create mode 100644 arch/loongarch/include/asm/thread_info.h
create mode 100644 arch/loongarch/include/asm/time.h
create mode 100644 arch/loongarch/include/asm/timex.h
create mode 100644 arch/loongarch/include/asm/tlb.h
create mode 100644 arch/loongarch/include/asm/tlbflush.h
create mode 100644 arch/loongarch/include/asm/topology.h
create mode 100644 arch/loongarch/include/asm/types.h
create mode 100644 arch/loongarch/include/asm/uaccess.h
create mode 100644 arch/loongarch/include/asm/unistd.h
create mode 100644 arch/loongarch/include/asm/vdso.h
create mode 100644 arch/loongarch/include/asm/vdso/clocksource.h
create mode 100644 arch/loongarch/include/asm/vdso/gettimeofday.h
create mode 100644 arch/loongarch/include/asm/vdso/processor.h
create mode 100644 arch/loongarch/include/asm/vdso/vdso.h
create mode 100644 arch/loongarch/include/asm/vdso/vsyscall.h
create mode 100644 arch/loongarch/include/asm/vermagic.h
create mode 100644 arch/loongarch/include/asm/vmalloc.h
create mode 100644 arch/loongarch/include/uapi/asm/Kbuild
create mode 100644 arch/loongarch/include/uapi/asm/abidefs.h
create mode 100644 arch/loongarch/include/uapi/asm/auxvec.h
create mode 100644 arch/loongarch/include/uapi/asm/bitfield.h
create mode 100644 arch/loongarch/include/uapi/asm/bitsperlong.h
create mode 100644 arch/loongarch/include/uapi/asm/break.h
create mode 100644 arch/loongarch/include/uapi/asm/byteorder.h
create mode 100644 arch/loongarch/include/uapi/asm/hwcap.h
create mode 100644 arch/loongarch/include/uapi/asm/ptrace.h
create mode 100644 arch/loongarch/include/uapi/asm/reg.h
create mode 100644 arch/loongarch/include/uapi/asm/sigcontext.h
create mode 100644 arch/loongarch/include/uapi/asm/swab.h
create mode 100644 arch/loongarch/include/uapi/asm/ucontext.h
create mode 100644 arch/loongarch/include/uapi/asm/unistd.h
create mode 100644 arch/loongarch/kernel/Makefile
create mode 100644 arch/loongarch/kernel/access-helper.h
create mode 100644 arch/loongarch/kernel/acpi.c
create mode 100644 arch/loongarch/kernel/asm-offsets.c
create mode 100644 arch/loongarch/kernel/cacheinfo.c
create mode 100644 arch/loongarch/kernel/cmdline.c
create mode 100644 arch/loongarch/kernel/cmpxchg.c
create mode 100644 arch/loongarch/kernel/cpu-probe.c
create mode 100644 arch/loongarch/kernel/dma.c
create mode 100644 arch/loongarch/kernel/efi.c
create mode 100644 arch/loongarch/kernel/elf.c
create mode 100644 arch/loongarch/kernel/entry.S
create mode 100644 arch/loongarch/kernel/env.c
create mode 100644 arch/loongarch/kernel/fpu.S
create mode 100644 arch/loongarch/kernel/genex.S
create mode 100644 arch/loongarch/kernel/head.S
create mode 100644 arch/loongarch/kernel/idle.c
create mode 100644 arch/loongarch/kernel/io.c
create mode 100644 arch/loongarch/kernel/irq.c
create mode 100644 arch/loongarch/kernel/mem.c
create mode 100644 arch/loongarch/kernel/module.c
create mode 100644 arch/loongarch/kernel/numa.c
create mode 100644 arch/loongarch/kernel/proc.c
create mode 100644 arch/loongarch/kernel/process.c
create mode 100644 arch/loongarch/kernel/ptrace.c
create mode 100644 arch/loongarch/kernel/reset.c
create mode 100644 arch/loongarch/kernel/rtc.c
create mode 100644 arch/loongarch/kernel/setup.c
create mode 100644 arch/loongarch/kernel/signal-common.h
create mode 100644 arch/loongarch/kernel/signal.c
create mode 100644 arch/loongarch/kernel/smp.c
create mode 100644 arch/loongarch/kernel/switch.S
create mode 100644 arch/loongarch/kernel/syscall.c
create mode 100644 arch/loongarch/kernel/time.c
create mode 100644 arch/loongarch/kernel/topology.c
create mode 100644 arch/loongarch/kernel/traps.c
create mode 100644 arch/loongarch/kernel/vdso.c
create mode 100644 arch/loongarch/kernel/vmlinux.lds.S
create mode 100644 arch/loongarch/lib/Makefile
create mode 100644 arch/loongarch/lib/clear_user.S
create mode 100644 arch/loongarch/lib/copy_user.S
create mode 100644 arch/loongarch/lib/delay.c
create mode 100644 arch/loongarch/lib/dump_tlb.c
create mode 100644 arch/loongarch/lib/memcpy.S
create mode 100644 arch/loongarch/lib/memmove.S
create mode 100644 arch/loongarch/lib/memset.S
create mode 100644 arch/loongarch/lib/strncpy_user.S
create mode 100644 arch/loongarch/lib/strnlen_user.S
create mode 100644 arch/loongarch/mm/Makefile
create mode 100644 arch/loongarch/mm/cache.c
create mode 100644 arch/loongarch/mm/extable.c
create mode 100644 arch/loongarch/mm/fault.c
create mode 100644 arch/loongarch/mm/hugetlbpage.c
create mode 100644 arch/loongarch/mm/init.c
create mode 100644 arch/loongarch/mm/ioremap.c
create mode 100644 arch/loongarch/mm/maccess.c
create mode 100644 arch/loongarch/mm/mmap.c
create mode 100644 arch/loongarch/mm/page.S
create mode 100644 arch/loongarch/mm/pgtable.c
create mode 100644 arch/loongarch/mm/tlb.c
create mode 100644 arch/loongarch/mm/tlbex.S
create mode 100644 arch/loongarch/pci/Makefile
create mode 100644 arch/loongarch/pci/acpi.c
create mode 100644 arch/loongarch/pci/pci.c
create mode 100644 arch/loongarch/vdso/Makefile
create mode 100644 arch/loongarch/vdso/elf.S
create mode 100755 arch/loongarch/vdso/gen_vdso_offsets.sh
create mode 100644 arch/loongarch/vdso/sigreturn.S
create mode 100644 arch/loongarch/vdso/vdso.S
create mode 100644 arch/loongarch/vdso/vdso.lds.S
create mode 100644 arch/loongarch/vdso/vgettimeofday.c
--
2.27.0


2021-09-17 16:01:21

by Huacai Chen

[permalink] [raw]
Subject: [PATCH V3 01/22] Documentation: LoongArch: Add basic documentations

Add some basic documentations for LoongArch. LoongArch is a new RISC
ISA, which is a bit like MIPS or RISC-V. LoongArch includes a reduced
32-bit version (LA32R), a standard 32-bit version (LA32S) and a 64-bit
version (LA64).

Signed-off-by: Huacai Chen <[email protected]>
---
Documentation/arch.rst | 1 +
Documentation/loongarch/features.rst | 3 +
Documentation/loongarch/index.rst | 21 ++
Documentation/loongarch/introduction.rst | 342 +++++++++++++++++++++
Documentation/loongarch/irq-chip-model.rst | 158 ++++++++++
5 files changed, 525 insertions(+)
create mode 100644 Documentation/loongarch/features.rst
create mode 100644 Documentation/loongarch/index.rst
create mode 100644 Documentation/loongarch/introduction.rst
create mode 100644 Documentation/loongarch/irq-chip-model.rst

diff --git a/Documentation/arch.rst b/Documentation/arch.rst
index f10bd32a5972..ed6956289e4d 100644
--- a/Documentation/arch.rst
+++ b/Documentation/arch.rst
@@ -12,6 +12,7 @@ implementation.
arm/index
arm64/index
ia64/index
+ loongarch/index
m68k/index
mips/index
nios2/index
diff --git a/Documentation/loongarch/features.rst b/Documentation/loongarch/features.rst
new file mode 100644
index 000000000000..ebacade3ea45
--- /dev/null
+++ b/Documentation/loongarch/features.rst
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features loongarch
diff --git a/Documentation/loongarch/index.rst b/Documentation/loongarch/index.rst
new file mode 100644
index 000000000000..d127e07a7ed3
--- /dev/null
+++ b/Documentation/loongarch/index.rst
@@ -0,0 +1,21 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+================================
+LoongArch-specific Documentation
+================================
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ introduction
+ irq-chip-model
+
+ features
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/loongarch/introduction.rst b/Documentation/loongarch/introduction.rst
new file mode 100644
index 000000000000..20ee20664e2c
--- /dev/null
+++ b/Documentation/loongarch/introduction.rst
@@ -0,0 +1,342 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================
+Introduction of LoongArch
+=========================
+
+LoongArch is a new RISC ISA, which is a bit like MIPS or RISC-V. LoongArch
+includes a reduced 32-bit version (LA32R), a standard 32-bit version (LA32S)
+and a 64-bit version (LA64). LoongArch has 4 privilege levels (PLV0~PLV3),
+PLV0 is the highest level which used by kernel, and PLV3 is the lowest level
+which used by applications. This document introduces the registers, basic
+instruction set, virtual memory and some other topics of LoongArch.
+
+Registers
+=========
+
+LoongArch registers include general purpose registers (GPRs), floating point
+registers (FPRs), vector registers (VRs) and control status registers (CSRs)
+used in privileged mode (PLV0).
+
+GPRs
+----
+
+LoongArch has 32 GPRs ($r0 - $r31), each one is 32bit wide in LA32 and 64bit
+wide in LA64. $r0 is always zero, and other registers has no special feature,
+but we actually have an ABI register conversion as below.
+
+================= =============== =================== ============
+Name Alias Usage Preserved
+ across calls
+================= =============== =================== ============
+``$r0`` ``$zero`` Constant zero Unused
+``$r1`` ``$ra`` Return address No
+``$r2`` ``$tp`` TLS Unused
+``$r3`` ``$sp`` Stack pointer Yes
+``$r4``-``$r11`` ``$a0``-``$a7`` Argument registers No
+``$r4``-``$r5`` ``$v0``-``$v1`` Return value No
+``$r12``-``$r20`` ``$t0``-``$t8`` Temp registers No
+``$r21`` ``$x`` Reserved Unused
+``$r22`` ``$fp`` Frame pointer Yes
+``$r23``-``$r31`` ``$s0``-``$s8`` Static registers Yes
+================= =============== =================== ============
+
+FPRs
+----
+
+LoongArch has 32 FPRs ($f0 - $f31), each one is 64bit wide. We also have an
+ABI register conversion as below.
+
+================= ================== =================== ============
+Name Alias Usage Preserved
+ across calls
+================= ================== =================== ============
+``$f0``-``$f7`` ``$fa0``-``$fa7`` Argument registers No
+``$f0``-``$f1`` ``$fv0``-``$fv1`` Return value No
+``$f8``-``$f23`` ``$ft0``-``$ft15`` Temp registers No
+``$f24``-``$f31`` ``$fs0``-``$fs7`` Static registers Yes
+================= ================== =================== ============
+
+VRs
+----
+
+LoongArch has 128bit vector extension (LSX, short for Loongson SIMD eXtention)
+and 256bit vector extension (LASX, short for Loongson Advanced SIMD eXtension).
+There are also 32 vector registers, for LSX is $v0 - $v31, and for LASX is $x0
+- $x31. FPRs and VRs are reused, e.g. the lower 128bits of $x0 is $v0, and the
+lower 64bits of $v0 is $f0, etc.
+
+CSRs
+----
+
+CSRs can only be used in privileged mode (PLV0):
+
+================= ===================================== ==============
+Address Full Name Abbrev Name
+================= ===================================== ==============
+0x0 Current Mode information CRMD
+0x1 Pre-exception Mode information PRMD
+0x2 Extended Unit Enable EUEN
+0x3 Miscellaneous controller MISC
+0x4 Exception Configuration ECFG
+0x5 Exception Status ESTAT
+0x6 Exception Return Address ERA
+0x7 Bad Virtual Address BADV
+0x8 Bad Instruction BADI
+0xC Exception Entry Base address EENTRY
+0x10 TLB Index TLBIDX
+0x11 TLB Entry High-order bits TLBEHI
+0x12 TLB Entry Low-order bits 0 TLBELO0
+0x13 TLB Entry Low-order bits 1 TLBELO1
+0x18 Address Space Identifier ASID
+0x19 Page Global Directory address for PGDL
+ Lower half address space
+0x1A Page Global Directory address for PGDH
+ Higher half address space
+0x1B Page Global Directory address PGD
+0x1C Page Walk Controller for Lower PWCL
+ half address space
+0x1D Page Walk Controller for Higher PWCH
+ half address space
+0x1E STLB Page Size STLBPS
+0x1F Reduced Virtual Address Configuration RVACFG
+0x20 CPU Identifier CPUID
+0x21 Privileged Resource Configuration 1 PRCFG1
+0x22 Privileged Resource Configuration 2 PRCFG2
+0x23 Privileged Resource Configuration 3 PRCFG3
+0x30+n (0≤n≤15) Data Save register SAVEn
+0x40 Timer Identifier TID
+0x41 Timer Configuration TCFG
+0x42 Timer Value TVAL
+0x43 Compensation of Timer Count CNTC
+0x44 Timer Interrupt Clearing TICLR
+0x60 LLBit Controller LLBCTL
+0x80 Implementation-specific Controller 1 IMPCTL1
+0x81 Implementation-specific Controller 2 IMPCTL2
+0x88 TLB Refill Exception Entry Base TLBRENTRY
+ address
+0x89 TLB Refill Exception BAD Virtual TLBRBADV
+ address
+0x8A TLB Refill Exception Return Address TLBRERA
+0x8B TLB Refill Exception data SAVE TLBRSAVE
+ register
+0x8C TLB Refill Exception Entry Low-order TLBRELO0
+ bits 0
+0x8D TLB Refill Exception Entry Low-order TLBRELO1
+ bits 1
+0x8E TLB Refill Exception Entry High-order TLBEHI
+ bits
+0x8F TLB Refill Exception Pre-exception TLBRPRMD
+ Mode information
+0x90 Machine Error Controller MERRCTL
+0x91 Machine Error Information 1 MERRINFO1
+0x92 Machine Error Information 2 MERRINFO2
+0x93 Machine Error Exception Entry Base MERRENTRY
+ address
+0x94 Machine Error Exception Return MERRERA
+ address
+0x95 Machine Error Exception data SAVE MERRSAVE
+ register
+0x98 Cache TAGs CTAG
+0x180+n (0≤n≤3) Direct Mapping configuration Window n DMWn
+0x200+2n (0≤n≤31) Performance Monitor Configuration n PMCFGn
+0x201+2n (0≤n≤31) Performance Monitor overall Counter n PMCNTn
+0x300 Memory load/store WatchPoint MWPC
+ overall Controller
+0x301 Memory load/store WatchPoint MWPS
+ overall Status
+0x310+8n (0≤n≤7) Memory load/store WatchPoint n MWPnCFG1
+ Configuration 1
+0x311+8n (0≤n≤7) Memory load/store WatchPoint n MWPnCFG2
+ Configuration 2
+0x312+8n (0≤n≤7) Memory load/store WatchPoint n MWPnCFG3
+ Configuration 3
+0x313+8n (0≤n≤7) Memory load/store WatchPoint n MWPnCFG4
+ Configuration 4
+0x380 Fetch WatchPoint overall Controller FWPC
+0x381 Fetch WatchPoint overall Status FWPS
+0x390+8n (0≤n≤7) Fetch WatchPoint n Configuration 1 FWPnCFG1
+0x391+8n (0≤n≤7) Fetch WatchPoint n Configuration 2 FWPnCFG2
+0x392+8n (0≤n≤7) Fetch WatchPoint n Configuration 3 FWPnCFG3
+0x393+8n (0≤n≤7) Fetch WatchPoint n Configuration 4 FWPnCFG4
+0x500 Debug register DBG
+0x501 Debug Exception Return address DERA
+0x502 Debug data SAVE register DSAVE
+================= ===================================== ==============
+
+Basic Instruction Set
+=====================
+
+Instruction formats
+-------------------
+
+LoongArch has 32-bit wide instructions, and there are 9 instruction formats::
+
+ 2R-type: Opcode + Rj + Rd
+ 3R-type: Opcode + Rk + Rj + Rd
+ 4R-type: Opcode + Ra + Rk + Rj + Rd
+ 2RI8-type: Opcode + I8 + Rj + Rd
+ 2RI12-type: Opcode + I12 + Rj + Rd
+ 2RI14-type: Opcode + I14 + Rj + Rd
+ 2RI16-type: Opcode + I16 + Rj + Rd
+ 1RI21-type: Opcode + I21L + Rj + I21H
+ I26-type: Opcode + I26L + I26H
+
+Rj and Rk are source operands (register), Rd is destination operand (register),
+and Ra is the additional operand (register) in 4R-type. I8/I12/I16/I21/I26 are
+8-bits/12-bits/16-bits/21-bits/26bits immediate data. 21bits/26bits immediate
+data are split into higher bits and lower bits in an instruction word, so you
+can see I21L/I21H and I26L/I26H here.
+
+Instruction names (Mnemonics)
+-----------------------------
+
+We only list the instruction names here, for details please read the references.
+
+Arithmetic Operation Instructions::
+
+ ADD.W SUB.W ADDI.W ADD.D SUB.D ADDI.D
+ SLT SLTU SLTI SLTUI
+ AND OR NOR XOR ANDN ORN ANDI ORI XORI
+ MUL.W MULH.W MULH.WU DIV.W DIV.WU MOD.W MOD.WU
+ MUL.D MULH.D MULH.DU DIV.D DIV.DU MOD.D MOD.DU
+ PCADDI PCADDU12I PCADDU18I
+ LU12I.W LU32I.D LU52I.D ADDU16I.D
+
+Bit-shift Instructions::
+
+ SLL.W SRL.W SRA.W ROTR.W SLLI.W SRLI.W SRAI.W ROTRI.W
+ SLL.D SRL.D SRA.D ROTR.D SLLI.D SRLI.D SRAI.D ROTRI.D
+
+Bit-manipulation Instructions::
+
+ EXT.W.B EXT.W.H CLO.W CLO.D SLZ.W CLZ.D CTO.W CTO.D CTZ.W CTZ.D
+ BYTEPICK.W BYTEPICK.D BSTRINS.W BSTRINS.D BSTRPICK.W BSTRPICK.D
+ REVB.2H REVB.4H REVB.2W REVB.D REVH.2W REVH.D BITREV.4B BITREV.8B BITREV.W BITREV.D
+ MASKEQZ MASKNEZ
+
+Branch Instructions::
+
+ BEQ BNE BLT BGE BLTU BGEU BEQZ BNEZ B BL JIRL
+
+Load/Store Instructions::
+
+ LD.B LD.BU LD.H LD.HU LD.W LD.WU LD.D ST.B ST.H ST.W ST.D
+ LDX.B LDX.BU LDX.H LDX.HU LDX.W LDX.WU LDX.D STX.B STX.H STX.W STX.D
+ LDPTR.W LDPTR.D STPTR.W STPTR.D
+ PRELD PRELDX
+
+Atomic Operation Instructions::
+
+ LL.W SC.W LL.D SC.D
+ AMSWAP.W AMSWAP.D AMADD.W AMADD.D AMAND.W AMAND.D AMOR.W AMOR.D AMXOR.W AMXOR.D
+ AMMAX.W AMMAX.D AMMIN.W AMMIN.D
+
+Barrier Instructions::
+
+ IBAR DBAR
+
+Special Instructions::
+
+ SYSCALL BREAK CPUCFG NOP IDLE ERTN DBCL RDTIMEL.W RDTIMEH.W RDTIME.D ASRTLE.D ASRTGT.D
+
+Privileged Instructions::
+
+ CSRRD CSRWR CSRXCHG
+ IOCSRRD.B IOCSRRD.H IOCSRRD.W IOCSRRD.D IOCSRWR.B IOCSRWR.H IOCSRWR.W IOCSRWR.D
+ CACOP TLBP(TLBSRCH) TLBRD TLBWR TLBFILL TLBCLR TLBFLUSH INVTLB LDDIR LDPTE
+
+Virtual Memory
+==============
+
+LoongArch can use direct-mapped virtual memory and page-mapped virtual memory.
+
+Direct-mapped virtual memory is configured by CSR.DMWn (n=0~3), it has a simple
+relationship between virtual address (VA) and physical address (PA)::
+
+ VA = PA + FixedOffset
+
+Page-mapped virtual memory has arbitrary relationship between VA and PA, which
+is recorded in TLB and page tables. LoongArch's TLB includes a fully-associative
+MTLB (Multiple Page Size TLB) and set-associative STLB (Single Page Size TLB).
+
+By default, the whole virtual address space of LA32 is configured like this:
+
+============ =========================== =============================
+Name Address Range Attributes
+============ =========================== =============================
+``UVRANGE`` ``0x00000000 - 0x7FFFFFFF`` Page-mapped, Cached, PLV0~3
+``KPRANGE0`` ``0x80000000 - 0x9FFFFFFF`` Direct-mapped, Uncached, PLV0
+``KPRANGE1`` ``0xA0000000 - 0xBFFFFFFF`` Direct-mapped, Cached, PLV0
+``KVRANGE`` ``0xC0000000 - 0xFFFFFFFF`` Page-mapped, Cached, PLV0
+============ =========================== =============================
+
+User mode (PLV3) can only access UVRANGE. For direct-mapped KPRANGE0 and
+KPRANGE1, PA is equal to VA with bit30~31 cleared. For example, the uncached
+direct-mapped VA of 0x00001000 is 0x80001000, and the cached direct-mapped
+VA of 0x00001000 is 0xA0001000.
+
+By default, the whole virtual address space of LA64 is configured like this:
+
+============ ====================== ======================================
+Name Address Range Attributes
+============ ====================== ======================================
+``XUVRANGE`` ``0x0000000000000000 - Page-mapped, Cached, PLV0~3
+ 0x3FFFFFFFFFFFFFFF``
+``XSPRANGE`` ``0x4000000000000000 - Direct-mapped, Cached / Uncached, PLV0
+ 0x7FFFFFFFFFFFFFFF``
+``XKPRANGE`` ``0x8000000000000000 - Direct-mapped, Cached / Uncached, PLV0
+ 0xBFFFFFFFFFFFFFFF``
+``XKVRANGE`` ``0xC000000000000000 - Page-mapped, Cached, PLV0
+ 0xFFFFFFFFFFFFFFFF``
+============ ====================== ======================================
+
+User mode (PLV3) can only access XUVRANGE. For direct-mapped XSPRANGE and XKPRANGE,
+PA is equal to VA with bit60~63 cleared, and the cache attributes is configured by
+bit60~61 (0 is strongly-ordered uncached, 1 is coherent cached, and 2 is weakly-
+ordered uncached) in VA. Currently we only use XKPRANGE for direct mapping and
+XSPRANGE is reserved. As an example, the strongly-ordered uncached direct-mapped VA
+(in XKPRANGE) of 0x00000000 00001000 is 0x80000000 00001000, the coherent cached
+direct-mapped VA (in XKPRANGE) of 0x00000000 00001000 is 0x90000000 00001000, and
+the weakly-ordered uncached direct-mapped VA (in XKPRANGE) of 0x00000000 00001000
+is 0xA0000000 00001000.
+
+Relationship of Loongson and LoongArch
+======================================
+
+LoongArch is a RISC ISA which is different from any other existing ones, while
+Loongson is a family of processors. Loongson includes 3 series: Loongson-1 is
+32-bit processors, Loongson-2 is low-end 64-bit processors, and Loongson-3 is
+high-end 64-bit processors. Old Loongson is based on MIPS, and New Loongson is
+based on LoongArch. Take Loongson-3 as an example: Loongson-3A1000/3B1500/3A2000
+/3A3000/3A4000 are MIPS-compatible, while Loongson-3A5000 (and future revisions)
+are all based on LoongArch.
+
+References
+==========
+
+Official web site of Loongson and LoongArch (Loongson Technology Corp. Ltd.):
+
+ http://www.loongson.cn/index.html
+
+Developer web site of Loongson and LoongArch (Software and Documentations):
+
+ http://www.loongnix.cn/index.php
+
+ https://github.com/loongson
+
+Documentations of LoongArch ISA:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (in Chinese)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (in English)
+
+Documentations of LoongArch ABI:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ABI-v1.00-CN.pdf (in Chinese)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ABI-v1.00-EN.pdf (in English)
+
+Linux kernel repository of Loongson and LoongArch:
+
+ https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
diff --git a/Documentation/loongarch/irq-chip-model.rst b/Documentation/loongarch/irq-chip-model.rst
new file mode 100644
index 000000000000..b33aaecbf810
--- /dev/null
+++ b/Documentation/loongarch/irq-chip-model.rst
@@ -0,0 +1,158 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======================================
+IRQ chip model (hierarchy) of LoongArch
+=======================================
+
+Currently, LoongArch based processors (e.g. Loongson-3A5000) can only work together
+with LS7A chipsets. The irq chips in LoongArch computers include CPUINTC (CPU Core
+Interrupt Controller), LIOINTC (Legacy I/O Interrupt Controller), EIOINTC (Extended
+I/O Interrupt Controller), HTVECINTC (Hyper-Transport Vector Interrupt Controller),
+PCH-PIC (Main Interrupt Controller in LS7A chipset), PCH-LPC (LPC Interrupt Controller
+in LS7A chipset) and PCH-MSI (MSI Interrupt Controller).
+
+CPUINTC is a per-core controller (in CPU), LIOINTC/EIOINTC/HTVECINTC are per-package
+controllers (in CPU), while PCH-PIC/PCH-LPC/PCH-MSI are controllers out of CPU (i.e.,
+in chipsets). These controllers (in other words, irqchips) are linked in a hierarchy,
+and there are two models of hierarchy (legacy model and extended model).
+
+Legacy IRQ model
+================
+
+In this model, IPI (Inter-Processor Interrupt) and CPU Local Timer interrupt go
+to CPUINTC directly, CPU UARTS interrupts go to LIOINTC, while all other devices
+interrupts go to PCH-PIC/PCH-LPC/PCH-MSI and gathered by HTVECINTC, and then go
+to LIOINTC, and then CPUINTC.
+
+ +---------------------------------------------+
+ |:: |
+ | |
+ | +-----+ +---------+ +-------+ |
+ | | IPI | --> | CPUINTC | <-- | Timer | |
+ | +-----+ +---------+ +-------+ |
+ | ^ |
+ | | |
+ | +---------+ +-------+ |
+ | | LIOINTC | <-- | UARTs | |
+ | +---------+ +-------+ |
+ | ^ |
+ | | |
+ | +-----------+ |
+ | | HTVECINTC | |
+ | +-----------+ |
+ | ^ ^ |
+ | | | |
+ | +---------+ +---------+ |
+ | | PCH-PIC | | PCH-MSI | |
+ | +---------+ +---------+ |
+ | ^ ^ ^ |
+ | | | | |
+ | +---------+ +---------+ +---------+ |
+ | | PCH-LPC | | Devices | | Devices | |
+ | +---------+ +---------+ +---------+ |
+ | ^ |
+ | | |
+ | +---------+ |
+ | | Devices | |
+ | +---------+ |
+ | |
+ | |
+ +---------------------------------------------+
+
+Extended IRQ model
+==================
+
+In this model, IPI (Inter-Processor Interrupt) and CPU Local Timer interrupt go
+to CPUINTC directly, CPU UARTS interrupts go to LIOINTC, while all other devices
+interrupts go to PCH-PIC/PCH-LPC/PCH-MSI and gathered by EIOINTC, and then go to
+to CPUINTC directly.
+
+ +--------------------------------------------------------+
+ |:: |
+ | |
+ | +-----+ +---------+ +-------+ |
+ | | IPI | --> | CPUINTC | <-- | Timer | |
+ | +-----+ +---------+ +-------+ |
+ | ^ ^ |
+ | | | |
+ | +---------+ +---------+ +-------+ |
+ | | EIOINTC | | LIOINTC | <-- | UARTs | |
+ | +---------+ +---------+ +-------+ |
+ | ^ ^ |
+ | | | |
+ | +---------+ +---------+ |
+ | | PCH-PIC | | PCH-MSI | |
+ | +---------+ +---------+ |
+ | ^ ^ ^ |
+ | | | | |
+ | +---------+ +---------+ +---------+ |
+ | | PCH-LPC | | Devices | | Devices | |
+ | +---------+ +---------+ +---------+ |
+ | ^ |
+ | | |
+ | +---------+ |
+ | | Devices | |
+ | +---------+ |
+ | |
+ | |
+ +--------------------------------------------------------+
+
+ACPI-related definitions
+========================
+
+CPUINTC::
+
+ ACPI_MADT_TYPE_CORE_PIC;
+ struct acpi_madt_core_pic;
+ enum acpi_madt_core_pic_version;
+
+LIOINTC::
+
+ ACPI_MADT_TYPE_LIO_PIC;
+ struct acpi_madt_lio_pic;
+ enum acpi_madt_lio_pic_version;
+
+EIOINTC::
+
+ ACPI_MADT_TYPE_EIO_PIC;
+ struct acpi_madt_eio_pic;
+ enum acpi_madt_eio_pic_version;
+
+HTVECINTC::
+
+ ACPI_MADT_TYPE_HT_PIC;
+ struct acpi_madt_ht_pic;
+ enum acpi_madt_ht_pic_version;
+
+PCH-PIC::
+
+ ACPI_MADT_TYPE_BIO_PIC;
+ struct acpi_madt_bio_pic;
+ enum acpi_madt_bio_pic_version;
+
+PCH-MSI::
+
+ ACPI_MADT_TYPE_MSI_PIC;
+ struct acpi_madt_msi_pic;
+ enum acpi_madt_msi_pic_version;
+
+PCH-LPC::
+
+ ACPI_MADT_TYPE_LPC_PIC;
+ struct acpi_madt_lpc_pic;
+ enum acpi_madt_lpc_pic_version;
+
+References
+==========
+
+Documentations of Loongson-3A5000:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-CN.pdf (in Chinese)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-EN.pdf (in English)
+
+Documentations of Loongson's LS7A chipset:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-CN.pdf (in Chinese)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-EN.pdf (in English)
--
2.27.0

2021-09-17 16:01:31

by Huacai Chen

[permalink] [raw]
Subject: [PATCH V3 04/22] LoongArch: Add writecombine support for drm

LoongArch maintains cache coherency in hardware, but its WUC attribute
(Weak-ordered UnCached, which is similar to WC) is out of the scope of
cache coherency machanism. This means WUC can only used for write-only
memory regions.

Signed-off-by: Huacai Chen <[email protected]>
---
drivers/gpu/drm/drm_vm.c | 2 +-
drivers/gpu/drm/ttm/ttm_module.c | 2 +-
include/drm/drm_cache.h | 8 ++++++++
3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index e957d4851dc0..f024dc93939e 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -69,7 +69,7 @@ static pgprot_t drm_io_prot(struct drm_local_map *map,
pgprot_t tmp = vm_get_page_prot(vma->vm_flags);

#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
- defined(__mips__)
+ defined(__mips__) || defined(__loongarch__)
if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
tmp = pgprot_noncached(tmp);
else
diff --git a/drivers/gpu/drm/ttm/ttm_module.c b/drivers/gpu/drm/ttm/ttm_module.c
index 7fcdef278c74..3dc43390e76b 100644
--- a/drivers/gpu/drm/ttm/ttm_module.c
+++ b/drivers/gpu/drm/ttm/ttm_module.c
@@ -60,7 +60,7 @@ pgprot_t ttm_prot_from_caching(enum ttm_caching caching, pgprot_t tmp)
tmp = pgprot_noncached(tmp);
#endif
#if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \
- defined(__powerpc__) || defined(__mips__)
+ defined(__powerpc__) || defined(__mips__) || defined(__loongarch__)
if (caching == ttm_write_combined)
tmp = pgprot_writecombine(tmp);
else
diff --git a/include/drm/drm_cache.h b/include/drm/drm_cache.h
index cc9de1632dd3..5c1059435369 100644
--- a/include/drm/drm_cache.h
+++ b/include/drm/drm_cache.h
@@ -67,6 +67,14 @@ static inline bool drm_arch_can_wc_memory(void)
* optimization entirely for ARM and arm64.
*/
return false;
+#elif defined(CONFIG_LOONGARCH)
+ /*
+ * LoongArch maintains cache coherency in hardware, but its WUC attribute
+ * (Weak-ordered UnCached, which is similar to WC) is out of the scope of
+ * cache coherency machanism. This means WUC can only used for write-only
+ * memory regions.
+ */
+ return false;
#else
return true;
#endif
--
2.27.0

2021-09-17 17:08:06

by Huacai Chen

[permalink] [raw]
Subject: [PATCH V3 14/22] LoongArch: Add signal handling support

This patch adds signal handling support for LoongArch.

Signed-off-by: Huacai Chen <[email protected]>
---
arch/loongarch/include/asm/abi.h | 27 ++
arch/loongarch/include/uapi/asm/sigcontext.h | 40 ++
arch/loongarch/include/uapi/asm/ucontext.h | 35 ++
arch/loongarch/kernel/signal-common.h | 38 ++
arch/loongarch/kernel/signal.c | 467 +++++++++++++++++++
5 files changed, 607 insertions(+)
create mode 100644 arch/loongarch/include/asm/abi.h
create mode 100644 arch/loongarch/include/uapi/asm/sigcontext.h
create mode 100644 arch/loongarch/include/uapi/asm/ucontext.h
create mode 100644 arch/loongarch/kernel/signal-common.h
create mode 100644 arch/loongarch/kernel/signal.c

diff --git a/arch/loongarch/include/asm/abi.h b/arch/loongarch/include/asm/abi.h
new file mode 100644
index 000000000000..ced8534db4df
--- /dev/null
+++ b/arch/loongarch/include/asm/abi.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ */
+#ifndef _ASM_ABI_H
+#define _ASM_ABI_H
+
+#include <linux/signal_types.h>
+
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+#include <asm/vdso.h>
+
+struct loongarch_abi {
+ const unsigned long restart;
+ const int audit_arch;
+
+ unsigned int off_sc_fpregs;
+ unsigned int off_sc_fcc;
+ unsigned int off_sc_fcsr;
+ unsigned int off_sc_vcsr;
+ unsigned int off_sc_flags;
+
+ struct loongarch_vdso_info *vdso;
+};
+
+#endif /* _ASM_ABI_H */
diff --git a/arch/loongarch/include/uapi/asm/sigcontext.h b/arch/loongarch/include/uapi/asm/sigcontext.h
new file mode 100644
index 000000000000..da0e5bac2d80
--- /dev/null
+++ b/arch/loongarch/include/uapi/asm/sigcontext.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Author: Hanlu Li <[email protected]>
+ * Huacai Chen <[email protected]>
+ *
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ */
+#ifndef _UAPI_ASM_SIGCONTEXT_H
+#define _UAPI_ASM_SIGCONTEXT_H
+
+#include <linux/types.h>
+#include <asm/processor.h>
+
+/* scalar FP context was used */
+#define USED_FP (1 << 0)
+
+/* extended context was used, see struct extcontext for details */
+#define USED_EXTCONTEXT (1 << 1)
+
+#include <linux/posix_types.h>
+/*
+ * Keep this struct definition in sync with the sigcontext fragment
+ * in arch/loongarch/kernel/asm-offsets.c
+ *
+ */
+struct sigcontext {
+ __u64 sc_pc;
+ __u64 sc_regs[32];
+ __u32 sc_flags;
+
+ __u32 sc_fcsr;
+ __u32 sc_vcsr;
+ __u64 sc_fcc;
+ __u64 sc_scr[4];
+
+ union fpureg sc_fpregs[32] FPU_ALIGN;
+ __u8 sc_reserved[4096] __attribute__((__aligned__(16)));
+};
+
+#endif /* _UAPI_ASM_SIGCONTEXT_H */
diff --git a/arch/loongarch/include/uapi/asm/ucontext.h b/arch/loongarch/include/uapi/asm/ucontext.h
new file mode 100644
index 000000000000..12577e22b1c7
--- /dev/null
+++ b/arch/loongarch/include/uapi/asm/ucontext.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LOONGARCH_UAPI_ASM_UCONTEXT_H
+#define __LOONGARCH_UAPI_ASM_UCONTEXT_H
+
+/**
+ * struct ucontext - user context structure
+ * @uc_flags:
+ * @uc_link:
+ * @uc_stack:
+ * @uc_mcontext: holds basic processor state
+ * @uc_sigmask:
+ * @uc_extcontext: holds extended processor state
+ */
+struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ 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 sigcontext uc_mcontext;
+};
+
+#endif /* __LOONGARCH_UAPI_ASM_UCONTEXT_H */
diff --git a/arch/loongarch/kernel/signal-common.h b/arch/loongarch/kernel/signal-common.h
new file mode 100644
index 000000000000..1693fbdedeaa
--- /dev/null
+++ b/arch/loongarch/kernel/signal-common.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Author: Hanlu Li <[email protected]>
+ * Huacai Chen <[email protected]>
+ *
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef __SIGNAL_COMMON_H
+#define __SIGNAL_COMMON_H
+
+/* #define DEBUG_SIG */
+
+#ifdef DEBUG_SIG
+# define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
+#else
+# define DEBUGP(fmt, args...)
+#endif
+
+/*
+ * Determine which stack to use..
+ */
+extern void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
+ size_t frame_size);
+/* Check and clear pending FPU exceptions in saved CSR */
+extern int fpcsr_pending(unsigned int __user *fpcsr);
+
+/* Make sure we will not lose FPU ownership */
+#define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); })
+#define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); })
+
+/* Assembly functions to move context to/from the FPU */
+extern asmlinkage int
+_save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
+extern asmlinkage int
+_restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
+
+#endif /* __SIGNAL_COMMON_H */
diff --git a/arch/loongarch/kernel/signal.c b/arch/loongarch/kernel/signal.c
new file mode 100644
index 000000000000..78319d2575c6
--- /dev/null
+++ b/arch/loongarch/kernel/signal.c
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author: Hanlu Li <[email protected]>
+ * Huacai Chen <[email protected]>
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ *
+ * Derived from MIPS:
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2014, Imagination Technologies Ltd.
+ */
+#include <linux/audit.h>
+#include <linux/cache.h>
+#include <linux/context_tracking.h>
+#include <linux/irqflags.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/personality.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/uprobes.h>
+#include <linux/compiler.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/tracehook.h>
+
+#include <asm/abi.h>
+#include <asm/asm.h>
+#include <asm/cacheflush.h>
+#include <asm/fpu.h>
+#include <asm/ucontext.h>
+#include <asm/cpu-features.h>
+
+#include "signal-common.h"
+
+static int (*save_fp_context)(void __user *sc);
+static int (*restore_fp_context)(void __user *sc);
+
+struct rt_sigframe {
+ struct siginfo rs_info;
+ struct ucontext rs_uctx;
+};
+
+/*
+ * Thread saved context copy to/from a signal context presumed to be on the
+ * user stack, and therefore accessed with appropriate macros from uaccess.h.
+ */
+static int copy_fp_to_sigcontext(void __user *sc)
+{
+ struct loongarch_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint64_t __user *fcc = sc + abi->off_sc_fcc;
+ uint32_t __user *csr = sc + abi->off_sc_fcsr;
+ int i;
+ int err = 0;
+ int inc = 1;
+
+ for (i = 0; i < NUM_FPU_REGS; i += inc) {
+ err |=
+ __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
+ &fpregs[4*i]);
+ }
+ err |= __put_user(current->thread.fpu.fcsr, csr);
+ err |= __put_user(current->thread.fpu.fcc, fcc);
+
+ return err;
+}
+
+static int copy_fp_from_sigcontext(void __user *sc)
+{
+ struct loongarch_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint64_t __user *fcc = sc + abi->off_sc_fcc;
+ uint32_t __user *csr = sc + abi->off_sc_fcsr;
+ int i;
+ int err = 0;
+ int inc = 1;
+ u64 fpr_val;
+
+ for (i = 0; i < NUM_FPU_REGS; i += inc) {
+ err |= __get_user(fpr_val, &fpregs[4*i]);
+ set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
+ }
+ err |= __get_user(current->thread.fpu.fcsr, csr);
+ err |= __get_user(current->thread.fpu.fcc, fcc);
+
+ return err;
+}
+
+/*
+ * Wrappers for the assembly _{save,restore}_fp_context functions.
+ */
+static int save_hw_fp_context(void __user *sc)
+{
+ struct loongarch_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint64_t __user *fcc = sc + abi->off_sc_fcc;
+ uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
+
+ return _save_fp_context(fpregs, fcc, fcsr);
+}
+
+static int restore_hw_fp_context(void __user *sc)
+{
+ struct loongarch_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint64_t __user *fcc = sc + abi->off_sc_fcc;
+ uint32_t __user *csr = sc + abi->off_sc_fcsr;
+
+ return _restore_fp_context(fpregs, fcc, csr);
+}
+
+/*
+ * Helper routines
+ */
+static int protected_save_fp_context(void __user *sc)
+{
+ int err = 0;
+ unsigned int used;
+ struct loongarch_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *fcc = sc + abi->off_sc_fcsr;
+ uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
+ uint32_t __user *vcsr = sc + abi->off_sc_vcsr;
+ uint32_t __user *flags = sc + abi->off_sc_flags;
+
+ used = used_math() ? USED_FP : 0;
+ if (!used)
+ goto fp_done;
+
+ while (1) {
+ lock_fpu_owner();
+ if (is_fpu_owner())
+ err = save_fp_context(sc);
+ else
+ err |= copy_fp_to_sigcontext(sc);
+ unlock_fpu_owner();
+ if (likely(!err))
+ break;
+ /* touch the sigcontext and try again */
+ err = __put_user(0, &fpregs[0]) |
+ __put_user(0, &fpregs[32*4 - 1]) |
+ __put_user(0, fcc) |
+ __put_user(0, fcsr) |
+ __put_user(0, vcsr);
+ if (err)
+ return err; /* really bad sigcontext */
+ }
+
+fp_done:
+ return __put_user(used, flags);
+}
+
+static int protected_restore_fp_context(void __user *sc)
+{
+ unsigned int used;
+ int err = 0, sig = 0, tmp __maybe_unused;
+ struct loongarch_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
+ uint32_t __user *fcc = sc + abi->off_sc_fcsr;
+ uint32_t __user *vcsr = sc + abi->off_sc_vcsr;
+ uint32_t __user *flags = sc + abi->off_sc_flags;
+
+ err = __get_user(used, flags);
+ conditional_used_math(used & USED_FP);
+
+ /*
+ * The signal handler may have used FPU; give it up if the program
+ * doesn't want it following sigreturn.
+ */
+ if (err || !(used & USED_FP))
+ lose_fpu(0);
+
+ if (err)
+ return err;
+
+ if (!(used & USED_FP))
+ goto fp_done;
+
+ err = sig = fpcsr_pending(fcsr);
+ if (err < 0)
+ return err;
+
+ while (1) {
+ lock_fpu_owner();
+ if (is_fpu_owner())
+ err = restore_fp_context(sc);
+ else
+ err |= copy_fp_from_sigcontext(sc);
+ unlock_fpu_owner();
+ if (likely(!err))
+ break;
+ /* touch the sigcontext and try again */
+ err = __get_user(tmp, &fpregs[0]) |
+ __get_user(tmp, &fpregs[32*4 - 1]) |
+ __get_user(tmp, fcc) |
+ __get_user(tmp, fcsr) |
+ __get_user(tmp, vcsr);
+ if (err)
+ break; /* really bad sigcontext */
+ }
+
+fp_done:
+ return err ?: sig;
+}
+
+static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ int err = 0;
+ int i;
+
+ err |= __put_user(regs->csr_epc, &sc->sc_pc);
+
+ err |= __put_user(0, &sc->sc_regs[0]);
+ for (i = 1; i < 32; i++)
+ err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
+
+ /*
+ * Save FPU state to signal context. Signal handler
+ * will "inherit" current FPU state.
+ */
+ err |= protected_save_fp_context(sc);
+
+ return err;
+}
+
+int fpcsr_pending(unsigned int __user *fpcsr)
+{
+ int err, sig = 0;
+ unsigned int csr, enabled;
+
+ err = __get_user(csr, fpcsr);
+ enabled = ((csr & FPU_CSR_ALL_E) << 24);
+ /*
+ * If the signal handler set some FPU exceptions, clear it and
+ * send SIGFPE.
+ */
+ if (csr & enabled) {
+ csr &= ~enabled;
+ err |= __put_user(csr, fpcsr);
+ sig = SIGFPE;
+ }
+ return err ?: sig;
+}
+
+static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ int err = 0;
+ int i;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current->restart_block.fn = do_no_restart_syscall;
+
+ err |= __get_user(regs->csr_epc, &sc->sc_pc);
+
+ for (i = 1; i < 32; i++)
+ err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
+
+ return err ?: protected_restore_fp_context(sc);
+}
+
+void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long sp;
+
+ /* Default to using normal stack */
+ sp = regs->regs[3];
+ sp -= 32; /* Reserve 32-bytes. */
+
+ sp = sigsp(sp, ksig);
+
+ return (void __user *)((sp - frame_size) & ALMASK);
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+asmlinkage long sys_rt_sigreturn(void)
+{
+ struct rt_sigframe __user *frame;
+ struct pt_regs *regs;
+ sigset_t set;
+ int sig;
+
+ regs = current_pt_regs();
+ frame = (struct rt_sigframe __user *)regs->regs[3];
+ if (!access_ok(frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->rs_uctx.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ set_current_blocked(&set);
+
+ sig = restore_sigcontext(regs, &frame->rs_uctx.uc_mcontext);
+ if (sig < 0)
+ goto badframe;
+ else if (sig)
+ force_sig(sig);
+
+ if (restore_altstack(&frame->rs_uctx.uc_stack))
+ goto badframe;
+
+ return regs->regs[4];
+
+badframe:
+ force_sig(SIGSEGV);
+ return 0;
+}
+
+static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
+{
+ struct rt_sigframe __user *frame;
+ int err = 0;
+
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
+ if (!access_ok(frame, sizeof(*frame)))
+ return -EFAULT;
+
+ /* Create siginfo. */
+ err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->rs_uctx.uc_flags);
+ err |= __put_user(NULL, &frame->rs_uctx.uc_link);
+ err |= __save_altstack(&frame->rs_uctx.uc_stack, regs->regs[3]);
+ err |= setup_sigcontext(regs, &frame->rs_uctx.uc_mcontext);
+ err |= __copy_to_user(&frame->rs_uctx.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ return -EFAULT;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to ucontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to
+ * the struct rt_sigframe.
+ */
+ regs->regs[4] = ksig->sig;
+ regs->regs[5] = (unsigned long) &frame->rs_info;
+ regs->regs[6] = (unsigned long) &frame->rs_uctx;
+ regs->regs[3] = (unsigned long) frame;
+ regs->regs[1] = (unsigned long) sig_return;
+ regs->csr_epc = (unsigned long) ksig->ka.sa.sa_handler;
+
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
+ current->comm, current->pid,
+ frame, regs->csr_epc, regs->regs[1]);
+
+ return 0;
+}
+
+struct loongarch_abi loongarch_abi = {
+ .restart = __NR_restart_syscall,
+#ifdef CONFIG_32BIT
+ .audit_arch = AUDIT_ARCH_LOONGARCH32,
+#else
+ .audit_arch = AUDIT_ARCH_LOONGARCH64,
+#endif
+
+ .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
+ .off_sc_fcc = offsetof(struct sigcontext, sc_fcc),
+ .off_sc_fcsr = offsetof(struct sigcontext, sc_fcsr),
+ .off_sc_vcsr = offsetof(struct sigcontext, sc_vcsr),
+ .off_sc_flags = offsetof(struct sigcontext, sc_flags),
+
+ .vdso = &vdso_info,
+};
+
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
+{
+ int ret;
+ sigset_t *oldset = sigmask_to_save();
+ struct loongarch_abi *abi = current->thread.abi;
+ void *vdso = current->mm->context.vdso;
+
+ /* Are we from a system call? */
+ if (regs->regs[0]) {
+ switch (regs->regs[4]) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ regs->regs[4] = -EINTR;
+ break;
+ case -ERESTARTSYS:
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
+ regs->regs[4] = -EINTR;
+ break;
+ }
+ fallthrough;
+ case -ERESTARTNOINTR:
+ regs->regs[4] = regs->orig_a0;
+ regs->csr_epc -= 4;
+ }
+
+ regs->regs[0] = 0; /* Don't deal with this again. */
+ }
+
+ rseq_signal_deliver(ksig, regs);
+
+ ret = setup_rt_frame(vdso + abi->vdso->offset_sigreturn, ksig, regs, oldset);
+
+ signal_setup_done(ret, ksig, 0);
+}
+
+void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
+{
+ struct ksignal ksig;
+
+ if (has_signal && get_signal(&ksig)) {
+ /* Whee! Actually deliver the signal. */
+ handle_signal(&ksig, regs);
+ return;
+ }
+
+ /* Are we from a system call? */
+ if (regs->regs[0]) {
+ switch (regs->regs[4]) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->regs[4] = regs->orig_a0;
+ regs->csr_epc -= 4;
+ break;
+
+ case -ERESTART_RESTARTBLOCK:
+ regs->regs[4] = regs->orig_a0;
+ regs->regs[11] = current->thread.abi->restart;
+ regs->csr_epc -= 4;
+ break;
+ }
+ regs->regs[0] = 0; /* Don't deal with this again. */
+ }
+
+ /*
+ * If there's no signal to deliver, we just put the saved sigmask
+ * back
+ */
+ restore_saved_sigmask();
+}
+
+static int signal_setup(void)
+{
+ if (cpu_has_fpu) {
+ save_fp_context = save_hw_fp_context;
+ restore_fp_context = restore_hw_fp_context;
+ } else {
+ save_fp_context = copy_fp_to_sigcontext;
+ restore_fp_context = copy_fp_from_sigcontext;
+ }
+
+ return 0;
+}
+
+arch_initcall(signal_setup);
--
2.27.0

2021-09-17 17:08:58

by Huacai Chen

[permalink] [raw]
Subject: [PATCH V3 18/22] LoongArch: Add PCI controller support

Loongson64 based systems are PC-like systems which use PCI/PCIe as its
I/O bus, This patch adds the PCI host controller support for LoongArch.

Signed-off-by: Jianmin Lv <[email protected]>
Signed-off-by: Huacai Chen <[email protected]>
---
arch/loongarch/include/asm/dma.h | 13 +++
arch/loongarch/include/asm/pci.h | 40 ++++++++
arch/loongarch/pci/acpi.c | 171 +++++++++++++++++++++++++++++++
arch/loongarch/pci/pci.c | 96 +++++++++++++++++
4 files changed, 320 insertions(+)
create mode 100644 arch/loongarch/include/asm/dma.h
create mode 100644 arch/loongarch/include/asm/pci.h
create mode 100644 arch/loongarch/pci/acpi.c
create mode 100644 arch/loongarch/pci/pci.c

diff --git a/arch/loongarch/include/asm/dma.h b/arch/loongarch/include/asm/dma.h
new file mode 100644
index 000000000000..a8a58dc93422
--- /dev/null
+++ b/arch/loongarch/include/asm/dma.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ */
+#ifndef __ASM_DMA_H
+#define __ASM_DMA_H
+
+#define MAX_DMA_ADDRESS PAGE_OFFSET
+#define MAX_DMA32_PFN (1UL << (32 - PAGE_SHIFT))
+
+extern int isa_dma_bridge_buggy;
+
+#endif
diff --git a/arch/loongarch/include/asm/pci.h b/arch/loongarch/include/asm/pci.h
new file mode 100644
index 000000000000..c5e5d14546f8
--- /dev/null
+++ b/arch/loongarch/include/asm/pci.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ */
+#ifndef _ASM_PCI_H
+#define _ASM_PCI_H
+
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#define PCIBIOS_MIN_IO 0x4000
+#define PCIBIOS_MIN_MEM 0x20000000
+#define PCIBIOS_MIN_CARDBUS_IO 0x4000
+
+#define HAVE_PCI_MMAP
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
+
+extern phys_addr_t mcfg_addr_init(int node);
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+ return 1; /* always show the domain in /proc */
+}
+
+/*
+ * Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader
+ */
+static inline unsigned int pcibios_assign_all_busses(void)
+{
+ return 0;
+}
+
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
+#endif /* _ASM_PCI_H */
diff --git a/arch/loongarch/pci/acpi.c b/arch/loongarch/pci/acpi.c
new file mode 100644
index 000000000000..dc8bc185dcad
--- /dev/null
+++ b/arch/loongarch/pci/acpi.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ */
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/pci-acpi.h>
+#include <linux/pci-ecam.h>
+
+#include <asm/pci.h>
+#include <asm/loongson.h>
+
+struct pci_root_info {
+ struct acpi_pci_root_info common;
+ struct pci_config_window *cfg;
+};
+
+void pcibios_add_bus(struct pci_bus *bus)
+{
+ acpi_pci_add_bus(bus);
+}
+
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+ struct pci_config_window *cfg = bridge->bus->sysdata;
+ struct acpi_device *adev = to_acpi_device(cfg->parent);
+
+ ACPI_COMPANION_SET(&bridge->dev, adev);
+
+ return 0;
+}
+
+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
+{
+ struct pci_config_window *cfg = bus->sysdata;
+ struct acpi_device *adev = to_acpi_device(cfg->parent);
+ struct acpi_pci_root *root = acpi_driver_data(adev);
+
+ return root->segment;
+}
+
+static void acpi_release_root_info(struct acpi_pci_root_info *ci)
+{
+ struct pci_root_info *info;
+
+ info = container_of(ci, struct pci_root_info, common);
+ pci_ecam_free(info->cfg);
+ kfree(ci->ops);
+ kfree(info);
+}
+
+static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
+{
+ struct acpi_device *device = ci->bridge;
+ struct resource_entry *entry, *tmp;
+ int status;
+
+ status = acpi_pci_probe_root_resources(ci);
+ if (status > 0)
+ return status;
+
+ resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
+ dev_dbg(&device->dev,
+ "host bridge window %pR (ignored)\n", entry->res);
+ resource_list_destroy_entry(entry);
+ }
+
+ return 0;
+}
+
+/*
+ * Lookup the bus range for the domain in MCFG, and set up config space
+ * mapping.
+ */
+static struct pci_config_window *
+pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
+{
+ int ret;
+ u16 seg = root->segment;
+ struct device *dev = &root->device->dev;
+ struct resource cfgres;
+ struct resource *bus_res = &root->secondary;
+ struct pci_config_window *cfg;
+ const struct pci_ecam_ops *ecam_ops;
+
+ ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops);
+ if (ret) {
+ dev_err(dev, "%04x:%pR ECAM region not found, use default value\n", seg, bus_res);
+ root->mcfg_addr = mcfg_addr_init(0);
+ ecam_ops = &loongson_pci_ecam_ops;
+ }
+
+ cfgres.start = root->mcfg_addr + (bus_res->start << ecam_ops->bus_shift);
+ cfgres.end = cfgres.start + (resource_size(bus_res) << ecam_ops->bus_shift) - 1;
+ cfgres.flags = IORESOURCE_MEM;
+
+ cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops);
+ if (IS_ERR(cfg)) {
+ dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res,
+ PTR_ERR(cfg));
+ return NULL;
+ }
+
+ return cfg;
+}
+
+struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
+{
+ struct pci_bus *bus;
+ struct pci_root_info *info;
+ struct acpi_pci_root_ops *root_ops;
+ int domain = root->segment;
+ int busnum = root->secondary.start;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ pr_warn("pci_bus %04x:%02x: ignored (out of memory)\n", domain, busnum);
+ return NULL;
+ }
+
+ root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL);
+ if (!root_ops) {
+ kfree(info);
+ return NULL;
+ }
+
+ info->cfg = pci_acpi_setup_ecam_mapping(root);
+ if (!info->cfg) {
+ kfree(info);
+ kfree(root_ops);
+ return NULL;
+ }
+
+ root_ops->release_info = acpi_release_root_info;
+ root_ops->prepare_resources = acpi_prepare_root_resources;
+ root_ops->pci_ops = (struct pci_ops *)&info->cfg->ops->pci_ops;
+
+ bus = pci_find_bus(domain, busnum);
+ if (bus) {
+ memcpy(bus->sysdata, info->cfg, sizeof(struct pci_config_window));
+ kfree(info);
+ } else {
+ bus = acpi_pci_root_create(root, root_ops,
+ &info->common, info->cfg);
+ if (bus) {
+ /*
+ * We insert PCI resources into the iomem_resource
+ * and ioport_resource trees in either
+ * pci_bus_claim_resources() or
+ * pci_bus_assign_resources().
+ */
+ if (pci_has_flag(PCI_PROBE_ONLY)) {
+ pci_bus_claim_resources(bus);
+ } else {
+ struct pci_bus *child;
+
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
+ }
+ } else {
+ kfree(info);
+ }
+ }
+
+ return bus;
+}
diff --git a/arch/loongarch/pci/pci.c b/arch/loongarch/pci/pci.c
new file mode 100644
index 000000000000..0e074ba8c189
--- /dev/null
+++ b/arch/loongarch/pci/pci.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
+ */
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/vgaarb.h>
+#include <asm/loongson.h>
+
+#define PCI_DEVICE_ID_LOONGSON_HOST 0x7a00
+#define PCI_DEVICE_ID_LOONGSON_DC 0x7a06
+
+int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *val)
+{
+ struct pci_bus *bus_tmp = pci_find_bus(domain, bus);
+
+ if (bus_tmp)
+ return bus_tmp->ops->read(bus_tmp, devfn, reg, len, val);
+ return -EINVAL;
+}
+
+int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 val)
+{
+ struct pci_bus *bus_tmp = pci_find_bus(domain, bus);
+
+ if (bus_tmp)
+ return bus_tmp->ops->write(bus_tmp, devfn, reg, len, val);
+ return -EINVAL;
+}
+
+phys_addr_t mcfg_addr_init(int node)
+{
+ return (((u64)node << 44) | MCFG_EXT_PCICFG_BASE);
+}
+
+static int __init pcibios_init(void)
+{
+ unsigned int lsize;
+
+ /*
+ * Set PCI cacheline size to that of the highest level in the
+ * cache hierarchy.
+ */
+ lsize = cpu_dcache_line_size();
+ lsize = cpu_vcache_line_size() ? : lsize;
+ lsize = cpu_scache_line_size() ? : lsize;
+
+ BUG_ON(!lsize);
+
+ pci_dfl_cache_line_size = lsize >> 2;
+
+ pr_debug("PCI: pci_cache_line_size set to %d bytes\n", lsize);
+
+ return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+int pcibios_add_device(struct pci_dev *dev)
+{
+ int id = pci_domain_nr(dev->bus);
+
+ dev_set_msi_domain(&dev->dev, pch_msi_domain[id]);
+
+ return 0;
+}
+
+int pcibios_alloc_irq(struct pci_dev *dev)
+{
+ if (acpi_disabled)
+ return 0;
+ if (pci_dev_msi_enabled(dev))
+ return 0;
+ return acpi_pci_irq_enable(dev);
+}
+
+static void pci_fixup_vgadev(struct pci_dev *pdev)
+{
+ struct pci_dev *devp = NULL;
+
+ while ((devp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, devp))) {
+ if (devp->vendor != PCI_VENDOR_ID_LOONGSON) {
+ vga_set_default_device(devp);
+ dev_info(&pdev->dev,
+ "Overriding boot device as %X:%X\n",
+ devp->vendor, devp->device);
+ }
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC, pci_fixup_vgadev);
--
2.27.0

2021-09-18 04:54:18

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH V3 14/22] LoongArch: Add signal handling support

Huacai Chen <[email protected]> writes:

> This patch adds signal handling support for LoongArch.

My overall impression is that it looks like this code has a lot of
boilerplate code copied from mips that mips needs because of it's
long history, but that a fresh architecture should not need.

For example does LoongArch have a version without built in floating
point support?

To the best of my knowledge it has been decades since anyone built
a cpu capable of running Linux that doesn't have built in floating point
support.

Similarly this includes code for parameterize some of the userspace ABI.
Since you only have a single userspace ABI there should not need to be
any parameters. So removing the unnecessary parameters should simplify
the code.

I have a few more comments inline along the same lines.

Eric

> Signed-off-by: Huacai Chen <[email protected]>
> ---
> arch/loongarch/include/asm/abi.h | 27 ++
> arch/loongarch/include/uapi/asm/sigcontext.h | 40 ++
> arch/loongarch/include/uapi/asm/ucontext.h | 35 ++
> arch/loongarch/kernel/signal-common.h | 38 ++
> arch/loongarch/kernel/signal.c | 467 +++++++++++++++++++
> 5 files changed, 607 insertions(+)
> create mode 100644 arch/loongarch/include/asm/abi.h
> create mode 100644 arch/loongarch/include/uapi/asm/sigcontext.h
> create mode 100644 arch/loongarch/include/uapi/asm/ucontext.h
> create mode 100644 arch/loongarch/kernel/signal-common.h
> create mode 100644 arch/loongarch/kernel/signal.c
>
> diff --git a/arch/loongarch/include/asm/abi.h b/arch/loongarch/include/asm/abi.h
> new file mode 100644
> index 000000000000..ced8534db4df
> --- /dev/null
> +++ b/arch/loongarch/include/asm/abi.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> + */
> +#ifndef _ASM_ABI_H
> +#define _ASM_ABI_H
> +
> +#include <linux/signal_types.h>
> +
> +#include <asm/signal.h>
> +#include <asm/siginfo.h>
> +#include <asm/vdso.h>
> +
> +struct loongarch_abi {
> + const unsigned long restart;
> + const int audit_arch;
> +
> + unsigned int off_sc_fpregs;
> + unsigned int off_sc_fcc;
> + unsigned int off_sc_fcsr;
> + unsigned int off_sc_vcsr;
> + unsigned int off_sc_flags;
> +
> + struct loongarch_vdso_info *vdso;
> +};

This header file is confusing. It says ABI but it isn't under the uapi
tree. On mips with decades of history and a nabi, oabi, etc, the
similar header file which includes function pointers makes a smidgen of
sense.

Since you aren't mips and your architecture is new you should be able to
have a single userspace ABI and hard code everything. At least to get
started with.

That should make for simpler code as well.

> +
> +#endif /* _ASM_ABI_H */
> diff --git a/arch/loongarch/include/uapi/asm/sigcontext.h b/arch/loongarch/include/uapi/asm/sigcontext.h
> new file mode 100644
> index 000000000000..da0e5bac2d80
> --- /dev/null
> +++ b/arch/loongarch/include/uapi/asm/sigcontext.h
> @@ -0,0 +1,40 @@
> +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
> +/*
> + * Author: Hanlu Li <[email protected]>
> + * Huacai Chen <[email protected]>
> + *
> + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> + */
> +#ifndef _UAPI_ASM_SIGCONTEXT_H
> +#define _UAPI_ASM_SIGCONTEXT_H
> +
> +#include <linux/types.h>
> +#include <asm/processor.h>
> +
> +/* scalar FP context was used */
> +#define USED_FP (1 << 0)
> +
> +/* extended context was used, see struct extcontext for details */
> +#define USED_EXTCONTEXT (1 << 1)
> +
> +#include <linux/posix_types.h>
> +/*
> + * Keep this struct definition in sync with the sigcontext fragment
> + * in arch/loongarch/kernel/asm-offsets.c

If this is uapi this can't change (except for consuming the reserved
fields). Making this comment misleading.

> + *
> + */
> +struct sigcontext {
> + __u64 sc_pc;
> + __u64 sc_regs[32];
> + __u32 sc_flags;
> +
> + __u32 sc_fcsr;
> + __u32 sc_vcsr;

You might want to document the 32bit hole in your structure here.

> + __u64 sc_fcc;
> + __u64 sc_scr[4];
> +
> + union fpureg sc_fpregs[32] FPU_ALIGN;
> + __u8 sc_reserved[4096] __attribute__((__aligned__(16)));
> +};
> +
> +#endif /* _UAPI_ASM_SIGCONTEXT_H */
> diff --git a/arch/loongarch/include/uapi/asm/ucontext.h b/arch/loongarch/include/uapi/asm/ucontext.h
> new file mode 100644
> index 000000000000..12577e22b1c7
> --- /dev/null
> +++ b/arch/loongarch/include/uapi/asm/ucontext.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +#ifndef __LOONGARCH_UAPI_ASM_UCONTEXT_H
> +#define __LOONGARCH_UAPI_ASM_UCONTEXT_H
> +
> +/**
> + * struct ucontext - user context structure
> + * @uc_flags:
> + * @uc_link:
> + * @uc_stack:
> + * @uc_mcontext: holds basic processor state
> + * @uc_sigmask:
> + * @uc_extcontext: holds extended processor state
> + */
> +struct ucontext {
> + unsigned long uc_flags;
> + struct ucontext *uc_link;
> + 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 sigcontext uc_mcontext;
> +};
> +
> +#endif /* __LOONGARCH_UAPI_ASM_UCONTEXT_H */
> diff --git a/arch/loongarch/kernel/signal-common.h b/arch/loongarch/kernel/signal-common.h
> new file mode 100644
> index 000000000000..1693fbdedeaa
> --- /dev/null
> +++ b/arch/loongarch/kernel/signal-common.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Author: Hanlu Li <[email protected]>
> + * Huacai Chen <[email protected]>
> + *
> + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef __SIGNAL_COMMON_H
> +#define __SIGNAL_COMMON_H
> +
> +/* #define DEBUG_SIG */
> +
> +#ifdef DEBUG_SIG
> +# define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
> +#else
> +# define DEBUGP(fmt, args...)
> +#endif

This is only used once in arch/loongarch/kernel/signal.c
so you probably want to keep this define local to that file.

> +/*
> + * Determine which stack to use..
> + */
> +extern void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
> + size_t frame_size);
> +/* Check and clear pending FPU exceptions in saved CSR */
> +extern int fpcsr_pending(unsigned int __user *fpcsr);
> +
> +/* Make sure we will not lose FPU ownership */
> +#define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); })
> +#define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); })
> +
> +/* Assembly functions to move context to/from the FPU */
> +extern asmlinkage int
> +_save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
> +extern asmlinkage int
> +_restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
> +
> +#endif /* __SIGNAL_COMMON_H */
> diff --git a/arch/loongarch/kernel/signal.c b/arch/loongarch/kernel/signal.c
> new file mode 100644
> index 000000000000..78319d2575c6
> --- /dev/null
> +++ b/arch/loongarch/kernel/signal.c
> @@ -0,0 +1,467 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Hanlu Li <[email protected]>
> + * Huacai Chen <[email protected]>
> + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> + *
> + * Derived from MIPS:
> + * Copyright (C) 1991, 1992 Linus Torvalds
> + * Copyright (C) 1994 - 2000 Ralf Baechle
> + * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
> + * Copyright (C) 2014, Imagination Technologies Ltd.
> + */
> +#include <linux/audit.h>
> +#include <linux/cache.h>
> +#include <linux/context_tracking.h>
> +#include <linux/irqflags.h>
> +#include <linux/sched.h>
> +#include <linux/mm.h>
> +#include <linux/personality.h>
> +#include <linux/smp.h>
> +#include <linux/kernel.h>
> +#include <linux/signal.h>
> +#include <linux/errno.h>
> +#include <linux/wait.h>
> +#include <linux/ptrace.h>
> +#include <linux/unistd.h>
> +#include <linux/uprobes.h>
> +#include <linux/compiler.h>
> +#include <linux/syscalls.h>
> +#include <linux/uaccess.h>
> +#include <linux/tracehook.h>
> +
> +#include <asm/abi.h>
> +#include <asm/asm.h>
> +#include <asm/cacheflush.h>
> +#include <asm/fpu.h>
> +#include <asm/ucontext.h>
> +#include <asm/cpu-features.h>
> +
> +#include "signal-common.h"
> +
> +static int (*save_fp_context)(void __user *sc);
> +static int (*restore_fp_context)(void __user *sc);
> +
> +struct rt_sigframe {
> + struct siginfo rs_info;
> + struct ucontext rs_uctx;
> +};
> +
> +/*
> + * Thread saved context copy to/from a signal context presumed to be on the
> + * user stack, and therefore accessed with appropriate macros from uaccess.h.
> + */
> +static int copy_fp_to_sigcontext(void __user *sc)
> +{
> + struct loongarch_abi *abi = current->thread.abi;
> + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> + uint32_t __user *csr = sc + abi->off_sc_fcsr;
> + int i;
> + int err = 0;
> + int inc = 1;
> +
> + for (i = 0; i < NUM_FPU_REGS; i += inc) {
> + err |=
> + __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
> + &fpregs[4*i]);
> + }
> + err |= __put_user(current->thread.fpu.fcsr, csr);
> + err |= __put_user(current->thread.fpu.fcc, fcc);
> +
> + return err;
> +}
> +
> +static int copy_fp_from_sigcontext(void __user *sc)
> +{
> + struct loongarch_abi *abi = current->thread.abi;
> + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> + uint32_t __user *csr = sc + abi->off_sc_fcsr;
> + int i;
> + int err = 0;
> + int inc = 1;
> + u64 fpr_val;
> +
> + for (i = 0; i < NUM_FPU_REGS; i += inc) {
> + err |= __get_user(fpr_val, &fpregs[4*i]);
> + set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
> + }
> + err |= __get_user(current->thread.fpu.fcsr, csr);
> + err |= __get_user(current->thread.fpu.fcc, fcc);
> +
> + return err;
> +}
> +
> +/*
> + * Wrappers for the assembly _{save,restore}_fp_context functions.
> + */
> +static int save_hw_fp_context(void __user *sc)
> +{
> + struct loongarch_abi *abi = current->thread.abi;
> + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> + uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
> +
> + return _save_fp_context(fpregs, fcc, fcsr);
> +}
> +
> +static int restore_hw_fp_context(void __user *sc)
> +{
> + struct loongarch_abi *abi = current->thread.abi;
> + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> + uint32_t __user *csr = sc + abi->off_sc_fcsr;
> +
> + return _restore_fp_context(fpregs, fcc, csr);
> +}
> +
> +/*
> + * Helper routines
> + */
> +static int protected_save_fp_context(void __user *sc)
> +{
> + int err = 0;
> + unsigned int used;
> + struct loongarch_abi *abi = current->thread.abi;
> + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> + uint32_t __user *fcc = sc + abi->off_sc_fcsr;
> + uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
> + uint32_t __user *vcsr = sc + abi->off_sc_vcsr;
> + uint32_t __user *flags = sc + abi->off_sc_flags;
> +
> + used = used_math() ? USED_FP : 0;
> + if (!used)
> + goto fp_done;
> +
> + while (1) {
> + lock_fpu_owner();
> + if (is_fpu_owner())
> + err = save_fp_context(sc);
> + else
> + err |= copy_fp_to_sigcontext(sc);
> + unlock_fpu_owner();
> + if (likely(!err))
> + break;
> + /* touch the sigcontext and try again */
> + err = __put_user(0, &fpregs[0]) |
> + __put_user(0, &fpregs[32*4 - 1]) |
> + __put_user(0, fcc) |
> + __put_user(0, fcsr) |
> + __put_user(0, vcsr);
> + if (err)
> + return err; /* really bad sigcontext */
> + }
> +
> +fp_done:
> + return __put_user(used, flags);
> +}
> +
> +static int protected_restore_fp_context(void __user *sc)
> +{
> + unsigned int used;
> + int err = 0, sig = 0, tmp __maybe_unused;
> + struct loongarch_abi *abi = current->thread.abi;
> + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> + uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
> + uint32_t __user *fcc = sc + abi->off_sc_fcsr;
> + uint32_t __user *vcsr = sc + abi->off_sc_vcsr;
> + uint32_t __user *flags = sc + abi->off_sc_flags;
> +
> + err = __get_user(used, flags);
> + conditional_used_math(used & USED_FP);
> +
> + /*
> + * The signal handler may have used FPU; give it up if the program
> + * doesn't want it following sigreturn.
> + */
> + if (err || !(used & USED_FP))
> + lose_fpu(0);
> +
> + if (err)
> + return err;
> +
> + if (!(used & USED_FP))
> + goto fp_done;
> +
> + err = sig = fpcsr_pending(fcsr);
> + if (err < 0)
> + return err;
> +
> + while (1) {
> + lock_fpu_owner();
> + if (is_fpu_owner())
> + err = restore_fp_context(sc);
> + else
> + err |= copy_fp_from_sigcontext(sc);
> + unlock_fpu_owner();
> + if (likely(!err))
> + break;
> + /* touch the sigcontext and try again */
> + err = __get_user(tmp, &fpregs[0]) |
> + __get_user(tmp, &fpregs[32*4 - 1]) |
> + __get_user(tmp, fcc) |
> + __get_user(tmp, fcsr) |
> + __get_user(tmp, vcsr);
> + if (err)
> + break; /* really bad sigcontext */
> + }
> +
> +fp_done:
> + return err ?: sig;
> +}
> +
> +static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
> +{
> + int err = 0;
> + int i;
> +
> + err |= __put_user(regs->csr_epc, &sc->sc_pc);
> +
> + err |= __put_user(0, &sc->sc_regs[0]);
> + for (i = 1; i < 32; i++)
> + err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
> +
> + /*
> + * Save FPU state to signal context. Signal handler
> + * will "inherit" current FPU state.
> + */
> + err |= protected_save_fp_context(sc);
> +
> + return err;
> +}
> +
> +int fpcsr_pending(unsigned int __user *fpcsr)
> +{
> + int err, sig = 0;
> + unsigned int csr, enabled;
> +
> + err = __get_user(csr, fpcsr);
> + enabled = ((csr & FPU_CSR_ALL_E) << 24);
> + /*
> + * If the signal handler set some FPU exceptions, clear it and
> + * send SIGFPE.
> + */
> + if (csr & enabled) {
> + csr &= ~enabled;
> + err |= __put_user(csr, fpcsr);
> + sig = SIGFPE;
> + }
> + return err ?: sig;
> +}
> +
> +static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
> +{
> + int err = 0;
> + int i;
> +
> + /* Always make any pending restarted system calls return -EINTR */
> + current->restart_block.fn = do_no_restart_syscall;
> +
> + err |= __get_user(regs->csr_epc, &sc->sc_pc);
> +
> + for (i = 1; i < 32; i++)
> + err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
> +
> + return err ?: protected_restore_fp_context(sc);
> +}
> +
> +void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
> + size_t frame_size)
> +{
> + unsigned long sp;
> +
> + /* Default to using normal stack */
> + sp = regs->regs[3];
> + sp -= 32; /* Reserve 32-bytes. */
> +
> + sp = sigsp(sp, ksig);
> +
> + return (void __user *)((sp - frame_size) & ALMASK);
> +}
> +
> +/*
> + * Atomically swap in the new signal mask, and wait for a signal.
> + */
> +
> +asmlinkage long sys_rt_sigreturn(void)
> +{
> + struct rt_sigframe __user *frame;
> + struct pt_regs *regs;
> + sigset_t set;
> + int sig;
> +
> + regs = current_pt_regs();
> + frame = (struct rt_sigframe __user *)regs->regs[3];
> + if (!access_ok(frame, sizeof(*frame)))
> + goto badframe;
> + if (__copy_from_user(&set, &frame->rs_uctx.uc_sigmask, sizeof(set)))
> + goto badframe;
> +
> + set_current_blocked(&set);
> +
> + sig = restore_sigcontext(regs, &frame->rs_uctx.uc_mcontext);
> + if (sig < 0)
> + goto badframe;
> + else if (sig)
> + force_sig(sig);
> +
> + if (restore_altstack(&frame->rs_uctx.uc_stack))
> + goto badframe;
> +
> + return regs->regs[4];
> +
> +badframe:
> + force_sig(SIGSEGV);
> + return 0;
> +}
> +
> +static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
> + struct pt_regs *regs, sigset_t *set)
> +{
> + struct rt_sigframe __user *frame;
> + int err = 0;
> +
> + frame = get_sigframe(ksig, regs, sizeof(*frame));
> + if (!access_ok(frame, sizeof(*frame)))
> + return -EFAULT;
> +
> + /* Create siginfo. */
> + err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
> +
> + /* Create the ucontext. */
> + err |= __put_user(0, &frame->rs_uctx.uc_flags);
> + err |= __put_user(NULL, &frame->rs_uctx.uc_link);
> + err |= __save_altstack(&frame->rs_uctx.uc_stack, regs->regs[3]);
> + err |= setup_sigcontext(regs, &frame->rs_uctx.uc_mcontext);
> + err |= __copy_to_user(&frame->rs_uctx.uc_sigmask, set, sizeof(*set));
> +
> + if (err)
> + return -EFAULT;
> +
> + /*
> + * Arguments to signal handler:
> + *
> + * a0 = signal number
> + * a1 = 0 (should be cause)
> + * a2 = pointer to ucontext
> + *
> + * $25 and c0_epc point to the signal handler, $29 points to
> + * the struct rt_sigframe.
> + */
> + regs->regs[4] = ksig->sig;
> + regs->regs[5] = (unsigned long) &frame->rs_info;
> + regs->regs[6] = (unsigned long) &frame->rs_uctx;
> + regs->regs[3] = (unsigned long) frame;
> + regs->regs[1] = (unsigned long) sig_return;
> + regs->csr_epc = (unsigned long) ksig->ka.sa.sa_handler;
> +
> + DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
> + current->comm, current->pid,
> + frame, regs->csr_epc, regs->regs[1]);
> +
> + return 0;
> +}
> +
> +struct loongarch_abi loongarch_abi = {
> + .restart = __NR_restart_syscall,
> +#ifdef CONFIG_32BIT
> + .audit_arch = AUDIT_ARCH_LOONGARCH32,
> +#else
> + .audit_arch = AUDIT_ARCH_LOONGARCH64,
> +#endif
> +
> + .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
> + .off_sc_fcc = offsetof(struct sigcontext, sc_fcc),
> + .off_sc_fcsr = offsetof(struct sigcontext, sc_fcsr),
> + .off_sc_vcsr = offsetof(struct sigcontext, sc_vcsr),
> + .off_sc_flags = offsetof(struct sigcontext, sc_flags),
> +
> + .vdso = &vdso_info,
> +};
> +
> +static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
> +{
> + int ret;
> + sigset_t *oldset = sigmask_to_save();
> + struct loongarch_abi *abi = current->thread.abi;
> + void *vdso = current->mm->context.vdso;
> +
> + /* Are we from a system call? */
> + if (regs->regs[0]) {
> + switch (regs->regs[4]) {
> + case -ERESTART_RESTARTBLOCK:
> + case -ERESTARTNOHAND:
> + regs->regs[4] = -EINTR;
> + break;
> + case -ERESTARTSYS:
> + if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
> + regs->regs[4] = -EINTR;
> + break;
> + }
> + fallthrough;
> + case -ERESTARTNOINTR:
> + regs->regs[4] = regs->orig_a0;
> + regs->csr_epc -= 4;
> + }
> +
> + regs->regs[0] = 0; /* Don't deal with this again. */
> + }
> +
> + rseq_signal_deliver(ksig, regs);
> +
> + ret = setup_rt_frame(vdso + abi->vdso->offset_sigreturn, ksig, regs, oldset);
> +
> + signal_setup_done(ret, ksig, 0);
> +}
> +
> +void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
> +{
> + struct ksignal ksig;
> +
> + if (has_signal && get_signal(&ksig)) {
> + /* Whee! Actually deliver the signal. */
> + handle_signal(&ksig, regs);
> + return;
> + }
> +
> + /* Are we from a system call? */
> + if (regs->regs[0]) {
> + switch (regs->regs[4]) {
> + case -ERESTARTNOHAND:
> + case -ERESTARTSYS:
> + case -ERESTARTNOINTR:
> + regs->regs[4] = regs->orig_a0;
> + regs->csr_epc -= 4;
> + break;
> +
> + case -ERESTART_RESTARTBLOCK:
> + regs->regs[4] = regs->orig_a0;
> + regs->regs[11] = current->thread.abi->restart;
> + regs->csr_epc -= 4;
> + break;
> + }
> + regs->regs[0] = 0; /* Don't deal with this again. */
> + }
> +
> + /*
> + * If there's no signal to deliver, we just put the saved sigmask
> + * back
> + */
> + restore_saved_sigmask();
> +}
> +
> +static int signal_setup(void)
> +{
> + if (cpu_has_fpu) {
> + save_fp_context = save_hw_fp_context;
> + restore_fp_context = restore_hw_fp_context;
> + } else {
> + save_fp_context = copy_fp_to_sigcontext;
> + restore_fp_context = copy_fp_from_sigcontext;
> + }
> +
> + return 0;
> +}
> +
> +arch_initcall(signal_setup);

2021-09-18 16:22:28

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH V3 14/22] LoongArch: Add signal handling support

Hi, Eric,

On Sat, Sep 18, 2021 at 5:10 AM Eric W. Biederman <[email protected]> wrote:
>
> Huacai Chen <[email protected]> writes:
>
> > This patch adds signal handling support for LoongArch.
>
> My overall impression is that it looks like this code has a lot of
> boilerplate code copied from mips that mips needs because of it's
> long history, but that a fresh architecture should not need.
>
> For example does LoongArch have a version without built in floating
> point support?
Some of these structures seems need rethinking, But we really have
LoongArch-based MCUs now (no FP, no SMP, and even no MMU).

>
> To the best of my knowledge it has been decades since anyone built
> a cpu capable of running Linux that doesn't have built in floating point
> support.
>
> Similarly this includes code for parameterize some of the userspace ABI.
> Since you only have a single userspace ABI there should not need to be
> any parameters. So removing the unnecessary parameters should simplify
> the code.
>
> I have a few more comments inline along the same lines.
>
> Eric
>
> > Signed-off-by: Huacai Chen <[email protected]>
> > ---
> > arch/loongarch/include/asm/abi.h | 27 ++
> > arch/loongarch/include/uapi/asm/sigcontext.h | 40 ++
> > arch/loongarch/include/uapi/asm/ucontext.h | 35 ++
> > arch/loongarch/kernel/signal-common.h | 38 ++
> > arch/loongarch/kernel/signal.c | 467 +++++++++++++++++++
> > 5 files changed, 607 insertions(+)
> > create mode 100644 arch/loongarch/include/asm/abi.h
> > create mode 100644 arch/loongarch/include/uapi/asm/sigcontext.h
> > create mode 100644 arch/loongarch/include/uapi/asm/ucontext.h
> > create mode 100644 arch/loongarch/kernel/signal-common.h
> > create mode 100644 arch/loongarch/kernel/signal.c
> >
> > diff --git a/arch/loongarch/include/asm/abi.h b/arch/loongarch/include/asm/abi.h
> > new file mode 100644
> > index 000000000000..ced8534db4df
> > --- /dev/null
> > +++ b/arch/loongarch/include/asm/abi.h
> > @@ -0,0 +1,27 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> > + */
> > +#ifndef _ASM_ABI_H
> > +#define _ASM_ABI_H
> > +
> > +#include <linux/signal_types.h>
> > +
> > +#include <asm/signal.h>
> > +#include <asm/siginfo.h>
> > +#include <asm/vdso.h>
> > +
> > +struct loongarch_abi {
> > + const unsigned long restart;
> > + const int audit_arch;
> > +
> > + unsigned int off_sc_fpregs;
> > + unsigned int off_sc_fcc;
> > + unsigned int off_sc_fcsr;
> > + unsigned int off_sc_vcsr;
> > + unsigned int off_sc_flags;
> > +
> > + struct loongarch_vdso_info *vdso;
> > +};
>
> This header file is confusing. It says ABI but it isn't under the uapi
> tree. On mips with decades of history and a nabi, oabi, etc, the
> similar header file which includes function pointers makes a smidgen of
> sense.
>
> Since you aren't mips and your architecture is new you should be able to
> have a single userspace ABI and hard code everything. At least to get
> started with.
>
> That should make for simpler code as well.
>
> > +
> > +#endif /* _ASM_ABI_H */
> > diff --git a/arch/loongarch/include/uapi/asm/sigcontext.h b/arch/loongarch/include/uapi/asm/sigcontext.h
> > new file mode 100644
> > index 000000000000..da0e5bac2d80
> > --- /dev/null
> > +++ b/arch/loongarch/include/uapi/asm/sigcontext.h
> > @@ -0,0 +1,40 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
> > +/*
> > + * Author: Hanlu Li <[email protected]>
> > + * Huacai Chen <[email protected]>
> > + *
> > + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> > + */
> > +#ifndef _UAPI_ASM_SIGCONTEXT_H
> > +#define _UAPI_ASM_SIGCONTEXT_H
> > +
> > +#include <linux/types.h>
> > +#include <asm/processor.h>
> > +
> > +/* scalar FP context was used */
> > +#define USED_FP (1 << 0)
> > +
> > +/* extended context was used, see struct extcontext for details */
> > +#define USED_EXTCONTEXT (1 << 1)
> > +
> > +#include <linux/posix_types.h>
> > +/*
> > + * Keep this struct definition in sync with the sigcontext fragment
> > + * in arch/loongarch/kernel/asm-offsets.c
>
> If this is uapi this can't change (except for consuming the reserved
> fields). Making this comment misleading.
>
> > + *
> > + */
> > +struct sigcontext {
> > + __u64 sc_pc;
> > + __u64 sc_regs[32];
> > + __u32 sc_flags;
> > +
> > + __u32 sc_fcsr;
> > + __u32 sc_vcsr;
>
> You might want to document the 32bit hole in your structure here.
>
> > + __u64 sc_fcc;
> > + __u64 sc_scr[4];
> > +
> > + union fpureg sc_fpregs[32] FPU_ALIGN;
> > + __u8 sc_reserved[4096] __attribute__((__aligned__(16)));
> > +};
> > +
> > +#endif /* _UAPI_ASM_SIGCONTEXT_H */
> > diff --git a/arch/loongarch/include/uapi/asm/ucontext.h b/arch/loongarch/include/uapi/asm/ucontext.h
> > new file mode 100644
> > index 000000000000..12577e22b1c7
> > --- /dev/null
> > +++ b/arch/loongarch/include/uapi/asm/ucontext.h
> > @@ -0,0 +1,35 @@
> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > +#ifndef __LOONGARCH_UAPI_ASM_UCONTEXT_H
> > +#define __LOONGARCH_UAPI_ASM_UCONTEXT_H
> > +
> > +/**
> > + * struct ucontext - user context structure
> > + * @uc_flags:
> > + * @uc_link:
> > + * @uc_stack:
> > + * @uc_mcontext: holds basic processor state
> > + * @uc_sigmask:
> > + * @uc_extcontext: holds extended processor state
> > + */
> > +struct ucontext {
> > + unsigned long uc_flags;
> > + struct ucontext *uc_link;
> > + 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 sigcontext uc_mcontext;
> > +};
> > +
> > +#endif /* __LOONGARCH_UAPI_ASM_UCONTEXT_H */
> > diff --git a/arch/loongarch/kernel/signal-common.h b/arch/loongarch/kernel/signal-common.h
> > new file mode 100644
> > index 000000000000..1693fbdedeaa
> > --- /dev/null
> > +++ b/arch/loongarch/kernel/signal-common.h
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Author: Hanlu Li <[email protected]>
> > + * Huacai Chen <[email protected]>
> > + *
> > + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> > + */
> > +
> > +#ifndef __SIGNAL_COMMON_H
> > +#define __SIGNAL_COMMON_H
> > +
> > +/* #define DEBUG_SIG */
> > +
> > +#ifdef DEBUG_SIG
> > +# define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
> > +#else
> > +# define DEBUGP(fmt, args...)
> > +#endif
>
> This is only used once in arch/loongarch/kernel/signal.c
> so you probably want to keep this define local to that file.
OK, thanks.

Huacai
>
> > +/*
> > + * Determine which stack to use..
> > + */
> > +extern void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
> > + size_t frame_size);
> > +/* Check and clear pending FPU exceptions in saved CSR */
> > +extern int fpcsr_pending(unsigned int __user *fpcsr);
> > +
> > +/* Make sure we will not lose FPU ownership */
> > +#define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); })
> > +#define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); })
> > +
> > +/* Assembly functions to move context to/from the FPU */
> > +extern asmlinkage int
> > +_save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
> > +extern asmlinkage int
> > +_restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
> > +
> > +#endif /* __SIGNAL_COMMON_H */
> > diff --git a/arch/loongarch/kernel/signal.c b/arch/loongarch/kernel/signal.c
> > new file mode 100644
> > index 000000000000..78319d2575c6
> > --- /dev/null
> > +++ b/arch/loongarch/kernel/signal.c
> > @@ -0,0 +1,467 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Author: Hanlu Li <[email protected]>
> > + * Huacai Chen <[email protected]>
> > + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> > + *
> > + * Derived from MIPS:
> > + * Copyright (C) 1991, 1992 Linus Torvalds
> > + * Copyright (C) 1994 - 2000 Ralf Baechle
> > + * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
> > + * Copyright (C) 2014, Imagination Technologies Ltd.
> > + */
> > +#include <linux/audit.h>
> > +#include <linux/cache.h>
> > +#include <linux/context_tracking.h>
> > +#include <linux/irqflags.h>
> > +#include <linux/sched.h>
> > +#include <linux/mm.h>
> > +#include <linux/personality.h>
> > +#include <linux/smp.h>
> > +#include <linux/kernel.h>
> > +#include <linux/signal.h>
> > +#include <linux/errno.h>
> > +#include <linux/wait.h>
> > +#include <linux/ptrace.h>
> > +#include <linux/unistd.h>
> > +#include <linux/uprobes.h>
> > +#include <linux/compiler.h>
> > +#include <linux/syscalls.h>
> > +#include <linux/uaccess.h>
> > +#include <linux/tracehook.h>
> > +
> > +#include <asm/abi.h>
> > +#include <asm/asm.h>
> > +#include <asm/cacheflush.h>
> > +#include <asm/fpu.h>
> > +#include <asm/ucontext.h>
> > +#include <asm/cpu-features.h>
> > +
> > +#include "signal-common.h"
> > +
> > +static int (*save_fp_context)(void __user *sc);
> > +static int (*restore_fp_context)(void __user *sc);
> > +
> > +struct rt_sigframe {
> > + struct siginfo rs_info;
> > + struct ucontext rs_uctx;
> > +};
> > +
> > +/*
> > + * Thread saved context copy to/from a signal context presumed to be on the
> > + * user stack, and therefore accessed with appropriate macros from uaccess.h.
> > + */
> > +static int copy_fp_to_sigcontext(void __user *sc)
> > +{
> > + struct loongarch_abi *abi = current->thread.abi;
> > + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> > + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> > + uint32_t __user *csr = sc + abi->off_sc_fcsr;
> > + int i;
> > + int err = 0;
> > + int inc = 1;
> > +
> > + for (i = 0; i < NUM_FPU_REGS; i += inc) {
> > + err |=
> > + __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
> > + &fpregs[4*i]);
> > + }
> > + err |= __put_user(current->thread.fpu.fcsr, csr);
> > + err |= __put_user(current->thread.fpu.fcc, fcc);
> > +
> > + return err;
> > +}
> > +
> > +static int copy_fp_from_sigcontext(void __user *sc)
> > +{
> > + struct loongarch_abi *abi = current->thread.abi;
> > + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> > + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> > + uint32_t __user *csr = sc + abi->off_sc_fcsr;
> > + int i;
> > + int err = 0;
> > + int inc = 1;
> > + u64 fpr_val;
> > +
> > + for (i = 0; i < NUM_FPU_REGS; i += inc) {
> > + err |= __get_user(fpr_val, &fpregs[4*i]);
> > + set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
> > + }
> > + err |= __get_user(current->thread.fpu.fcsr, csr);
> > + err |= __get_user(current->thread.fpu.fcc, fcc);
> > +
> > + return err;
> > +}
> > +
> > +/*
> > + * Wrappers for the assembly _{save,restore}_fp_context functions.
> > + */
> > +static int save_hw_fp_context(void __user *sc)
> > +{
> > + struct loongarch_abi *abi = current->thread.abi;
> > + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> > + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> > + uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
> > +
> > + return _save_fp_context(fpregs, fcc, fcsr);
> > +}
> > +
> > +static int restore_hw_fp_context(void __user *sc)
> > +{
> > + struct loongarch_abi *abi = current->thread.abi;
> > + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> > + uint64_t __user *fcc = sc + abi->off_sc_fcc;
> > + uint32_t __user *csr = sc + abi->off_sc_fcsr;
> > +
> > + return _restore_fp_context(fpregs, fcc, csr);
> > +}
> > +
> > +/*
> > + * Helper routines
> > + */
> > +static int protected_save_fp_context(void __user *sc)
> > +{
> > + int err = 0;
> > + unsigned int used;
> > + struct loongarch_abi *abi = current->thread.abi;
> > + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> > + uint32_t __user *fcc = sc + abi->off_sc_fcsr;
> > + uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
> > + uint32_t __user *vcsr = sc + abi->off_sc_vcsr;
> > + uint32_t __user *flags = sc + abi->off_sc_flags;
> > +
> > + used = used_math() ? USED_FP : 0;
> > + if (!used)
> > + goto fp_done;
> > +
> > + while (1) {
> > + lock_fpu_owner();
> > + if (is_fpu_owner())
> > + err = save_fp_context(sc);
> > + else
> > + err |= copy_fp_to_sigcontext(sc);
> > + unlock_fpu_owner();
> > + if (likely(!err))
> > + break;
> > + /* touch the sigcontext and try again */
> > + err = __put_user(0, &fpregs[0]) |
> > + __put_user(0, &fpregs[32*4 - 1]) |
> > + __put_user(0, fcc) |
> > + __put_user(0, fcsr) |
> > + __put_user(0, vcsr);
> > + if (err)
> > + return err; /* really bad sigcontext */
> > + }
> > +
> > +fp_done:
> > + return __put_user(used, flags);
> > +}
> > +
> > +static int protected_restore_fp_context(void __user *sc)
> > +{
> > + unsigned int used;
> > + int err = 0, sig = 0, tmp __maybe_unused;
> > + struct loongarch_abi *abi = current->thread.abi;
> > + uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
> > + uint32_t __user *fcsr = sc + abi->off_sc_fcsr;
> > + uint32_t __user *fcc = sc + abi->off_sc_fcsr;
> > + uint32_t __user *vcsr = sc + abi->off_sc_vcsr;
> > + uint32_t __user *flags = sc + abi->off_sc_flags;
> > +
> > + err = __get_user(used, flags);
> > + conditional_used_math(used & USED_FP);
> > +
> > + /*
> > + * The signal handler may have used FPU; give it up if the program
> > + * doesn't want it following sigreturn.
> > + */
> > + if (err || !(used & USED_FP))
> > + lose_fpu(0);
> > +
> > + if (err)
> > + return err;
> > +
> > + if (!(used & USED_FP))
> > + goto fp_done;
> > +
> > + err = sig = fpcsr_pending(fcsr);
> > + if (err < 0)
> > + return err;
> > +
> > + while (1) {
> > + lock_fpu_owner();
> > + if (is_fpu_owner())
> > + err = restore_fp_context(sc);
> > + else
> > + err |= copy_fp_from_sigcontext(sc);
> > + unlock_fpu_owner();
> > + if (likely(!err))
> > + break;
> > + /* touch the sigcontext and try again */
> > + err = __get_user(tmp, &fpregs[0]) |
> > + __get_user(tmp, &fpregs[32*4 - 1]) |
> > + __get_user(tmp, fcc) |
> > + __get_user(tmp, fcsr) |
> > + __get_user(tmp, vcsr);
> > + if (err)
> > + break; /* really bad sigcontext */
> > + }
> > +
> > +fp_done:
> > + return err ?: sig;
> > +}
> > +
> > +static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
> > +{
> > + int err = 0;
> > + int i;
> > +
> > + err |= __put_user(regs->csr_epc, &sc->sc_pc);
> > +
> > + err |= __put_user(0, &sc->sc_regs[0]);
> > + for (i = 1; i < 32; i++)
> > + err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
> > +
> > + /*
> > + * Save FPU state to signal context. Signal handler
> > + * will "inherit" current FPU state.
> > + */
> > + err |= protected_save_fp_context(sc);
> > +
> > + return err;
> > +}
> > +
> > +int fpcsr_pending(unsigned int __user *fpcsr)
> > +{
> > + int err, sig = 0;
> > + unsigned int csr, enabled;
> > +
> > + err = __get_user(csr, fpcsr);
> > + enabled = ((csr & FPU_CSR_ALL_E) << 24);
> > + /*
> > + * If the signal handler set some FPU exceptions, clear it and
> > + * send SIGFPE.
> > + */
> > + if (csr & enabled) {
> > + csr &= ~enabled;
> > + err |= __put_user(csr, fpcsr);
> > + sig = SIGFPE;
> > + }
> > + return err ?: sig;
> > +}
> > +
> > +static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
> > +{
> > + int err = 0;
> > + int i;
> > +
> > + /* Always make any pending restarted system calls return -EINTR */
> > + current->restart_block.fn = do_no_restart_syscall;
> > +
> > + err |= __get_user(regs->csr_epc, &sc->sc_pc);
> > +
> > + for (i = 1; i < 32; i++)
> > + err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
> > +
> > + return err ?: protected_restore_fp_context(sc);
> > +}
> > +
> > +void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
> > + size_t frame_size)
> > +{
> > + unsigned long sp;
> > +
> > + /* Default to using normal stack */
> > + sp = regs->regs[3];
> > + sp -= 32; /* Reserve 32-bytes. */
> > +
> > + sp = sigsp(sp, ksig);
> > +
> > + return (void __user *)((sp - frame_size) & ALMASK);
> > +}
> > +
> > +/*
> > + * Atomically swap in the new signal mask, and wait for a signal.
> > + */
> > +
> > +asmlinkage long sys_rt_sigreturn(void)
> > +{
> > + struct rt_sigframe __user *frame;
> > + struct pt_regs *regs;
> > + sigset_t set;
> > + int sig;
> > +
> > + regs = current_pt_regs();
> > + frame = (struct rt_sigframe __user *)regs->regs[3];
> > + if (!access_ok(frame, sizeof(*frame)))
> > + goto badframe;
> > + if (__copy_from_user(&set, &frame->rs_uctx.uc_sigmask, sizeof(set)))
> > + goto badframe;
> > +
> > + set_current_blocked(&set);
> > +
> > + sig = restore_sigcontext(regs, &frame->rs_uctx.uc_mcontext);
> > + if (sig < 0)
> > + goto badframe;
> > + else if (sig)
> > + force_sig(sig);
> > +
> > + if (restore_altstack(&frame->rs_uctx.uc_stack))
> > + goto badframe;
> > +
> > + return regs->regs[4];
> > +
> > +badframe:
> > + force_sig(SIGSEGV);
> > + return 0;
> > +}
> > +
> > +static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
> > + struct pt_regs *regs, sigset_t *set)
> > +{
> > + struct rt_sigframe __user *frame;
> > + int err = 0;
> > +
> > + frame = get_sigframe(ksig, regs, sizeof(*frame));
> > + if (!access_ok(frame, sizeof(*frame)))
> > + return -EFAULT;
> > +
> > + /* Create siginfo. */
> > + err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
> > +
> > + /* Create the ucontext. */
> > + err |= __put_user(0, &frame->rs_uctx.uc_flags);
> > + err |= __put_user(NULL, &frame->rs_uctx.uc_link);
> > + err |= __save_altstack(&frame->rs_uctx.uc_stack, regs->regs[3]);
> > + err |= setup_sigcontext(regs, &frame->rs_uctx.uc_mcontext);
> > + err |= __copy_to_user(&frame->rs_uctx.uc_sigmask, set, sizeof(*set));
> > +
> > + if (err)
> > + return -EFAULT;
> > +
> > + /*
> > + * Arguments to signal handler:
> > + *
> > + * a0 = signal number
> > + * a1 = 0 (should be cause)
> > + * a2 = pointer to ucontext
> > + *
> > + * $25 and c0_epc point to the signal handler, $29 points to
> > + * the struct rt_sigframe.
> > + */
> > + regs->regs[4] = ksig->sig;
> > + regs->regs[5] = (unsigned long) &frame->rs_info;
> > + regs->regs[6] = (unsigned long) &frame->rs_uctx;
> > + regs->regs[3] = (unsigned long) frame;
> > + regs->regs[1] = (unsigned long) sig_return;
> > + regs->csr_epc = (unsigned long) ksig->ka.sa.sa_handler;
> > +
> > + DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
> > + current->comm, current->pid,
> > + frame, regs->csr_epc, regs->regs[1]);
> > +
> > + return 0;
> > +}
> > +
> > +struct loongarch_abi loongarch_abi = {
> > + .restart = __NR_restart_syscall,
> > +#ifdef CONFIG_32BIT
> > + .audit_arch = AUDIT_ARCH_LOONGARCH32,
> > +#else
> > + .audit_arch = AUDIT_ARCH_LOONGARCH64,
> > +#endif
> > +
> > + .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
> > + .off_sc_fcc = offsetof(struct sigcontext, sc_fcc),
> > + .off_sc_fcsr = offsetof(struct sigcontext, sc_fcsr),
> > + .off_sc_vcsr = offsetof(struct sigcontext, sc_vcsr),
> > + .off_sc_flags = offsetof(struct sigcontext, sc_flags),
> > +
> > + .vdso = &vdso_info,
> > +};
> > +
> > +static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
> > +{
> > + int ret;
> > + sigset_t *oldset = sigmask_to_save();
> > + struct loongarch_abi *abi = current->thread.abi;
> > + void *vdso = current->mm->context.vdso;
> > +
> > + /* Are we from a system call? */
> > + if (regs->regs[0]) {
> > + switch (regs->regs[4]) {
> > + case -ERESTART_RESTARTBLOCK:
> > + case -ERESTARTNOHAND:
> > + regs->regs[4] = -EINTR;
> > + break;
> > + case -ERESTARTSYS:
> > + if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
> > + regs->regs[4] = -EINTR;
> > + break;
> > + }
> > + fallthrough;
> > + case -ERESTARTNOINTR:
> > + regs->regs[4] = regs->orig_a0;
> > + regs->csr_epc -= 4;
> > + }
> > +
> > + regs->regs[0] = 0; /* Don't deal with this again. */
> > + }
> > +
> > + rseq_signal_deliver(ksig, regs);
> > +
> > + ret = setup_rt_frame(vdso + abi->vdso->offset_sigreturn, ksig, regs, oldset);
> > +
> > + signal_setup_done(ret, ksig, 0);
> > +}
> > +
> > +void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
> > +{
> > + struct ksignal ksig;
> > +
> > + if (has_signal && get_signal(&ksig)) {
> > + /* Whee! Actually deliver the signal. */
> > + handle_signal(&ksig, regs);
> > + return;
> > + }
> > +
> > + /* Are we from a system call? */
> > + if (regs->regs[0]) {
> > + switch (regs->regs[4]) {
> > + case -ERESTARTNOHAND:
> > + case -ERESTARTSYS:
> > + case -ERESTARTNOINTR:
> > + regs->regs[4] = regs->orig_a0;
> > + regs->csr_epc -= 4;
> > + break;
> > +
> > + case -ERESTART_RESTARTBLOCK:
> > + regs->regs[4] = regs->orig_a0;
> > + regs->regs[11] = current->thread.abi->restart;
> > + regs->csr_epc -= 4;
> > + break;
> > + }
> > + regs->regs[0] = 0; /* Don't deal with this again. */
> > + }
> > +
> > + /*
> > + * If there's no signal to deliver, we just put the saved sigmask
> > + * back
> > + */
> > + restore_saved_sigmask();
> > +}
> > +
> > +static int signal_setup(void)
> > +{
> > + if (cpu_has_fpu) {
> > + save_fp_context = save_hw_fp_context;
> > + restore_fp_context = restore_hw_fp_context;
> > + } else {
> > + save_fp_context = copy_fp_to_sigcontext;
> > + restore_fp_context = copy_fp_from_sigcontext;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +arch_initcall(signal_setup);

2021-09-19 13:00:41

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH V3 14/22] LoongArch: Add signal handling support

On Sat, Sep 18, 2021 at 9:12 AM Huacai Chen <[email protected]> wrote:
> On Sat, Sep 18, 2021 at 5:10 AM Eric W. Biederman <[email protected]> wrote:
> > For example does LoongArch have a version without built in floating
> > point support?
>
> Some of these structures seems need rethinking, But we really have
> LoongArch-based MCUs now (no FP, no SMP, and even no MMU).

NOMMU Linux is kind-of on the way out as interest is fading, so I hope you
don't plan on supporting this in the future.

Do you expect to see future products with MMU but no FP or no SMP?

Arnd

2021-09-20 10:32:49

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH V3 14/22] LoongArch: Add signal handling support

Hi, Arnd,

On Sun, Sep 19, 2021 at 5:59 PM Arnd Bergmann <[email protected]> wrote:
>
> On Sat, Sep 18, 2021 at 9:12 AM Huacai Chen <[email protected]> wrote:
> > On Sat, Sep 18, 2021 at 5:10 AM Eric W. Biederman <[email protected]> wrote:
> > > For example does LoongArch have a version without built in floating
> > > point support?
> >
> > Some of these structures seems need rethinking, But we really have
> > LoongArch-based MCUs now (no FP, no SMP, and even no MMU).
>
> NOMMU Linux is kind-of on the way out as interest is fading, so I hope you
> don't plan on supporting this in the future.
>
> Do you expect to see future products with MMU but no FP or no SMP?
OK, we will not care no-MMU hardware in Linux, but no-FP and no-SMP
hardware will be supported.

Huacai
>
> Arnd

2021-09-21 03:57:57

by Richard Henderson

[permalink] [raw]
Subject: Re: [PATCH V3 14/22] LoongArch: Add signal handling support

On 9/19/21 7:36 PM, Huacai Chen wrote:
> Hi, Arnd,
>
> On Sun, Sep 19, 2021 at 5:59 PM Arnd Bergmann <[email protected]> wrote:
>>
>> On Sat, Sep 18, 2021 at 9:12 AM Huacai Chen <[email protected]> wrote:
>>> On Sat, Sep 18, 2021 at 5:10 AM Eric W. Biederman <[email protected]> wrote:
>>>> For example does LoongArch have a version without built in floating
>>>> point support?
>>>
>>> Some of these structures seems need rethinking, But we really have
>>> LoongArch-based MCUs now (no FP, no SMP, and even no MMU).
>>
>> NOMMU Linux is kind-of on the way out as interest is fading, so I hope you
>> don't plan on supporting this in the future.
>>
>> Do you expect to see future products with MMU but no FP or no SMP?
> OK, we will not care no-MMU hardware in Linux, but no-FP and no-SMP
> hardware will be supported.

Please consider requiring the FP registers to be present even on no-FP hardware.

With this plus the FP data movement instructions (FMOV, MOVGR2FR, MOVFR2GR, FLD, FST), it
is possible to implement soft-float without requiring a separate soft-float ABI. This can
vastly simplify compatibility and deployment.


r~

2021-09-22 02:46:19

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH V3 14/22] LoongArch: Add signal handling support

Hi, Richard,

On Tue, Sep 21, 2021 at 5:14 AM Richard Henderson <[email protected]> wrote:
>
> On 9/19/21 7:36 PM, Huacai Chen wrote:
> > Hi, Arnd,
> >
> > On Sun, Sep 19, 2021 at 5:59 PM Arnd Bergmann <[email protected]> wrote:
> >>
> >> On Sat, Sep 18, 2021 at 9:12 AM Huacai Chen <[email protected]> wrote:
> >>> On Sat, Sep 18, 2021 at 5:10 AM Eric W. Biederman <[email protected]> wrote:
> >>>> For example does LoongArch have a version without built in floating
> >>>> point support?
> >>>
> >>> Some of these structures seems need rethinking, But we really have
> >>> LoongArch-based MCUs now (no FP, no SMP, and even no MMU).
> >>
> >> NOMMU Linux is kind-of on the way out as interest is fading, so I hope you
> >> don't plan on supporting this in the future.
> >>
> >> Do you expect to see future products with MMU but no FP or no SMP?
> > OK, we will not care no-MMU hardware in Linux, but no-FP and no-SMP
> > hardware will be supported.
>
> Please consider requiring the FP registers to be present even on no-FP hardware.
>
> With this plus the FP data movement instructions (FMOV, MOVGR2FR, MOVFR2GR, FLD, FST), it
> is possible to implement soft-float without requiring a separate soft-float ABI. This can
> vastly simplify compatibility and deployment.
OK, I'll send an updated version.

>
>
> r~

2021-09-23 20:41:19

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH V3 01/22] Documentation: LoongArch: Add basic documentations

Hi!

> Add some basic documentations for LoongArch. LoongArch is a new RISC

... documentation ...

> +wide in LA64. $r0 is always zero, and other registers has no special feature,

...have no special features...

> +but we actually have an ABI register conversion as below.

convention?

> +``$r21`` ``$x`` Reserved Unused
> +``$r22`` ``$fp`` Frame pointer Yes
> +``$r23``-``$r31`` ``$s0``-``$s8`` Static registers Yes
> +================= =============== =================== ============

Not sure I know the term 'static registers' before.
Pavel

2021-09-23 21:02:00

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH V3 01/22] Documentation: LoongArch: Add basic documentations

Hi!

> Add some basic documentations for LoongArch. LoongArch is a new RISC
> ISA, which is a bit like MIPS or RISC-V. LoongArch includes a reduced
> 32-bit version (LA32R), a standard 32-bit version (LA32S) and a 64-bit
> version (LA64).
>
> Signed-off-by: Huacai Chen <[email protected]>

> +Relationship of Loongson and LoongArch
> +======================================
> +
> +LoongArch is a RISC ISA which is different from any other existing ones, while
> +Loongson is a family of processors. Loongson includes 3 series: Loongson-1 is
> +32-bit processors, Loongson-2 is low-end 64-bit processors, and Loongson-3 is
> +high-end 64-bit processors. Old Loongson is based on MIPS, and New
> Loongson is

s/processors/processor/ , I guess.

> +Official web site of Loongson and LoongArch (Loongson Technology Corp. Ltd.):
> +
> + http://www.loongson.cn/index.html

It would be better to point to english version of page.

> +Developer web site of Loongson and LoongArch (Software and Documentations):

Documentation.

BR, Pavel
--
http://www.livejournal.com/~pavelmachek


Attachments:
(No filename) (1.10 kB)
signature.asc (201.00 B)
Download all attachments

2021-09-24 04:11:37

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH V3 01/22] Documentation: LoongArch: Add basic documentations

Hi, Pavel,

On Fri, Sep 24, 2021 at 4:37 AM Pavel Machek <[email protected]> wrote:
>
> Hi!
>
> > Add some basic documentations for LoongArch. LoongArch is a new RISC
>
> ... documentation ...
OK, thanks.

>
> > +wide in LA64. $r0 is always zero, and other registers has no special feature,
>
> ...have no special features...
OK, thanks.

>
> > +but we actually have an ABI register conversion as below.
>
> convention?
Yes, should be convention here.

>
> > +``$r21`` ``$x`` Reserved Unused
> > +``$r22`` ``$fp`` Frame pointer Yes
> > +``$r23``-``$r31`` ``$s0``-``$s8`` Static registers Yes
> > +================= =============== =================== ============
>
> Not sure I know the term 'static registers' before.
"Static register" comes from the MIPS code "SAVE_STATIC", maybe it is
called "Saved register" in other places, but I think "static register"
is also OK.

Huacai
> Pavel

2021-09-24 04:13:01

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH V3 01/22] Documentation: LoongArch: Add basic documentations

Hi, Pavel,

On Fri, Sep 24, 2021 at 4:59 AM Pavel Machek <[email protected]> wrote:
>
> Hi!
>
> > Add some basic documentations for LoongArch. LoongArch is a new RISC
> > ISA, which is a bit like MIPS or RISC-V. LoongArch includes a reduced
> > 32-bit version (LA32R), a standard 32-bit version (LA32S) and a 64-bit
> > version (LA64).
> >
> > Signed-off-by: Huacai Chen <[email protected]>
>
> > +Relationship of Loongson and LoongArch
> > +======================================
> > +
> > +LoongArch is a RISC ISA which is different from any other existing ones, while
> > +Loongson is a family of processors. Loongson includes 3 series: Loongson-1 is
> > +32-bit processors, Loongson-2 is low-end 64-bit processors, and Loongson-3 is
> > +high-end 64-bit processors. Old Loongson is based on MIPS, and New
> > Loongson is
>
> s/processors/processor/ , I guess.
Should be processor series here, thanks.

>
> > +Official web site of Loongson and LoongArch (Loongson Technology Corp. Ltd.):
> > +
> > + http://www.loongson.cn/index.html
>
> It would be better to point to english version of page.
The English version doesn't exist at present.

>
> > +Developer web site of Loongson and LoongArch (Software and Documentations):
>
> Documentation.
OK, thanks.

Huacai
>
> BR, Pavel
> --
> http://www.livejournal.com/~pavelmachek

2021-09-24 07:02:56

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH V3 01/22] Documentation: LoongArch: Add basic documentations

Hi!

> > > Signed-off-by: Huacai Chen <[email protected]>
> >
> > > +Relationship of Loongson and LoongArch
> > > +======================================
> > > +
> > > +LoongArch is a RISC ISA which is different from any other existing ones, while
> > > +Loongson is a family of processors. Loongson includes 3 series: Loongson-1 is
> > > +32-bit processors, Loongson-2 is low-end 64-bit processors, and Loongson-3 is
> > > +high-end 64-bit processors. Old Loongson is based on MIPS, and New
> > > Loongson is
> >
> > s/processors/processor/ , I guess.
> Should be processor series here, thanks.

Makes sense (as do the other fixes), thanks.

> > > +Official web site of Loongson and LoongArch (Loongson Technology Corp. Ltd.):
> > > +
> > > + http://www.loongson.cn/index.html
> >
> > It would be better to point to english version of page.
> The English version doesn't exist at present.

Append (cn) so that people know what to expect?

Best regards,
Pavel
--
http://www.livejournal.com/~pavelmachek


Attachments:
(No filename) (1.02 kB)
signature.asc (188.00 B)
Digital signature
Download all attachments

2021-09-24 07:34:00

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH V3 01/22] Documentation: LoongArch: Add basic documentations

Hi, Pavel,

On Fri, Sep 24, 2021 at 2:58 PM Pavel Machek <[email protected]> wrote:
>
> Hi!
>
> > > > Signed-off-by: Huacai Chen <[email protected]>
> > >
> > > > +Relationship of Loongson and LoongArch
> > > > +======================================
> > > > +
> > > > +LoongArch is a RISC ISA which is different from any other existing ones, while
> > > > +Loongson is a family of processors. Loongson includes 3 series: Loongson-1 is
> > > > +32-bit processors, Loongson-2 is low-end 64-bit processors, and Loongson-3 is
> > > > +high-end 64-bit processors. Old Loongson is based on MIPS, and New
> > > > Loongson is
> > >
> > > s/processors/processor/ , I guess.
> > Should be processor series here, thanks.
>
> Makes sense (as do the other fixes), thanks.
>
> > > > +Official web site of Loongson and LoongArch (Loongson Technology Corp. Ltd.):
> > > > +
> > > > + http://www.loongson.cn/index.html
> > >
> > > It would be better to point to english version of page.
> > The English version doesn't exist at present.
>
> Append (cn) so that people know what to expect?
The English web page is in progress, we can update in later versions.

Huacai
>
> Best regards,
> Pavel
> --
> http://www.livejournal.com/~pavelmachek