aboutsummaryrefslogtreecommitdiffstats
path: root/linux-user/ppc
diff options
context:
space:
mode:
authorTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
committerTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
commite02cda008591317b1625707ff8e115a4841aa889 (patch)
treeaee302e3cf8b59ec2d32ec481be3d1afddfc8968 /linux-user/ppc
parentcc668e6b7e0ffd8c9d130513d12053cf5eda1d3b (diff)
Introduce Virtio-loopback epsilon release:
Epsilon release introduces a new compatibility layer which make virtio-loopback design to work with QEMU and rust-vmm vhost-user backend without require any changes. Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> Change-Id: I52e57563e08a7d0bdc002f8e928ee61ba0c53dd9
Diffstat (limited to 'linux-user/ppc')
-rw-r--r--linux-user/ppc/cpu_loop.c493
-rw-r--r--linux-user/ppc/meson.build5
-rw-r--r--linux-user/ppc/signal.c727
-rw-r--r--linux-user/ppc/sockbits.h26
-rw-r--r--linux-user/ppc/syscall.tbl528
-rw-r--r--linux-user/ppc/syscallhdr.sh34
-rw-r--r--linux-user/ppc/target_cpu.h59
-rw-r--r--linux-user/ppc/target_elf.h18
-rw-r--r--linux-user/ppc/target_errno_defs.h7
-rw-r--r--linux-user/ppc/target_fcntl.h17
-rw-r--r--linux-user/ppc/target_signal.h29
-rw-r--r--linux-user/ppc/target_structs.h60
-rw-r--r--linux-user/ppc/target_syscall.h80
-rw-r--r--linux-user/ppc/termbits.h247
14 files changed, 2330 insertions, 0 deletions
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
new file mode 100644
index 000000000..483e66930
--- /dev/null
+++ b/linux-user/ppc/cpu_loop.c
@@ -0,0 +1,493 @@
+/*
+ * qemu user cpu loop
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu.h"
+#include "user-internals.h"
+#include "cpu_loop-common.h"
+#include "signal-common.h"
+
+static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
+{
+ return cpu_get_host_ticks();
+}
+
+uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
+{
+ return cpu_ppc_get_tb(env);
+}
+
+uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
+{
+ return cpu_ppc_get_tb(env) >> 32;
+}
+
+uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
+{
+ return cpu_ppc_get_tb(env);
+}
+
+uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
+{
+ return cpu_ppc_get_tb(env) >> 32;
+}
+
+uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
+{
+ return cpu_ppc_get_tb(env);
+}
+
+uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
+__attribute__ (( alias ("cpu_ppc_load_tbu") ));
+
+uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
+{
+ return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+}
+
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
+{
+ return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
+{
+ return -1;
+}
+
+void cpu_loop(CPUPPCState *env)
+{
+ CPUState *cs = env_cpu(env);
+ target_siginfo_t info;
+ int trapnr;
+ target_ulong ret;
+
+ for(;;) {
+ bool arch_interrupt;
+
+ cpu_exec_start(cs);
+ trapnr = cpu_exec(cs);
+ cpu_exec_end(cs);
+ process_queued_cpu_work(cs);
+
+ arch_interrupt = true;
+ switch (trapnr) {
+ case POWERPC_EXCP_NONE:
+ /* Just go on */
+ break;
+ case POWERPC_EXCP_CRITICAL: /* Critical input */
+ cpu_abort(cs, "Critical interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ cpu_abort(cs, "Machine check exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
+ /* XXX: check this. Seems bugged */
+ switch (env->error_code & 0xFF000000) {
+ case 0x40000000:
+ case 0x42000000:
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ break;
+ case 0x04000000:
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLADR;
+ break;
+ case 0x08000000:
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_ACCERR;
+ break;
+ default:
+ /* Let's send a regular segfault... */
+ EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+ env->error_code);
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ break;
+ }
+ info._sifields._sigfault._addr = env->spr[SPR_DAR];
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ /* XXX: check this */
+ switch (env->error_code & 0xFF000000) {
+ case 0x40000000:
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ break;
+ case 0x10000000:
+ case 0x08000000:
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_ACCERR;
+ break;
+ default:
+ /* Let's send a regular segfault... */
+ EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+ env->error_code);
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ break;
+ }
+ info._sifields._sigfault._addr = env->nip - 4;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ cpu_abort(cs, "External interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ case POWERPC_EXCP_HV_EMU: /* HV emulation */
+ /* XXX: check this */
+ switch (env->error_code & ~0xF) {
+ case POWERPC_EXCP_FP:
+ info.si_signo = TARGET_SIGFPE;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_FP_OX:
+ info.si_code = TARGET_FPE_FLTOVF;
+ break;
+ case POWERPC_EXCP_FP_UX:
+ info.si_code = TARGET_FPE_FLTUND;
+ break;
+ case POWERPC_EXCP_FP_ZX:
+ case POWERPC_EXCP_FP_VXZDZ:
+ info.si_code = TARGET_FPE_FLTDIV;
+ break;
+ case POWERPC_EXCP_FP_XX:
+ info.si_code = TARGET_FPE_FLTRES;
+ break;
+ case POWERPC_EXCP_FP_VXSOFT:
+ info.si_code = TARGET_FPE_FLTINV;
+ break;
+ case POWERPC_EXCP_FP_VXSNAN:
+ case POWERPC_EXCP_FP_VXISI:
+ case POWERPC_EXCP_FP_VXIDI:
+ case POWERPC_EXCP_FP_VXIMZ:
+ case POWERPC_EXCP_FP_VXVC:
+ case POWERPC_EXCP_FP_VXSQRT:
+ case POWERPC_EXCP_FP_VXCVI:
+ info.si_code = TARGET_FPE_FLTSUB;
+ break;
+ default:
+ EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+ env->error_code);
+ break;
+ }
+ break;
+ case POWERPC_EXCP_INVAL:
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_INVAL_INVAL:
+ info.si_code = TARGET_ILL_ILLOPC;
+ break;
+ case POWERPC_EXCP_INVAL_LSWX:
+ info.si_code = TARGET_ILL_ILLOPN;
+ break;
+ case POWERPC_EXCP_INVAL_SPR:
+ info.si_code = TARGET_ILL_PRVREG;
+ break;
+ case POWERPC_EXCP_INVAL_FP:
+ info.si_code = TARGET_ILL_COPROC;
+ break;
+ default:
+ EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+ env->error_code & 0xF);
+ info.si_code = TARGET_ILL_ILLADR;
+ break;
+ }
+ break;
+ case POWERPC_EXCP_PRIV:
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_PRIV_OPC:
+ info.si_code = TARGET_ILL_PRVOPC;
+ break;
+ case POWERPC_EXCP_PRIV_REG:
+ info.si_code = TARGET_ILL_PRVREG;
+ break;
+ default:
+ EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+ env->error_code & 0xF);
+ info.si_code = TARGET_ILL_PRVOPC;
+ break;
+ }
+ break;
+ case POWERPC_EXCP_TRAP:
+ cpu_abort(cs, "Tried to call a TRAP\n");
+ break;
+ default:
+ /* Should not happen ! */
+ cpu_abort(cs, "Unknown program exception (%02x)\n",
+ env->error_code);
+ break;
+ }
+ info._sifields._sigfault._addr = env->nip;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case POWERPC_EXCP_SYSCALL: /* System call exception */
+ case POWERPC_EXCP_SYSCALL_VECTORED:
+ cpu_abort(cs, "Syscall exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ cpu_abort(cs, "Decrementer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ cpu_abort(cs, "Fix interval timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ cpu_abort(cs, "Watchdog timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DTLB: /* Data TLB error */
+ cpu_abort(cs, "Data TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ITLB: /* Instruction TLB error */
+ cpu_abort(cs, "Instruction TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
+ cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
+ cpu_abort(cs, "Embedded floating-point round IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(cs, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
+ cpu_abort(cs, "Doorbell interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
+ cpu_abort(cs, "Doorbell critical interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ cpu_abort(cs, "Reset interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DSEG: /* Data segment exception */
+ cpu_abort(cs, "Data segment exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ISEG: /* Instruction segment exception */
+ cpu_abort(cs, "Instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+ /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
+ cpu_abort(cs, "Hypervisor decrementer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_TRACE: /* Trace exception */
+ /* Nothing to do:
+ * we use this exception to emulate step-by-step execution mode.
+ */
+ break;
+ /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
+ cpu_abort(cs, "Hypervisor data storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
+ cpu_abort(cs, "Hypervisor instruction storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
+ cpu_abort(cs, "Hypervisor data segment exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
+ cpu_abort(cs, "Hypervisor instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
+ cpu_abort(cs, "Programmable interval timer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_IO: /* IO error exception */
+ cpu_abort(cs, "IO error exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RUNM: /* Run mode exception */
+ cpu_abort(cs, "Run mode exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
+ cpu_abort(cs, "Emulation trap exception not handled\n");
+ break;
+ case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
+ cpu_abort(cs, "Instruction fetch TLB exception "
+ "while in user-mode. Aborting");
+ break;
+ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
+ cpu_abort(cs, "Data load TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
+ cpu_abort(cs, "Data store TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_FPA: /* Floating-point assist exception */
+ cpu_abort(cs, "Floating-point assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
+ cpu_abort(cs, "Instruction address breakpoint exception "
+ "not handled\n");
+ break;
+ case POWERPC_EXCP_SMI: /* System management interrupt */
+ cpu_abort(cs, "System management interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_THERM: /* Thermal interrupt */
+ cpu_abort(cs, "Thermal interrupt interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(cs, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_VPUA: /* Vector assist exception */
+ cpu_abort(cs, "Vector assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_SOFTP: /* Soft patch exception */
+ cpu_abort(cs, "Soft patch exception not handled\n");
+ break;
+ case POWERPC_EXCP_MAINT: /* Maintenance exception */
+ cpu_abort(cs, "Maintenance exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_SYSCALL_USER:
+ /* system call in user-mode emulation */
+ /* WARNING:
+ * PPC ABI uses overflow flag in cr0 to signal an error
+ * in syscalls.
+ */
+ env->crf[0] &= ~0x1;
+ env->nip += 4;
+ ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], 0, 0);
+ if (ret == -TARGET_ERESTARTSYS) {
+ env->nip -= 4;
+ break;
+ }
+ if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
+ /* Returning from a successful sigreturn syscall.
+ Avoid corrupting register state. */
+ break;
+ }
+ if (ret > (target_ulong)(-515)) {
+ env->crf[0] |= 0x1;
+ ret = -ret;
+ }
+ env->gpr[3] = ret;
+ break;
+ case EXCP_DEBUG:
+ info.si_signo = TARGET_SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
+ case EXCP_ATOMIC:
+ cpu_exec_step_atomic(cs);
+ arch_interrupt = false;
+ break;
+ default:
+ cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr);
+ break;
+ }
+ process_pending_signals(env);
+
+ /* Most of the traps imply a transition through kernel mode,
+ * which implies an REI instruction has been executed. Which
+ * means that RX and LOCK_ADDR should be cleared. But there
+ * are a few exceptions for traps internal to QEMU.
+ */
+ if (arch_interrupt) {
+ env->reserve_addr = -1;
+ }
+ }
+}
+
+void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
+{
+ int i;
+
+#if defined(TARGET_PPC64)
+ int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF;
+#if defined(TARGET_ABI32)
+ ppc_store_msr(env, env->msr & ~((target_ulong)1 << flag));
+#else
+ ppc_store_msr(env, env->msr | (target_ulong)1 << flag);
+#endif
+#endif
+
+ env->nip = regs->nip;
+ for(i = 0; i < 32; i++) {
+ env->gpr[i] = regs->gpr[i];
+ }
+}
diff --git a/linux-user/ppc/meson.build b/linux-user/ppc/meson.build
new file mode 100644
index 000000000..19fead7bc
--- /dev/null
+++ b/linux-user/ppc/meson.build
@@ -0,0 +1,5 @@
+syscall_nr_generators += {
+ 'ppc': generator(sh,
+ arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
+ output: '@BASENAME@_nr.h')
+}
diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
new file mode 100644
index 000000000..90a036963
--- /dev/null
+++ b/linux-user/ppc/signal.c
@@ -0,0 +1,727 @@
+/*
+ * Emulation of Linux signals
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "user-internals.h"
+#include "signal-common.h"
+#include "linux-user/trace.h"
+
+/* Size of dummy stack frame allocated when calling signal handler.
+ See arch/powerpc/include/asm/ptrace.h. */
+#if defined(TARGET_PPC64)
+#define SIGNAL_FRAMESIZE 128
+#else
+#define SIGNAL_FRAMESIZE 64
+#endif
+
+/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
+ on 64-bit PPC, sigcontext and mcontext are one and the same. */
+struct target_mcontext {
+ target_ulong mc_gregs[48];
+ /* Includes fpscr. */
+ uint64_t mc_fregs[33];
+
+#if defined(TARGET_PPC64)
+ /* Pointer to the vector regs */
+ target_ulong v_regs;
+ /*
+ * On ppc64, this mcontext structure is naturally *unaligned*,
+ * or rather it is aligned on a 8 bytes boundary but not on
+ * a 16 byte boundary. This pad fixes it up. This is why we
+ * cannot use ppc_avr_t, which would force alignment. This is
+ * also why the vector regs are referenced in the ABI by the
+ * v_regs pointer above so any amount of padding can be added here.
+ */
+ target_ulong pad;
+ /* VSCR and VRSAVE are saved separately. Also reserve space for VSX. */
+ struct {
+ uint64_t altivec[34 + 16][2];
+ } mc_vregs;
+#else
+ target_ulong mc_pad[2];
+
+ /* We need to handle Altivec and SPE at the same time, which no
+ kernel needs to do. Fortunately, the kernel defines this bit to
+ be Altivec-register-large all the time, rather than trying to
+ twiddle it based on the specific platform. */
+ union {
+ /* SPE vector registers. One extra for SPEFSCR. */
+ uint32_t spe[33];
+ /*
+ * Altivec vector registers. One extra for VRSAVE.
+ * On ppc32, we are already aligned to 16 bytes. We could
+ * use ppc_avr_t, but choose to share the same type as ppc64.
+ */
+ uint64_t altivec[33][2];
+ } mc_vregs;
+#endif
+};
+
+/* See arch/powerpc/include/asm/sigcontext.h. */
+struct target_sigcontext {
+ target_ulong _unused[4];
+ int32_t signal;
+#if defined(TARGET_PPC64)
+ int32_t pad0;
+#endif
+ target_ulong handler;
+ target_ulong oldmask;
+ target_ulong regs; /* struct pt_regs __user * */
+#if defined(TARGET_PPC64)
+ struct target_mcontext mcontext;
+#endif
+};
+
+/* Indices for target_mcontext.mc_gregs, below.
+ See arch/powerpc/include/asm/ptrace.h for details. */
+enum {
+ TARGET_PT_R0 = 0,
+ TARGET_PT_R1 = 1,
+ TARGET_PT_R2 = 2,
+ TARGET_PT_R3 = 3,
+ TARGET_PT_R4 = 4,
+ TARGET_PT_R5 = 5,
+ TARGET_PT_R6 = 6,
+ TARGET_PT_R7 = 7,
+ TARGET_PT_R8 = 8,
+ TARGET_PT_R9 = 9,
+ TARGET_PT_R10 = 10,
+ TARGET_PT_R11 = 11,
+ TARGET_PT_R12 = 12,
+ TARGET_PT_R13 = 13,
+ TARGET_PT_R14 = 14,
+ TARGET_PT_R15 = 15,
+ TARGET_PT_R16 = 16,
+ TARGET_PT_R17 = 17,
+ TARGET_PT_R18 = 18,
+ TARGET_PT_R19 = 19,
+ TARGET_PT_R20 = 20,
+ TARGET_PT_R21 = 21,
+ TARGET_PT_R22 = 22,
+ TARGET_PT_R23 = 23,
+ TARGET_PT_R24 = 24,
+ TARGET_PT_R25 = 25,
+ TARGET_PT_R26 = 26,
+ TARGET_PT_R27 = 27,
+ TARGET_PT_R28 = 28,
+ TARGET_PT_R29 = 29,
+ TARGET_PT_R30 = 30,
+ TARGET_PT_R31 = 31,
+ TARGET_PT_NIP = 32,
+ TARGET_PT_MSR = 33,
+ TARGET_PT_ORIG_R3 = 34,
+ TARGET_PT_CTR = 35,
+ TARGET_PT_LNK = 36,
+ TARGET_PT_XER = 37,
+ TARGET_PT_CCR = 38,
+ /* Yes, there are two registers with #39. One is 64-bit only. */
+ TARGET_PT_MQ = 39,
+ TARGET_PT_SOFTE = 39,
+ TARGET_PT_TRAP = 40,
+ TARGET_PT_DAR = 41,
+ TARGET_PT_DSISR = 42,
+ TARGET_PT_RESULT = 43,
+ TARGET_PT_REGS_COUNT = 44
+};
+
+
+struct target_ucontext {
+ target_ulong tuc_flags;
+ target_ulong tuc_link; /* ucontext_t __user * */
+ struct target_sigaltstack tuc_stack;
+#if !defined(TARGET_PPC64)
+ int32_t tuc_pad[7];
+ target_ulong tuc_regs; /* struct mcontext __user *
+ points to uc_mcontext field */
+#endif
+ target_sigset_t tuc_sigmask;
+#if defined(TARGET_PPC64)
+ target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
+ struct target_sigcontext tuc_sigcontext;
+#else
+ int32_t tuc_maskext[30];
+ int32_t tuc_pad2[3];
+ struct target_mcontext tuc_mcontext;
+#endif
+};
+
+/* See arch/powerpc/kernel/signal_32.c. */
+struct target_sigframe {
+ struct target_sigcontext sctx;
+ struct target_mcontext mctx;
+ int32_t abigap[56];
+};
+
+#if defined(TARGET_PPC64)
+
+#define TARGET_TRAMP_SIZE 6
+
+struct target_rt_sigframe {
+ /* sys_rt_sigreturn requires the ucontext be the first field */
+ struct target_ucontext uc;
+ target_ulong _unused[2];
+ uint32_t trampoline[TARGET_TRAMP_SIZE];
+ target_ulong pinfo; /* struct siginfo __user * */
+ target_ulong puc; /* void __user * */
+ struct target_siginfo info;
+ /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
+ char abigap[288];
+} __attribute__((aligned(16)));
+
+#else
+
+struct target_rt_sigframe {
+ struct target_siginfo info;
+ struct target_ucontext uc;
+ int32_t abigap[56];
+};
+
+#endif
+
+#if defined(TARGET_PPC64)
+
+struct target_func_ptr {
+ target_ulong entry;
+ target_ulong toc;
+};
+
+#endif
+
+/* See arch/powerpc/kernel/signal.c. */
+static target_ulong get_sigframe(struct target_sigaction *ka,
+ CPUPPCState *env,
+ int frame_size)
+{
+ target_ulong oldsp;
+
+ oldsp = target_sigsp(get_sp_from_cpustate(env), ka);
+
+ return (oldsp - frame_size) & ~0xFUL;
+}
+
+#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
+ (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
+#define PPC_VEC_HI 0
+#define PPC_VEC_LO 1
+#else
+#define PPC_VEC_HI 1
+#define PPC_VEC_LO 0
+#endif
+
+
+static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
+{
+ target_ulong msr = env->msr;
+ int i;
+ target_ulong ccr = 0;
+
+ /* In general, the kernel attempts to be intelligent about what it
+ needs to save for Altivec/FP/SPE registers. We don't care that
+ much, so we just go ahead and save everything. */
+
+ /* Save general registers. */
+ for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
+ __put_user(env->gpr[i], &frame->mc_gregs[i]);
+ }
+ __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
+ __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
+ __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
+ __put_user(cpu_read_xer(env), &frame->mc_gregs[TARGET_PT_XER]);
+
+ for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
+ ccr |= env->crf[i] << (32 - ((i + 1) * 4));
+ }
+ __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
+
+ /* Save Altivec registers if necessary. */
+ if (env->insns_flags & PPC_ALTIVEC) {
+ uint32_t *vrsave;
+ for (i = 0; i < 32; i++) {
+ ppc_avr_t *avr = cpu_avr_ptr(env, i);
+ ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
+
+ __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
+ __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
+ }
+#if defined(TARGET_PPC64)
+ vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
+ /* 64-bit needs to put a pointer to the vectors in the frame */
+ __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
+#else
+ vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
+#endif
+ __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
+ }
+
+#if defined(TARGET_PPC64)
+ /* Save VSX second halves */
+ if (env->insns_flags2 & PPC2_VSX) {
+ uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
+ for (i = 0; i < 32; i++) {
+ uint64_t *vsrl = cpu_vsrl_ptr(env, i);
+ __put_user(*vsrl, &vsregs[i]);
+ }
+ }
+#endif
+
+ /* Save floating point registers. */
+ if (env->insns_flags & PPC_FLOAT) {
+ for (i = 0; i < 32; i++) {
+ uint64_t *fpr = cpu_fpr_ptr(env, i);
+ __put_user(*fpr, &frame->mc_fregs[i]);
+ }
+ __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
+ }
+
+#if !defined(TARGET_PPC64)
+ /* Save SPE registers. The kernel only saves the high half. */
+ if (env->insns_flags & PPC_SPE) {
+ for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
+ __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
+ }
+ __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
+ }
+#endif
+
+ /* Store MSR. */
+ __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
+}
+
+static void encode_trampoline(int sigret, uint32_t *tramp)
+{
+ /* Set up the sigreturn trampoline: li r0,sigret; sc. */
+ __put_user(0x38000000 | sigret, &tramp[0]);
+ __put_user(0x44000002, &tramp[1]);
+}
+
+static void restore_user_regs(CPUPPCState *env,
+ struct target_mcontext *frame, int sig)
+{
+ target_ulong save_r2 = 0;
+ target_ulong msr;
+ target_ulong xer;
+ target_ulong ccr;
+
+ int i;
+
+ if (!sig) {
+ save_r2 = env->gpr[2];
+ }
+
+ /* Restore general registers. */
+ for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
+ __get_user(env->gpr[i], &frame->mc_gregs[i]);
+ }
+ __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
+ __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
+ __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
+
+ __get_user(xer, &frame->mc_gregs[TARGET_PT_XER]);
+ cpu_write_xer(env, xer);
+
+ __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
+ for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
+ env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
+ }
+
+ if (!sig) {
+ env->gpr[2] = save_r2;
+ }
+ /* Restore MSR. */
+ __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
+
+ /* If doing signal return, restore the previous little-endian mode. */
+ if (sig) {
+ ppc_store_msr(env, ((env->msr & ~(1ull << MSR_LE)) |
+ (msr & (1ull << MSR_LE))));
+ }
+
+ /* Restore Altivec registers if necessary. */
+ if (env->insns_flags & PPC_ALTIVEC) {
+ ppc_avr_t *v_regs;
+ uint32_t *vrsave;
+#if defined(TARGET_PPC64)
+ uint64_t v_addr;
+ /* 64-bit needs to recover the pointer to the vectors from the frame */
+ __get_user(v_addr, &frame->v_regs);
+ v_regs = g2h(env_cpu(env), v_addr);
+#else
+ v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
+#endif
+ for (i = 0; i < 32; i++) {
+ ppc_avr_t *avr = cpu_avr_ptr(env, i);
+ ppc_avr_t *vreg = &v_regs[i];
+
+ __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
+ __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
+ }
+#if defined(TARGET_PPC64)
+ vrsave = (uint32_t *)&v_regs[33];
+#else
+ vrsave = (uint32_t *)&v_regs[32];
+#endif
+ __get_user(env->spr[SPR_VRSAVE], vrsave);
+ }
+
+#if defined(TARGET_PPC64)
+ /* Restore VSX second halves */
+ if (env->insns_flags2 & PPC2_VSX) {
+ uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
+ for (i = 0; i < 32; i++) {
+ uint64_t *vsrl = cpu_vsrl_ptr(env, i);
+ __get_user(*vsrl, &vsregs[i]);
+ }
+ }
+#endif
+
+ /* Restore floating point registers. */
+ if (env->insns_flags & PPC_FLOAT) {
+ uint64_t fpscr;
+ for (i = 0; i < 32; i++) {
+ uint64_t *fpr = cpu_fpr_ptr(env, i);
+ __get_user(*fpr, &frame->mc_fregs[i]);
+ }
+ __get_user(fpscr, &frame->mc_fregs[32]);
+ env->fpscr = (uint32_t) fpscr;
+ }
+
+#if !defined(TARGET_PPC64)
+ /* Save SPE registers. The kernel only saves the high half. */
+ if (env->insns_flags & PPC_SPE) {
+ for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
+ __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
+ }
+ __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
+ }
+#endif
+}
+
+#if !defined(TARGET_PPC64)
+void setup_frame(int sig, struct target_sigaction *ka,
+ target_sigset_t *set, CPUPPCState *env)
+{
+ struct target_sigframe *frame;
+ struct target_sigcontext *sc;
+ target_ulong frame_addr, newsp;
+ int err = 0;
+
+ frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ trace_user_setup_frame(env, frame_addr);
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
+ goto sigsegv;
+ sc = &frame->sctx;
+
+ __put_user(ka->_sa_handler, &sc->handler);
+ __put_user(set->sig[0], &sc->oldmask);
+ __put_user(set->sig[1], &sc->_unused[3]);
+ __put_user(h2g(&frame->mctx), &sc->regs);
+ __put_user(sig, &sc->signal);
+
+ /* Save user regs. */
+ save_user_regs(env, &frame->mctx);
+
+ env->lr = default_sigreturn;
+
+ /* Turn off all fp exceptions. */
+ env->fpscr = 0;
+
+ /* Create a stack frame for the caller of the handler. */
+ newsp = frame_addr - SIGNAL_FRAMESIZE;
+ err |= put_user(env->gpr[1], newsp, target_ulong);
+
+ if (err)
+ goto sigsegv;
+
+ /* Set up registers for signal handler. */
+ env->gpr[1] = newsp;
+ env->gpr[3] = sig;
+ env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
+
+ env->nip = (target_ulong) ka->_sa_handler;
+
+ /* Signal handlers are entered in big-endian mode. */
+ ppc_store_msr(env, env->msr & ~(1ull << MSR_LE));
+
+ unlock_user_struct(frame, frame_addr, 1);
+ return;
+
+sigsegv:
+ unlock_user_struct(frame, frame_addr, 1);
+ force_sigsegv(sig);
+}
+#endif /* !defined(TARGET_PPC64) */
+
+void setup_rt_frame(int sig, struct target_sigaction *ka,
+ target_siginfo_t *info,
+ target_sigset_t *set, CPUPPCState *env)
+{
+ struct target_rt_sigframe *rt_sf;
+ struct target_mcontext *mctx = 0;
+ target_ulong rt_sf_addr, newsp = 0;
+ int i, err = 0;
+#if defined(TARGET_PPC64)
+ struct target_sigcontext *sc = 0;
+#if !defined(TARGET_ABI32)
+ struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
+#endif
+#endif
+
+ rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
+ if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
+ goto sigsegv;
+
+ tswap_siginfo(&rt_sf->info, info);
+
+ __put_user(0, &rt_sf->uc.tuc_flags);
+ __put_user(0, &rt_sf->uc.tuc_link);
+ target_save_altstack(&rt_sf->uc.tuc_stack, env);
+#if !defined(TARGET_PPC64)
+ __put_user(h2g (&rt_sf->uc.tuc_mcontext),
+ &rt_sf->uc.tuc_regs);
+#endif
+ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+ __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
+ }
+
+#if defined(TARGET_PPC64)
+ mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
+
+ sc = &rt_sf->uc.tuc_sigcontext;
+ __put_user(h2g(mctx), &sc->regs);
+ __put_user(sig, &sc->signal);
+#else
+ mctx = &rt_sf->uc.tuc_mcontext;
+#endif
+
+ save_user_regs(env, mctx);
+
+ env->lr = default_rt_sigreturn;
+
+ /* Turn off all fp exceptions. */
+ env->fpscr = 0;
+
+ /* Create a stack frame for the caller of the handler. */
+ newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
+ err |= put_user(env->gpr[1], newsp, target_ulong);
+
+ if (err)
+ goto sigsegv;
+
+ /* Set up registers for signal handler. */
+ env->gpr[1] = newsp;
+ env->gpr[3] = (target_ulong) sig;
+ env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
+ env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
+ env->gpr[6] = (target_ulong) h2g(rt_sf);
+
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+ if (get_ppc64_abi(image) < 2) {
+ /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
+ struct target_func_ptr *handler =
+ (struct target_func_ptr *)g2h(env_cpu(env), ka->_sa_handler);
+ env->nip = tswapl(handler->entry);
+ env->gpr[2] = tswapl(handler->toc);
+ } else {
+ /* ELFv2 PPC64 function pointers are entry points. R12 must also be set. */
+ env->gpr[12] = env->nip = ka->_sa_handler;
+ }
+#else
+ env->nip = (target_ulong) ka->_sa_handler;
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ /* Signal handlers are entered in big-endian mode. */
+ ppc_store_msr(env, env->msr & ~(1ull << MSR_LE));
+#else
+ /* Signal handlers are entered in little-endian mode. */
+ ppc_store_msr(env, env->msr | (1ull << MSR_LE));
+#endif
+
+ unlock_user_struct(rt_sf, rt_sf_addr, 1);
+ return;
+
+sigsegv:
+ unlock_user_struct(rt_sf, rt_sf_addr, 1);
+ force_sigsegv(sig);
+
+}
+
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
+long do_sigreturn(CPUPPCState *env)
+{
+ struct target_sigcontext *sc = NULL;
+ struct target_mcontext *sr = NULL;
+ target_ulong sr_addr = 0, sc_addr;
+ sigset_t blocked;
+ target_sigset_t set;
+
+ sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
+ if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
+ goto sigsegv;
+
+#if defined(TARGET_PPC64)
+ set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
+#else
+ __get_user(set.sig[0], &sc->oldmask);
+ __get_user(set.sig[1], &sc->_unused[3]);
+#endif
+ target_to_host_sigset_internal(&blocked, &set);
+ set_sigmask(&blocked);
+
+ __get_user(sr_addr, &sc->regs);
+ if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
+ goto sigsegv;
+ restore_user_regs(env, sr, 1);
+
+ unlock_user_struct(sr, sr_addr, 1);
+ unlock_user_struct(sc, sc_addr, 1);
+ return -TARGET_QEMU_ESIGRETURN;
+
+sigsegv:
+ unlock_user_struct(sr, sr_addr, 1);
+ unlock_user_struct(sc, sc_addr, 1);
+ force_sig(TARGET_SIGSEGV);
+ return -TARGET_QEMU_ESIGRETURN;
+}
+#endif /* !defined(TARGET_PPC64) */
+
+/* See arch/powerpc/kernel/signal_32.c. */
+static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
+{
+ struct target_mcontext *mcp;
+ target_ulong mcp_addr;
+ sigset_t blocked;
+ target_sigset_t set;
+
+ if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
+ sizeof (set)))
+ return 1;
+
+#if defined(TARGET_PPC64)
+ mcp_addr = h2g(ucp) +
+ offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
+#else
+ __get_user(mcp_addr, &ucp->tuc_regs);
+#endif
+
+ if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
+ return 1;
+
+ target_to_host_sigset_internal(&blocked, &set);
+ set_sigmask(&blocked);
+ restore_user_regs(env, mcp, sig);
+
+ unlock_user_struct(mcp, mcp_addr, 1);
+ return 0;
+}
+
+long do_rt_sigreturn(CPUPPCState *env)
+{
+ struct target_rt_sigframe *rt_sf = NULL;
+ target_ulong rt_sf_addr;
+
+ rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
+ if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
+ goto sigsegv;
+
+ if (do_setcontext(&rt_sf->uc, env, 1))
+ goto sigsegv;
+
+ target_restore_altstack(&rt_sf->uc.tuc_stack, env);
+
+ unlock_user_struct(rt_sf, rt_sf_addr, 1);
+ return -TARGET_QEMU_ESIGRETURN;
+
+sigsegv:
+ unlock_user_struct(rt_sf, rt_sf_addr, 1);
+ force_sig(TARGET_SIGSEGV);
+ return -TARGET_QEMU_ESIGRETURN;
+}
+
+/* This syscall implements {get,set,swap}context for userland. */
+abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
+ abi_ulong unew_ctx, abi_long ctx_size)
+{
+ struct target_ucontext *uctx;
+ struct target_mcontext *mctx;
+
+ /* For ppc32, ctx_size is "reserved for future use".
+ * For ppc64, we do not yet support the VSX extension.
+ */
+ if (ctx_size < sizeof(struct target_ucontext)) {
+ return -TARGET_EINVAL;
+ }
+
+ if (uold_ctx) {
+ TaskState *ts = (TaskState *)thread_cpu->opaque;
+
+ if (!lock_user_struct(VERIFY_WRITE, uctx, uold_ctx, 1)) {
+ return -TARGET_EFAULT;
+ }
+
+#ifdef TARGET_PPC64
+ mctx = &uctx->tuc_sigcontext.mcontext;
+#else
+ /* ??? The kernel aligns the pointer down here into padding, but
+ * in setup_rt_frame we don't. Be self-compatible for now.
+ */
+ mctx = &uctx->tuc_mcontext;
+ __put_user(h2g(mctx), &uctx->tuc_regs);
+#endif
+
+ save_user_regs(env, mctx);
+ host_to_target_sigset(&uctx->tuc_sigmask, &ts->signal_mask);
+
+ unlock_user_struct(uctx, uold_ctx, 1);
+ }
+
+ if (unew_ctx) {
+ int err;
+
+ if (!lock_user_struct(VERIFY_READ, uctx, unew_ctx, 1)) {
+ return -TARGET_EFAULT;
+ }
+ err = do_setcontext(uctx, env, 0);
+ unlock_user_struct(uctx, unew_ctx, 1);
+
+ if (err) {
+ /* We cannot return to a partially updated context. */
+ force_sig(TARGET_SIGSEGV);
+ }
+ return -TARGET_QEMU_ESIGRETURN;
+ }
+
+ return 0;
+}
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+ uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+ assert(tramp != NULL);
+
+#ifdef TARGET_ARCH_HAS_SETUP_FRAME
+ default_sigreturn = sigtramp_page;
+ encode_trampoline(TARGET_NR_sigreturn, tramp + 0);
+#endif
+
+ default_rt_sigreturn = sigtramp_page + 8;
+ encode_trampoline(TARGET_NR_rt_sigreturn, tramp + 2);
+
+ unlock_user(tramp, sigtramp_page, 2 * 8);
+}
diff --git a/linux-user/ppc/sockbits.h b/linux-user/ppc/sockbits.h
new file mode 100644
index 000000000..ee453347a
--- /dev/null
+++ b/linux-user/ppc/sockbits.h
@@ -0,0 +1,26 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_SOCKBITS_H
+#define PPC_SOCKBITS_H
+
+#include "../generic/sockbits.h"
+
+#undef TARGET_SO_RCVLOWAT
+#define TARGET_SO_RCVLOWAT 16
+#undef TARGET_SO_SNDLOWAT
+#define TARGET_SO_SNDLOWAT 17
+#undef TARGET_SO_RCVTIMEO
+#define TARGET_SO_RCVTIMEO 18
+#undef TARGET_SO_SNDTIMEO
+#define TARGET_SO_SNDTIMEO 19
+#undef TARGET_SO_PASSCRED
+#define TARGET_SO_PASSCRED 20
+#undef TARGET_SO_PEERCRED
+#define TARGET_SO_PEERCRED 21
+
+#endif
diff --git a/linux-user/ppc/syscall.tbl b/linux-user/ppc/syscall.tbl
new file mode 100644
index 000000000..8f052ff40
--- /dev/null
+++ b/linux-user/ppc/syscall.tbl
@@ -0,0 +1,528 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+#
+# system call numbers and entry vectors for powerpc
+#
+# The format is:
+# <number> <abi> <name> <entry point> <compat entry point>
+#
+# The <abi> can be common, spu, nospu, 64, or 32 for this file.
+#
+0 nospu restart_syscall sys_restart_syscall
+1 nospu exit sys_exit
+2 nospu fork sys_fork
+3 common read sys_read
+4 common write sys_write
+5 common open sys_open compat_sys_open
+6 common close sys_close
+7 common waitpid sys_waitpid
+8 common creat sys_creat
+9 common link sys_link
+10 common unlink sys_unlink
+11 nospu execve sys_execve compat_sys_execve
+12 common chdir sys_chdir
+13 32 time sys_time32
+13 64 time sys_time
+13 spu time sys_time
+14 common mknod sys_mknod
+15 common chmod sys_chmod
+16 common lchown sys_lchown
+17 common break sys_ni_syscall
+18 32 oldstat sys_stat sys_ni_syscall
+18 64 oldstat sys_ni_syscall
+18 spu oldstat sys_ni_syscall
+19 common lseek sys_lseek compat_sys_lseek
+20 common getpid sys_getpid
+21 nospu mount sys_mount
+22 32 umount sys_oldumount
+22 64 umount sys_ni_syscall
+22 spu umount sys_ni_syscall
+23 common setuid sys_setuid
+24 common getuid sys_getuid
+25 32 stime sys_stime32
+25 64 stime sys_stime
+25 spu stime sys_stime
+26 nospu ptrace sys_ptrace compat_sys_ptrace
+27 common alarm sys_alarm
+28 32 oldfstat sys_fstat sys_ni_syscall
+28 64 oldfstat sys_ni_syscall
+28 spu oldfstat sys_ni_syscall
+29 nospu pause sys_pause
+30 32 utime sys_utime32
+30 64 utime sys_utime
+31 common stty sys_ni_syscall
+32 common gtty sys_ni_syscall
+33 common access sys_access
+34 common nice sys_nice
+35 common ftime sys_ni_syscall
+36 common sync sys_sync
+37 common kill sys_kill
+38 common rename sys_rename
+39 common mkdir sys_mkdir
+40 common rmdir sys_rmdir
+41 common dup sys_dup
+42 common pipe sys_pipe
+43 common times sys_times compat_sys_times
+44 common prof sys_ni_syscall
+45 common brk sys_brk
+46 common setgid sys_setgid
+47 common getgid sys_getgid
+48 nospu signal sys_signal
+49 common geteuid sys_geteuid
+50 common getegid sys_getegid
+51 nospu acct sys_acct
+52 nospu umount2 sys_umount
+53 common lock sys_ni_syscall
+54 common ioctl sys_ioctl compat_sys_ioctl
+55 common fcntl sys_fcntl compat_sys_fcntl
+56 common mpx sys_ni_syscall
+57 common setpgid sys_setpgid
+58 common ulimit sys_ni_syscall
+59 32 oldolduname sys_olduname
+59 64 oldolduname sys_ni_syscall
+59 spu oldolduname sys_ni_syscall
+60 common umask sys_umask
+61 common chroot sys_chroot
+62 nospu ustat sys_ustat compat_sys_ustat
+63 common dup2 sys_dup2
+64 common getppid sys_getppid
+65 common getpgrp sys_getpgrp
+66 common setsid sys_setsid
+67 32 sigaction sys_sigaction compat_sys_sigaction
+67 64 sigaction sys_ni_syscall
+67 spu sigaction sys_ni_syscall
+68 common sgetmask sys_sgetmask
+69 common ssetmask sys_ssetmask
+70 common setreuid sys_setreuid
+71 common setregid sys_setregid
+72 32 sigsuspend sys_sigsuspend
+72 64 sigsuspend sys_ni_syscall
+72 spu sigsuspend sys_ni_syscall
+73 32 sigpending sys_sigpending compat_sys_sigpending
+73 64 sigpending sys_ni_syscall
+73 spu sigpending sys_ni_syscall
+74 common sethostname sys_sethostname
+75 common setrlimit sys_setrlimit compat_sys_setrlimit
+76 32 getrlimit sys_old_getrlimit compat_sys_old_getrlimit
+76 64 getrlimit sys_ni_syscall
+76 spu getrlimit sys_ni_syscall
+77 common getrusage sys_getrusage compat_sys_getrusage
+78 common gettimeofday sys_gettimeofday compat_sys_gettimeofday
+79 common settimeofday sys_settimeofday compat_sys_settimeofday
+80 common getgroups sys_getgroups
+81 common setgroups sys_setgroups
+82 32 select ppc_select sys_ni_syscall
+82 64 select sys_ni_syscall
+82 spu select sys_ni_syscall
+83 common symlink sys_symlink
+84 32 oldlstat sys_lstat sys_ni_syscall
+84 64 oldlstat sys_ni_syscall
+84 spu oldlstat sys_ni_syscall
+85 common readlink sys_readlink
+86 nospu uselib sys_uselib
+87 nospu swapon sys_swapon
+88 nospu reboot sys_reboot
+89 32 readdir sys_old_readdir compat_sys_old_readdir
+89 64 readdir sys_ni_syscall
+89 spu readdir sys_ni_syscall
+90 common mmap sys_mmap
+91 common munmap sys_munmap
+92 common truncate sys_truncate compat_sys_truncate
+93 common ftruncate sys_ftruncate compat_sys_ftruncate
+94 common fchmod sys_fchmod
+95 common fchown sys_fchown
+96 common getpriority sys_getpriority
+97 common setpriority sys_setpriority
+98 common profil sys_ni_syscall
+99 nospu statfs sys_statfs compat_sys_statfs
+100 nospu fstatfs sys_fstatfs compat_sys_fstatfs
+101 common ioperm sys_ni_syscall
+102 common socketcall sys_socketcall compat_sys_socketcall
+103 common syslog sys_syslog
+104 common setitimer sys_setitimer compat_sys_setitimer
+105 common getitimer sys_getitimer compat_sys_getitimer
+106 common stat sys_newstat compat_sys_newstat
+107 common lstat sys_newlstat compat_sys_newlstat
+108 common fstat sys_newfstat compat_sys_newfstat
+109 32 olduname sys_uname
+109 64 olduname sys_ni_syscall
+109 spu olduname sys_ni_syscall
+110 common iopl sys_ni_syscall
+111 common vhangup sys_vhangup
+112 common idle sys_ni_syscall
+113 common vm86 sys_ni_syscall
+114 common wait4 sys_wait4 compat_sys_wait4
+115 nospu swapoff sys_swapoff
+116 common sysinfo sys_sysinfo compat_sys_sysinfo
+117 nospu ipc sys_ipc compat_sys_ipc
+118 common fsync sys_fsync
+119 32 sigreturn sys_sigreturn compat_sys_sigreturn
+119 64 sigreturn sys_ni_syscall
+119 spu sigreturn sys_ni_syscall
+120 nospu clone sys_clone
+121 common setdomainname sys_setdomainname
+122 common uname sys_newuname
+123 common modify_ldt sys_ni_syscall
+124 32 adjtimex sys_adjtimex_time32
+124 64 adjtimex sys_adjtimex
+124 spu adjtimex sys_adjtimex
+125 common mprotect sys_mprotect
+126 32 sigprocmask sys_sigprocmask compat_sys_sigprocmask
+126 64 sigprocmask sys_ni_syscall
+126 spu sigprocmask sys_ni_syscall
+127 common create_module sys_ni_syscall
+128 nospu init_module sys_init_module
+129 nospu delete_module sys_delete_module
+130 common get_kernel_syms sys_ni_syscall
+131 nospu quotactl sys_quotactl
+132 common getpgid sys_getpgid
+133 common fchdir sys_fchdir
+134 common bdflush sys_bdflush
+135 common sysfs sys_sysfs
+136 32 personality sys_personality ppc64_personality
+136 64 personality ppc64_personality
+136 spu personality ppc64_personality
+137 common afs_syscall sys_ni_syscall
+138 common setfsuid sys_setfsuid
+139 common setfsgid sys_setfsgid
+140 common _llseek sys_llseek
+141 common getdents sys_getdents compat_sys_getdents
+142 common _newselect sys_select compat_sys_select
+143 common flock sys_flock
+144 common msync sys_msync
+145 common readv sys_readv
+146 common writev sys_writev
+147 common getsid sys_getsid
+148 common fdatasync sys_fdatasync
+149 nospu _sysctl sys_ni_syscall
+150 common mlock sys_mlock
+151 common munlock sys_munlock
+152 common mlockall sys_mlockall
+153 common munlockall sys_munlockall
+154 common sched_setparam sys_sched_setparam
+155 common sched_getparam sys_sched_getparam
+156 common sched_setscheduler sys_sched_setscheduler
+157 common sched_getscheduler sys_sched_getscheduler
+158 common sched_yield sys_sched_yield
+159 common sched_get_priority_max sys_sched_get_priority_max
+160 common sched_get_priority_min sys_sched_get_priority_min
+161 32 sched_rr_get_interval sys_sched_rr_get_interval_time32
+161 64 sched_rr_get_interval sys_sched_rr_get_interval
+161 spu sched_rr_get_interval sys_sched_rr_get_interval
+162 32 nanosleep sys_nanosleep_time32
+162 64 nanosleep sys_nanosleep
+162 spu nanosleep sys_nanosleep
+163 common mremap sys_mremap
+164 common setresuid sys_setresuid
+165 common getresuid sys_getresuid
+166 common query_module sys_ni_syscall
+167 common poll sys_poll
+168 common nfsservctl sys_ni_syscall
+169 common setresgid sys_setresgid
+170 common getresgid sys_getresgid
+171 common prctl sys_prctl
+172 nospu rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn
+173 nospu rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
+174 nospu rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
+175 nospu rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending
+176 32 rt_sigtimedwait sys_rt_sigtimedwait_time32 compat_sys_rt_sigtimedwait_time32
+176 64 rt_sigtimedwait sys_rt_sigtimedwait
+177 nospu rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
+178 nospu rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
+179 common pread64 sys_pread64 compat_sys_pread64
+180 common pwrite64 sys_pwrite64 compat_sys_pwrite64
+181 common chown sys_chown
+182 common getcwd sys_getcwd
+183 common capget sys_capget
+184 common capset sys_capset
+185 nospu sigaltstack sys_sigaltstack compat_sys_sigaltstack
+186 32 sendfile sys_sendfile compat_sys_sendfile
+186 64 sendfile sys_sendfile64
+186 spu sendfile sys_sendfile64
+187 common getpmsg sys_ni_syscall
+188 common putpmsg sys_ni_syscall
+189 nospu vfork sys_vfork
+190 common ugetrlimit sys_getrlimit compat_sys_getrlimit
+191 common readahead sys_readahead compat_sys_readahead
+192 32 mmap2 sys_mmap2 compat_sys_mmap2
+193 32 truncate64 sys_truncate64 compat_sys_truncate64
+194 32 ftruncate64 sys_ftruncate64 compat_sys_ftruncate64
+195 32 stat64 sys_stat64
+196 32 lstat64 sys_lstat64
+197 32 fstat64 sys_fstat64
+198 nospu pciconfig_read sys_pciconfig_read
+199 nospu pciconfig_write sys_pciconfig_write
+200 nospu pciconfig_iobase sys_pciconfig_iobase
+201 common multiplexer sys_ni_syscall
+202 common getdents64 sys_getdents64
+203 common pivot_root sys_pivot_root
+204 32 fcntl64 sys_fcntl64 compat_sys_fcntl64
+205 common madvise sys_madvise
+206 common mincore sys_mincore
+207 common gettid sys_gettid
+208 common tkill sys_tkill
+209 common setxattr sys_setxattr
+210 common lsetxattr sys_lsetxattr
+211 common fsetxattr sys_fsetxattr
+212 common getxattr sys_getxattr
+213 common lgetxattr sys_lgetxattr
+214 common fgetxattr sys_fgetxattr
+215 common listxattr sys_listxattr
+216 common llistxattr sys_llistxattr
+217 common flistxattr sys_flistxattr
+218 common removexattr sys_removexattr
+219 common lremovexattr sys_lremovexattr
+220 common fremovexattr sys_fremovexattr
+221 32 futex sys_futex_time32
+221 64 futex sys_futex
+221 spu futex sys_futex
+222 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity
+223 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
+# 224 unused
+225 common tuxcall sys_ni_syscall
+226 32 sendfile64 sys_sendfile64 compat_sys_sendfile64
+227 common io_setup sys_io_setup compat_sys_io_setup
+228 common io_destroy sys_io_destroy
+229 32 io_getevents sys_io_getevents_time32
+229 64 io_getevents sys_io_getevents
+229 spu io_getevents sys_io_getevents
+230 common io_submit sys_io_submit compat_sys_io_submit
+231 common io_cancel sys_io_cancel
+232 nospu set_tid_address sys_set_tid_address
+233 common fadvise64 sys_fadvise64 ppc32_fadvise64
+234 nospu exit_group sys_exit_group
+235 nospu lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+236 common epoll_create sys_epoll_create
+237 common epoll_ctl sys_epoll_ctl
+238 common epoll_wait sys_epoll_wait
+239 common remap_file_pages sys_remap_file_pages
+240 common timer_create sys_timer_create compat_sys_timer_create
+241 32 timer_settime sys_timer_settime32
+241 64 timer_settime sys_timer_settime
+241 spu timer_settime sys_timer_settime
+242 32 timer_gettime sys_timer_gettime32
+242 64 timer_gettime sys_timer_gettime
+242 spu timer_gettime sys_timer_gettime
+243 common timer_getoverrun sys_timer_getoverrun
+244 common timer_delete sys_timer_delete
+245 32 clock_settime sys_clock_settime32
+245 64 clock_settime sys_clock_settime
+245 spu clock_settime sys_clock_settime
+246 32 clock_gettime sys_clock_gettime32
+246 64 clock_gettime sys_clock_gettime
+246 spu clock_gettime sys_clock_gettime
+247 32 clock_getres sys_clock_getres_time32
+247 64 clock_getres sys_clock_getres
+247 spu clock_getres sys_clock_getres
+248 32 clock_nanosleep sys_clock_nanosleep_time32
+248 64 clock_nanosleep sys_clock_nanosleep
+248 spu clock_nanosleep sys_clock_nanosleep
+249 nospu swapcontext sys_swapcontext compat_sys_swapcontext
+250 common tgkill sys_tgkill
+251 32 utimes sys_utimes_time32
+251 64 utimes sys_utimes
+251 spu utimes sys_utimes
+252 common statfs64 sys_statfs64 compat_sys_statfs64
+253 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
+254 32 fadvise64_64 ppc_fadvise64_64
+254 spu fadvise64_64 sys_ni_syscall
+255 common rtas sys_rtas
+256 32 sys_debug_setcontext sys_debug_setcontext sys_ni_syscall
+256 64 sys_debug_setcontext sys_ni_syscall
+256 spu sys_debug_setcontext sys_ni_syscall
+# 257 reserved for vserver
+258 nospu migrate_pages sys_migrate_pages compat_sys_migrate_pages
+259 nospu mbind sys_mbind compat_sys_mbind
+260 nospu get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
+261 nospu set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
+262 nospu mq_open sys_mq_open compat_sys_mq_open
+263 nospu mq_unlink sys_mq_unlink
+264 32 mq_timedsend sys_mq_timedsend_time32
+264 64 mq_timedsend sys_mq_timedsend
+265 32 mq_timedreceive sys_mq_timedreceive_time32
+265 64 mq_timedreceive sys_mq_timedreceive
+266 nospu mq_notify sys_mq_notify compat_sys_mq_notify
+267 nospu mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
+268 nospu kexec_load sys_kexec_load compat_sys_kexec_load
+269 nospu add_key sys_add_key
+270 nospu request_key sys_request_key
+271 nospu keyctl sys_keyctl compat_sys_keyctl
+272 nospu waitid sys_waitid compat_sys_waitid
+273 nospu ioprio_set sys_ioprio_set
+274 nospu ioprio_get sys_ioprio_get
+275 nospu inotify_init sys_inotify_init
+276 nospu inotify_add_watch sys_inotify_add_watch
+277 nospu inotify_rm_watch sys_inotify_rm_watch
+278 nospu spu_run sys_spu_run
+279 nospu spu_create sys_spu_create
+280 32 pselect6 sys_pselect6_time32 compat_sys_pselect6_time32
+280 64 pselect6 sys_pselect6
+281 32 ppoll sys_ppoll_time32 compat_sys_ppoll_time32
+281 64 ppoll sys_ppoll
+282 common unshare sys_unshare
+283 common splice sys_splice
+284 common tee sys_tee
+285 common vmsplice sys_vmsplice
+286 common openat sys_openat compat_sys_openat
+287 common mkdirat sys_mkdirat
+288 common mknodat sys_mknodat
+289 common fchownat sys_fchownat
+290 32 futimesat sys_futimesat_time32
+290 64 futimesat sys_futimesat
+290 spu utimesat sys_futimesat
+291 32 fstatat64 sys_fstatat64
+291 64 newfstatat sys_newfstatat
+291 spu newfstatat sys_newfstatat
+292 common unlinkat sys_unlinkat
+293 common renameat sys_renameat
+294 common linkat sys_linkat
+295 common symlinkat sys_symlinkat
+296 common readlinkat sys_readlinkat
+297 common fchmodat sys_fchmodat
+298 common faccessat sys_faccessat
+299 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
+300 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
+301 common move_pages sys_move_pages compat_sys_move_pages
+302 common getcpu sys_getcpu
+303 nospu epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
+304 32 utimensat sys_utimensat_time32
+304 64 utimensat sys_utimensat
+304 spu utimensat sys_utimensat
+305 common signalfd sys_signalfd compat_sys_signalfd
+306 common timerfd_create sys_timerfd_create
+307 common eventfd sys_eventfd
+308 common sync_file_range2 sys_sync_file_range2 compat_sys_sync_file_range2
+309 nospu fallocate sys_fallocate compat_sys_fallocate
+310 nospu subpage_prot sys_subpage_prot
+311 32 timerfd_settime sys_timerfd_settime32
+311 64 timerfd_settime sys_timerfd_settime
+311 spu timerfd_settime sys_timerfd_settime
+312 32 timerfd_gettime sys_timerfd_gettime32
+312 64 timerfd_gettime sys_timerfd_gettime
+312 spu timerfd_gettime sys_timerfd_gettime
+313 common signalfd4 sys_signalfd4 compat_sys_signalfd4
+314 common eventfd2 sys_eventfd2
+315 common epoll_create1 sys_epoll_create1
+316 common dup3 sys_dup3
+317 common pipe2 sys_pipe2
+318 nospu inotify_init1 sys_inotify_init1
+319 common perf_event_open sys_perf_event_open
+320 common preadv sys_preadv compat_sys_preadv
+321 common pwritev sys_pwritev compat_sys_pwritev
+322 nospu rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
+323 nospu fanotify_init sys_fanotify_init
+324 nospu fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark
+325 common prlimit64 sys_prlimit64
+326 common socket sys_socket
+327 common bind sys_bind
+328 common connect sys_connect
+329 common listen sys_listen
+330 common accept sys_accept
+331 common getsockname sys_getsockname
+332 common getpeername sys_getpeername
+333 common socketpair sys_socketpair
+334 common send sys_send
+335 common sendto sys_sendto
+336 common recv sys_recv compat_sys_recv
+337 common recvfrom sys_recvfrom compat_sys_recvfrom
+338 common shutdown sys_shutdown
+339 common setsockopt sys_setsockopt sys_setsockopt
+340 common getsockopt sys_getsockopt sys_getsockopt
+341 common sendmsg sys_sendmsg compat_sys_sendmsg
+342 common recvmsg sys_recvmsg compat_sys_recvmsg
+343 32 recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32
+343 64 recvmmsg sys_recvmmsg
+343 spu recvmmsg sys_recvmmsg
+344 common accept4 sys_accept4
+345 common name_to_handle_at sys_name_to_handle_at
+346 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at
+347 32 clock_adjtime sys_clock_adjtime32
+347 64 clock_adjtime sys_clock_adjtime
+347 spu clock_adjtime sys_clock_adjtime
+348 common syncfs sys_syncfs
+349 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
+350 common setns sys_setns
+351 nospu process_vm_readv sys_process_vm_readv
+352 nospu process_vm_writev sys_process_vm_writev
+353 nospu finit_module sys_finit_module
+354 nospu kcmp sys_kcmp
+355 common sched_setattr sys_sched_setattr
+356 common sched_getattr sys_sched_getattr
+357 common renameat2 sys_renameat2
+358 common seccomp sys_seccomp
+359 common getrandom sys_getrandom
+360 common memfd_create sys_memfd_create
+361 common bpf sys_bpf
+362 nospu execveat sys_execveat compat_sys_execveat
+363 32 switch_endian sys_ni_syscall
+363 64 switch_endian sys_switch_endian
+363 spu switch_endian sys_ni_syscall
+364 common userfaultfd sys_userfaultfd
+365 common membarrier sys_membarrier
+# 366-377 originally left for IPC, now unused
+378 nospu mlock2 sys_mlock2
+379 nospu copy_file_range sys_copy_file_range
+380 common preadv2 sys_preadv2 compat_sys_preadv2
+381 common pwritev2 sys_pwritev2 compat_sys_pwritev2
+382 nospu kexec_file_load sys_kexec_file_load
+383 nospu statx sys_statx
+384 nospu pkey_alloc sys_pkey_alloc
+385 nospu pkey_free sys_pkey_free
+386 nospu pkey_mprotect sys_pkey_mprotect
+387 nospu rseq sys_rseq
+388 32 io_pgetevents sys_io_pgetevents_time32 compat_sys_io_pgetevents
+388 64 io_pgetevents sys_io_pgetevents
+# room for arch specific syscalls
+392 64 semtimedop sys_semtimedop
+393 common semget sys_semget
+394 common semctl sys_semctl compat_sys_semctl
+395 common shmget sys_shmget
+396 common shmctl sys_shmctl compat_sys_shmctl
+397 common shmat sys_shmat compat_sys_shmat
+398 common shmdt sys_shmdt
+399 common msgget sys_msgget
+400 common msgsnd sys_msgsnd compat_sys_msgsnd
+401 common msgrcv sys_msgrcv compat_sys_msgrcv
+402 common msgctl sys_msgctl compat_sys_msgctl
+403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime
+404 32 clock_settime64 sys_clock_settime sys_clock_settime
+405 32 clock_adjtime64 sys_clock_adjtime sys_clock_adjtime
+406 32 clock_getres_time64 sys_clock_getres sys_clock_getres
+407 32 clock_nanosleep_time64 sys_clock_nanosleep sys_clock_nanosleep
+408 32 timer_gettime64 sys_timer_gettime sys_timer_gettime
+409 32 timer_settime64 sys_timer_settime sys_timer_settime
+410 32 timerfd_gettime64 sys_timerfd_gettime sys_timerfd_gettime
+411 32 timerfd_settime64 sys_timerfd_settime sys_timerfd_settime
+412 32 utimensat_time64 sys_utimensat sys_utimensat
+413 32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64
+414 32 ppoll_time64 sys_ppoll compat_sys_ppoll_time64
+416 32 io_pgetevents_time64 sys_io_pgetevents sys_io_pgetevents
+417 32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64
+418 32 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend
+419 32 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive
+420 32 semtimedop_time64 sys_semtimedop sys_semtimedop
+421 32 rt_sigtimedwait_time64 sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time64
+422 32 futex_time64 sys_futex sys_futex
+423 32 sched_rr_get_interval_time64 sys_sched_rr_get_interval sys_sched_rr_get_interval
+424 common pidfd_send_signal sys_pidfd_send_signal
+425 common io_uring_setup sys_io_uring_setup
+426 common io_uring_enter sys_io_uring_enter
+427 common io_uring_register sys_io_uring_register
+428 common open_tree sys_open_tree
+429 common move_mount sys_move_mount
+430 common fsopen sys_fsopen
+431 common fsconfig sys_fsconfig
+432 common fsmount sys_fsmount
+433 common fspick sys_fspick
+434 common pidfd_open sys_pidfd_open
+435 nospu clone3 sys_clone3
+436 common close_range sys_close_range
+437 common openat2 sys_openat2
+438 common pidfd_getfd sys_pidfd_getfd
+439 common faccessat2 sys_faccessat2
+440 common process_madvise sys_process_madvise
+441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2
+442 common mount_setattr sys_mount_setattr
+# 443 reserved for quotactl_path
+444 common landlock_create_ruleset sys_landlock_create_ruleset
+445 common landlock_add_rule sys_landlock_add_rule
+446 common landlock_restrict_self sys_landlock_restrict_self
diff --git a/linux-user/ppc/syscallhdr.sh b/linux-user/ppc/syscallhdr.sh
new file mode 100644
index 000000000..6c44e0eaa
--- /dev/null
+++ b/linux-user/ppc/syscallhdr.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+prefix="$4"
+offset="$5"
+
+fileguard=LINUX_USER_PPC_`basename "$out" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'`
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | (
+ printf "#ifndef %s\n" "${fileguard}"
+ printf "#define %s\n" "${fileguard}"
+ printf "\n"
+
+ while read nr abi name entry compat ; do
+ if [ "$entry" = "sys_ni_syscall" ] ; then
+ continue
+ fi
+ if [ -z "$offset" ]; then
+ printf "#define TARGET_NR_%s%s\t%s\n" \
+ "${prefix}" "${name}" "${nr}"
+ else
+ printf "#define TARGET_NR_%s%s\t(%s + %s)\n" \
+ "${prefix}" "${name}" "${offset}" "${nr}"
+ fi
+ done
+
+ printf "\n"
+ printf "#endif /* %s */" "${fileguard}"
+ printf "\n"
+) > "$out"
diff --git a/linux-user/ppc/target_cpu.h b/linux-user/ppc/target_cpu.h
new file mode 100644
index 000000000..51ee1481b
--- /dev/null
+++ b/linux-user/ppc/target_cpu.h
@@ -0,0 +1,59 @@
+/*
+ * PowerPC specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef PPC_TARGET_CPU_H
+#define PPC_TARGET_CPU_H
+
+static inline void cpu_clone_regs_child(CPUPPCState *env, target_ulong newsp,
+ unsigned flags)
+{
+ if (newsp) {
+ env->gpr[1] = newsp;
+ }
+ env->gpr[3] = 0;
+}
+
+static inline void cpu_clone_regs_parent(CPUPPCState *env, unsigned flags)
+{
+}
+
+static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls)
+{
+#if defined(TARGET_PPC64)
+ /* The kernel checks TIF_32BIT here; we don't support loading 32-bit
+ binaries on PPC64 yet. */
+ env->gpr[13] = newtls;
+#else
+ env->gpr[2] = newtls;
+#endif
+}
+
+#ifndef EF_PPC64_ABI
+#define EF_PPC64_ABI 0x3
+#endif
+
+static inline uint32_t get_ppc64_abi(struct image_info *infop)
+{
+ return infop->elf_flags & EF_PPC64_ABI;
+}
+
+static inline abi_ulong get_sp_from_cpustate(CPUPPCState *state)
+{
+ return state->gpr[1];
+}
+#endif
diff --git a/linux-user/ppc/target_elf.h b/linux-user/ppc/target_elf.h
new file mode 100644
index 000000000..061661885
--- /dev/null
+++ b/linux-user/ppc/target_elf.h
@@ -0,0 +1,18 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_TARGET_ELF_H
+#define PPC_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+#ifdef TARGET_PPC64
+ return "POWER9";
+#else
+ return "750";
+#endif
+}
+#endif
diff --git a/linux-user/ppc/target_errno_defs.h b/linux-user/ppc/target_errno_defs.h
new file mode 100644
index 000000000..a24a97334
--- /dev/null
+++ b/linux-user/ppc/target_errno_defs.h
@@ -0,0 +1,7 @@
+#ifndef PPC_TARGET_ERRNO_DEFS_H
+#define PPC_TARGET_ERRNO_DEFS_H
+
+/* Target uses generic errno */
+#include "../generic/target_errno_defs.h"
+
+#endif
diff --git a/linux-user/ppc/target_fcntl.h b/linux-user/ppc/target_fcntl.h
new file mode 100644
index 000000000..d74ab710c
--- /dev/null
+++ b/linux-user/ppc/target_fcntl.h
@@ -0,0 +1,17 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_TARGET_FCNTL_H
+#define PPC_TARGET_FCNTL_H
+
+#define TARGET_O_DIRECTORY 040000 /* must be a directory */
+#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */
+#define TARGET_O_LARGEFILE 0200000
+#define TARGET_O_DIRECT 0400000 /* direct disk access hint */
+
+#include "../generic/fcntl.h"
+#endif
diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h
new file mode 100644
index 000000000..82184ab8f
--- /dev/null
+++ b/linux-user/ppc/target_signal.h
@@ -0,0 +1,29 @@
+#ifndef PPC_TARGET_SIGNAL_H
+#define PPC_TARGET_SIGNAL_H
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_int ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+#include "../generic/signal.h"
+
+#if !defined(TARGET_PPC64)
+#define TARGET_ARCH_HAS_SETUP_FRAME
+#endif
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
+#endif /* PPC_TARGET_SIGNAL_H */
diff --git a/linux-user/ppc/target_structs.h b/linux-user/ppc/target_structs.h
new file mode 100644
index 000000000..520e32664
--- /dev/null
+++ b/linux-user/ppc/target_structs.h
@@ -0,0 +1,60 @@
+/*
+ * PowerPC specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef PPC_TARGET_STRUCTS_H
+#define PPC_TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+ abi_int __key; /* Key. */
+ abi_uint uid; /* Owner's user ID. */
+ abi_uint gid; /* Owner's group ID. */
+ abi_uint cuid; /* Creator's user ID. */
+ abi_uint cgid; /* Creator's group ID. */
+ abi_uint mode; /* Read/write permission. */
+ uint32_t __seq; /* Sequence number. */
+ uint32_t __pad1;
+ uint64_t __unused1;
+ uint64_t __unused2;
+};
+
+struct target_shmid_ds {
+ struct target_ipc_perm shm_perm; /* operation permission struct */
+#if TARGET_ABI_BITS == 32
+ abi_uint __unused1;
+#endif
+ abi_ulong shm_atime; /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+ abi_uint __unused2;
+#endif
+ abi_ulong shm_dtime; /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+ abi_uint __unused3;
+#endif
+ abi_ulong shm_ctime; /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+ abi_uint __unused4;
+#endif
+ abi_long shm_segsz; /* size of segment in bytes */
+ abi_int shm_cpid; /* pid of creator */
+ abi_int shm_lpid; /* pid of last shmop */
+ abi_ulong shm_nattch; /* number of current attaches */
+ abi_ulong __unused5;
+ abi_ulong __unused6;
+};
+
+#endif
diff --git a/linux-user/ppc/target_syscall.h b/linux-user/ppc/target_syscall.h
new file mode 100644
index 000000000..b9c4b813d
--- /dev/null
+++ b/linux-user/ppc/target_syscall.h
@@ -0,0 +1,80 @@
+/*
+ * PPC emulation for qemu: syscall definitions.
+ *
+ * Copyright (c) 2003 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PPC_TARGET_SYSCALL_H
+#define PPC_TARGET_SYSCALL_H
+
+/* XXX: ABSOLUTELY BUGGY:
+ * for now, this is quite just a cut-and-paste from i386 target...
+ */
+
+/* default linux values for the selectors */
+#define __USER_DS (1)
+
+struct target_pt_regs {
+ abi_ulong gpr[32];
+ abi_ulong nip;
+ abi_ulong msr;
+ abi_ulong orig_gpr3; /* Used for restarting system calls */
+ abi_ulong ctr;
+ abi_ulong link;
+ abi_ulong xer;
+ abi_ulong ccr;
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+ abi_ulong softe;
+#else
+ abi_ulong mq; /* 601 only (not used at present) */
+#endif
+ /* Used on APUS to hold IPL value. */
+ abi_ulong trap; /* Reason for being here */
+ abi_ulong dar; /* Fault registers */
+ abi_ulong dsisr;
+ abi_ulong result; /* Result of a system call */
+};
+
+/* ioctls */
+struct target_revectored_struct {
+ abi_ulong __map[8]; /* 256 bits */
+};
+
+
+/*
+ * flags masks
+ */
+
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+#ifdef TARGET_WORDS_BIGENDIAN
+#define UNAME_MACHINE "ppc64"
+#else
+#define UNAME_MACHINE "ppc64le"
+#endif
+#else
+#define UNAME_MACHINE "ppc"
+#endif
+#define UNAME_MINIMUM_RELEASE "2.6.32"
+
+#define TARGET_CLONE_BACKWARDS
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_MCL_CURRENT 0x2000
+#define TARGET_MCL_FUTURE 0x4000
+#define TARGET_MCL_ONFAULT 0x8000
+#define TARGET_WANT_NI_OLD_SELECT
+
+#endif /* PPC_TARGET_SYSCALL_H */
diff --git a/linux-user/ppc/termbits.h b/linux-user/ppc/termbits.h
new file mode 100644
index 000000000..eb226e099
--- /dev/null
+++ b/linux-user/ppc/termbits.h
@@ -0,0 +1,247 @@
+/* from asm/termbits.h */
+
+#ifndef LINUX_USER_PPC_TERMBITS_H
+#define LINUX_USER_PPC_TERMBITS_H
+
+#define TARGET_NCCS 19
+
+typedef unsigned char target_cc_t; /* cc_t */
+typedef unsigned int target_speed_t; /* speed_t */
+typedef unsigned int target_tcflag_t; /* tcflag_t */
+
+struct target_termios {
+ target_tcflag_t c_iflag; /* input mode flags */
+ target_tcflag_t c_oflag; /* output mode flags */
+ target_tcflag_t c_cflag; /* control mode flags */
+ target_tcflag_t c_lflag; /* local mode flags */
+ target_cc_t c_cc[TARGET_NCCS]; /* control characters */
+ target_cc_t c_line; /* line discipline */
+ target_speed_t c_ispeed; /* input speed */
+ target_speed_t c_ospeed; /* output speed */
+};
+
+/* c_cc character offsets */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VEOF 4
+#define TARGET_VMIN 5
+#define TARGET_VEOL 6
+#define TARGET_VTIME 7
+#define TARGET_VEOL2 8
+#define TARGET_VSWTC 9
+
+#define TARGET_VWERASE 10
+#define TARGET_VREPRINT 11
+#define TARGET_VSUSP 12
+#define TARGET_VSTART 13
+#define TARGET_VSTOP 14
+#define TARGET_VLNEXT 15
+#define TARGET_VDISCARD 16
+
+#define TARGET_IGNBRK 0000001
+#define TARGET_BRKINT 0000002
+#define TARGET_IGNPAR 0000004
+#define TARGET_PARMRK 0000010
+#define TARGET_INPCK 0000020
+#define TARGET_ISTRIP 0000040
+#define TARGET_INLCR 0000100
+#define TARGET_IGNCR 0000200
+#define TARGET_ICRNL 0000400
+#define TARGET_IXON 0001000
+#define TARGET_IXOFF 0002000
+#define TARGET_IXANY 0004000
+#define TARGET_IUCLC 0010000
+#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST 0000001
+#define TARGET_ONLCR 0000002
+#define TARGET_OLCUC 0000004
+
+#define TARGET_OCRNL 0000010
+#define TARGET_ONOCR 0000020
+#define TARGET_ONLRET 0000040
+
+#define TARGET_OFILL 00000100
+#define TARGET_OFDEL 00000200
+#define TARGET_NLDLY 00001400
+#define TARGET_NL0 00000000
+#define TARGET_NL1 00000400
+#define TARGET_NL2 00001000
+#define TARGET_NL3 00001400
+#define TARGET_TABDLY 00006000
+#define TARGET_TAB0 00000000
+#define TARGET_TAB1 00002000
+#define TARGET_TAB2 00004000
+#define TARGET_TAB3 00006000
+#define TARGET_XTABS 00006000 /* required by POSIX to == TAB3 */
+#define TARGET_CRDLY 00030000
+#define TARGET_CR0 00000000
+#define TARGET_CR1 00010000
+#define TARGET_CR2 00020000
+#define TARGET_CR3 00030000
+#define TARGET_FFDLY 00040000
+#define TARGET_FF0 00000000
+#define TARGET_FF1 00040000
+#define TARGET_BSDLY 00100000
+#define TARGET_BS0 00000000
+#define TARGET_BS1 00100000
+#define TARGET_VTDLY 00200000
+#define TARGET_VT0 00000000
+#define TARGET_VT1 00200000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD 0000377
+#define TARGET_B0 0000000 /* hang up */
+#define TARGET_B50 0000001
+#define TARGET_B75 0000002
+#define TARGET_B110 0000003
+#define TARGET_B134 0000004
+#define TARGET_B150 0000005
+#define TARGET_B200 0000006
+#define TARGET_B300 0000007
+#define TARGET_B600 0000010
+#define TARGET_B1200 0000011
+#define TARGET_B1800 0000012
+#define TARGET_B2400 0000013
+#define TARGET_B4800 0000014
+#define TARGET_B9600 0000015
+#define TARGET_B19200 0000016
+#define TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CBAUDEX 0000000
+#define TARGET_B57600 00020
+#define TARGET_B115200 00021
+#define TARGET_B230400 00022
+#define TARGET_B460800 00023
+#define TARGET_B500000 00024
+#define TARGET_B576000 00025
+#define TARGET_B921600 00026
+#define TARGET_B1000000 00027
+#define TARGET_B1152000 00030
+#define TARGET_B1500000 00031
+#define TARGET_B2000000 00032
+#define TARGET_B2500000 00033
+#define TARGET_B3000000 00034
+#define TARGET_B3500000 00035
+#define TARGET_B4000000 00036
+
+#define TARGET_CSIZE 00001400
+#define TARGET_CS5 00000000
+#define TARGET_CS6 00000400
+#define TARGET_CS7 00001000
+#define TARGET_CS8 00001400
+
+#define TARGET_CSTOPB 00002000
+#define TARGET_CREAD 00004000
+#define TARGET_PARENB 00010000
+#define TARGET_PARODD 00020000
+#define TARGET_HUPCL 00040000
+
+#define TARGET_CLOCAL 00100000
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG 0x00000080
+#define TARGET_ICANON 0x00000100
+#define TARGET_XCASE 0x00004000
+#define TARGET_ECHO 0x00000008
+#define TARGET_ECHOE 0x00000002
+#define TARGET_ECHOK 0x00000004
+#define TARGET_ECHONL 0x00000010
+#define TARGET_NOFLSH 0x80000000
+#define TARGET_TOSTOP 0x00400000
+#define TARGET_ECHOCTL 0x00000040
+#define TARGET_ECHOPRT 0x00000020
+#define TARGET_ECHOKE 0x00000001
+#define TARGET_FLUSHO 0x00800000
+#define TARGET_PENDIN 0x20000000
+#define TARGET_IEXTEN 0x00000400
+#define TARGET_EXTPROC 0x10000000
+
+/* ioctls */
+
+#define TARGET_FIOCLEX TARGET_IO('f', 1)
+#define TARGET_FIONCLEX TARGET_IO('f', 2)
+#define TARGET_FIOASYNC TARGET_IOW('f', 125, int)
+#define TARGET_FIONBIO TARGET_IOW('f', 126, int)
+#define TARGET_FIONREAD TARGET_IOR('f', 127, int)
+#define TARGET_TIOCINQ TARGET_FIONREAD
+//#define TARGET_FIOQSIZE TARGET_IOR('f', 128, loff_t)
+
+#define TARGET_TCGETS TARGET_IOR('t', 19, struct target_termios)
+#define TARGET_TCSETS TARGET_IOW('t', 20, struct target_termios)
+#define TARGET_TCSETSW TARGET_IOW('t', 21, struct target_termios)
+#define TARGET_TCSETSF TARGET_IOW('t', 22, struct target_termios)
+
+#define TARGET_TCGETA TARGET_IOR('t', 23, struct target_termio)
+#define TARGET_TCSETA TARGET_IOW('t', 24, struct target_termio)
+#define TARGET_TCSETAW TARGET_IOW('t', 25, struct target_termio)
+#define TARGET_TCSETAF TARGET_IOW('t', 28, struct target_termio)
+
+#define TARGET_TCSBRK TARGET_IO('t', 29)
+#define TARGET_TCXONC TARGET_IO('t', 30)
+#define TARGET_TCFLSH TARGET_IO('t', 31)
+
+#define TARGET_TIOCSWINSZ TARGET_IOW('t', 103, struct target_winsize)
+#define TARGET_TIOCGWINSZ TARGET_IOR('t', 104, struct target_winsize)
+#define TARGET_TIOCSTART TARGET_IO('t', 110) /* start output, like ^Q */
+#define TARGET_TIOCSTOP TARGET_IO('t', 111) /* stop output, like ^S */
+#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int) /* output queue size */
+
+#define TARGET_TIOCGLTC TARGET_IOR('t', 116, struct target_ltchars)
+#define TARGET_TIOCSLTC TARGET_IOW('t', 117, struct target_ltchars)
+#define TARGET_TIOCSPGRP TARGET_IOW('t', 118, int)
+#define TARGET_TIOCGPGRP TARGET_IOR('t', 119, int)
+
+#define TARGET_TIOCEXCL 0x540C
+#define TARGET_TIOCNXCL 0x540D
+#define TARGET_TIOCSCTTY 0x540E
+
+#define TARGET_TIOCSTI 0x5412
+#define TARGET_TIOCMGET 0x5415
+#define TARGET_TIOCMBIS 0x5416
+#define TARGET_TIOCMBIC 0x5417
+#define TARGET_TIOCMSET 0x5418
+
+#define TARGET_TIOCGSOFTCAR 0x5419
+#define TARGET_TIOCSSOFTCAR 0x541A
+#define TARGET_TIOCLINUX 0x541C
+#define TARGET_TIOCCONS 0x541D
+#define TARGET_TIOCGSERIAL 0x541E
+#define TARGET_TIOCSSERIAL 0x541F
+#define TARGET_TIOCPKT 0x5420
+
+#define TARGET_TIOCNOTTY 0x5422
+#define TARGET_TIOCSETD 0x5423
+#define TARGET_TIOCGETD 0x5424
+#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
+#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
+#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
+#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */
+
+#define TARGET_TIOCSERCONFIG 0x5453
+#define TARGET_TIOCSERGWILD 0x5454
+#define TARGET_TIOCSERSWILD 0x5455
+#define TARGET_TIOCGLCKTRMIOS 0x5456
+#define TARGET_TIOCSLCKTRMIOS 0x5457
+#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
+ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+
+#endif