Commit 03262486 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/afaerber/tags/qom-cpu-for-peter' into staging



QOM CPUState and X86CPU

* Further QOM'ification of CPU initialization
* Propagation of CPUState arguments and elimination of ENV_GET_CPU() usage
* cpu_set_pc() abstraction
* CPUClass::disas_set_info() hook

# gpg: Signature made Thu Jul  9 14:23:12 2015 BST using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg:                 aka "Andreas Färber <afaerber@suse.com>"

* remotes/afaerber/tags/qom-cpu-for-peter: (22 commits)
  disas: cris: QOMify target specific disas setup
  disas: cris: Fix 0 buffer length case
  disas: microblaze: QOMify target specific disas setup
  disas: arm: QOMify target specific disas setup
  disas: arm-a64: Make printfer and stream variable
  disas: QOMify target specific setup
  disas: Add print_insn to disassemble info
  microblaze: boot: Use cpu_set_pc()
  hw/arm/boot: Use cpu_set_pc()
  gdbstub: Use cpu_set_pc() helper
  cpu: Add wrapper for the set_pc() hook
  cpu-exec: Purge all uses of ENV_GET_CPU()
  cpu: Change cpu_exec_init() arg to cpu, not env
  cpu: Change tcg_cpu_exec() arg to cpu, not env
  gdbstub: Change gdbserver_fork() to accept cpu instead of env
  translate-all: Change tb_flush() env argument to cpu
  target-ppc: Move cpu_exec_init() call to realize function
  cpu: Convert cpu_index into a bitmap
  cpu: Add Error argument to cpu_exec_init()
  cpu: Reorder cpu->as, cpu->thread_id, cpu->memory_dispatch init
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 5a2db896 6b625fde
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ void fork_start(void)
void fork_end(int child)
{
    if (child) {
        gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
        gdbserver_fork(thread_cpu);
    }
}

@@ -166,6 +166,8 @@ static void set_idt(int n, unsigned int dpl)

void cpu_loop(CPUX86State *env)
{
    X86CPU *cpu = x86_env_get_cpu(env);
    CPUState *cs = CPU(cpu);
    int trapnr;
    abi_ulong pc;
    //target_siginfo_t info;
@@ -512,7 +514,7 @@ void cpu_loop(CPUSPARCState *env)
    //target_siginfo_t info;

    while (1) {
        trapnr = cpu_sparc_exec (env);
        trapnr = cpu_sparc_exec(cs);

        switch (trapnr) {
#ifndef TARGET_SPARC64
+13 −15
Original line number Diff line number Diff line
@@ -227,10 +227,9 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)

/* Execute the code without caching the generated code. An interpreter
   could be used if available. */
static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
static void cpu_exec_nocache(CPUState *cpu, int max_cycles,
                             TranslationBlock *orig_tb)
{
    CPUState *cpu = ENV_GET_CPU(env);
    TranslationBlock *tb;
    target_ulong pc = orig_tb->pc;
    target_ulong cs_base = orig_tb->cs_base;
@@ -254,12 +253,12 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
    tb_free(tb);
}

static TranslationBlock *tb_find_slow(CPUArchState *env,
static TranslationBlock *tb_find_slow(CPUState *cpu,
                                      target_ulong pc,
                                      target_ulong cs_base,
                                      uint64_t flags)
{
    CPUState *cpu = ENV_GET_CPU(env);
    CPUArchState *env = (CPUArchState *)cpu->env_ptr;
    TranslationBlock *tb, **ptb1;
    unsigned int h;
    tb_page_addr_t phys_pc, phys_page1;
@@ -311,9 +310,9 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
    return tb;
}

static inline TranslationBlock *tb_find_fast(CPUArchState *env)
static inline TranslationBlock *tb_find_fast(CPUState *cpu)
{
    CPUState *cpu = ENV_GET_CPU(env);
    CPUArchState *env = (CPUArchState *)cpu->env_ptr;
    TranslationBlock *tb;
    target_ulong cs_base, pc;
    int flags;
@@ -325,14 +324,13 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env)
    tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                 tb->flags != flags)) {
        tb = tb_find_slow(env, pc, cs_base, flags);
        tb = tb_find_slow(cpu, pc, cs_base, flags);
    }
    return tb;
}

