summaryrefslogtreecommitdiffstats
path: root/tools/include/nolibc/arch-powerpc.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-19 10:09:22 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-19 10:09:22 -0700
commitf4cdf7ca9a1fdcca413157df19753f388a5a224e (patch)
tree60a31895b2446cd7fa27514e8c2843534a0de0da /tools/include/nolibc/arch-powerpc.h
downloadlinux-stable-f4cdf7ca9a1fdcca413157df19753f388a5a224e.tar.gz
linux-stable-f4cdf7ca9a1fdcca413157df19753f388a5a224e.zip
Merge tag 'media/v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-mediagrafted
Pull media updates from Mauro Carvalho Chehab: - v4l2-core: added ISP statistics support and per-block validation - v4l2-core: Allow unknown HDR10 white point and luminance - New camera sensors: Sony IMX678 and IMX471m, Himax HM1092 IR sensor - New codec: Milos: VPU v2.0 codec support - isp driver: gained support for Dreamchip RPPX1 ISP framework - vsp1 driver: gained support for RZ/T2H and RZ/N2H - Novalake driver: gained CVS support for new NVL hardware - dvb-core: fix feed leak on failed DMX_ADD_PID - several driver fixes, cleanups and minor improvements * tag 'media/v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (308 commits) media: ipu-bridge: check all DMI entries when overriding sensor rotation media: v4l2-async: avoid deleting unlinked ASC entry on link error media: rzg2l-cru: Align bytesperline to hardware DMA stride requirement media: intel/ipu6: fix async notifier cleanup leak on parse error media: staging/ipu7: fix async notifier UAF on probe error path media: amd: isp4: fix self-deadlock in isp4sd_pwron_and_init() error path media: amd: isp4: release partial allocations in isp4if_alloc_fw_gpumem() media: rcar-isp: Fix VSPX reference leaks media: rcar-isp: Release ISPCORE resources media: i2c: imx415: Release runtime PM reference on VBLANK error media: i2c: imx415: Return test pattern write errors media: renesas: vsp1: Declare index variables in for loop statement media: renesas: vsp1: Make reset control optional to support platforms without a reset line media: dt-bindings: media: renesas,vsp1: Document RZ/T2H and RZ/N2H SoCs media: dt-bindings: media: renesas,fcp: Document RZ/T2H and RZ/N2H SoCs media: nxp: imx8-isi: Add additional 32-bit RGB format support media: nxp: imx8-isi: Add 16-bit raw Bayer format support media: nxp: imx8-isi: Implement per-stream reference counting for multiplexed streams media: nxp: imx8-isi: Use BIT_ULL() for 64-bit stream masks media: nxp: imx8-isi: Correct color map between V4L2 and ISI ...
Diffstat (limited to 'tools/include/nolibc/arch-powerpc.h')
-rw-r--r--tools/include/nolibc/arch-powerpc.h233
1 files changed, 233 insertions, 0 deletions
diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h
new file mode 100644
index 000000000..dbe2e5205
--- /dev/null
+++ b/tools/include/nolibc/arch-powerpc.h
@@ -0,0 +1,233 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * PowerPC specific definitions for NOLIBC
+ * Copyright (C) 2023 Zhangjin Wu <falcon@tinylab.org>
+ */
+
+#ifndef _NOLIBC_ARCH_POWERPC_H
+#define _NOLIBC_ARCH_POWERPC_H
+
+#include <linux/unistd.h>
+
+#include "compiler.h"
+#include "crt.h"
+#include "std.h"
+
+/* Syscalls for PowerPC :
+ * - stack is 16-byte aligned
+ * - syscall number is passed in r0
+ * - arguments are in r3, r4, r5, r6, r7, r8, r9
+ * - the system call is performed by calling "sc"
+ * - syscall return comes in r3, and the summary overflow bit is checked
+ * to know if an error occurred, in which case errno is in r3.
+ * - the arguments are cast to long and assigned into the target
+ * registers which are then simply passed as registers to the asm code,
+ * so that we don't have to experience issues with register constraints.
+ */
+
+#define _NOLIBC_SYSCALL_CLOBBERLIST \
+ "memory", "cr0", "ctr", "xer", "r12", "r11", "r10", "r9"
+
+#define __nolibc_syscall0(num) \
+({ \
+ register long _ret __asm__ ("r3"); \
+ register long _num __asm__ ("r0") = (num); \
+ \
+ __asm__ volatile ( \
+ " sc\n" \
+ " bns+ 1f\n" \
+ " neg %0, %0\n" \
+ "1:\n" \
+ : "=r"(_ret), "+r"(_num) \
+ : \
+ : _NOLIBC_SYSCALL_CLOBBERLIST, "r8", "r7", "r6", "r5", "r4" \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall1(num, arg1) \
+({ \
+ register long _ret __asm__ ("r3"); \
+ register long _num __asm__ ("r0") = (num); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ \
+ __asm__ volatile ( \
+ " sc\n" \
+ " bns+ 1f\n" \
+ " neg %0, %0\n" \
+ "1:\n" \
+ : "=r"(_ret), "+r"(_num) \
+ : "0"(_arg1) \
+ : _NOLIBC_SYSCALL_CLOBBERLIST, "r8", "r7", "r6", "r5", "r4" \
+ ); \
+ _ret; \
+})
+
+
+#define __nolibc_syscall2(num, arg1, arg2) \
+({ \
+ register long _ret __asm__ ("r3"); \
+ register long _num __asm__ ("r0") = (num); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ \
+ __asm__ volatile ( \
+ " sc\n" \
+ " bns+ 1f\n" \
+ " neg %0, %0\n" \
+ "1:\n" \
+ : "=r"(_ret), "+r"(_num), "+r"(_arg2) \
+ : "0"(_arg1) \
+ : _NOLIBC_SYSCALL_CLOBBERLIST, "r8", "r7", "r6", "r5" \
+ ); \
+ _ret; \
+})
+
+
+#define __nolibc_syscall3(num, arg1, arg2, arg3) \
+({ \
+ register long _ret __asm__ ("r3"); \
+ register long _num __asm__ ("r0") = (num); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ \
+ __asm__ volatile ( \
+ " sc\n" \
+ " bns+ 1f\n" \
+ " neg %0, %0\n" \
+ "1:\n" \
+ : "=r"(_ret), "+r"(_num), "+r"(_arg2), "+r"(_arg3) \
+ : "0"(_arg1) \
+ : _NOLIBC_SYSCALL_CLOBBERLIST, "r8", "r7", "r6" \
+ ); \
+ _ret; \
+})
+
+
+#define __nolibc_syscall4(num, arg1, arg2, arg3, arg4) \
+({ \
+ register long _ret __asm__ ("r3"); \
+ register long _num __asm__ ("r0") = (num); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ register long _arg4 __asm__ ("r6") = (long)(arg4); \
+ \
+ __asm__ volatile ( \
+ " sc\n" \
+ " bns+ 1f\n" \
+ " neg %0, %0\n" \
+ "1:\n" \
+ : "=r"(_ret), "+r"(_num), "+r"(_arg2), "+r"(_arg3), \
+ "+r"(_arg4) \
+ : "0"(_arg1) \
+ : _NOLIBC_SYSCALL_CLOBBERLIST, "r8", "r7" \
+ ); \
+ _ret; \
+})
+
+
+#define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+({ \
+ register long _ret __asm__ ("r3"); \
+ register long _num __asm__ ("r0") = (num); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ register long _arg4 __asm__ ("r6") = (long)(arg4); \
+ register long _arg5 __asm__ ("r7") = (long)(arg5); \
+ \
+ __asm__ volatile ( \
+ " sc\n" \
+ " bns+ 1f\n" \
+ " neg %0, %0\n" \
+ "1:\n" \
+ : "=r"(_ret), "+r"(_num), "+r"(_arg2), "+r"(_arg3), \
+ "+r"(_arg4), "+r"(_arg5) \
+ : "0"(_arg1) \
+ : _NOLIBC_SYSCALL_CLOBBERLIST, "r8" \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+({ \
+ register long _ret __asm__ ("r3"); \
+ register long _num __asm__ ("r0") = (num); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ register long _arg4 __asm__ ("r6") = (long)(arg4); \
+ register long _arg5 __asm__ ("r7") = (long)(arg5); \
+ register long _arg6 __asm__ ("r8") = (long)(arg6); \
+ \
+ __asm__ volatile ( \
+ " sc\n" \
+ " bns+ 1f\n" \
+ " neg %0, %0\n" \
+ "1:\n" \
+ : "=r"(_ret), "+r"(_num), "+r"(_arg2), "+r"(_arg3), \
+ "+r"(_arg4), "+r"(_arg5), "+r"(_arg6) \
+ : "0"(_arg1) \
+ : _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#if !defined(__powerpc64__) && !defined(__clang__)
+/* FIXME: For 32-bit PowerPC, with newer gcc compilers (e.g. gcc 13.1.0),
+ * "omit-frame-pointer" fails with __attribute__((no_stack_protector)) but
+ * works with __attribute__((__optimize__("-fno-stack-protector")))
+ */
+#ifdef __nolibc_no_stack_protector
+#undef __nolibc_no_stack_protector
+#define __nolibc_no_stack_protector __attribute__((__optimize__("-fno-stack-protector")))
+#endif
+#endif /* !__powerpc64__ */
+
+#ifndef NOLIBC_NO_RUNTIME
+/* startup code */
+void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_protector _start(void)
+{
+#ifdef __powerpc64__
+#if _CALL_ELF == 2
+ /* with -mabi=elfv2, save TOC/GOT pointer to r2
+ * r12 is global entry pointer, we use it to compute TOC from r12
+ * https://www.llvm.org/devmtg/2014-04/PDFs/Talks/Euro-LLVM-2014-Weigand.pdf
+ * https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.pdf
+ */
+ __asm__ volatile (
+ "addis 2, 12, .TOC. - _start@ha\n"
+ "addi 2, 2, .TOC. - _start@l\n"
+ );
+#endif /* _CALL_ELF == 2 */
+
+ __asm__ volatile (
+ "mr 3, 1\n" /* save stack pointer to r3, as arg1 of _start_c */
+ "li 0, 0\n" /* zero the frame pointer */
+ "stdu 1, -32(1)\n" /* the initial stack frame */
+ "bl _start_c\n" /* transfer to c runtime */
+ );
+#else
+ __asm__ volatile (
+ "mr 3, 1\n" /* save stack pointer to r3, as arg1 of _start_c */
+ "li 0, 0\n" /* zero the frame pointer */
+ "stwu 1, -16(1)\n" /* the initial stack frame */
+ "bl _start_c\n" /* transfer to c runtime */
+ );
+#endif
+ __nolibc_entrypoint_epilogue();
+}
+#endif /* NOLIBC_NO_RUNTIME */
+
+#if !defined(__powerpc64__)
+static __attribute__((unused))
+int _sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
+{
+ return __nolibc_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
+}
+#define _sys_ftruncate64 _sys_ftruncate64
+#endif
+
+#endif /* _NOLIBC_ARCH_POWERPC_H */