Index: Makefile =================================================================== --- Makefile (revision 358452) +++ Makefile (working copy) @@ -3,7 +3,7 @@ PORTNAME= qemu PORTVERSION= 2.0.0 -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= emulators MASTER_SITES= http://wiki.qemu.org/download/:release \ LOCAL/nox:snapshot @@ -68,6 +68,7 @@ EXTRA_PATCHES+= ${FILESDIR}/extra-patch-sysctl-0ol EXTRA_PATCHES+= ${FILESDIR}/extra-patch-bsd-user-mmap.c EXTRA_PATCHES+= ${FILESDIR}/extra-patch-sysctl-hw-pagesizes EXTRA_PATCHES+= ${FILESDIR}/extra-patch-bsd-user-x86_64-target_arch_vmparam.h +EXTRA_PATCHES+= ${FILESDIR}/extra-patch-ppc-001 .endif CONFIGURE_ARGS+= --extra-ldflags=-L${LOCALBASE}/lib @@ -76,17 +77,17 @@ PORTDOCS= docs qemu-doc.html qemu-tech.html qmp-co .if defined(QEMU_USER_STATIC) .if ${ARCH} != "amd64" -CONFIGURE_ARGS+= --target-list=i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user +CONFIGURE_ARGS+= --target-list=i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user,ppc-bsd-user .else -CONFIGURE_ARGS+= --target-list=i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user,mips64el-bsd-user +CONFIGURE_ARGS+= --target-list=i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user,mips64el-bsd-user,ppc-bsd-user,ppc64-bsd-user .endif .else .if ${PORT_OPTIONS:MX86_TARGETS} .if ${PORT_OPTIONS:MBSD_USER} .if ${ARCH} != "amd64" -CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user +CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user,ppc-bsd-user .else -CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user,mips64el-bsd-user +CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user,mips64el-bsd-user,ppc-bsd-user,ppc64-bsd-user .endif .else CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu @@ -96,7 +97,7 @@ CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64 CONFIGURE_ARGS+= --disable-bsd-user .else .if ${ARCH} != "amd64" -CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,aarch64-softmmu,alpha-softmmu,arm-softmmu,cris-softmmu,lm32-softmmu,m68k-softmmu,microblaze-softmmu,microblazeel-softmmu,mips-softmmu,mipsel-softmmu,mips64-softmmu,mips64el-softmmu,or32-softmmu,ppc-softmmu,ppcemb-softmmu,ppc64-softmmu,sh4-softmmu,sh4eb-softmmu,sparc-softmmu,sparc64-softmmu,s390x-softmmu,xtensa-softmmu,xtensaeb-softmmu,unicore32-softmmu,moxie-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user +CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,aarch64-softmmu,alpha-softmmu,arm-softmmu,cris-softmmu,lm32-softmmu,m68k-softmmu,microblaze-softmmu,microblazeel-softmmu,mips-softmmu,mipsel-softmmu,mips64-softmmu,mips64el-softmmu,or32-softmmu,ppc-softmmu,ppcemb-softmmu,ppc64-softmmu,sh4-softmmu,sh4eb-softmmu,sparc-softmmu,sparc64-softmmu,s390x-softmmu,xtensa-softmmu,xtensaeb-softmmu,unicore32-softmmu,moxie-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user,ppc-bsd-user .endif .endif .endif Index: files/extra-patch-ppc-001 =================================================================== --- files/extra-patch-ppc-001 (revision 0) +++ files/extra-patch-ppc-001 (working copy) @@ -0,0 +1,1304 @@ +From 018d7d9129963bc238a6aafc90d649660289ed1e Mon Sep 17 00:00:00 2001 +From: Justin Hibbits +Date: Mon, 26 May 2014 16:24:05 -0700 +Subject: [PATCH] First cut of PowerPC(64) bsd-user + +--- + bsd-user/freebsd/os-sys.c | 3 +- + bsd-user/freebsd/os-thread.c | 5 +- + bsd-user/freebsd/os-thread.h | 2 +- + bsd-user/freebsd/target_os_siginfo.h | 15 + + bsd-user/main.c | 13 +- + bsd-user/ppc/syscall.h | 56 ++++ + bsd-user/ppc/target_arch.h | 7 + + bsd-user/ppc/target_arch_cpu.c | 62 ++++ + bsd-user/ppc/target_arch_cpu.h | 555 +++++++++++++++++++++++++++++++++++ + bsd-user/ppc/target_arch_elf.h | 66 +++++ + bsd-user/ppc/target_arch_signal.h | 223 ++++++++++++++ + bsd-user/ppc/target_arch_sigtramp.h | 43 +++ + bsd-user/ppc/target_arch_sysarch.h | 36 +++ + bsd-user/ppc/target_arch_thread.h | 65 ++++ + bsd-user/ppc/target_arch_vmparam.h | 52 ++++ + bsd-user/signal.c | 14 +- + default-configs/ppc-bsd-user.mak | 1 + + default-configs/ppc64-bsd-user.mak | 1 + + 18 files changed, 1204 insertions(+), 15 deletions(-) + create mode 100644 bsd-user/ppc/syscall.h + create mode 100644 bsd-user/ppc/target_arch.h + create mode 100644 bsd-user/ppc/target_arch_cpu.c + create mode 100644 bsd-user/ppc/target_arch_cpu.h + create mode 100644 bsd-user/ppc/target_arch_elf.h + create mode 100644 bsd-user/ppc/target_arch_signal.h + create mode 100644 bsd-user/ppc/target_arch_sigtramp.h + create mode 100644 bsd-user/ppc/target_arch_sysarch.h + create mode 100644 bsd-user/ppc/target_arch_thread.h + create mode 100644 bsd-user/ppc/target_arch_vmparam.h + create mode 100644 default-configs/ppc-bsd-user.mak + create mode 100644 default-configs/ppc64-bsd-user.mak + +diff --git a/bsd-user/freebsd/target_os_siginfo.h b/bsd-user/freebsd/target_os_siginfo.h +index 39180ec..206b878 100644 +--- a/bsd-user/freebsd/target_os_siginfo.h ++++ b/bsd-user/freebsd/target_os_siginfo.h +@@ -107,4 +107,19 @@ typedef struct target_siginfo { + #define TARGET_TRAP_BRKPT (1) /* process beakpoint */ + #define TARGET_TRAP_TRACE (2) /* process trace trap */ + ++/* SIGBUS si_codes */ ++#define TARGET_BUS_ADRALN (1) ++#define TARGET_BUS_ADRERR (2) ++#define TARGET_BUS_OBJERR (3) ++ ++/* SIGFPE codes */ ++#define TARGET_FPE_INTOVF (1) /* Integer overflow. */ ++#define TARGET_FPE_INTDIV (2) /* Integer divide by zero. */ ++#define TARGET_FPE_FLTDIV (3) /* Floating point divide by zero. */ ++#define TARGET_FPE_FLTOVF (4) /* Floating point overflow. */ ++#define TARGET_FPE_FLTUND (5) /* Floating point underflow. */ ++#define TARGET_FPE_FLTRES (6) /* Floating point inexact result. */ ++#define TARGET_FPE_FLTINV (7) /* Invalid floating point operation. */ ++#define TARGET_FPE_FLTSUB (8) /* Subscript out of range. */ ++ + #endif /* !_TARGET_OS_SIGINFO_H_ */ +diff --git a/bsd-user/ppc/syscall.h b/bsd-user/ppc/syscall.h +new file mode 100644 +index 0000000..5d71f8d +--- /dev/null ++++ b/bsd-user/ppc/syscall.h +@@ -0,0 +1,56 @@ ++/* ++ * powerpc system call definitions ++ * ++ * ++ * 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 . ++ */ ++#ifndef _POWERPC_SYSCALL_H_ ++#define _POWERPC_SYSCALL_H_ ++ ++/* ++ * struct target_pt_regs defines the way the registers are stored on the stack ++ * during a system call. ++ */ ++ ++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 lr; ++ 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 */ ++}; ++ ++ ++#define UNAME_MACHINE "powerpc" ++#define TARGET_HW_MACHINE "powerpc" ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE"64" ++#else ++#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE ++#endif ++ ++#endif /* !_POWERPC_SYSCALL_H_ */ +diff --git a/bsd-user/ppc/target_arch.h b/bsd-user/ppc/target_arch.h +new file mode 100644 +index 0000000..0e1d73c +--- /dev/null ++++ b/bsd-user/ppc/target_arch.h +@@ -0,0 +1,7 @@ ++ ++#ifndef _TARGET_ARCH_H_ ++#define _TARGET_ARCH_H_ ++ ++#include "qemu.h" ++ ++#endif /* !_TARGET_ARCH_H_ */ +diff --git a/bsd-user/ppc/target_arch_cpu.c b/bsd-user/ppc/target_arch_cpu.c +new file mode 100644 +index 0000000..6e74217 +--- /dev/null ++++ b/bsd-user/ppc/target_arch_cpu.c +@@ -0,0 +1,62 @@ ++/* ++ * powerpc cpu related code ++ * ++ * 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 . ++ */ ++#include "target_arch.h" ++ ++static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) ++{ ++ /* TO FIX */ ++ return 0; ++} ++ ++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; ++} ++ ++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; ++} +diff --git a/bsd-user/ppc/target_arch_cpu.h b/bsd-user/ppc/target_arch_cpu.h +new file mode 100644 +index 0000000..19b634d +--- /dev/null ++++ b/bsd-user/ppc/target_arch_cpu.h +@@ -0,0 +1,555 @@ ++/* ++ * powerpc cpu init and loop ++ * ++ * ++ * 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 . ++ */ ++ ++#ifndef _TARGET_ARCH_CPU_H_ ++#define _TARGET_ARCH_CPU_H_ ++ ++#include "target_arch.h" ++ ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++#define TARGET_DEFAULT_CPU_MODEL "ppc64" ++#else ++#define TARGET_DEFAULT_CPU_MODEL "ppc" ++#endif ++ ++#define TARGET_CPU_RESET(env) ++ ++static inline void target_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 ++} ++ ++static inline void target_cpu_init(CPUPPCState *env, ++ struct target_pt_regs *regs) ++{ ++ int i; ++ ++ for (i = 0; i < 32; i++) { ++ env->gpr[i] = regs->gpr[i]; ++ } ++ env->nip = regs->nip; ++} ++ ++static int do_store_exclusive(CPUPPCState *env) ++{ ++ target_ulong addr; ++ target_ulong page_addr; ++ target_ulong val, val2 __attribute__((unused)); ++ int flags; ++ int segv = 0; ++ ++ addr = env->reserve_ea; ++ page_addr = addr & TARGET_PAGE_MASK; ++ start_exclusive(); ++ mmap_lock(); ++ flags = page_get_flags(page_addr); ++ if ((flags & PAGE_READ) == 0) { ++ segv = 1; ++ } else { ++ int reg = env->reserve_info & 0x1f; ++ int size = (env->reserve_info >> 5) & 0xf; ++ int stored = 0; ++ ++ if (addr == env->reserve_addr) { ++ switch (size) { ++ case 1: segv = get_user_u8(val, addr); break; ++ case 2: segv = get_user_u16(val, addr); break; ++ case 4: segv = get_user_u32(val, addr); break; ++#if defined(TARGET_PPC64) ++ case 8: segv = get_user_u64(val, addr); break; ++ case 16: { ++ segv = get_user_u64(val, addr); ++ if (!segv) { ++ segv = get_user_u64(val2, addr + 8); ++ } ++ break; ++ } ++#endif ++ default: abort(); ++ } ++ if (!segv && val == env->reserve_val) { ++ val = env->gpr[reg]; ++ switch (size) { ++ case 1: segv = put_user_u8(val, addr); break; ++ case 2: segv = put_user_u16(val, addr); break; ++ case 4: segv = put_user_u32(val, addr); break; ++#if defined(TARGET_PPC64) ++ case 8: segv = put_user_u64(val, addr); break; ++ case 16: { ++ if (val2 == env->reserve_val2) { ++ segv = put_user_u64(val, addr); ++ if (!segv) { ++ segv = put_user_u64(val2, addr + 8); ++ } ++ } ++ break; ++ } ++#endif ++ default: abort(); ++ } ++ if (!segv) { ++ stored = 1; ++ } ++ } ++ } ++ env->crf[0] = (stored << 1) | xer_so; ++ env->reserve_addr = (target_ulong)-1; ++ } ++ if (!segv) { ++ env->nip += 4; ++ } ++ mmap_unlock(); ++ end_exclusive(); ++ return segv; ++} ++ ++static inline void target_cpu_loop(CPUPPCState *env) ++{ ++ CPUState *cs = CPU(ppc_env_get_cpu(env)); ++ target_siginfo_t info; ++ int trapnr; ++ target_ulong ret; ++ ++ for(;;) { ++ cpu_exec_start(cs); ++ trapnr = cpu_ppc_exec(env); ++ cpu_exec_end(cs); ++ 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 */ ++ fprintf(stderr, "Invalid data memory access: 0x" TARGET_FMT_lx "\n", ++ env->spr[SPR_DAR]); ++ /* XXX: check this. Seems bugged */ ++ switch (env->error_code & 0xFF000000) { ++ case 0x40000000: ++ 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... */ ++ fprintf(stderr, "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.si_addr = env->nip; ++ queue_signal(env, info.si_signo, &info); ++ break; ++ case POWERPC_EXCP_ISI: /* Instruction storage exception */ ++ fprintf(stderr, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx ++ "\n", env->spr[SPR_SRR0]); ++ /* 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... */ ++ fprintf(stderr, "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.si_addr = env->nip - 4; ++ queue_signal(env, info.si_signo, &info); ++ break; ++ case POWERPC_EXCP_EXTERNAL: /* External input */ ++ cpu_abort(cs, "External interrupt while in user mode. " ++ "Aborting\n"); ++ break; ++ case POWERPC_EXCP_ALIGN: /* Alignment exception */ ++ fprintf(stderr, "Unaligned memory access\n"); ++ /* XXX: check this */ ++ info.si_signo = TARGET_SIGBUS; ++ info.si_errno = 0; ++ info.si_code = TARGET_BUS_ADRALN; ++ info.si_addr = env->nip - 4; ++ queue_signal(env, info.si_signo, &info); ++ break; ++ case POWERPC_EXCP_PROGRAM: /* Program exception */ ++ /* XXX: check this */ ++ switch (env->error_code & ~0xF) { ++ case POWERPC_EXCP_FP: ++ fprintf(stderr, "Floating point program exception\n"); ++ 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: ++ fprintf(stderr, "Unknown floating point exception (%02x)\n", ++ env->error_code); ++ break; ++ } ++ break; ++ case POWERPC_EXCP_INVAL: ++ fprintf(stderr, "Invalid instruction\n"); ++ 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: ++ fprintf(stderr, "Unknown invalid operation (%02x)\n", ++ env->error_code & 0xF); ++ info.si_code = TARGET_ILL_ILLADR; ++ break; ++ } ++ break; ++ case POWERPC_EXCP_PRIV: ++ fprintf(stderr, "Privilege violation\n"); ++ 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: ++ fprintf(stderr, "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.si_addr = env->nip - 4; ++ queue_signal(env, info.si_signo, &info); ++ break; ++ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ ++ fprintf(stderr, "No floating point allowed\n"); ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_COPROC; ++ info.si_addr = env->nip - 4; ++ queue_signal(env, info.si_signo, &info); ++ break; ++ case POWERPC_EXCP_SYSCALL: /* System call exception */ ++ cpu_abort(cs, "Syscall exception while in user mode. " ++ "Aborting\n"); ++ break; ++ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ ++ fprintf(stderr, "No APU instruction allowed\n"); ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_COPROC; ++ info.si_addr = env->nip - 4; ++ queue_signal(env, info.si_signo, &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. */ ++ fprintf(stderr, "No SPE/floating-point instruction allowed\n"); ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_COPROC; ++ info.si_addr = env->nip - 4; ++ queue_signal(env, info.si_signo, &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 */ ++ fprintf(stderr, "No Altivec instructions allowed\n"); ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_COPROC; ++ info.si_addr = env->nip - 4; ++ queue_signal(env, info.si_signo, &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_STOP: /* stop translation */ ++ /* We did invalidate the instruction cache. Go on */ ++ break; ++ case POWERPC_EXCP_BRANCH: /* branch instruction: */ ++ /* We just stopped because of a branch. Go on */ ++ 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; ++ ret = do_freebsd_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_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 POWERPC_EXCP_STCX: ++ if (do_store_exclusive(env)) { ++ info.si_signo = TARGET_SIGSEGV; ++ info.si_errno = 0; ++ info.si_code = TARGET_SEGV_MAPERR; ++ info.si_addr = env->nip; ++ queue_signal(env, info.si_signo, &info); ++ } ++ break; ++ case EXCP_DEBUG: ++ { ++ int sig; ++ ++ sig = gdb_handlesig(cs, TARGET_SIGTRAP); ++ if (sig) { ++ info.si_signo = sig; ++ info.si_errno = 0; ++ info.si_code = TARGET_TRAP_BRKPT; ++ queue_signal(env, info.si_signo, &info); ++ } ++ } ++ break; ++ case EXCP_INTERRUPT: ++ /* just indicate that signals should be handled asap */ ++ break; ++ default: ++ cpu_abort(cs, "Unknown exception 0x%d. Aborting\n", trapnr); ++ break; ++ } ++ process_pending_signals(env); ++ } ++} ++ ++static inline void target_cpu_clone_regs(CPUPPCState *env, target_ulong newsp) ++{ ++ if (newsp) ++ env->gpr[1] = newsp; ++ env->gpr[3] = 0; ++} ++ ++static inline void target_cpu_reset(CPUArchState *cpu) ++{ ++ cpu_reset(ENV_GET_CPU(cpu)); ++} ++ ++#endif /* ! _TARGET_ARCH_CPU_H_ */ +diff --git a/bsd-user/ppc/target_arch_elf.h b/bsd-user/ppc/target_arch_elf.h +new file mode 100644 +index 0000000..dee7585 +--- /dev/null ++++ b/bsd-user/ppc/target_arch_elf.h +@@ -0,0 +1,66 @@ ++/* ++ * powerpc ELF definitions ++ * ++ * Copyright (c) 2013 Stacey D. Son ++ * ++ * 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 . ++ */ ++#ifndef _TARGET_ARCH_ELF_H_ ++#define _TARGET_ARCH_ELF_H_ ++ ++#define ELF_START_MMAP 0x80000000 ++ ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++ ++#define elf_check_arch(x) ( (x) == EM_PPC64 ) ++#define ELF_CLASS ELFCLASS64 ++ ++#else ++ ++#define elf_check_arch(x) ( (x) == EM_PPC ) ++#define ELF_CLASS ELFCLASS32 ++ ++#endif ++ ++#define ELF_ARCH EM_PPC ++ ++#ifdef TARGET_WORDS_BIGENDIAN ++#define ELF_DATA ELFDATA2MSB ++#else ++#define ELF_DATA ELFDATA2LSB ++#endif ++#define ELF_ARCH EM_PPC ++ ++#define USE_ELF_CORE_DUMP ++#define ELF_EXEC_PAGESIZE 4096 ++ ++enum ++{ ++ PPC_FEATURE_32 = 0x80000000, /* Always true */ ++ PPC_FEATURE_64 = 0x40000000, /* Defined on a 64-bit CPU */ ++ PPC_FEATURE_HAS_ALTIVEC = 0x10000000, ++ PPC_FEATURE_HAS_FPU = 0x08000000, ++ PPC_FEATURE_HAS_MMU = 0x04000000, ++ PPC_FEATURE_UNIFIED_CACHE = 0x01000000 ++}; ++ ++#define TARET_ELF_HWCAP (PPC_FEATURE_32 | PPC_FEATURE_HAS_ALTIVEC | \ ++ PPC_FEATURE_HAS_FPU | PPC_HAS_FEATURE_MMU | PPC_FEATURE_UNIFIED_CACHE) ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++#define ELF_HWCAP (TARGET_ELF_HWCAP | PPC_FEATURE_64) ++#else ++#define ELF_HWCAP TARGET_ELF_HWCAP ++#endif ++ ++#endif /* _TARGET_ARCH_ELF_H_ */ +diff --git a/bsd-user/ppc/target_arch_signal.h b/bsd-user/ppc/target_arch_signal.h +new file mode 100644 +index 0000000..b9b9a5c +--- /dev/null ++++ b/bsd-user/ppc/target_arch_signal.h +@@ -0,0 +1,223 @@ ++/* ++ * powerpc signal definitions ++ * ++ * ++ * 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 . ++ */ ++#ifndef _TARGET_ARCH_SIGNAL_H_ ++#define _TARGET_ARCH_SIGNAL_H_ ++ ++#include "cpu.h" ++ ++#define TARGET_INSN_SIZE 4 /* powerpc instruction size */ ++ ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++/* Size of the signal trampolin code placed on the stack. */ ++#define TARGET_SZSIGCODE ((abi_ulong)(12 * TARGET_INSN_SIZE)) ++#else ++#define TARGET_SZSIGCODE ((abi_ulong)(7 * TARGET_INSN_SIZE)) ++#endif ++ ++#define TARGET_MINSIGSTKSZ (512 * 4) ++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) ++ ++/* compare to sys/powerpc/include/frame.h */ ++#define TARGET_SZREG 4 ++#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 6) ++#define TARGET_SZREG64 8 ++#define TARGET_CALLFRAME_SIZ64 (TARGET_SZREG * 10) ++ ++/* powerpc/powerpc/exec_machdep.c */ ++#define TARGET_MC_GET_CLEAR_RET 0x0001 ++#define TARGET_MC_SET_ONSTACK 0x0004 ++#define TARGET_MC_FP_VALID 0x0001 ++#define TARGET_MC_AV_VALID 0x0002 ++ ++typedef struct target_trapframe { ++ abi_long fixreg[32]; ++ abi_long lr; ++ abi_long cr; ++ abi_long xer; ++ abi_long ctr; ++ abi_long srr0; ++ abi_long srr1; ++ abi_long exc; ++ union { ++ struct { ++ /* dar & dsisr are only filled on a DSI trap */ ++ abi_long dar; ++ abi_long dsisr; ++ } aim; ++ struct { ++ abi_long dear; ++ abi_long esr; ++ abi_long dbcr0; ++ } booke; ++ } cpu; ++} target_trapframe_t; ++ ++struct target_sigcontext { ++ int32_t sc_onstack; /* sigstack state to restore */ ++ int32_t __sc_mask13; ++ target_trapframe_t sc_frame; ++ target_sigset_t sc_mask; /* signal mask to retstore */ ++}; ++ ++typedef struct target_mcontext { ++ int32_t mc_vers; ++ int32_t mc_flags; ++ int32_t mc_onstack; /* sigstack state to restore */ ++ int32_t mc_len; ++ uint64_t mc_avec[32*2]; ++ uint32_t mc_av[2]; ++ abi_long mc_frame[42]; /* process regs 0 to 31 */ ++ uint64_t mc_fpreg[33]; /* fp regs 0 to 31 */ ++} target_mcontext_t; ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ ++struct target_sigframe { ++ target_ucontext_t sf_uc; ++ target_siginfo_t sf_si; ++}; ++ ++/* ++ * Compare to powerpc/powerpc/exec_machdep.c sendsig() ++ * Assumes that target stack frame memory is locked. ++ */ ++static inline abi_long ++set_sigtramp_args(CPUPPCState *regs, int sig, struct target_sigframe *frame, ++ abi_ulong frame_addr, struct target_sigaction *ka) ++{ ++ /* XXX:TODO: set_sigtramp_args(). */ ++ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */ ++ ++ /* ++ * Arguments to signal handler: ++ * r1 = point to sigframe struct ++ * r3 = signal number ++ * r4 = siginfo pointer ++ * r5 = ucontext pointer ++ * PC = signal handler pointer ++ * lr = sigtramp at base of user stack ++ */ ++ regs->gpr[1] = frame_addr; ++ regs->gpr[3] = sig; ++ regs->gpr[4] = frame_addr + ++ offsetof(struct target_sigframe, sf_si); ++ regs->gpr[5] = frame_addr + ++ offsetof(struct target_sigframe, sf_uc); ++ regs->nip = ka->_sa_handler; ++ regs->lr = TARGET_PS_STRINGS - TARGET_SZSIGCODE; ++ ++ return 0; ++} ++ ++/* ++ * Compare to powerpc/powerpc/exec_machdep.c get_mcontext() ++ * Assumes that the memory is locked if mcp points to user memory. ++ */ ++static inline abi_long get_mcontext(CPUPPCState *regs, target_mcontext_t *mcp, ++ int flags) ++{ ++ int i, err = 0; ++ ++ if (flags & TARGET_MC_SET_ONSTACK) { ++ mcp->mc_onstack = tswapal(1); ++ } else { ++ mcp->mc_onstack = 0; ++ } ++ ++ for (i = 1; i < 32; i++) { ++ mcp->mc_frame[i] = tswapal(regs->gpr[i]); ++ } ++ ++ mcp->mc_flags |= TARGET_MC_FP_VALID; ++ for (i = 0; i < 32; i++) { ++ mcp->mc_fpreg[i] = tswapal(regs->fpr[i]); ++ } ++ mcp->mc_fpreg[32] = tswapal(regs->fpscr); ++ ++ mcp->mc_flags |= TARGET_MC_AV_VALID; ++ for (i = 0; i < 32*2; i++) { ++ mcp->mc_avec[i] = tswapal(regs->avr[i/2].u64[i%2]); ++ } ++ mcp->mc_av[0] = tswapal(regs->vscr); ++ mcp->mc_av[1] = tswapal(regs->spr[SPR_VRSAVE]); ++ ++ if (flags & TARGET_MC_GET_CLEAR_RET) { ++ mcp->mc_frame[3] = 0; /* r3 = 0 */ ++ mcp->mc_frame[4] = 0; /* r4 = 0 */ ++ } ++ ++ mcp->mc_frame[32] = tswapal(regs->lr); ++ mcp->mc_frame[33] = tswapal(regs->crf[0]); ++ mcp->mc_frame[34] = tswapal(regs->xer); ++ mcp->mc_frame[35] = tswapal(regs->ctr); ++ mcp->mc_frame[36] = tswapal(regs->nip); ++ mcp->mc_frame[37] = tswapal(regs->msr); ++ ++ mcp->mc_len = sizeof(*mcp); ++ /* Don't do any of the status and cause registers. */ ++ ++ return err; ++} ++ ++/* Compare to powerpc/powerpc/exec_machdep.c set_mcontext() */ ++static inline abi_long set_mcontext(CPUPPCState *regs, target_mcontext_t *mcp, ++ int srflag) ++{ ++ /* XXX:TODO:set_mcontext() TLS handling. */ ++ int i, err = 0; ++ ++ for (i = 1; i < 32; i++) { ++ regs->gpr[i] = tswapal(mcp->mc_frame[i]); ++ } ++ ++ if (mcp->mc_flags & TARGET_MC_FP_VALID) { ++ /* restore fpu context if we have used it before */ ++ for (i = 0; i < 32; i++) { ++ regs->fpr[i] = tswapal(mcp->mc_fpreg[i]); ++ } ++ regs->fpscr = tswapal(mcp->mc_fpreg[32]); ++ } ++ ++ if (mcp->mc_flags & TARGET_MC_AV_VALID) { ++ /* restore fpu context if we have used it before */ ++ for (i = 0; i < 32*2; i++) { ++ regs->avr[i/2].u64[i%2] = tswapal(mcp->mc_avec[i]); ++ } ++ regs->fpscr = tswapal(mcp->mc_fpreg[32]); ++ } ++ ++ return err; ++} ++ ++static inline abi_long get_ucontext_sigreturn(CPUPPCState *regs, ++ abi_ulong target_sf, abi_ulong *target_uc) ++{ ++ ++ /* powerpc passes ucontext struct as the stack frame */ ++ *target_uc = target_sf; ++ return 0; ++} ++ ++#endif /* !_TARGET_ARCH_SIGNAL_H_ */ +diff --git a/bsd-user/ppc/target_arch_sigtramp.h b/bsd-user/ppc/target_arch_sigtramp.h +new file mode 100644 +index 0000000..2db9329 +--- /dev/null ++++ b/bsd-user/ppc/target_arch_sigtramp.h +@@ -0,0 +1,43 @@ ++ ++#ifndef _TARGET_ARCH_SIGTRAMP_H_ ++#define _TARGET_ARCH_SIGTRAMP_H_ ++ ++/* Compare to mips/mips/locore.S sigcode() */ ++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc, ++ unsigned sys_sigreturn) ++{ ++ int i; ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++ uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = { ++ /* 1 */ 0x3821FFF0, /* addi r1,r1,-48 */ ++ /* 2 */ 0x7C4802A6, /* mflr r2 */ ++ /* 3 */ 0xE8020000, /* ld r0,0(r2) */ ++ /* 4 */ 0xE8420008, /* ld r2,8(r2) */ ++ /* 5 */ 0x7C0803A6, /* mtlr r0 */ ++ /* 6 */ 0x4E800021, /* blrl */ ++ /* 7 */ 0x38610030, /* addi r3,r1,16 */ ++ /* 8 */ 0x380001A1, /* li r0,417 */ ++ /* 9 */ 0x44000002, /* sc */ ++ /* 10 */ 0x38000001, /* li r0,1 */ ++ /* 11 */ 0x44000002, /* sc */ ++ /* 12 */ 0x60000000 /* nop */ ++ }; ++#else ++ uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = { ++ /* 1 */ 0x3821FFF0, /* addi r1,r1,-16 */ ++ /* 2 */ 0x4E800021, /* blrl */ ++ /* 3 */ 0x38610010, /* addi r3,r1,16 */ ++ /* 4 */ 0x380001A1, /* li r0,417 */ ++ /* 5 */ 0x44000002, /* sc */ ++ /* 6 */ 0x38000001, /* li r0,1 */ ++ /* 7 */ 0x44000002 /* sc */ ++ }; ++#endif ++ ++ for (i = 0; i < 4; i++) { ++ tswap32s(&sigtramp_code[i]); ++ } ++ ++ return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE); ++} ++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */ +diff --git a/bsd-user/ppc/target_arch_sysarch.h b/bsd-user/ppc/target_arch_sysarch.h +new file mode 100644 +index 0000000..765f722 +--- /dev/null ++++ b/bsd-user/ppc/target_arch_sysarch.h +@@ -0,0 +1,36 @@ ++/* ++ * powerpc cpu init and loop ++ * ++ * ++ * 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 . ++ */ ++ ++#ifndef _TARGET_ARCH_SYSARCH_H_ ++#define _TARGET_ARCH_SYSARCH_H_ ++ ++static inline abi_long do_freebsd_arch_sysarch(CPUPPCState *env, int op, ++ abi_ulong parms) ++{ ++ int ret = -TARGET_EINVAL; ++ ++ return ret; ++} ++ ++static inline void do_freebsd_arch_print_sysarch( ++ const struct syscallname *name, abi_long arg1, abi_long arg2, ++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) ++{ ++ gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2); ++} ++#endif +diff --git a/bsd-user/ppc/target_arch_thread.h b/bsd-user/ppc/target_arch_thread.h +new file mode 100644 +index 0000000..b82e470 +--- /dev/null ++++ b/bsd-user/ppc/target_arch_thread.h +@@ -0,0 +1,65 @@ ++/* ++ * powerpc thread support ++ * ++ * Copyright (c) 2013 Stacey D. Son ++ * ++ * 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 . ++ */ ++#ifndef _TARGET_ARCH_THREAD_H_ ++#define _TARGET_ARCH_THREAD_H_ ++ ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++#define STACK_ALIGN 8 ++#else ++#define STACK_ALIGN 4 ++#endif ++ ++/* Compare to powerpc/powerpc/exec_machdep.c cpu_set_upcall_kse() */ ++static inline void target_thread_set_upcall(CPUPPCState *regs, abi_ulong entry, ++ abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size) ++{ ++ abi_ulong sp; ++ ++ /* ++ * Make sure the stack is properly aligned. ++ * powerpc/include/param.h (STACKLIGN() macro) ++ */ ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++ sp = ((u_int)(stack_base + stack_size) - 48) & ~0x1f; ++#else ++ sp = ((u_int)(stack_base + stack_size) - 8) & ~0x1f; ++#endif ++ ++ /* r1 = stack base */ ++ regs->gpr[1] = sp; ++ /* r3 = arg */ ++ regs->gpr[3] = arg; ++ /* srr0 = start function entry */ ++ regs->spr[SPR_SRR0] = entry; ++ ++ /* TODO:ppc64 target_thread_set_upcall */ ++} ++ ++static inline void target_thread_init(struct target_pt_regs *regs, ++ struct image_info *infop) ++{ ++ memset(regs, 0, sizeof(*regs)); ++ regs->nip = infop->entry; ++ regs->gpr[1] = infop->start_stack; ++ if (bsd_type == target_freebsd) { ++ regs->lr = infop->entry; ++ } ++} ++ ++#endif /* !_TARGET_ARCH_THREAD_H_ */ +diff --git a/bsd-user/ppc/target_arch_vmparam.h b/bsd-user/ppc/target_arch_vmparam.h +new file mode 100644 +index 0000000..1ad5c9d +--- /dev/null ++++ b/bsd-user/ppc/target_arch_vmparam.h +@@ -0,0 +1,52 @@ ++/* ++ * powerpc VM parameters definitions ++ * ++ * Copyright (c) 2013 Stacey D. Son ++ * ++ * 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 . ++ */ ++#ifndef _TARGET_ARCH_VMPARAM_H_ ++#define _TARGET_ARCH_VMPARAM_H_ ++ ++#include "cpu.h" ++ ++/* compare to sys/arm/include/vmparam.h */ ++#define TARGET_MAXTSIZ (64UL*1024*1024) /* max text size */ ++#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */ ++#define TARGET_MAXDSIZ (1UL*1024*1024*1024) /* max data size */ ++#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */ ++#define TARGET_MAXSSIZ (64UL*1024*1024) /* max stack size */ ++#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */ ++ ++#define TARGET_RESERVED_VA 0xfffff000 ++ ++ /* KERNBASE - 512 MB */ ++#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) ++#define TARGET_VM_MAXUSER_ADDRESS 0xfffffffffffff000ULL ++#else ++#define TARGET_VM_MAXUSER_ADDRESS 0xfffff000UL ++#endif ++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - 4096) ++ ++static inline abi_ulong get_sp_from_cpustate(CPUPPCState *state) ++{ ++ return state->gpr[1]; /* sp */ ++} ++ ++static inline void set_second_rval(CPUPPCState *state, abi_ulong retval2) ++{ ++ state->gpr[4] = retval2; ++} ++ ++#endif /* ! _TARGET_ARCH_VMPARAM_H_ */ +diff --git a/default-configs/ppc-bsd-user.mak b/default-configs/ppc-bsd-user.mak +new file mode 100644 +index 0000000..bc51df9 +--- /dev/null ++++ b/default-configs/ppc-bsd-user.mak +@@ -0,0 +1 @@ ++# Default configuration for ppc-bsd-user +diff --git a/default-configs/ppc64-bsd-user.mak b/default-configs/ppc64-bsd-user.mak +new file mode 100644 +index 0000000..bc51df9 +--- /dev/null ++++ b/default-configs/ppc64-bsd-user.mak +@@ -0,0 +1 @@ ++# Default configuration for ppc-bsd-user +-- +1.9.3 + Property changes on: files/extra-patch-ppc-001 ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: pkg-plist =================================================================== --- pkg-plist (revision 358294) +++ pkg-plist (working copy) @@ -33,8 +33,10 @@ %%BSD_USER64%%bin/qemu-mips64el%%STATIC%% %%BSD_USER%%bin/qemu-mipsel%%STATIC%% %%BSD_USER%%bin/qemu-sparc%%STATIC%% +%%BSD_USER%%bin/qemu-ppc%%STATIC%% %%BSD_USER64%%bin/qemu-sparc64%%STATIC%% %%BSD_USER64%%bin/qemu-x86_64%%STATIC%% +%%BSD_USER64%%bin/qemu-ppc64%%STATIC%% %%SOFTMMU%%bin/qemu-system-x86_64 %%NONX86%%bin/qemu-system-xtensa %%NONX86%%bin/qemu-system-xtensaeb