static void cpu_handle_debug_exception(CPUArchState *env)
static void cpu_handle_debug_exception(CPUState *cpu)
{
    CPUState *cpu = ENV_GET_CPU(env);
    CPUClass *cc = CPU_GET_CLASS(cpu);
    CPUWatchpoint *wp;

@@ -349,12 +347,12 @@ static void cpu_handle_debug_exception(CPUArchState *env)

volatile sig_atomic_t exit_request;

int cpu_exec(CPUArchState *env)
int cpu_exec(CPUState *cpu)
{
    CPUState *cpu = ENV_GET_CPU(env);
    CPUClass *cc = CPU_GET_CLASS(cpu);
#ifdef TARGET_I386
    X86CPU *x86_cpu = X86_CPU(cpu);
    CPUArchState *env = &x86_cpu->env;
#endif
    int ret, interrupt_request;
    TranslationBlock *tb;
@@ -407,7 +405,7 @@ int cpu_exec(CPUArchState *env)
                    /* exit request from the cpu execution loop */
                    ret = cpu->exception_index;
                    if (ret == EXCP_DEBUG) {
                        cpu_handle_debug_exception(env);
                        cpu_handle_debug_exception(cpu);
                    }
                    cpu->exception_index = -1;
                    break;
@@ -483,7 +481,7 @@ int cpu_exec(CPUArchState *env)
                }
                spin_lock(&tcg_ctx.tb_ctx.tb_lock);
                have_tb_lock = true;
                tb = tb_find_fast(env);
                tb = tb_find_fast(cpu);
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
                   doing it in tb_find_slow */
                if (tcg_ctx.tb_ctx.tb_invalidated_flag) {
@@ -543,7 +541,7 @@ int cpu_exec(CPUArchState *env)
                            if (insns_left > 0) {
                                /* Execute remaining instructions.  */
                                tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
                                cpu_exec_nocache(env, insns_left, tb);
                                cpu_exec_nocache(cpu, insns_left, tb);
                                align_clocks(&sc, cpu);
                            }
                            cpu->exception_index = EXCP_INTERRUPT;
@@ -567,11 +565,11 @@ int cpu_exec(CPUArchState *env)
            /* Reload env after longjmp - the compiler may have smashed all
             * local variables as longjmp is marked 'noreturn'. */
            cpu = current_cpu;
            env = cpu->env_ptr;
            cc = CPU_GET_CLASS(cpu);
            cpu->can_do_io = 1;
#ifdef TARGET_I386
            x86_cpu = X86_CPU(cpu);
            env = &x86_cpu->env;
#endif
            if (have_tb_lock) {
                spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
+3 −5
Original line number Diff line number Diff line
@@ -1357,9 +1357,8 @@ int vm_stop_force_state(RunState state)
    }
}

static int tcg_cpu_exec(CPUArchState *env)
static int tcg_cpu_exec(CPUState *cpu)
{
    CPUState *cpu = ENV_GET_CPU(env);
    int ret;
#ifdef CONFIG_PROFILER
    int64_t ti;
@@ -1394,7 +1393,7 @@ static int tcg_cpu_exec(CPUArchState *env)
        cpu->icount_decr.u16.low = decr;
        cpu->icount_extra = count;
    }
    ret = cpu_exec(env);
    ret = cpu_exec(cpu);
#ifdef CONFIG_PROFILER
    tcg_time += profile_getclock() - ti;
#endif
@@ -1421,13 +1420,12 @@ static void tcg_exec_all(void)
    }
    for (; next_cpu != NULL && !exit_request; next_cpu = CPU_NEXT(next_cpu)) {
        CPUState *cpu = next_cpu;
        CPUArchState *env = cpu->env_ptr;

        qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
                          (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);

        if (cpu_can_run(cpu)) {
            r = tcg_cpu_exec(env);
            r = tcg_cpu_exec(cpu);
            if (r == EXCP_DEBUG) {
                cpu_handle_guest_debug(cpu);
                break;
+44 −75
Original line number Diff line number Diff line
/* General "disassemble this chunk" code.  Used for debugging. */
#include "config.h"
#include "qemu-common.h"
#include "disas/bfd.h"
#include "elf.h"
#include <errno.h>
@@ -150,14 +151,6 @@ bfd_vma bfd_getb16 (const bfd_byte *addr)
  return (bfd_vma) v;
}

#ifdef TARGET_ARM
static int
print_insn_thumb1(bfd_vma pc, disassemble_info *info)
{
  return print_insn_arm(pc | 1, info);
}
#endif

static int print_insn_objdump(bfd_vma pc, disassemble_info *info,
                              const char *prefix)
{
@@ -190,7 +183,6 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
/* Disassemble this for me please... (debugging). 'flags' has the following
   values:
    i386 - 1 means 16 bit code, 2 means 64 bit code
    arm  - bit 0 = thumb, bit 1 = reverse endian, bit 2 = A64
    ppc  - bits 0:15 specify (optionally) the machine instruction set;
           bit 16 indicates little endian.
    other targets - unused
@@ -198,10 +190,10 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
void target_disas(FILE *out, CPUState *cpu, target_ulong code,
                  target_ulong size, int flags)
{
    CPUClass *cc = CPU_GET_CLASS(cpu);
    target_ulong pc;
    int count;
    CPUDebug s;
    int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;

    INIT_DISASSEMBLE_INFO(s.info, out, fprintf);

@@ -216,6 +208,11 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
#else
    s.info.endian = BFD_ENDIAN_LITTLE;
#endif

    if (cc->disas_set_info) {
        cc->disas_set_info(cpu, &s.info);
    }

#if defined(TARGET_I386)
    if (flags == 2) {
        s.info.mach = bfd_mach_x86_64;
@@ -224,30 +221,9 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
    } else {
        s.info.mach = bfd_mach_i386_i386;
    }
    print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
    if (flags & 4) {
        /* We might not be compiled with the A64 disassembler
         * because it needs a C++ compiler; in that case we will
         * fall through to the default print_insn_od case.
         */
#if defined(CONFIG_ARM_A64_DIS)
        print_insn = print_insn_arm_a64;
#endif
    } else if (flags & 1) {
        print_insn = print_insn_thumb1;
    } else {
        print_insn = print_insn_arm;
    }
    if (flags & 2) {
#ifdef TARGET_WORDS_BIGENDIAN
        s.info.endian = BFD_ENDIAN_LITTLE;
#else
        s.info.endian = BFD_ENDIAN_BIG;
#endif
    }
    s.info.print_insn = print_insn_i386;
#elif defined(TARGET_SPARC)
    print_insn = print_insn_sparc;
    s.info.print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
    s.info.mach = bfd_mach_sparc_v9b;
#endif
@@ -266,49 +242,38 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
#endif
    }
    s.info.disassembler_options = (char *)"any";
    print_insn = print_insn_ppc;
    s.info.print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
    print_insn = print_insn_m68k;
    s.info.print_insn = print_insn_m68k;
#elif defined(TARGET_MIPS)
#ifdef TARGET_WORDS_BIGENDIAN
    print_insn = print_insn_big_mips;
    s.info.print_insn = print_insn_big_mips;
#else
    print_insn = print_insn_little_mips;
    s.info.print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_SH4)
    s.info.mach = bfd_mach_sh4;
    print_insn = print_insn_sh;
    s.info.print_insn = print_insn_sh;
