summaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-07-10 10:54:16 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2013-07-10 10:54:16 -0500
commit51455c59ddc370612f6e070d8eb0e594aaa7ef24 (patch)
treea3044bd466cb3a548e6abad273663469bf68647a /linux-user
parent9f9a03b9818194da39c6759d9b0cbee5d7ace4e1 (diff)
parent91b1df8cf9e1ecaa8679c9ea8713d1e25c28e6c4 (diff)
Merge remote-tracking branch 'afaerber/tags/qom-cpu-for-anthony' into staging
QOM CPUState refactorings * Fix for OpenRISCCPU subclasses * Fix for gdbstub CPU selection * Move linux-user CPU functions into new header * CPUState part 10 refactoring: first_cpu, next_cpu, cpu_single_env et al. * Fix some targets to consistently inline TCG code generation * Centrally log CPU reset # gpg: Signature made Wed 10 Jul 2013 07:52:39 AM CDT using RSA key ID 3E7E013F # gpg: Can't check signature: public key not found # By Andreas Färber (41) and others # Via Andreas Färber * afaerber/tags/qom-cpu-for-anthony: (43 commits) cpu: Move reset logging to CPUState target-ppc: Change LOG_MMU_STATE() argument to CPUState target-i386: Change LOG_PCALL_STATE() argument to CPUState log: Change log_cpu_state[_mask]() argument to CPUState target-i386: Change do_smm_enter() argument to X86CPU target-i386: Change do_interrupt_all() argument to X86CPU target-xtensa: Change gen_intermediate_code_internal() arg to XtensaCPU target-unicore32: Change gen_intermediate_code_internal() signature target-sparc: Change gen_intermediate_code_internal() argument to SPARCCPU target-sh4: Change gen_intermediate_code_internal() argument to SuperHCPU target-s390x: Change gen_intermediate_code_internal() argument to S390CPU target-ppc: Change gen_intermediate_code_internal() argument to PowerPCCPU target-mips: Change gen_intermediate_code_internal() argument to MIPSCPU target-microblaze: Change gen_intermediate_code_internal() argument types target-m68k: Change gen_intermediate_code_internal() argument to M68kCPU target-lm32: Change gen_intermediate_code_internal() argument to LM32CPU target-i386: Change gen_intermediate_code_internal() argument to X86CPU target-cris: Change gen_intermediate_code_internal() argument to CRISCPU target-arm: Change gen_intermediate_code_internal() argument to ARMCPU target-alpha: Change gen_intermediate_code_internal() argument to AlphaCPU ...
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/alpha/target_cpu.h36
-rw-r--r--linux-user/arm/target_cpu.h35
-rw-r--r--linux-user/cris/target_cpu.h36
-rw-r--r--linux-user/elfload.c21
-rw-r--r--linux-user/i386/target_cpu.h33
-rw-r--r--linux-user/linuxload.c3
-rw-r--r--linux-user/m68k/target_cpu.h34
-rw-r--r--linux-user/main.c21
-rw-r--r--linux-user/microblaze/target_cpu.h35
-rw-r--r--linux-user/mips/target_cpu.h36
-rw-r--r--linux-user/mips64/target_cpu.h1
-rw-r--r--linux-user/openrisc/target_cpu.h33
-rw-r--r--linux-user/ppc/target_cpu.h41
-rw-r--r--linux-user/qemu.h3
-rw-r--r--linux-user/s390x/target_cpu.h39
-rw-r--r--linux-user/sh4/target_cpu.h35
-rw-r--r--linux-user/signal.c12
-rw-r--r--linux-user/sparc/target_cpu.h36
-rw-r--r--linux-user/sparc64/target_cpu.h1
-rw-r--r--linux-user/syscall.c80
-rw-r--r--linux-user/unicore32/target_cpu.h27
-rw-r--r--linux-user/x86_64/target_cpu.h1
22 files changed, 534 insertions, 65 deletions
diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h
new file mode 100644
index 0000000000..42562452b2
--- /dev/null
+++ b/linux-user/alpha/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * Alpha specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->ir[IR_SP] = newsp;
+ }
+ env->ir[IR_V0] = 0;
+ env->ir[IR_A3] = 0;
+}
+
+static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
+{
+ env->unique = newtls;
+}
+
+#endif
diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
new file mode 100644
index 0000000000..ed323c079d
--- /dev/null
+++ b/linux-user/arm/target_cpu.h
@@ -0,0 +1,35 @@
+/*
+ * ARM specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2003 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regs[13] = newsp;
+ }
+ env->regs[0] = 0;
+}
+
+static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
+{
+ env->cp15.c13_tls2 = newtls;
+}
+
+#endif
diff --git a/linux-user/cris/target_cpu.h b/linux-user/cris/target_cpu.h
new file mode 100644
index 0000000000..4d787e5ff3
--- /dev/null
+++ b/linux-user/cris/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * CRIS specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * 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 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
+ * 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regs[14] = newsp;
+ }
+ env->regs[10] = 0;
+}
+
+static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls)
+{
+ env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls;
+}
+
+#endif
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ddef23e6dc..7ce2eab1bb 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -125,7 +125,7 @@ typedef abi_int target_pid_t;
static const char *get_elf_platform(void)
{
static char elf_platform[] = "i386";
- int family = (thread_env->cpuid_version >> 8) & 0xff;
+ int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
if (family > 6)
family = 6;
if (family >= 3)
@@ -137,7 +137,9 @@ static const char *get_elf_platform(void)
static uint32_t get_elf_hwcap(void)
{
- return thread_env->features[FEAT_1_EDX];
+ X86CPU *cpu = X86_CPU(thread_cpu);
+
+ return cpu->env.features[FEAT_1_EDX];
}
#ifdef TARGET_X86_64
@@ -404,7 +406,7 @@ static int validate_guest_space(unsigned long guest_base,
static uint32_t get_elf_hwcap(void)
{
- CPUARMState *e = thread_env;
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
uint32_t hwcaps = 0;
hwcaps |= ARM_HWCAP_ARM_SWP;
@@ -415,7 +417,7 @@ static uint32_t get_elf_hwcap(void)
/* probe for the extra features */
#define GET_FEATURE(feat, hwcap) \
- do {if (arm_feature(e, feat)) { hwcaps |= hwcap; } } while (0)
+ do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
@@ -619,13 +621,13 @@ enum {
static uint32_t get_elf_hwcap(void)
{
- CPUPPCState *e = thread_env;
+ PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
uint32_t features = 0;
/* We don't have to be terribly complete here; the high points are
Altivec/FP/SPE support. Anything else is just a bonus. */
#define GET_FEATURE(flag, feature) \
- do {if (e->insns_flags & flag) features |= feature; } while(0)
+ do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
@@ -2628,7 +2630,7 @@ static int fill_note_info(struct elf_note_info *info,
long signr, const CPUArchState *env)
{
#define NUMNOTES 3
- CPUArchState *cpu = NULL;
+ CPUState *cpu = NULL;
TaskState *ts = (TaskState *)env->opaque;
int i;
@@ -2667,9 +2669,10 @@ static int fill_note_info(struct elf_note_info *info,
/* read and fill status of all threads */
cpu_list_lock();
for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
- if (cpu == thread_env)
+ if (cpu == thread_cpu) {
continue;
- fill_thread_info(info, cpu);
+ }
+ fill_thread_info(info, (CPUArchState *)cpu->env_ptr);
}
cpu_list_unlock();
diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h
new file mode 100644
index 0000000000..abcac79d25
--- /dev/null
+++ b/linux-user/i386/target_cpu.h
@@ -0,0 +1,33 @@
+/*
+ * i386 specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2003 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regs[R_ESP] = newsp;
+ }
+ env->regs[R_EAX] = 0;
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 381ab8914b..5cd6d91554 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -89,7 +89,8 @@ static int prepare_binprm(struct linux_binprm *bprm)
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
abi_ulong stringp, int push_ptr)
{
- TaskState *ts = (TaskState *)thread_env->opaque;
+ CPUArchState *env = thread_cpu->env_ptr;
+ TaskState *ts = (TaskState *)env->opaque;
int n = sizeof(abi_ulong);
abi_ulong envp;
abi_ulong argv;
diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h
new file mode 100644
index 0000000000..8a2a305a0b
--- /dev/null
+++ b/linux-user/m68k/target_cpu.h
@@ -0,0 +1,34 @@
+/*
+ * m68k specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2005-2007 CodeSourcery
+ * Written by Paul Brook
+ *
+ * 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 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
+ * 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->aregs[7] = newsp;
+ }
+ env->dregs[0] = 0;
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/main.c b/linux-user/main.c
index af82db87b8..7f15d3da2b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -120,15 +120,15 @@ void fork_end(int child)
if (child) {
/* Child processes created by fork() only have a single thread.
Discard information about the parent threads. */
- first_cpu = thread_env;
- thread_env->next_cpu = NULL;
+ first_cpu = thread_cpu;
+ first_cpu->next_cpu = NULL;
pending_cpus = 0;
pthread_mutex_init(&exclusive_lock, NULL);
pthread_mutex_init(&cpu_list_mutex, NULL);
pthread_cond_init(&exclusive_cond, NULL);
pthread_cond_init(&exclusive_resume, NULL);
pthread_mutex_init(&tcg_ctx.tb_ctx.tb_lock, NULL);
- gdbserver_fork(thread_env);
+ gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
} else {
pthread_mutex_unlock(&exclusive_lock);
pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
@@ -148,7 +148,6 @@ static inline void exclusive_idle(void)
Must only be called from outside cpu_arm_exec. */
static inline void start_exclusive(void)
{
- CPUArchState *other;
CPUState *other_cpu;
pthread_mutex_lock(&exclusive_lock);
@@ -156,8 +155,7 @@ static inline void start_exclusive(void)
pending_cpus = 1;
/* Make all other cpus stop executing. */
- for (other = first_cpu; other; other = other->next_cpu) {
- other_cpu = ENV_GET_CPU(other);
+ for (other_cpu = first_cpu; other_cpu; other_cpu = other_cpu->next_cpu) {
if (other_cpu->running) {
pending_cpus++;
cpu_exit(other_cpu);
@@ -234,7 +232,7 @@ void fork_start(void)
void fork_end(int child)
{
if (child) {
- gdbserver_fork(thread_env);
+ gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
}
}
@@ -1304,11 +1302,12 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
#define EXCP_DUMP(env, fmt, ...) \
do { \
+ CPUState *cs = ENV_GET_CPU(env); \
fprintf(stderr, fmt , ## __VA_ARGS__); \
- cpu_dump_state(ENV_GET_CPU(env), stderr, fprintf, 0); \
+ cpu_dump_state(cs, stderr, fprintf, 0); \
qemu_log(fmt, ## __VA_ARGS__); \
if (qemu_log_enabled()) { \
- log_cpu_state(env, 0); \
+ log_cpu_state(cs, 0); \
} \
} while (0)
@@ -3152,7 +3151,7 @@ void cpu_loop(CPUS390XState *env)
#endif /* TARGET_S390X */
-THREAD CPUArchState *thread_env;
+THREAD CPUState *thread_cpu;
void task_settid(TaskState *ts)
{
@@ -3642,7 +3641,7 @@ int main(int argc, char **argv, char **envp)
cpu_reset(ENV_GET_CPU(env));
#endif
- thread_env = env;
+ thread_cpu = ENV_GET_CPU(env);
if (getenv("QEMU_STRACE")) {
do_strace = 1;
diff --git a/linux-user/microblaze/target_cpu.h b/linux-user/microblaze/target_cpu.h
new file mode 100644
index 0000000000..c6386ea9e4
--- /dev/null
+++ b/linux-user/microblaze/target_cpu.h
@@ -0,0 +1,35 @@
+/*
+ * MicroBlaze specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias
+ *
+ * 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 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
+ * 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regs[R_SP] = newsp;
+ }
+ env->regs[3] = 0;
+}
+
+static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls)
+{
+ env->regs[21] = newtls;
+}
+
+#endif
diff --git a/linux-user/mips/target_cpu.h b/linux-user/mips/target_cpu.h
new file mode 100644
index 0000000000..ba8e9eb1f9
--- /dev/null
+++ b/linux-user/mips/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * MIPS specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2004-2005 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->active_tc.gpr[29] = newsp;
+ }
+ env->active_tc.gpr[7] = 0;
+ env->active_tc.gpr[2] = 0;
+}
+
+static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
+{
+ env->tls_value = newtls;
+}
+
+#endif
diff --git a/linux-user/mips64/target_cpu.h b/linux-user/mips64/target_cpu.h
new file mode 100644
index 0000000000..fa36407c68
--- /dev/null
+++ b/linux-user/mips64/target_cpu.h
@@ -0,0 +1 @@
+#include "../mips/target_cpu.h"
diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h
new file mode 100644
index 0000000000..501fb81162
--- /dev/null
+++ b/linux-user/openrisc/target_cpu.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->gpr[1] = newsp;
+ }
+ env->gpr[2] = 0;
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/ppc/target_cpu.h b/linux-user/ppc/target_cpu.h
new file mode 100644
index 0000000000..9cc0c3ba9c
--- /dev/null
+++ b/linux-user/ppc/target_cpu.h
@@ -0,0 +1,41 @@
+/*
+ * 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->gpr[1] = newsp;
+ }
+ env->gpr[3] = 0;
+}
+
+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
+}
+
+#endif
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index b10e9572a9..6569608b64 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -16,6 +16,7 @@
#include "exec/user/thunk.h"
#include "syscall_defs.h"
#include "syscall.h"
+#include "target_cpu.h"
#include "target_signal.h"
#include "exec/gdbstub.h"
#include "qemu/queue.h"
@@ -197,7 +198,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8);
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-extern THREAD CPUArchState *thread_env;
+extern THREAD CPUState *thread_cpu;
void cpu_loop(CPUArchState *env);
char *target_strerror(int err);
int get_osversion(void);
diff --git a/linux-user/s390x/target_cpu.h b/linux-user/s390x/target_cpu.h
new file mode 100644
index 0000000000..f10abe8e54
--- /dev/null
+++ b/linux-user/s390x/target_cpu.h
@@ -0,0 +1,39 @@
+/*
+ * S/390 specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ *
+ * 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 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.
+ *
+ * Contributions after 2012-10-29 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ *
+ * 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regs[15] = newsp;
+ }
+ env->regs[2] = 0;
+}
+
+static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
+{
+ env->aregs[0] = newtls >> 32;
+ env->aregs[1] = newtls & 0xffffffffULL;
+}
+
+#endif
diff --git a/linux-user/sh4/target_cpu.h b/linux-user/sh4/target_cpu.h
new file mode 100644
index 0000000000..141856f845
--- /dev/null
+++ b/linux-user/sh4/target_cpu.h
@@ -0,0 +1,35 @@
+/*
+ * SH4 specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2005 Samuel Tardieu
+ *
+ * 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->gregs[15] = newsp;
+ }
+ env->gregs[0] = 0;
+}
+
+static inline void cpu_set_tls(CPUSH4State *env, target_ulong newtls)
+{
+ env->gbr = newtls;
+}
+
+#endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index d84e189bc8..d0727becc2 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -388,17 +388,18 @@ static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
/* abort execution with signal */
static void QEMU_NORETURN force_sig(int target_sig)
{
- TaskState *ts = (TaskState *)thread_env->opaque;
+ CPUArchState *env = thread_cpu->env_ptr;
+ TaskState *ts = (TaskState *)env->opaque;
int host_sig, core_dumped = 0;
struct sigaction act;
host_sig = target_to_host_signal(target_sig);
- gdb_signalled(thread_env, target_sig);
+ gdb_signalled(env, target_sig);
/* dump core if supported by target binary format */
if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
stop_all_tasks();
core_dumped =
- ((*ts->bprm->core_dump)(target_sig, thread_env) == 0);
+ ((*ts->bprm->core_dump)(target_sig, env) == 0);
}
if (core_dumped) {
/* we already dumped the core of target process, we don't want
@@ -503,6 +504,7 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
+ CPUArchState *env = thread_cpu->env_ptr;
int sig;
target_siginfo_t tinfo;
@@ -522,9 +524,9 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
fprintf(stderr, "qemu: got signal %d\n", sig);
#endif
host_to_target_siginfo_noswap(&tinfo, info);
- if (queue_signal(thread_env, sig, &tinfo) == 1) {
+ if (queue_signal(env, sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
- cpu_exit(ENV_GET_CPU(thread_env));
+ cpu_exit(thread_cpu);
}
}
diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h
new file mode 100644
index 0000000000..5a620a2bb7
--- /dev/null
+++ b/linux-user/sparc/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * SPARC specific CPU ABI and functions for linux-user
+ *
+ * Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
+ * Copyright (C) 2003-2005 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 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regwptr[22] = newsp;
+ }
+ env->regwptr[0] = 0;
+ /* FIXME: Do we also need to clear CF? */
+ /* XXXXX */
+ printf("HELPME: %s:%d\n", __FILE__, __LINE__);
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/sparc64/target_cpu.h b/linux-user/sparc64/target_cpu.h
new file mode 100644
index 0000000000..b22263d2db
--- /dev/null
+++ b/linux-user/sparc64/target_cpu.h
@@ -0,0 +1 @@
+#include "../sparc/target_cpu.h"
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a6a7828cc3..00a0390ea9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4250,8 +4250,8 @@ static void *clone_func(void *arg)
env = info->env;
cpu = ENV_GET_CPU(env);
- thread_env = env;
- ts = (TaskState *)thread_env->opaque;
+ thread_cpu = cpu;
+ ts = (TaskState *)env->opaque;
info->tid = gettid();
cpu->host_tid = info->tid;
task_settid(ts);
@@ -5132,6 +5132,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8)
{
+#ifdef CONFIG_USE_NPTL
+ CPUState *cpu = ENV_GET_CPU(cpu_env);
+#endif
abi_long ret;
struct stat st;
struct statfs stfs;
@@ -5146,42 +5149,43 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
switch(num) {
case TARGET_NR_exit:
#ifdef CONFIG_USE_NPTL
- /* In old applications this may be used to implement _exit(2).
- However in threaded applictions it is used for thread termination,
- and _exit_group is used for application termination.
- Do thread termination if we have more then one thread. */
- /* FIXME: This probably breaks if a signal arrives. We should probably
- be disabling signals. */
- if (first_cpu->next_cpu) {
- TaskState *ts;
- CPUArchState **lastp;
- CPUArchState *p;
-
- cpu_list_lock();
- lastp = &first_cpu;
- p = first_cpu;
- while (p && p != (CPUArchState *)cpu_env) {
- lastp = &p->next_cpu;
- p = p->next_cpu;
- }
- /* If we didn't find the CPU for this thread then something is
- horribly wrong. */
- if (!p)
- abort();
- /* Remove the CPU from the list. */
- *lastp = p->next_cpu;
- cpu_list_unlock();
- ts = ((CPUArchState *)cpu_env)->opaque;
- if (ts->child_tidptr) {
- put_user_u32(0, ts->child_tidptr);
- sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
- NULL, NULL, 0);
- }
- thread_env = NULL;
- object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
- g_free(ts);
- pthread_exit(NULL);
- }
+ /* In old applications this may be used to implement _exit(2).
+ However in threaded applictions it is used for thread termination,
+ and _exit_group is used for application termination.
+ Do thread termination if we have more then one thread. */
+ /* FIXME: This probably breaks if a signal arrives. We should probably
+ be disabling signals. */
+ if (first_cpu->next_cpu) {
+ TaskState *ts;
+ CPUState **lastp;
+ CPUState *p;
+
+ cpu_list_lock();
+ lastp = &first_cpu;
+ p = first_cpu;
+ while (p && p != cpu) {
+ lastp = &p->next_cpu;
+ p = p->next_cpu;
+ }
+ /* If we didn't find the CPU for this thread then something is
+ horribly wrong. */
+ if (!p) {
+ abort();
+ }
+ /* Remove the CPU from the list. */
+ *lastp = p->next_cpu;
+ cpu_list_unlock();
+ ts = ((CPUArchState *)cpu_env)->opaque;
+ if (ts->child_tidptr) {
+ put_user_u32(0, ts->child_tidptr);
+ sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
+ NULL, NULL, 0);
+ }
+ thread_cpu = NULL;
+ object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
+ g_free(ts);
+ pthread_exit(NULL);
+ }
#endif
#ifdef TARGET_GPROF
_mcleanup();
diff --git a/linux-user/unicore32/target_cpu.h b/linux-user/unicore32/target_cpu.h
new file mode 100644
index 0000000000..fb7908719f
--- /dev/null
+++ b/linux-user/unicore32/target_cpu.h
@@ -0,0 +1,27 @@
+/*
+ * UniCore32 specific CPU ABI and functions for linux-user
+ *
+ * Copyright (C) 2010-2012 Guan Xuetao
+ *
+ * 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 TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUUniCore32State *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regs[29] = newsp;
+ }
+ env->regs[0] = 0;
+}
+
+static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls)
+{
+ env->regs[16] = newtls;
+}
+
+#endif
diff --git a/linux-user/x86_64/target_cpu.h b/linux-user/x86_64/target_cpu.h
new file mode 100644
index 0000000000..9ec7cbb7a4
--- /dev/null
+++ b/linux-user/x86_64/target_cpu.h
@@ -0,0 +1 @@
+#include "../i386/target_cpu.h"