On Thu, Nov 26, 2009 at 02:23:10PM +0100, Alexander Graf wrote: > Because Qemu currently requires a TCG target to exist and there are quite some > useful helpers here to lay the groundwork for out KVM target, let's create a > stub TCG emulation target for S390X CPUs. > > This is required to make tcg happy. The emulation target itself won't work > though.
Please find the comments below. > Signed-off-by: Alexander Graf <ag...@suse.de> > --- > cpu-exec.c | 2 + > target-s390x/cpu.h | 119 > ++++++++++++++++++++++++++++++++++++++++++++++ > target-s390x/exec.h | 51 ++++++++++++++++++++ > target-s390x/helper.c | 57 ++++++++++++++++++++++ > target-s390x/op_helper.c | 74 ++++++++++++++++++++++++++++ > target-s390x/translate.c | 57 ++++++++++++++++++++++ > 6 files changed, 360 insertions(+), 0 deletions(-) > create mode 100644 target-s390x/cpu.h > create mode 100644 target-s390x/exec.h > create mode 100644 target-s390x/helper.c > create mode 100644 target-s390x/op_helper.c > create mode 100644 target-s390x/translate.c > > diff --git a/cpu-exec.c b/cpu-exec.c > index 2c0765c..af4595b 100644 > --- a/cpu-exec.c > +++ b/cpu-exec.c > @@ -249,6 +249,7 @@ int cpu_exec(CPUState *env1) > #elif defined(TARGET_MIPS) > #elif defined(TARGET_SH4) > #elif defined(TARGET_CRIS) > +#elif defined(TARGET_S390X) > /* XXXXX */ > #else > #error unsupported target CPU > @@ -673,6 +674,7 @@ int cpu_exec(CPUState *env1) > #elif defined(TARGET_SH4) > #elif defined(TARGET_ALPHA) > #elif defined(TARGET_CRIS) > +#elif defined(TARGET_S390X) > /* XXXXX */ > #else > #error unsupported target CPU > diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h > new file mode 100644 > index 0000000..f45b00c > --- /dev/null > +++ b/target-s390x/cpu.h > @@ -0,0 +1,119 @@ > +/* > + * S/390 virtual CPU header > + * > + * 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 > USA > + */ > +#ifndef CPU_S390X_H > +#define CPU_S390X_H > + > +#define TARGET_LONG_BITS 64 > + > +#define ELF_MACHINE EM_S390 > + > +#define CPUState struct CPUS390XState > + > +#include "cpu-defs.h" > + > +#include "softfloat.h" > + > +#define NB_MMU_MODES 2 // guess > +#define MMU_USER_IDX 0 // guess > + > +typedef union FPReg { > + struct { > +#ifdef WORDS_BIGENDIAN > + float32 e; > + int32_t __pad; > +#else > + int32_t __pad; > + float32 e; > +#endif > + }; > + float64 d; > + uint64_t i; > +} FPReg; > + > +typedef struct CPUS390XState { > + uint64_t regs[16]; /* GP registers */ > + > + uint32_t aregs[16]; /* access registers */ > + > + uint32_t fpc; /* floating-point control register */ > + FPReg fregs[16]; /* FP registers */ > + float_status fpu_status; /* passed to softfloat lib */ > + > + struct { > + uint64_t mask; > + uint64_t addr; > + } psw; > + > + int cc; /* condition code (0-3) */ > + > + uint64_t __excp_addr; > + > + CPU_COMMON > +} CPUS390XState; > + > +#if defined(CONFIG_USER_ONLY) > +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) > +{ > + if (newsp) > + env->regs[15] = newsp; Coding style. > + env->regs[0] = 0; > +} > +#endif > + > +CPUS390XState *cpu_s390x_init(const char *cpu_model); > +int cpu_s390x_exec(CPUS390XState *s); > +void cpu_s390x_close(CPUS390XState *s); > + > +/* you can call this signal handler from your SIGBUS and SIGSEGV > + signal handlers to inform the virtual CPU of exceptions. non zero > + is returned if the signal was handled by the virtual CPU. */ > +int cpu_s390x_signal_handler(int host_signum, void *pinfo, > + void *puc); > +int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, > int rw, > + int mmu_idx, int is_softmuu); > +#define cpu_handle_mmu_fault cpu_s390x_handle_mmu_fault > + > +#define TARGET_PAGE_BITS 12 > + > +#define cpu_init cpu_s390x_init > +#define cpu_exec cpu_s390x_exec > +#define cpu_gen_code cpu_s390x_gen_code > + > +#include "cpu-all.h" > +#include "exec-all.h" > + > +#define EXCP_OPEX 1 /* operation exception (sigill) */ > +#define EXCP_SVC 2 /* supervisor call (syscall) */ > +#define EXCP_ADDR 5 /* addressing exception */ > +#define EXCP_EXECUTE_SVC 0xff00000 /* supervisor call via execute insn */ > + > +static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb) > +{ > + env->psw.addr = tb->pc; > +} > + > +static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc, > + target_ulong *cs_base, int *flags) > +{ > + *pc = env->psw.addr; > + *cs_base = 0; > + *flags = env->psw.mask; // guess I don't know what psw.mask represent, but it may be wrong. It should be a way to identify which TB can be reused, that is they have been generated in the same CPU mode. > +} > +#endif > diff --git a/target-s390x/exec.h b/target-s390x/exec.h > new file mode 100644 > index 0000000..5198359 > --- /dev/null > +++ b/target-s390x/exec.h > @@ -0,0 +1,51 @@ > +/* > + * S/390 execution defines > + * > + * 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 > USA > + */ > + > +#include "dyngen-exec.h" > + > +register struct CPUS390XState *env asm(AREG0); > + > +#include "cpu.h" > +#include "exec-all.h" > + > +static inline int cpu_has_work(CPUState *env) > +{ > + return env->interrupt_request & CPU_INTERRUPT_HARD; // guess > +} > + > +static inline void regs_to_env(void) > +{ > +} > + > +static inline void env_to_regs(void) > +{ > +} > + > +static inline int cpu_halted(CPUState *env) > +{ > + if (!env->halted) { > + return 0; > + } > + if (cpu_has_work(env)) { > + env->halted = 0; > + return 0; > + } > + return EXCP_HALTED; > +} > diff --git a/target-s390x/helper.c b/target-s390x/helper.c > new file mode 100644 > index 0000000..4e23b4a > --- /dev/null > +++ b/target-s390x/helper.c > @@ -0,0 +1,57 @@ > +/* > + * S/390 helpers > + * > + * 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 > USA > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "cpu.h" > +#include "exec-all.h" > +#include "gdbstub.h" > +#include "qemu-common.h" > + > +CPUS390XState *cpu_s390x_init(const char *cpu_model) > +{ > + CPUS390XState *env; > + static int inited = 0; > + > + env = qemu_mallocz(sizeof(CPUS390XState)); > + cpu_exec_init(env); > + if (!inited) { > + inited = 1; > + } > + > + env->cpu_model_str = cpu_model; > + cpu_reset(env); > + qemu_init_vcpu(env); > + return env; > +} > + > +void cpu_reset(CPUS390XState *env) > +{ > + if (qemu_loglevel_mask(CPU_LOG_RESET)) { > + qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); > + log_cpu_state(env, 0); > + } > + > + memset(env, 0, offsetof(CPUS390XState, breakpoints)); > + /* FIXME: reset vector? */ Isn't it also needed by kvm to make reset working? > + tlb_flush(env, 1); > +} > diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c > new file mode 100644 > index 0000000..e623de9 > --- /dev/null > +++ b/target-s390x/op_helper.c > @@ -0,0 +1,74 @@ > +/* > + * S/390 helper routines > + * > + * Copyright (c) 2009 Alexander Graf > + * > + * 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, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 > USA > + */ > + > +#include "exec.h" > + > +/*****************************************************************************/ > +/* Softmmu support */ > +#if !defined (CONFIG_USER_ONLY) > + > +#define MMUSUFFIX _mmu > + > +#define SHIFT 0 > +#include "softmmu_template.h" > + > +#define SHIFT 1 > +#include "softmmu_template.h" > + > +#define SHIFT 2 > +#include "softmmu_template.h" > + > +#define SHIFT 3 > +#include "softmmu_template.h" > + > +/* try to fill the TLB and return an exception if error. If retaddr is > + NULL, it means that the function was called in C code (i.e. not > + from generated code or from helper.c) */ > +/* XXX: fix it to restore all registers */ > +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) > +{ > + TranslationBlock *tb; > + CPUState *saved_env; > + unsigned long pc; > + int ret; > + > + /* XXX: hack to restore env in all cases, even if not called from > + generated code */ > + saved_env = env; > + env = cpu_single_env; > + ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); > + if (unlikely(ret != 0)) { > + if (likely(retaddr)) { > + /* now we have a real cpu fault */ > + pc = (unsigned long)retaddr; > + tb = tb_find_pc(pc); > + if (likely(tb)) { > + /* the PC is inside the translated code. It means that we > have > + a virtual CPU fault */ > + cpu_restore_state(tb, env, pc, NULL); > + } > + } > + /* XXX */ > + /* helper_raise_exception_err(env->exception_index, > env->error_code); */ > + } > + env = saved_env; > +} > + > +#endif > diff --git a/target-s390x/translate.c b/target-s390x/translate.c > new file mode 100644 > index 0000000..f304411 > --- /dev/null > +++ b/target-s390x/translate.c > @@ -0,0 +1,57 @@ > +/* > + * S/390 translation > + * > + * 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 > USA > + */ > + > +#include "cpu.h" > +#include "exec-all.h" > +#include "disas.h" > +#include "tcg-op.h" > +#include "qemu-log.h" > + > +void cpu_dump_state(CPUState *env, FILE *f, > + int (*cpu_fprintf)(FILE *f, const char *fmt, ...), > + int flags) > +{ > + int i; > + for (i = 0; i < 16; i++) { > + cpu_fprintf(f, "R%02d=%016lx", i, env->regs[i]); > + if ((i % 4) == 3) cpu_fprintf(f, "\n"); > + else cpu_fprintf(f, " "); > + } > + for (i = 0; i < 16; i++) { > + cpu_fprintf(f, "F%02d=%016lx", i, env->fregs[i]); > + if ((i % 4) == 3) cpu_fprintf(f, "\n"); > + else cpu_fprintf(f, " "); > + } > + cpu_fprintf(f, "PSW=mask %016lx addr %016lx cc %02x\n", env->psw.mask, > env->psw.addr, env->cc); > +} > + > +void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) > +{ > +} > + > +void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) > +{ > +} > + > +void gen_pc_load(CPUState *env, TranslationBlock *tb, > + unsigned long searched_pc, int pc_pos, void *puc) > +{ > + env->psw.addr = gen_opc_pc[pc_pos]; > +} > -- > 1.6.0.2 > > > > -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net