#elif defined(TARGET_ALPHA)
    s.info.mach = bfd_mach_alpha_ev6;
    print_insn = print_insn_alpha;
#elif defined(TARGET_CRIS)
    if (flags != 32) {
        s.info.mach = bfd_mach_cris_v0_v10;
        print_insn = print_insn_crisv10;
    } else {
        s.info.mach = bfd_mach_cris_v32;
        print_insn = print_insn_crisv32;
    }
    s.info.print_insn = print_insn_alpha;
#elif defined(TARGET_S390X)
    s.info.mach = bfd_mach_s390_64;
    print_insn = print_insn_s390;
#elif defined(TARGET_MICROBLAZE)
    s.info.mach = bfd_arch_microblaze;
    print_insn = print_insn_microblaze;
    s.info.print_insn = print_insn_s390;
#elif defined(TARGET_MOXIE)
    s.info.mach = bfd_arch_moxie;
    print_insn = print_insn_moxie;
    s.info.print_insn = print_insn_moxie;
#elif defined(TARGET_LM32)
    s.info.mach = bfd_mach_lm32;
    print_insn = print_insn_lm32;
    s.info.print_insn = print_insn_lm32;
#endif
    if (print_insn == NULL) {
        print_insn = print_insn_od_target;
    if (s.info.print_insn == NULL) {
        s.info.print_insn = print_insn_od_target;
    }

    for (pc = code; size > 0; pc += count, size -= count) {
	fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
	count = print_insn(pc, &s.info);
	count = s.info.print_insn(pc, &s.info);
#if 0
        {
            int i;
@@ -450,9 +415,9 @@ monitor_fprintf(FILE *stream, const char *fmt, ...)
void monitor_disas(Monitor *mon, CPUState *cpu,
                   target_ulong pc, int nb_insn, int is_physical, int flags)
{
    CPUClass *cc = CPU_GET_CLASS(cpu);
    int count, i;
    CPUDebug s;
    int (*print_insn)(bfd_vma pc, disassemble_info *info);

    INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf);

@@ -468,6 +433,11 @@ void monitor_disas(Monitor *mon, CPUState *cpu,
#else
    s.info.endian = BFD_ENDIAN_LITTLE;
#endif

    if (cc->disas_set_info) {
        cc->disas_set_info(cpu, &s.info);
    }

#if defined(TARGET_I386)
    if (flags == 2) {
        s.info.mach = bfd_mach_x86_64;
@@ -476,13 +446,11 @@ void monitor_disas(Monitor *mon, CPUState *cpu,
    } else {
        s.info.mach = bfd_mach_i386_i386;
    }
    print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
    print_insn = print_insn_arm;
    s.info.print_insn = print_insn_i386;
#elif defined(TARGET_ALPHA)
    print_insn = print_insn_alpha;
    s.info.print_insn = print_insn_alpha;
#elif defined(TARGET_SPARC)
    print_insn = print_insn_sparc;
    s.info.print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
    s.info.mach = bfd_mach_sparc_v9b;
#endif
@@ -500,36 +468,37 @@ void monitor_disas(Monitor *mon, CPUState *cpu,
    if ((flags >> 16) & 1) {
        s.info.endian = BFD_ENDIAN_LITTLE;
    }
    print_insn = print_insn_ppc;
    s.info.print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
    print_insn = print_insn_m68k;
    s.info.print_insn = print_insn_m68k;
#elif defined(TARGET_MIPS)
#ifdef TARGET_WORDS_BIGENDIAN
    print_insn = print_insn_big_mips;
    s.info.print_insn = print_insn_big_mips;
#else
    print_insn = print_insn_little_mips;
    s.info.print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_SH4)
    s.info.mach = bfd_mach_sh4;
    print_insn = print_insn_sh;
    s.info.print_insn = print_insn_sh;
#elif defined(TARGET_S390X)
    s.info.mach = bfd_mach_s390_64;
    print_insn = print_insn_s390;
    s.info.print_insn = print_insn_s390;
#elif defined(TARGET_MOXIE)
    s.info.mach = bfd_arch_moxie;
    print_insn = print_insn_moxie;
    s.info.print_insn = print_insn_moxie;
#elif defined(TARGET_LM32)
    s.info.mach = bfd_mach_lm32;
    print_insn = print_insn_lm32;
#else
    s.info.print_insn = print_insn_lm32;
#endif
    if (!s.info.print_insn) {
        monitor_printf(mon, "0x" TARGET_FMT_lx
                       ": Asm output not supported on this arch\n", pc);
        return;
#endif
    }

    for(i = 0; i < nb_insn; i++) {
	monitor_printf(mon, "0x" TARGET_FMT_lx ":  ", pc);
        count = print_insn(pc, &s.info);
        count = s.info.print_insn(pc, &s.info);
	monitor_printf(mon, "\n");
	if (count < 0)
	    break;
+17 −5
Original line number Diff line number Diff line
@@ -35,16 +35,25 @@ static Disassembler *vixl_disasm = NULL;
 */
class QEMUDisassembler : public Disassembler {
public:
    explicit QEMUDisassembler(FILE *stream) : stream_(stream) { }
    QEMUDisassembler() : printf_(NULL), stream_(NULL) { }
    ~QEMUDisassembler() { }

    void SetStream(FILE *stream) {
        stream_ = stream;
    }

    void SetPrintf(int (*printf_fn)(FILE *, const char *, ...)) {
        printf_ = printf_fn;
    }

protected:
    virtual void ProcessOutput(const Instruction *instr) {
        fprintf(stream_, "%08" PRIx32 "      %s",
        printf_(stream_, "%08" PRIx32 "      %s",
                instr->InstructionBits(), GetOutput());
    }

private:
    int (*printf_)(FILE *, const char *, ...);
    FILE *stream_;
};

@@ -53,9 +62,9 @@ static int vixl_is_initialized(void)
    return vixl_decoder != NULL;
}

static void vixl_init(FILE *f) {
static void vixl_init() {
    vixl_decoder = new Decoder();
    vixl_disasm = new QEMUDisassembler(f);
    vixl_disasm = new QEMUDisassembler();
    vixl_decoder->AppendVisitor(vixl_disasm);
}

@@ -78,9 +87,12 @@ int print_insn_arm_a64(uint64_t addr, disassemble_info *info)
    }

    if (!vixl_is_initialized()) {
        vixl_init(info->stream);
        vixl_init();
    }

    ((QEMUDisassembler *)vixl_disasm)->SetPrintf(info->fprintf_func);
    ((QEMUDisassembler *)vixl_disasm)->SetStream(info->stream);

    instrval = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24;
    instr = reinterpret_cast<const Instruction *>(&instrval);
    vixl_disasm->MapCodeAddress(addr, instr);
Loading