diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2013-02-18 08:37:29 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-02-18 08:37:29 -0600 |
commit | 3c3adde005ec929d7d581d495d9a0bb223e6e055 (patch) | |
tree | 05d51a8fa7e87f9ed196b6926c3db84e56c41ca5 | |
parent | f4c0f986c061f34fd5b020c30e2aa8c37e17193b (diff) | |
parent | 2d64255bd7c0d3933ff5ab2cabff11bcb09117a8 (diff) |
Merge remote-tracking branch 'afaerber/qom-cpu' into staging
# By Andreas Färber
# Via Andreas Färber
* afaerber/qom-cpu: (47 commits)
target-i386: Split command line parsing out of cpu_x86_register()
target-i386: Move cpu_x86_init()
target-lm32: Drop unused cpu_lm32_close() prototype
target-s390x: Drop unused cpu_s390x_close() prototype
spapr_hcall: Replace open-coded CPU loop with qemu_get_cpu()
ppce500_spin: Replace open-coded CPU loop with qemu_get_cpu()
e500: Replace open-coded loop with qemu_get_cpu()
cpu: Add CPUArchState pointer to CPUState
cputlb: Pass CPUState to cpu_unlink_tb()
cpu: Move current_tb field to CPUState
cpu: Move exit_request field to CPUState
cpu: Move running field to CPUState
cpu: Move host_tid field to CPUState
target-cris: Introduce CRISCPU subclasses
target-m68k: Pass M68kCPU to m68k_set_irq_level()
mcf_intc: Pass M68kCPU to mcf_intc_init()
mcf5206: Pass M68kCPU to mcf5206_init()
target-m68k: Return M68kCPU from cpu_m68k_init()
ppc405_uc: Pass PowerPCCPU to ppc40x_{core,chip,system}_reset()
target-xtensa: Move TCG initialization to XtensaCPU initfn
...
83 files changed, 780 insertions, 363 deletions
diff --git a/cpu-exec.c b/cpu-exec.c index ff9a884a96..9fcfe9e0db 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -32,7 +32,9 @@ bool qemu_cpu_has_work(CPUState *cpu) void cpu_loop_exit(CPUArchState *env) { - env->current_tb = NULL; + CPUState *cpu = ENV_GET_CPU(env); + + cpu->current_tb = NULL; longjmp(env->jmp_env, 1); } @@ -54,6 +56,7 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc) static void cpu_exec_nocache(CPUArchState *env, int max_cycles, TranslationBlock *orig_tb) { + CPUState *cpu = ENV_GET_CPU(env); tcg_target_ulong next_tb; TranslationBlock *tb; @@ -64,10 +67,10 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles, tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, max_cycles); - env->current_tb = tb; + cpu->current_tb = tb; /* execute the generated code */ next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr); - env->current_tb = NULL; + cpu->current_tb = NULL; if ((next_tb & 3) == 2) { /* Restore PC. This may happen if async event occurs before @@ -196,7 +199,7 @@ int cpu_exec(CPUArchState *env) cpu_single_env = env; if (unlikely(exit_request)) { - env->exit_request = 1; + cpu->exit_request = 1; } #if defined(TARGET_I386) @@ -537,8 +540,8 @@ int cpu_exec(CPUArchState *env) next_tb = 0; } } - if (unlikely(env->exit_request)) { - env->exit_request = 0; + if (unlikely(cpu->exit_request)) { + cpu->exit_request = 0; env->exception_index = EXCP_INTERRUPT; cpu_loop_exit(env); } @@ -589,9 +592,9 @@ int cpu_exec(CPUArchState *env) TB, but before it is linked into a potentially infinite loop and becomes env->current_tb. Avoid starting execution if there is a pending interrupt. */ - env->current_tb = tb; + cpu->current_tb = tb; barrier(); - if (likely(!env->exit_request)) { + if (likely(!cpu->exit_request)) { tc_ptr = tb->tc_ptr; /* execute the generated code */ next_tb = tcg_qemu_tb_exec(env, tc_ptr); @@ -623,7 +626,7 @@ int cpu_exec(CPUArchState *env) } } } - env->current_tb = NULL; + cpu->current_tb = NULL; /* reset soft MMU for next block (it can currently only be set by a memory fault) */ } /* for(;;) */ @@ -54,6 +54,7 @@ static const CPUTLBEntry s_cputlb_empty_entry = { */ void tlb_flush(CPUArchState *env, int flush_global) { + CPUState *cpu = ENV_GET_CPU(env); int i; #if defined(DEBUG_TLB) @@ -61,7 +62,7 @@ void tlb_flush(CPUArchState *env, int flush_global) #endif /* must reset current TB so that interrupts cannot modify the links while we are modifying them */ - env->current_tb = NULL; + cpu->current_tb = NULL; for (i = 0; i < CPU_TLB_SIZE; i++) { int mmu_idx; @@ -92,6 +93,7 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) void tlb_flush_page(CPUArchState *env, target_ulong addr) { + CPUState *cpu = ENV_GET_CPU(env); int i; int mmu_idx; @@ -110,7 +112,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr) } /* must reset current TB so that interrupts cannot modify the links while we are modifying them */ - env->current_tb = NULL; + cpu->current_tb = NULL; addr &= TARGET_PAGE_MASK; i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); @@ -271,11 +271,13 @@ static int write_elf64_note(DumpState *s) static int write_elf64_notes(DumpState *s) { CPUArchState *env; + CPUState *cpu; int ret; int id; for (env = first_cpu; env != NULL; env = env->next_cpu) { - id = cpu_index(env); + cpu = ENV_GET_CPU(env); + id = cpu_index(cpu); ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s); if (ret < 0) { dump_error(s, "dump: failed to write elf notes.\n"); @@ -321,11 +323,13 @@ static int write_elf32_note(DumpState *s) static int write_elf32_notes(DumpState *s) { CPUArchState *env; + CPUState *cpu; int ret; int id; for (env = first_cpu; env != NULL; env = env->next_cpu) { - id = cpu_index(env); + cpu = ENV_GET_CPU(env); + id = cpu_index(cpu); ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s); if (ret < 0) { dump_error(s, "dump: failed to write elf notes.\n"); @@ -492,8 +492,10 @@ void cpu_reset_interrupt(CPUArchState *env, int mask) void cpu_exit(CPUArchState *env) { - env->exit_request = 1; - cpu_unlink_tb(env); + CPUState *cpu = ENV_GET_CPU(env); + + cpu->exit_request = 1; + cpu_unlink_tb(cpu); } void cpu_abort(CPUArchState *env, const char *fmt, ...) @@ -2066,9 +2066,11 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) static CPUArchState *find_cpu(uint32_t thread_id) { CPUArchState *env; + CPUState *cpu; for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (cpu_index(env) == thread_id) { + cpu = ENV_GET_CPU(env); + if (cpu_index(cpu) == thread_id) { return env; } } @@ -2096,7 +2098,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) case '?': /* TODO: Make this return the correct value for user-mode. */ snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP, - cpu_index(s->c_cpu)); + cpu_index(ENV_GET_CPU(s->c_cpu))); put_packet(s, buf); /* Remove all the breakpoints when this query is issued, * because gdb is doing and initial connect and the state @@ -2391,7 +2393,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) } else if (strcmp(p,"sThreadInfo") == 0) { report_cpuinfo: if (s->query_cpu) { - snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu)); + snprintf(buf, sizeof(buf), "m%x", + cpu_index(ENV_GET_CPU(s->query_cpu))); put_packet(s, buf); s->query_cpu = s->query_cpu->next_cpu; } else @@ -2512,6 +2515,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) { GDBState *s = gdbserver_state; CPUArchState *env = s->c_cpu; + CPUState *cpu = ENV_GET_CPU(env); char buf[256]; const char *type; int ret; @@ -2540,7 +2544,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) } snprintf(buf, sizeof(buf), "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";", - GDB_SIGNAL_TRAP, cpu_index(env), type, + GDB_SIGNAL_TRAP, cpu_index(cpu), type, env->watchpoint_hit->vaddr); env->watchpoint_hit = NULL; goto send_packet; @@ -2573,7 +2577,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) ret = GDB_SIGNAL_UNKNOWN; break; } - snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(env)); + snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu)); send_packet: put_packet(s, buf); diff --git a/hw/an5206.c b/hw/an5206.c index 750115a3aa..924be81d57 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -24,6 +24,7 @@ static void an5206_init(QEMUMachineInitArgs *args) ram_addr_t ram_size = args->ram_size; const char *cpu_model = args->cpu_model; const char *kernel_filename = args->kernel_filename; + M68kCPU *cpu; CPUM68KState *env; int kernel_size; uint64_t elf_entry; @@ -32,12 +33,14 @@ static void an5206_init(QEMUMachineInitArgs *args) MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); - if (!cpu_model) + if (!cpu_model) { cpu_model = "m5206"; - env = cpu_init(cpu_model); - if (!env) { + } + cpu = cpu_m68k_init(cpu_model); + if (!cpu) { hw_error("Unable to find m68k CPU definition\n"); } + env = &cpu->env; /* Initialize CPU registers. */ env->vbr = 0; @@ -55,7 +58,7 @@ static void an5206_init(QEMUMachineInitArgs *args) vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram); - mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, env); + mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, cpu); /* Load kernel. */ if (!kernel_filename) { diff --git a/hw/apic_common.c b/hw/apic_common.c index 6e1b1e0320..d8c9810509 100644 --- a/hw/apic_common.c +++ b/hw/apic_common.c @@ -103,7 +103,7 @@ void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, { APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - vapic_report_tpr_access(s->vapic, &s->cpu->env, ip, access); + vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access); } void apic_report_irq_delivered(int delivered) diff --git a/hw/apic_internal.h b/hw/apic_internal.h index dcbbfd41cb..9265e52cd6 100644 --- a/hw/apic_internal.h +++ b/hw/apic_internal.h @@ -143,7 +143,7 @@ bool apic_next_timer(APICCommonState *s, int64_t current_time); void apic_enable_tpr_access_reporting(DeviceState *d, bool enable); void apic_enable_vapic(DeviceState *d, hwaddr paddr); -void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip, +void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip, TPRAccess access); #endif /* !QEMU_APIC_INTERNAL_H */ diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c index 1b5f416a78..9265baf568 100644 --- a/hw/kvmvapic.c +++ b/hw/kvmvapic.c @@ -382,8 +382,10 @@ static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip, cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1); } -static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong ip) +static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip) { + CPUState *cs = CPU(cpu); + CPUX86State *env = &cpu->env; VAPICHandlers *handlers; uint8_t opcode[2]; uint32_t imm32; @@ -439,17 +441,18 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i resume_all_vcpus(); if (!kvm_enabled()) { - env->current_tb = NULL; + cs->current_tb = NULL; tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); cpu_resume_from_signal(env, NULL); } } -void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip, +void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip, TPRAccess access) { VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev); - CPUX86State *env = cpu; + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; cpu_synchronize_state(env); @@ -465,7 +468,7 @@ void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip, if (vapic_enable(s, env) < 0) { return; } - patch_instruction(s, env, ip); + patch_instruction(s, cpu, ip); } typedef struct VAPICEnableTPRReporting { @@ -17,7 +17,7 @@ void mcf_uart_mm_init(struct MemoryRegion *sysmem, /* mcf_intc.c */ qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem, hwaddr base, - CPUM68KState *env); + M68kCPU *cpu); /* mcf_fec.c */ void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd, @@ -25,6 +25,6 @@ void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd, /* mcf5206.c */ qemu_irq *mcf5206_init(struct MemoryRegion *sysmem, - uint32_t base, CPUM68KState *env); + uint32_t base, M68kCPU *cpu); #endif diff --git a/hw/mcf5206.c b/hw/mcf5206.c index d8c0059ed6..ea2db2325a 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -145,7 +145,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq) /* System Integration Module. */ typedef struct { - CPUM68KState *env; + M68kCPU *cpu; MemoryRegion iomem; m5206_timer_state *timer[2]; void *uart[2]; @@ -226,7 +226,7 @@ static void m5206_mbar_update(m5206_mbar_state *s) level = 0; vector = 0; } - m68k_set_irq_level(s->env, level, vector); + m68k_set_irq_level(s->cpu, level, vector); } static void m5206_mbar_set_irq(void *opaque, int irq, int level) @@ -525,7 +525,7 @@ static const MemoryRegionOps m5206_mbar_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUM68KState *env) +qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu) { m5206_mbar_state *s; qemu_irq *pic; @@ -541,7 +541,7 @@ qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUM68KState *env) s->timer[1] = m5206_timer_init(pic[10]); s->uart[0] = mcf_uart_init(pic[12], serial_hds[0]); s->uart[1] = mcf_uart_init(pic[13], serial_hds[1]); - s->env = env; + s->cpu = cpu; m5206_mbar_reset(s); return pic; diff --git a/hw/mcf5208.c b/hw/mcf5208.c index 2c9a5dc98a..86402d30d5 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -192,6 +192,7 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args) ram_addr_t ram_size = args->ram_size; const char *cpu_model = args->cpu_model; const char *kernel_filename = args->kernel_filename; + M68kCPU *cpu; CPUM68KState *env; int kernel_size; uint64_t elf_entry; @@ -201,13 +202,15 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args) MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); - if (!cpu_model) + if (!cpu_model) { cpu_model = "m5208"; - env = cpu_init(cpu_model); - if (!env) { + } + cpu = cpu_m68k_init(cpu_model); + if (!cpu) { fprintf(stderr, "Unable to find m68k CPU definition\n"); exit(1); } + env = &cpu->env; /* Initialize CPU registers. */ env->vbr = 0; @@ -224,7 +227,7 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args) memory_region_add_subregion(address_space_mem, 0x80000000, sram); /* Internal peripherals. */ - pic = mcf_intc_init(address_space_mem, 0xfc048000, env); + pic = mcf_intc_init(address_space_mem, 0xfc048000, cpu); mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]); mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]); diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c index 3bed3a2e4c..b213656300 100644 --- a/hw/mcf_intc.c +++ b/hw/mcf_intc.c @@ -16,7 +16,7 @@ typedef struct { uint64_t ifr; uint64_t enabled; uint8_t icr[64]; - CPUM68KState *env; + M68kCPU *cpu; int active_vector; } mcf_intc_state; @@ -40,7 +40,7 @@ static void mcf_intc_update(mcf_intc_state *s) } } s->active_vector = ((best == 64) ? 24 : (best + 64)); - m68k_set_irq_level(s->env, best_level, s->active_vector); + m68k_set_irq_level(s->cpu, best_level, s->active_vector); } static uint64_t mcf_intc_read(void *opaque, hwaddr addr, @@ -139,12 +139,12 @@ static const MemoryRegionOps mcf_intc_ops = { qemu_irq *mcf_intc_init(MemoryRegion *sysmem, hwaddr base, - CPUM68KState *env) + M68kCPU *cpu) { mcf_intc_state *s; s = g_malloc0(sizeof(mcf_intc_state)); - s->env = env; + s->cpu = cpu; mcf_intc_reset(s); memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100); @@ -876,7 +876,6 @@ void pc_cpus_init(const char *cpu_model) for (i = 0; i < smp_cpus; i++) { if (!cpu_x86_init(cpu_model)) { - fprintf(stderr, "Unable to find x86 CPU definition\n"); exit(1); } } @@ -300,20 +300,20 @@ static void ppc40x_set_irq(void *opaque, int pin, int level) if (level) { LOG_IRQ("%s: reset the PowerPC system\n", __func__); - ppc40x_system_reset(env); + ppc40x_system_reset(cpu); } break; case PPC40x_INPUT_RESET_CHIP: if (level) { LOG_IRQ("%s: reset the PowerPC chip\n", __func__); - ppc40x_chip_reset(env); + ppc40x_chip_reset(cpu); } break; case PPC40x_INPUT_RESET_CORE: /* XXX: TODO: update DBSR[MRR] */ if (level) { LOG_IRQ("%s: reset the PowerPC core\n", __func__); - ppc40x_core_reset(env); + ppc40x_core_reset(cpu); } break; case PPC40x_INPUT_CINT: @@ -1011,13 +1011,13 @@ static void cpu_4xx_wdt_cb (void *opaque) /* No reset */ break; case 0x1: /* Core reset */ - ppc40x_core_reset(env); + ppc40x_core_reset(cpu); break; case 0x2: /* Chip reset */ - ppc40x_chip_reset(env); + ppc40x_chip_reset(cpu); break; case 0x3: /* System reset */ - ppc40x_system_reset(env); + ppc40x_system_reset(cpu); break; } } @@ -58,9 +58,9 @@ clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, unsigned int decr_excp); /* Embedded PowerPC reset */ -void ppc40x_core_reset (CPUPPCState *env); -void ppc40x_chip_reset (CPUPPCState *env); -void ppc40x_system_reset (CPUPPCState *env); +void ppc40x_core_reset(PowerPCCPU *cpu); +void ppc40x_chip_reset(PowerPCCPU *cpu); +void ppc40x_system_reset(PowerPCCPU *cpu); void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); extern CPUWriteMemoryFunc * const PPC_io_write[]; diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index b7474c05f9..451682cb83 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -240,20 +240,15 @@ static int ppce500_load_device_tree(CPUPPCState *env, /* We need to generate the cpu nodes in reverse order, so Linux can pick the first node as boot node and be happy */ for (i = smp_cpus - 1; i >= 0; i--) { - CPUState *cpu = NULL; + CPUState *cpu; char cpu_name[128]; uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); - if (cpu->cpu_index == i) { - break; - } - } - + cpu = qemu_get_cpu(i); if (cpu == NULL) { continue; } + env = cpu->env_ptr; snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", cpu->cpu_index); diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index c96d103d1c..d8cbe875bd 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -1770,8 +1770,9 @@ static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]) /*****************************************************************************/ /* SPR */ -void ppc40x_core_reset (CPUPPCState *env) +void ppc40x_core_reset(PowerPCCPU *cpu) { + CPUPPCState *env = &cpu->env; target_ulong dbsr; printf("Reset PowerPC core\n"); @@ -1782,8 +1783,9 @@ void ppc40x_core_reset (CPUPPCState *env) env->spr[SPR_40x_DBSR] = dbsr; } -void ppc40x_chip_reset (CPUPPCState *env) +void ppc40x_chip_reset(PowerPCCPU *cpu) { + CPUPPCState *env = &cpu->env; target_ulong dbsr; printf("Reset PowerPC chip\n"); @@ -1795,7 +1797,7 @@ void ppc40x_chip_reset (CPUPPCState *env) env->spr[SPR_40x_DBSR] = dbsr; } -void ppc40x_system_reset (CPUPPCState *env) +void ppc40x_system_reset(PowerPCCPU *cpu) { printf("Reset PowerPC system\n"); qemu_system_reset_request(); @@ -1803,21 +1805,23 @@ void ppc40x_system_reset (CPUPPCState *env) void store_40x_dbcr0 (CPUPPCState *env, uint32_t val) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + switch ((val >> 28) & 0x3) { case 0x0: /* No action */ break; case 0x1: /* Core reset */ - ppc40x_core_reset(env); + ppc40x_core_reset(cpu); break; case 0x2: /* Chip reset */ - ppc40x_chip_reset(env); + ppc40x_chip_reset(cpu); break; case 0x3: /* System reset */ - ppc40x_system_reset(env); + ppc40x_system_reset(cpu); break; } } diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 7e90fb9824..5bdce52e24 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -123,18 +123,11 @@ static void spin_write(void *opaque, hwaddr addr, uint64_t value, { SpinState *s = opaque; int env_idx = addr / sizeof(SpinInfo); - CPUPPCState *env; - CPUState *cpu = NULL; + CPUState *cpu; SpinInfo *curspin = &s->spin[env_idx]; uint8_t *curspin_p = (uint8_t*)curspin; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = CPU(ppc_env_get_cpu(env)); - if (cpu->cpu_index == env_idx) { - break; - } - } - + cpu = qemu_get_cpu(env_idx); if (cpu == NULL) { /* Unknown CPU */ return; @@ -161,11 +154,11 @@ static void spin_write(void *opaque, hwaddr addr, uint64_t value, if (!(ldq_p(&curspin->addr) & 1)) { /* run CPU */ SpinKick kick = { - .cpu = ppc_env_get_cpu(env), + .cpu = POWERPC_CPU(cpu), .spin = curspin, }; - run_on_cpu(CPU(kick.cpu), spin_kick, &kick); + run_on_cpu(cpu, spin_kick, &kick); } } diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 2889742788..7b8959488e 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -469,16 +469,11 @@ static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr, CPUPPCState *tenv; CPUState *tcpu; - for (tenv = first_cpu; tenv; tenv = tenv->next_cpu) { - tcpu = CPU(ppc_env_get_cpu(tenv)); - if (tcpu->cpu_index == procno) { - break; - } - } - - if (!tenv) { + tcpu = qemu_get_cpu(procno); + if (!tcpu) { return H_PARAMETER; } + tenv = tcpu->env_ptr; switch (flags) { case FLAGS_REGISTER_VPA: @@ -513,13 +508,14 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); env->msr |= (1ULL << MSR_EE); hreg_compute_hflags(env); - if (!cpu_has_work(CPU(cpu))) { + if (!cpu_has_work(cs)) { env->halted = 1; env->exception_index = EXCP_HLT; - env->exit_request = 1; + cs->exit_request = 1; } return H_SUCCESS; } diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 2911b9fc90..ae64590cdf 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -26,7 +26,6 @@ #include "config.h" #include <setjmp.h> #include <inttypes.h> -#include <signal.h> #include "qemu/osdep.h" #include "qemu/queue.h" #include "exec/hwaddr.h" @@ -149,7 +148,6 @@ typedef struct CPUWatchpoint { #define CPU_TEMP_BUF_NLONGS 128 #define CPU_COMMON \ - struct TranslationBlock *current_tb; /* currently executing TB */ \ /* soft mmu support */ \ /* in order to avoid passing too many arguments to the MMIO \ helpers, we store some rarely used information in the CPU \ @@ -160,7 +158,6 @@ typedef struct CPUWatchpoint { memory was accessed */ \ uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ uint32_t interrupt_request; \ - volatile sig_atomic_t exit_request; \ CPU_COMMON_TLB \ struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ /* buffer for temporaries in the code generator */ \ @@ -191,8 +188,6 @@ typedef struct CPUWatchpoint { int exception_index; \ \ CPUArchState *next_cpu; /* next CPU sharing TB cache */ \ - uint32_t host_tid; /* host thread ID */ \ - int running; /* Nonzero if cpu is currently running(usermode). */ \ /* user data */ \ void *opaque; \ \ diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index f685c28573..e856191e40 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -404,11 +404,13 @@ extern volatile sig_atomic_t exit_request; instruction of a TB so that interrupts take effect immediately. */ static inline int can_do_io(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); + if (!use_icount) { return 1; } /* If not executing code then assume we are ok. */ - if (!env->current_tb) { + if (cpu->current_tb == NULL) { return 1; } return env->can_do_io != 0; diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index 49231feb29..ba20afa091 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -30,12 +30,11 @@ void gdb_register_coprocessor(CPUArchState *env, gdb_reg_cb get_reg, gdb_reg_cb set_reg, int num_regs, const char *xml, int g_pos); -static inline int cpu_index(CPUArchState *env) +static inline int cpu_index(CPUState *cpu) { #if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL) - return env->host_tid; + return cpu->host_tid; #else - CPUState *cpu = ENV_GET_CPU(env); return cpu->cpu_index + 1; #endif } diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 46f2247274..ee1a7c878a 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -20,6 +20,7 @@ #ifndef QEMU_CPU_H #define QEMU_CPU_H +#include <signal.h> #include "hw/qdev-core.h" #include "qemu/thread.h" @@ -65,9 +66,13 @@ struct kvm_run; * @nr_cores: Number of cores within this CPU package. * @nr_threads: Number of threads within this CPU. * @numa_node: NUMA node this CPU is belonging to. + * @host_tid: Host thread ID. + * @running: #true if CPU is currently running (usermode). * @created: Indicates whether the CPU thread has been successfully created. * @stop: Indicates a pending stop request. * @stopped: Indicates the CPU has been artificially stopped. + * @env_ptr: Pointer to subclass-specific CPUArchState field. + * @current_tb: Currently executing TB. * @kvm_fd: vCPU file descriptor for KVM. * * State of one CPU core or thread. @@ -86,12 +91,18 @@ struct CPUState { HANDLE hThread; #endif int thread_id; + uint32_t host_tid; + bool running; struct QemuCond *halt_cond; struct qemu_work_item *queued_work_first, *queued_work_last; bool thread_kicked; bool created; bool stop; bool stopped; + volatile sig_atomic_t exit_request; + + void *env_ptr; /* CPUArchState */ + struct TranslationBlock *current_tb; int kvm_fd; bool kvm_vcpu_dirty; @@ -1537,7 +1537,7 @@ int kvm_cpu_exec(CPUArchState *env) DPRINTF("kvm_cpu_exec()\n"); if (kvm_arch_process_async_events(cpu)) { - env->exit_request = 0; + cpu->exit_request = 0; return EXCP_HLT; } @@ -1548,7 +1548,7 @@ int kvm_cpu_exec(CPUArchState *env) } kvm_arch_pre_run(cpu, run); - if (env->exit_request) { + if (cpu->exit_request) { DPRINTF("interrupt exit requested\n"); /* * KVM requires us to reenter the kernel after IO exits to complete @@ -1622,7 +1622,7 @@ int kvm_cpu_exec(CPUArchState *env) vm_stop(RUN_STATE_INTERNAL_ERROR); } - env->exit_request = 0; + cpu->exit_request = 0; return ret; } diff --git a/linux-user/main.c b/linux-user/main.c index 146a4683a5..e51568430f 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -151,13 +151,16 @@ static inline void exclusive_idle(void) static inline void start_exclusive(void) { CPUArchState *other; + CPUState *other_cpu; + pthread_mutex_lock(&exclusive_lock); exclusive_idle(); pending_cpus = 1; /* Make all other cpus stop executing. */ for (other = first_cpu; other; other = other->next_cpu) { - if (other->running) { + other_cpu = ENV_GET_CPU(other); + if (other_cpu->running) { pending_cpus++; cpu_exit(other); } @@ -176,19 +179,19 @@ static inline void end_exclusive(void) } /* Wait for exclusive ops to finish, and begin cpu execution. */ -static inline void cpu_exec_start(CPUArchState *env) +static inline void cpu_exec_start(CPUState *cpu) { pthread_mutex_lock(&exclusive_lock); exclusive_idle(); - env->running = 1; + cpu->running = true; pthread_mutex_unlock(&exclusive_lock); } /* Mark cpu as not executing, and release pending exclusive ops. */ -static inline void cpu_exec_end(CPUArchState *env) +static inline void cpu_exec_end(CPUState *cpu) { pthread_mutex_lock(&exclusive_lock); - env->running = 0; + cpu->running = false; if (pending_cpus > 1) { pending_cpus--; if (pending_cpus == 1) { @@ -210,11 +213,11 @@ void cpu_list_unlock(void) } #else /* if !CONFIG_USE_NPTL */ /* These are no-ops because we are not threadsafe. */ -static inline void cpu_exec_start(CPUArchState *env) +static inline void cpu_exec_start(CPUState *cpu) { } -static inline void cpu_exec_end(CPUArchState *env) +static inline void cpu_exec_end(CPUState *cpu) { } @@ -697,15 +700,16 @@ done: void cpu_loop(CPUARMState *env) { + CPUState *cs = CPU(arm_env_get_cpu(env)); int trapnr; unsigned int n, insn; target_siginfo_t info; uint32_t addr; for(;;) { - cpu_exec_start(env); + cpu_exec_start(cs); trapnr = cpu_arm_exec(env); - cpu_exec_end(env); + cpu_exec_end(cs); switch(trapnr) { case EXCP_UDEF: { @@ -912,14 +916,15 @@ void cpu_loop(CPUARMState *env) void cpu_loop(CPUUniCore32State *env) { + CPUState *cs = CPU(uc32_env_get_cpu(env)); int trapnr; unsigned int n, insn; target_siginfo_t info; for (;;) { - cpu_exec_start(env); + cpu_exec_start(cs); trapnr = uc32_cpu_exec(env); - cpu_exec_end(env); + cpu_exec_end(cs); switch (trapnr) { case UC32_EXCP_PRIV: { @@ -1367,14 +1372,15 @@ static int do_store_exclusive(CPUPPCState *env) void 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(env); + cpu_exec_start(cs); trapnr = cpu_ppc_exec(env); - cpu_exec_end(env); + cpu_exec_end(cs); switch(trapnr) { case POWERPC_EXCP_NONE: /* Just go on */ @@ -2184,14 +2190,15 @@ static int do_store_exclusive(CPUMIPSState *env) void cpu_loop(CPUMIPSState *env) { + CPUState *cs = CPU(mips_env_get_cpu(env)); target_siginfo_t info; int trapnr, ret; unsigned int syscall_num; for(;;) { - cpu_exec_start(env); + cpu_exec_start(cs); trapnr = cpu_mips_exec(env); - cpu_exec_end(env); + cpu_exec_end(cs); switch(trapnr) { case EXCP_SYSCALL: syscall_num = env->active_tc.gpr[2] - 4000; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9e31ea7200..19630eaf20 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4312,13 +4312,15 @@ static void *clone_func(void *arg) { new_thread_info *info = arg; CPUArchState *env; + CPUState *cpu; TaskState *ts; env = info->env; + cpu = ENV_GET_CPU(env); thread_env = env; ts = (TaskState *)thread_env->opaque; info->tid = gettid(); - env->host_tid = info->tid; + cpu->host_tid = info->tid; task_settid(ts); if (info->child_tidptr) put_user_u32(info->tid, info->child_tidptr); @@ -32,6 +32,8 @@ void cpu_reset(CPUState *cpu) static void cpu_common_reset(CPUState *cpu) { + cpu->exit_request = 0; + cpu->current_tb = NULL; } ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model) @@ -46,6 +48,10 @@ static ObjectClass *cpu_common_class_by_name(const char *cpu_model) return NULL; } +static void cpu_common_realizefn(DeviceState *dev, Error **errp) +{ +} + static void cpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -53,6 +59,7 @@ static void cpu_class_init(ObjectClass *klass, void *data) k->class_by_name = cpu_common_class_by_name; k->reset = cpu_common_reset; + dc->realize = cpu_common_realizefn; dc->no_user = 1; } diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h index 16367d2ea4..c0f6c6d165 100644 --- a/target-alpha/cpu-qom.h +++ b/target-alpha/cpu-qom.h @@ -34,6 +34,7 @@ /** * AlphaCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * An Alpha CPU model. @@ -43,6 +44,7 @@ typedef struct AlphaCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } AlphaCPUClass; diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index 0ad69f0859..cec9989925 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -21,14 +21,16 @@ #include "cpu.h" #include "qemu-common.h" -#include "qapi/error.h" -static void alpha_cpu_realize(Object *obj, Error **errp) +static void alpha_cpu_realizefn(DeviceState *dev, Error **errp) { - AlphaCPU *cpu = ALPHA_CPU(obj); + AlphaCPU *cpu = ALPHA_CPU(dev); + AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev); qemu_init_vcpu(&cpu->env); + + acc->parent_realize(dev, errp); } /* Sort alphabetically by type name. */ @@ -134,7 +136,8 @@ AlphaCPU *cpu_alpha_init(const char *cpu_model) env->cpu_model_str = cpu_model; - alpha_cpu_realize(OBJECT(cpu), NULL); + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); + return cpu; } @@ -230,9 +233,11 @@ static const TypeInfo ev68_cpu_type_info = { static void alpha_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); AlphaCPU *cpu = ALPHA_CPU(obj); CPUAlphaState *env = &cpu->env; + cs->env_ptr = env; cpu_exec_init(env); tlb_flush(env, 1); @@ -250,7 +255,12 @@ static void alpha_cpu_initfn(Object *obj) static void alpha_cpu_class_init(ObjectClass *oc, void *data) { + DeviceClass *dc = DEVICE_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); + AlphaCPUClass *acc = ALPHA_CPU_CLASS(oc); + + acc->parent_realize = dc->realize; + dc->realize = alpha_cpu_realizefn; cc->class_by_name = alpha_cpu_class_by_name; } diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h index 0f455c40ff..aff7bf302e 100644 --- a/target-arm/cpu-qom.h +++ b/target-arm/cpu-qom.h @@ -33,6 +33,7 @@ /** * ARMCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * An ARM CPU model. @@ -42,6 +43,7 @@ typedef struct ARMCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } ARMCPUClass; @@ -107,7 +109,6 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env) #define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e)) -void arm_cpu_realize(ARMCPU *cpu); void register_cp_regs_for_features(ARMCPU *cpu); #endif diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 1c6a628df4..5dfcb740d9 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -134,11 +134,19 @@ static inline void set_feature(CPUARMState *env, int feature) static void arm_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); ARMCPU *cpu = ARM_CPU(obj); + static bool inited; + cs->env_ptr = &cpu->env; cpu_exec_init(&cpu->env); cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free); + + if (tcg_enabled() && !inited) { + inited = true; + arm_translate_init(); + } } static void arm_cpu_finalizefn(Object *obj) @@ -147,15 +155,12 @@ static void arm_cpu_finalizefn(Object *obj) g_hash_table_destroy(cpu->cp_regs); } -void arm_cpu_realize(ARMCPU *cpu) +static void arm_cpu_realizefn(DeviceState *dev, Error **errp) { - /* This function is called by cpu_arm_init() because it - * needs to do common actions based on feature bits, etc - * that have been set by the subclass init functions. - * When we have QOM realize support it should become - * a true realize function instead. - */ + ARMCPU *cpu = ARM_CPU(dev); + ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev); CPUARMState *env = &cpu->env; + /* Some features automatically imply others: */ if (arm_feature(env, ARM_FEATURE_V7)) { set_feature(env, ARM_FEATURE_VAPA); @@ -197,6 +202,12 @@ void arm_cpu_realize(ARMCPU *cpu) } register_cp_regs_for_features(cpu); + arm_cpu_register_gdb_regs_for_features(cpu); + + cpu_reset(CPU(cpu)); + qemu_init_vcpu(env); + + acc->parent_realize(dev, errp); } /* CPU models */ @@ -782,6 +793,10 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) { ARMCPUClass *acc = ARM_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(acc); + DeviceClass *dc = DEVICE_CLASS(oc); + + acc->parent_realize = dc->realize; + dc->realize = arm_cpu_realizefn; acc->parent_reset = cc->reset; cc->reset = arm_cpu_reset; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index ffddfcbc0d..2902ba575b 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -234,6 +234,7 @@ typedef struct CPUARMState { ARMCPU *cpu_arm_init(const char *cpu_model); void arm_translate_init(void); +void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); int cpu_arm_exec(CPUARMState *s); void do_interrupt(CPUARMState *); void switch_mode(CPUARMState *, int); diff --git a/target-arm/helper.c b/target-arm/helper.c index eb7b2910c3..e63da57a51 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1263,7 +1263,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model) ARMCPU *cpu; CPUARMState *env; ObjectClass *oc; - static int inited = 0; oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model); if (!oc) { @@ -1272,14 +1271,17 @@ ARMCPU *cpu_arm_init(const char *cpu_model) cpu = ARM_CPU(object_new(object_class_get_name(oc))); env = &cpu->env; env->cpu_model_str = cpu_model; - arm_cpu_realize(cpu); - if (tcg_enabled() && !inited) { - inited = 1; - arm_translate_init(); - } + /* TODO this should be set centrally, once possible */ + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); + + return cpu; +} + +void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) +{ + CPUARMState *env = &cpu->env; - cpu_reset(CPU(cpu)); if (arm_feature(env, ARM_FEATURE_NEON)) { gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg, 51, "arm-neon.xml", 0); @@ -1290,8 +1292,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model) gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg, 19, "arm-vfp.xml", 0); } - qemu_init_vcpu(env); - return cpu; } /* Sort alphabetically by type name, except for "any". */ diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h index 41ab9b2fa5..2bac71fd81 100644 --- a/target-cris/cpu-qom.h +++ b/target-cris/cpu-qom.h @@ -33,7 +33,9 @@ /** * CRISCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. + * @vr: Version Register value. * * A CRIS CPU model. */ @@ -42,7 +44,10 @@ typedef struct CRISCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); + + uint32_t vr; } CRISCPUClass; /** diff --git a/target-cris/cpu.c b/target-cris/cpu.c index 3f64a5747e..7974be33f2 100644 --- a/target-cris/cpu.c +++ b/target-cris/cpu.c @@ -55,21 +55,194 @@ static void cris_cpu_reset(CPUState *s) #endif } +static ObjectClass *cris_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + char *typename; + + if (cpu_model == NULL) { + return NULL; + } + + typename = g_strdup_printf("%s-" TYPE_CRIS_CPU, cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_CRIS_CPU) || + object_class_is_abstract(oc))) { + oc = NULL; + } + return oc; +} + +CRISCPU *cpu_cris_init(const char *cpu_model) +{ + CRISCPU *cpu; + ObjectClass *oc; + + oc = cris_cpu_class_by_name(cpu_model); + if (oc == NULL) { + return NULL; + } + cpu = CRIS_CPU(object_new(object_class_get_name(oc))); + + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); + + return cpu; +} + +/* Sort alphabetically by VR. */ +static gint cris_cpu_list_compare(gconstpointer a, gconstpointer b) +{ + CRISCPUClass *ccc_a = CRIS_CPU_CLASS(a); + CRISCPUClass *ccc_b = CRIS_CPU_CLASS(b); + + /* */ + if (ccc_a->vr > ccc_b->vr) { + return 1; + } else if (ccc_a->vr < ccc_b->vr) { + return -1; + } else { + return 0; + } +} + +static void cris_cpu_list_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + CPUListState *s = user_data; + const char *typename = object_class_get_name(oc); + char *name; + + name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_CRIS_CPU)); + (*s->cpu_fprintf)(s->file, " %s\n", name); + g_free(name); +} + +void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf) +{ + CPUListState s = { + .file = f, + .cpu_fprintf = cpu_fprintf, + }; + GSList *list; + + list = object_class_get_list(TYPE_CRIS_CPU, false); + list = g_slist_sort(list, cris_cpu_list_compare); + (*cpu_fprintf)(f, "Available CPUs:\n"); + g_slist_foreach(list, cris_cpu_list_entry, &s); + g_slist_free(list); +} + +static void cris_cpu_realizefn(DeviceState *dev, Error **errp) +{ + CRISCPU *cpu = CRIS_CPU(dev); + CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(dev); + + cpu_reset(CPU(cpu)); + qemu_init_vcpu(&cpu->env); + + ccc->parent_realize(dev, errp); +} + static void cris_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); CRISCPU *cpu = CRIS_CPU(obj); + CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj); CPUCRISState *env = &cpu->env; + static bool tcg_initialized; + cs->env_ptr = env; cpu_exec_init(env); + + env->pregs[PR_VR] = ccc->vr; + + if (tcg_enabled() && !tcg_initialized) { + tcg_initialized = true; + if (env->pregs[PR_VR] < 32) { + cris_initialize_crisv10_tcg(); + } else { + cris_initialize_tcg(); + } + } } +static void crisv8_cpu_class_init(ObjectClass *oc, void *data) +{ + CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); + + ccc->vr = 8; +} + +static void crisv9_cpu_class_init(ObjectClass *oc, void *data) +{ + CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); + + ccc->vr = 9; +} + +static void crisv10_cpu_class_init(ObjectClass *oc, void *data) +{ + CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); + + ccc->vr = 10; +} + +static void crisv11_cpu_class_init(ObjectClass *oc, void *data) +{ + CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); + + ccc->vr = 11; +} + +static void crisv32_cpu_class_init(ObjectClass *oc, void *data) +{ + CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); + + ccc->vr = 32; +} + +#define TYPE(model) model "-" TYPE_CRIS_CPU + +static const TypeInfo cris_cpu_model_type_infos[] = { + { + .name = TYPE("crisv8"), + .parent = TYPE_CRIS_CPU, + .class_init = crisv8_cpu_class_init, + }, { + .name = TYPE("crisv9"), + .parent = TYPE_CRIS_CPU, + .class_init = crisv9_cpu_class_init, + }, { + .name = TYPE("crisv10"), + .parent = TYPE_CRIS_CPU, + .class_init = crisv10_cpu_class_init, + }, { + .name = TYPE("crisv11"), + .parent = TYPE_CRIS_CPU, + .class_init = crisv11_cpu_class_init, + }, { + .name = TYPE("crisv32"), + .parent = TYPE_CRIS_CPU, + .class_init = crisv32_cpu_class_init, + } +}; + +#undef TYPE + static void cris_cpu_class_init(ObjectClass *oc, void *data) { + DeviceClass *dc = DEVICE_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); + ccc->parent_realize = dc->realize; + dc->realize = cris_cpu_realizefn; + ccc->parent_reset = cc->reset; cc->reset = cris_cpu_reset; + + cc->class_by_name = cris_cpu_class_by_name; } static const TypeInfo cris_cpu_type_info = { @@ -77,14 +250,19 @@ static const TypeInfo cris_cpu_type_info = { .parent = TYPE_CPU, .instance_size = sizeof(CRISCPU), .instance_init = cris_cpu_initfn, - .abstract = false, + .abstract = true, .class_size = sizeof(CRISCPUClass), .class_init = cris_cpu_class_init, }; static void cris_cpu_register_types(void) { + int i; + type_register_static(&cris_cpu_type_info); + for (i = 0; i < ARRAY_SIZE(cris_cpu_model_type_infos); i++) { + type_register_static(&cris_cpu_model_type_infos[i]); + } } type_init(cris_cpu_register_types) diff --git a/target-cris/cpu.h b/target-cris/cpu.h index 257cb52be2..ebf2d4027f 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -182,6 +182,9 @@ void do_interrupt(CPUCRISState *env); int cpu_cris_signal_handler(int host_signum, void *pinfo, void *puc); +void cris_initialize_tcg(void); +void cris_initialize_crisv10_tcg(void); + enum { CC_OP_DYNAMIC, /* Use env->cc_op */ CC_OP_FLAGS, diff --git a/target-cris/translate.c b/target-cris/translate.c index 09e6011ea4..04a5379775 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3513,69 +3513,13 @@ void cpu_dump_state (CPUCRISState *env, FILE *f, fprintf_function cpu_fprintf, } -struct -{ - uint32_t vr; - const char *name; -} cris_cores[] = { - {8, "crisv8"}, - {9, "crisv9"}, - {10, "crisv10"}, - {11, "crisv11"}, - {32, "crisv32"}, -}; - -void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf) -{ - unsigned int i; - - (*cpu_fprintf)(f, "Available CPUs:\n"); - for (i = 0; i < ARRAY_SIZE(cris_cores); i++) { - (*cpu_fprintf)(f, " %s\n", cris_cores[i].name); - } -} - -static uint32_t vr_by_name(const char *name) -{ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(cris_cores); i++) { - if (strcmp(name, cris_cores[i].name) == 0) { - return cris_cores[i].vr; - } - } - return 32; -} - -CRISCPU *cpu_cris_init(const char *cpu_model) +void cris_initialize_tcg(void) { - CRISCPU *cpu; - CPUCRISState *env; - static int tcg_initialized = 0; int i; - cpu = CRIS_CPU(object_new(TYPE_CRIS_CPU)); - env = &cpu->env; - - env->pregs[PR_VR] = vr_by_name(cpu_model); - - cpu_reset(CPU(cpu)); - qemu_init_vcpu(env); - - if (tcg_initialized) { - return cpu; - } - - tcg_initialized = 1; - #define GEN_HELPER 2 #include "helper.h" - if (env->pregs[PR_VR] < 32) { - cpu_crisv10_init(env); - return cpu; - } - - cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); cc_x = tcg_global_mem_new(TCG_AREG0, offsetof(CPUCRISState, cc_x), "cc_x"); @@ -3615,8 +3559,6 @@ CRISCPU *cpu_cris_init(const char *cpu_model) offsetof(CPUCRISState, pregs[i]), pregnames[i]); } - - return cpu; } void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos) diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c index d2cca892e0..d6ef084483 100644 --- a/target-cris/translate_v10.c +++ b/target-cris/translate_v10.c @@ -1257,7 +1257,7 @@ static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc) return insn_len; } -static CPUCRISState *cpu_crisv10_init (CPUCRISState *env) +void cris_initialize_crisv10_tcg(void) { int i; @@ -1300,7 +1300,4 @@ static CPUCRISState *cpu_crisv10_init (CPUCRISState *env) offsetof(CPUCRISState, pregs[i]), pregnames_v10[i]); } - - return env; } - diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index 332916a185..48e6b54b1f 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -39,6 +39,7 @@ /** * X86CPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * An x86 CPU model or family. @@ -48,6 +49,7 @@ typedef struct X86CPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } X86CPUClass; @@ -72,8 +74,5 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env) #define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e)) -/* TODO Drop once ObjectClass::realize is available */ -void x86_cpu_realize(Object *obj, Error **errp); - #endif diff --git a/target-i386/cpu.c b/target-i386/cpu.c index aab35c74d9..dfcf86e862 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1516,27 +1516,16 @@ static void filter_features_for_kvm(X86CPU *cpu) } #endif -int cpu_x86_register(X86CPU *cpu, const char *cpu_model) +static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp) { CPUX86State *env = &cpu->env; x86_def_t def1, *def = &def1; - Error *error = NULL; - char *name, *features; - gchar **model_pieces; memset(def, 0, sizeof(*def)); - model_pieces = g_strsplit(cpu_model, ",", 2); - if (!model_pieces[0]) { - error_setg(&error, "Invalid/empty CPU model name"); - goto out; - } - name = model_pieces[0]; - features = model_pieces[1]; - if (cpu_x86_find_by_name(def, name) < 0) { - error_setg(&error, "Unable to find CPU definition: %s", name); - goto out; + error_setg(errp, "Unable to find CPU definition: %s", name); + return; } if (kvm_enabled()) { @@ -1544,36 +1533,71 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) } def->ext_features |= CPUID_EXT_HYPERVISOR; - object_property_set_str(OBJECT(cpu), def->vendor, "vendor", &error); - object_property_set_int(OBJECT(cpu), def->level, "level", &error); - object_property_set_int(OBJECT(cpu), def->family, "family", &error); - object_property_set_int(OBJECT(cpu), def->model, "model", &error); - object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error); + object_property_set_str(OBJECT(cpu), def->vendor, "vendor", errp); + object_property_set_int(OBJECT(cpu), def->level, "level", errp); + object_property_set_int(OBJECT(cpu), def->family, "family", errp); + object_property_set_int(OBJECT(cpu), def->model, "model", errp); + object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp); env->cpuid_features = def->features; env->cpuid_ext_features = def->ext_features; env->cpuid_ext2_features = def->ext2_features; env->cpuid_ext3_features = def->ext3_features; - object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error); + object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp); env->cpuid_kvm_features = def->kvm_features; env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features; env->cpuid_xlevel2 = def->xlevel2; - object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); + object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp); +} + +X86CPU *cpu_x86_init(const char *cpu_model) +{ + X86CPU *cpu = NULL; + CPUX86State *env; + gchar **model_pieces; + char *name, *features; + Error *error = NULL; + + model_pieces = g_strsplit(cpu_model, ",", 2); + if (!model_pieces[0]) { + error_setg(&error, "Invalid/empty CPU model name"); + goto out; + } + name = model_pieces[0]; + features = model_pieces[1]; + + cpu = X86_CPU(object_new(TYPE_X86_CPU)); + env = &cpu->env; + env->cpu_model_str = cpu_model; + + cpu_x86_register(cpu, name, &error); if (error) { goto out; } cpu_x86_parse_featurestr(cpu, features, &error); + if (error) { + goto out; + } + + object_property_set_bool(OBJECT(cpu), true, "realized", &error); + if (error) { + goto out; + } + out: g_strfreev(model_pieces); if (error) { fprintf(stderr, "%s\n", error_get_pretty(error)); error_free(error); - return -1; + if (cpu != NULL) { + object_unref(OBJECT(cpu)); + cpu = NULL; + } } - return 0; + return cpu; } #if !defined(CONFIG_USER_ONLY) @@ -2060,10 +2084,14 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp) } #endif -void x86_cpu_realize(Object *obj, Error **errp) +static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { - X86CPU *cpu = X86_CPU(obj); + X86CPU *cpu = X86_CPU(dev); + X86CPUClass *xcc = X86_CPU_GET_CLASS(dev); CPUX86State *env = &cpu->env; +#ifndef CONFIG_USER_ONLY + Error *local_err = NULL; +#endif if (env->cpuid_7_0_ebx_features && env->cpuid_level < 7) { env->cpuid_level = 7; @@ -2105,8 +2133,9 @@ void x86_cpu_realize(Object *obj, Error **errp) qemu_register_reset(x86_cpu_machine_reset_cb, cpu); if (cpu->env.cpuid_features & CPUID_APIC || smp_cpus > 1) { - x86_cpu_apic_init(cpu, errp); - if (error_is_set(errp)) { + x86_cpu_apic_init(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); return; } } @@ -2115,6 +2144,8 @@ void x86_cpu_realize(Object *obj, Error **errp) mce_init(cpu); qemu_init_vcpu(&cpu->env); cpu_reset(CPU(cpu)); + + xcc->parent_realize(dev, errp); } /* Enables contiguous-apic-ID mode, for compatibility */ @@ -2157,6 +2188,7 @@ static void x86_cpu_initfn(Object *obj) CPUX86State *env = &cpu->env; static int inited; + cs->env_ptr = env; cpu_exec_init(env); object_property_add(obj, "family", "int", @@ -2200,6 +2232,10 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) { X86CPUClass *xcc = X86_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + xcc->parent_realize = dc->realize; + dc->realize = x86_cpu_realizefn; xcc->parent_reset = cc->reset; cc->reset = x86_cpu_reset; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 9e6e1a652f..7577e4f8bb 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1002,7 +1002,6 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo, void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); -int cpu_x86_register(X86CPU *cpu, const char *cpu_model); void cpu_clear_apic_feature(CPUX86State *env); void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); diff --git a/target-i386/helper.c b/target-i386/helper.c index d1cb4e2445..4bf9db7f7d 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1267,30 +1267,6 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector, return 1; } -X86CPU *cpu_x86_init(const char *cpu_model) -{ - X86CPU *cpu; - CPUX86State *env; - Error *error = NULL; - - cpu = X86_CPU(object_new(TYPE_X86_CPU)); - env = &cpu->env; - env->cpu_model_str = cpu_model; - - if (cpu_x86_register(cpu, cpu_model) < 0) { - object_unref(OBJECT(cpu)); - return NULL; - } - - x86_cpu_realize(OBJECT(cpu), &error); - if (error) { - error_free(error); - object_unref(OBJECT(cpu)); - return NULL; - } - return cpu; -} - #if !defined(CONFIG_USER_ONLY) void do_cpu_init(X86CPU *cpu) { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 9ebf1816d9..0cf413dbfd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1777,7 +1777,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) * or pending TPR access reports. */ if (env->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) { - env->exit_request = 1; + cpu->exit_request = 1; } /* Try to inject an interrupt if the guest can accept it */ @@ -1847,7 +1847,7 @@ int kvm_arch_process_async_events(CPUState *cs) if (env->exception_injected == EXCP08_DBLE) { /* this means triple fault */ qemu_system_reset_request(); - env->exit_request = 1; + cs->exit_request = 1; return 0; } env->exception_injected = EXCP12_MCHK; diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h index 400cdbd554..d7525b300c 100644 --- a/target-lm32/cpu-qom.h +++ b/target-lm32/cpu-qom.h @@ -34,6 +34,7 @@ /** * LM32CPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A LatticeMico32 CPU model. @@ -43,6 +44,7 @@ typedef struct LM32CPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } LM32CPUClass; diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c index eca2dca427..a2badb5701 100644 --- a/target-lm32/cpu.c +++ b/target-lm32/cpu.c @@ -42,22 +42,44 @@ static void lm32_cpu_reset(CPUState *s) memset(env, 0, offsetof(CPULM32State, breakpoints)); } +static void lm32_cpu_realizefn(DeviceState *dev, Error **errp) +{ + LM32CPU *cpu = LM32_CPU(dev); + LM32CPUClass *lcc = LM32_CPU_GET_CLASS(dev); + + cpu_reset(CPU(cpu)); + + qemu_init_vcpu(&cpu->env); + + lcc->parent_realize(dev, errp); +} + static void lm32_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); LM32CPU *cpu = LM32_CPU(obj); CPULM32State *env = &cpu->env; + static bool tcg_initialized; + cs->env_ptr = env; cpu_exec_init(env); env->flags = 0; - cpu_reset(CPU(cpu)); + if (tcg_enabled() && !tcg_initialized) { + tcg_initialized = true; + lm32_translate_init(); + } } static void lm32_cpu_class_init(ObjectClass *oc, void *data) { LM32CPUClass *lcc = LM32_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + lcc->parent_realize = dc->realize; + dc->realize = lm32_cpu_realizefn; lcc->parent_reset = cc->reset; cc->reset = lm32_cpu_reset; diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index 4e202db32c..6948d0e248 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -189,7 +189,6 @@ struct CPULM32State { LM32CPU *cpu_lm32_init(const char *cpu_model); void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf); int cpu_lm32_exec(CPULM32State *s); -void cpu_lm32_close(CPULM32State *s); void do_interrupt(CPULM32State *env); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero diff --git a/target-lm32/helper.c b/target-lm32/helper.c index d76ea3fe09..47ae7e775a 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -197,7 +197,6 @@ LM32CPU *cpu_lm32_init(const char *cpu_model) LM32CPU *cpu; CPULM32State *env; const LM32Def *def; - static int tcg_initialized; def = cpu_lm32_find_by_name(cpu_model); if (!def) { @@ -212,12 +211,7 @@ LM32CPU *cpu_lm32_init(const char *cpu_model) env->num_wps = def->num_watchpoints; env->cfg = cfg_by_def(def); - qemu_init_vcpu(env); - - if (tcg_enabled() && !tcg_initialized) { - tcg_initialized = 1; - lm32_translate_init(); - } + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); return cpu; } diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h index 170daa7c96..20e5684552 100644 --- a/target-m68k/cpu-qom.h +++ b/target-m68k/cpu-qom.h @@ -33,6 +33,7 @@ /** * M68kCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A Motorola 68k CPU model. @@ -42,6 +43,7 @@ typedef struct M68kCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } M68kCPUClass; diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c index c71f715174..f5a109854b 100644 --- a/target-m68k/cpu.c +++ b/target-m68k/cpu.c @@ -139,12 +139,33 @@ static const M68kCPUInfo m68k_cpus[] = { { .name = "any", .instance_init = any_cpu_initfn }, }; +static void m68k_cpu_realizefn(DeviceState *dev, Error **errp) +{ + M68kCPU *cpu = M68K_CPU(dev); + M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev); + + m68k_cpu_init_gdb(cpu); + + cpu_reset(CPU(cpu)); + qemu_init_vcpu(&cpu->env); + + mcc->parent_realize(dev, errp); +} + static void m68k_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); M68kCPU *cpu = M68K_CPU(obj); CPUM68KState *env = &cpu->env; + static bool inited; + cs->env_ptr = env; cpu_exec_init(env); + + if (tcg_enabled() && !inited) { + inited = true; + m68k_tcg_init(); + } } static const VMStateDescription vmstate_m68k_cpu = { @@ -158,6 +179,9 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data) CPUClass *cc = CPU_CLASS(c); DeviceClass *dc = DEVICE_CLASS(c); + mcc->parent_realize = dc->realize; + dc->realize = m68k_cpu_realizefn; + mcc->parent_reset = cc->reset; cc->reset = m68k_cpu_reset; diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index adaf56c471..2672eae7c8 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -116,7 +116,8 @@ typedef struct CPUM68KState { #include "cpu-qom.h" void m68k_tcg_init(void); -CPUM68KState *cpu_m68k_init(const char *cpu_model); +void m68k_cpu_init_gdb(M68kCPU *cpu); +M68kCPU *cpu_m68k_init(const char *cpu_model); int cpu_m68k_exec(CPUM68KState *s); void do_interrupt(CPUM68KState *env1); void do_interrupt_m68k_hardirq(CPUM68KState *env1); @@ -168,7 +169,7 @@ enum { #define MACSR_V 0x002 #define MACSR_EV 0x001 -void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector); +void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector); void m68k_set_macsr(CPUM68KState *env, uint32_t val); void m68k_switch_sp(CPUM68KState *env); @@ -214,7 +215,15 @@ void register_m68k_insns (CPUM68KState *env); #define TARGET_PHYS_ADDR_SPACE_BITS 32 #define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define cpu_init cpu_m68k_init +static inline CPUM68KState *cpu_init(const char *cpu_model) +{ + M68kCPU *cpu = cpu_m68k_init(cpu_model); + if (cpu == NULL) { + return NULL; + } + return &cpu->env; +} + #define cpu_exec cpu_m68k_exec #define cpu_gen_code cpu_m68k_gen_code #define cpu_signal_handler cpu_m68k_signal_handler diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 5ddcd707fd..1bae3ab326 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -98,12 +98,11 @@ static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n) return 0; } -CPUM68KState *cpu_m68k_init(const char *cpu_model) +M68kCPU *cpu_m68k_init(const char *cpu_model) { M68kCPU *cpu; CPUM68KState *env; ObjectClass *oc; - static int inited; oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model); if (oc == NULL) { @@ -111,24 +110,24 @@ CPUM68KState *cpu_m68k_init(const char *cpu_model) } cpu = M68K_CPU(object_new(object_class_get_name(oc))); env = &cpu->env; - - if (!inited) { - inited = 1; - m68k_tcg_init(); - } - env->cpu_model_str = cpu_model; register_m68k_insns(env); + + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); + + return cpu; +} + +void m68k_cpu_init_gdb(M68kCPU *cpu) +{ + CPUM68KState *env = &cpu->env; + if (m68k_feature(env, M68K_FEATURE_CF_FPU)) { gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg, 11, "cf-fp.xml", 18); } /* TODO: Add [E]MAC registers. */ - - cpu_reset(ENV_GET_CPU(env)); - qemu_init_vcpu(env); - return env; } void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) @@ -311,8 +310,10 @@ int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw, be handled by the interrupt controller. Real hardware only requests the vector when the interrupt is acknowledged by the CPU. For simplicitly we calculate it when the interrupt is signalled. */ -void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector) +void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) { + CPUM68KState *env = &cpu->env; + env->pending_level = level; env->pending_vector = vector; if (level) diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h index f75549dc22..5ea911c8e4 100644 --- a/target-microblaze/cpu-qom.h +++ b/target-microblaze/cpu-qom.h @@ -33,6 +33,7 @@ /** * MicroBlazeCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A MicroBlaze CPU model. @@ -42,6 +43,7 @@ typedef struct MicroBlazeCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } MicroBlazeCPUClass; diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c index 39230fddcc..81359db168 100644 --- a/target-microblaze/cpu.c +++ b/target-microblaze/cpu.c @@ -85,14 +85,33 @@ static void mb_cpu_reset(CPUState *s) #endif } +static void mb_cpu_realizefn(DeviceState *dev, Error **errp) +{ + MicroBlazeCPU *cpu = MICROBLAZE_CPU(dev); + MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev); + + cpu_reset(CPU(cpu)); + qemu_init_vcpu(&cpu->env); + + mcc->parent_realize(dev, errp); +} + static void mb_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj); CPUMBState *env = &cpu->env; + static bool tcg_initialized; + cs->env_ptr = env; cpu_exec_init(env); set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + + if (tcg_enabled() && !tcg_initialized) { + tcg_initialized = true; + mb_tcg_init(); + } } static const VMStateDescription vmstate_mb_cpu = { @@ -106,6 +125,9 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) CPUClass *cc = CPU_CLASS(oc); MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_CLASS(oc); + mcc->parent_realize = dc->realize; + dc->realize = mb_cpu_realizefn; + mcc->parent_reset = cc->reset; cc->reset = mb_cpu_reset; diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 41480e71e1..c3dd7f6219 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -272,6 +272,7 @@ struct CPUMBState { #include "cpu-qom.h" +void mb_tcg_init(void); MicroBlazeCPU *cpu_mb_init(const char *cpu_model); int cpu_mb_exec(CPUMBState *s); void do_interrupt(CPUMBState *env); diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 58ce71267d..12ea820522 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1965,19 +1965,17 @@ void cpu_dump_state (CPUMBState *env, FILE *f, fprintf_function cpu_fprintf, MicroBlazeCPU *cpu_mb_init(const char *cpu_model) { MicroBlazeCPU *cpu; - static int tcg_initialized = 0; - int i; cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU)); - cpu_reset(CPU(cpu)); - qemu_init_vcpu(&cpu->env); + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); - if (tcg_initialized) { - return cpu; - } + return cpu; +} - tcg_initialized = 1; +void mb_tcg_init(void) +{ + int i; cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); @@ -2008,8 +2006,6 @@ MicroBlazeCPU *cpu_mb_init(const char *cpu_model) } #define GEN_HELPER 2 #include "helper.h" - - return cpu; } void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos) diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h index 2a4b812402..55aa692a85 100644 --- a/target-mips/cpu-qom.h +++ b/target-mips/cpu-qom.h @@ -37,6 +37,7 @@ /** * MIPSCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A MIPS CPU model. @@ -46,6 +47,7 @@ typedef struct MIPSCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } MIPSCPUClass; diff --git a/target-mips/cpu.c b/target-mips/cpu.c index 10ff46d6a7..4d62031c36 100644 --- a/target-mips/cpu.c +++ b/target-mips/cpu.c @@ -42,18 +42,39 @@ static void mips_cpu_reset(CPUState *s) cpu_state_reset(env); } +static void mips_cpu_realizefn(DeviceState *dev, Error **errp) +{ + MIPSCPU *cpu = MIPS_CPU(dev); + MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); + + cpu_reset(CPU(cpu)); + qemu_init_vcpu(&cpu->env); + + mcc->parent_realize(dev, errp); +} + static void mips_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); MIPSCPU *cpu = MIPS_CPU(obj); CPUMIPSState *env = &cpu->env; + cs->env_ptr = env; cpu_exec_init(env); + + if (tcg_enabled()) { + mips_tcg_init(); + } } static void mips_cpu_class_init(ObjectClass *c, void *data) { MIPSCPUClass *mcc = MIPS_CPU_CLASS(c); CPUClass *cc = CPU_CLASS(c); + DeviceClass *dc = DEVICE_CLASS(c); + + mcc->parent_realize = dc->realize; + dc->realize = mips_cpu_realizefn; mcc->parent_reset = cc->reset; cc->reset = mips_cpu_reset; diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 5963d62973..0e198b12db 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -629,6 +629,7 @@ enum { #define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 int cpu_mips_exec(CPUMIPSState *s); +void mips_tcg_init(void); MIPSCPU *cpu_mips_init(const char *cpu_model); int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc); diff --git a/target-mips/translate.c b/target-mips/translate.c index 3b77b53b93..4ee9615fda 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -15836,7 +15836,7 @@ void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf, #endif } -static void mips_tcg_init(void) +void mips_tcg_init(void) { int i; static int inited; @@ -15915,9 +15915,9 @@ MIPSCPU *cpu_mips_init(const char *cpu_model) #endif fpu_init(env, def); mvp_init(env, def); - mips_tcg_init(); - cpu_reset(CPU(cpu)); - qemu_init_vcpu(env); + + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); + return cpu; } diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c index a7a8de8a37..72d5e8d2a5 100644 --- a/target-openrisc/cpu.c +++ b/target-openrisc/cpu.c @@ -62,19 +62,24 @@ static inline void set_feature(OpenRISCCPU *cpu, int feature) cpu->env.cpucfgr = cpu->feature; } -void openrisc_cpu_realize(Object *obj, Error **errp) +static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp) { - OpenRISCCPU *cpu = OPENRISC_CPU(obj); + OpenRISCCPU *cpu = OPENRISC_CPU(dev); + OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(dev); qemu_init_vcpu(&cpu->env); cpu_reset(CPU(cpu)); + + occ->parent_realize(dev, errp); } static void openrisc_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); OpenRISCCPU *cpu = OPENRISC_CPU(obj); static int inited; + cs->env_ptr = &cpu->env; cpu_exec_init(&cpu->env); #ifndef CONFIG_USER_ONLY @@ -134,6 +139,10 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data) { OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(occ); + DeviceClass *dc = DEVICE_CLASS(oc); + + occ->parent_realize = dc->realize; + dc->realize = openrisc_cpu_realizefn; occ->parent_reset = cc->reset; cc->reset = openrisc_cpu_reset; @@ -187,7 +196,7 @@ OpenRISCCPU *cpu_openrisc_init(const char *cpu_model) cpu = OPENRISC_CPU(object_new(object_class_get_name(oc))); cpu->env.cpu_model_str = cpu_model; - openrisc_cpu_realize(OBJECT(cpu), NULL); + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); return cpu; } diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 3beab45c3c..419f007991 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -33,7 +33,6 @@ struct OpenRISCCPU; #include "exec/cpu-defs.h" #include "fpu/softfloat.h" #include "qom/cpu.h" -#include "qapi/error.h" #define TYPE_OPENRISC_CPU "or32-cpu" @@ -46,6 +45,7 @@ struct OpenRISCCPU; /** * OpenRISCCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A OpenRISC CPU model. @@ -55,6 +55,7 @@ typedef struct OpenRISCCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } OpenRISCCPUClass; @@ -340,7 +341,6 @@ static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env) #define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e)) OpenRISCCPU *cpu_openrisc_init(const char *cpu_model); -void openrisc_cpu_realize(Object *obj, Error **errp); void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf); int cpu_openrisc_exec(CPUOpenRISCState *s); diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index b338f8fb56..2b82cdbe40 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -40,6 +40,7 @@ /** * PowerPCCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A PowerPC CPU model. @@ -49,6 +50,7 @@ typedef struct PowerPCCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); /* TODO inline fields here */ diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 6cebaa1982..5df205757b 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -10030,9 +10030,9 @@ static int ppc_fixup_cpu(PowerPCCPU *cpu) return 0; } -static void ppc_cpu_realize(Object *obj, Error **errp) +static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) { - PowerPCCPU *cpu = POWERPC_CPU(obj); + PowerPCCPU *cpu = POWERPC_CPU(dev); CPUPPCState *env = &cpu->env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); ppc_def_t *def = pcc->info; @@ -10083,6 +10083,8 @@ static void ppc_cpu_realize(Object *obj, Error **errp) qemu_init_vcpu(env); + pcc->parent_realize(dev, errp); + #if defined(PPC_DUMP_CPU) { const char *mmu_model, *excp_model, *bus_model; @@ -10347,14 +10349,9 @@ PowerPCCPU *cpu_ppc_init(const char *cpu_model) cpu = POWERPC_CPU(object_new(object_class_get_name(oc))); env = &cpu->env; - - if (tcg_enabled()) { - ppc_translate_init(); - } - env->cpu_model_str = cpu_model; - ppc_cpu_realize(OBJECT(cpu), &err); + object_property_set_bool(OBJECT(cpu), true, "realized", &err); if (err != NULL) { fprintf(stderr, "%s\n", error_get_pretty(err)); error_free(err); @@ -10532,11 +10529,13 @@ static void ppc_cpu_reset(CPUState *s) static void ppc_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); PowerPCCPU *cpu = POWERPC_CPU(obj); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); CPUPPCState *env = &cpu->env; ppc_def_t *def = pcc->info; + cs->env_ptr = env; cpu_exec_init(env); env->msr_mask = def->msr_mask; @@ -10569,12 +10568,20 @@ static void ppc_cpu_initfn(Object *obj) env->sps = defsps; } #endif /* defined(TARGET_PPC64) */ + + if (tcg_enabled()) { + ppc_translate_init(); + } } static void ppc_cpu_class_init(ObjectClass *oc, void *data) { PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + pcc->parent_realize = dc->realize; + dc->realize = ppc_cpu_realizefn; pcc->parent_reset = cc->reset; cc->reset = ppc_cpu_reset; diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index d54e4a2ee2..237184f55a 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -34,6 +34,7 @@ /** * S390CPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * An S/390 CPU model. @@ -43,6 +44,7 @@ typedef struct S390CPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } S390CPUClass; diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index d765e7b984..b74654724d 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -97,15 +97,29 @@ static void s390_cpu_machine_reset_cb(void *opaque) } #endif +static void s390_cpu_realizefn(DeviceState *dev, Error **errp) +{ + S390CPU *cpu = S390_CPU(dev); + S390CPUClass *scc = S390_CPU_GET_CLASS(dev); + + qemu_init_vcpu(&cpu->env); + cpu_reset(CPU(cpu)); + + scc->parent_realize(dev, errp); +} + static void s390_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); S390CPU *cpu = S390_CPU(obj); CPUS390XState *env = &cpu->env; + static bool inited; static int cpu_num = 0; #if !defined(CONFIG_USER_ONLY) struct tm tm; #endif + cs->env_ptr = env; cpu_exec_init(env); #if !defined(CONFIG_USER_ONLY) qemu_register_reset(s390_cpu_machine_reset_cb, cpu); @@ -123,7 +137,10 @@ static void s390_cpu_initfn(Object *obj) env->cpu_num = cpu_num++; env->ext_index = -1; - cpu_reset(CPU(cpu)); + if (tcg_enabled() && !inited) { + inited = true; + s390x_translate_init(); + } } static void s390_cpu_finalize(Object *obj) @@ -146,6 +163,9 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) CPUClass *cc = CPU_CLASS(scc); DeviceClass *dc = DEVICE_CLASS(oc); + scc->parent_realize = dc->realize; + dc->realize = s390_cpu_realizefn; + scc->parent_reset = cc->reset; cc->reset = s390_cpu_reset; diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index fa8dfe0737..e450db74a2 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -315,7 +315,6 @@ static inline int get_ilen(uint8_t opc) S390CPU *cpu_s390x_init(const char *cpu_model); void s390x_translate_init(void); int cpu_s390x_exec(CPUS390XState *s); -void cpu_s390x_close(CPUS390XState *s); void do_interrupt (CPUS390XState *env); /* you can call this signal handler from your SIGBUS and SIGSEGV diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 76268317a3..1183b45ca1 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -74,18 +74,13 @@ S390CPU *cpu_s390x_init(const char *cpu_model) { S390CPU *cpu; CPUS390XState *env; - static int inited; cpu = S390_CPU(object_new(TYPE_S390_CPU)); env = &cpu->env; + env->cpu_model_str = cpu_model; - if (tcg_enabled() && !inited) { - inited = 1; - s390x_translate_init(); - } + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); - env->cpu_model_str = cpu_model; - qemu_init_vcpu(env); return cpu; } diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h index 09573c9c34..d368db1b0a 100644 --- a/target-sh4/cpu-qom.h +++ b/target-sh4/cpu-qom.h @@ -33,6 +33,7 @@ /** * SuperHCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A SuperH CPU model. @@ -42,6 +43,7 @@ typedef struct SuperHCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } SuperHCPUClass; diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c index d2831226b9..ef0e62195d 100644 --- a/target-sh4/cpu.c +++ b/target-sh4/cpu.c @@ -54,14 +54,31 @@ static void superh_cpu_reset(CPUState *s) set_default_nan_mode(1, &env->fp_status); } +static void superh_cpu_realizefn(DeviceState *dev, Error **errp) +{ + SuperHCPU *cpu = SUPERH_CPU(dev); + SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(dev); + + cpu_reset(CPU(cpu)); + qemu_init_vcpu(&cpu->env); + + scc->parent_realize(dev, errp); +} + static void superh_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); SuperHCPU *cpu = SUPERH_CPU(obj); CPUSH4State *env = &cpu->env; + cs->env_ptr = env; cpu_exec_init(env); env->movcal_backup_tail = &(env->movcal_backup); + + if (tcg_enabled()) { + sh4_translate_init(); + } } static const VMStateDescription vmstate_sh_cpu = { @@ -75,6 +92,9 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data) CPUClass *cc = CPU_CLASS(oc); SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc); + scc->parent_realize = dc->realize; + dc->realize = superh_cpu_realizefn; + scc->parent_reset = cc->reset; cc->reset = superh_cpu_reset; diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 34e9b0acf7..49dcd9e7f3 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -191,6 +191,7 @@ typedef struct CPUSH4State { #include "cpu-qom.h" +void sh4_translate_init(void); SuperHCPU *cpu_sh4_init(const char *cpu_model); int cpu_sh4_exec(CPUSH4State * s); int cpu_sh4_signal_handler(int host_signum, void *pinfo, diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 260aaab559..c58d79a5cd 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -71,7 +71,7 @@ static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; #include "exec/gen-icount.h" -static void sh4_translate_init(void) +void sh4_translate_init(void) { int i; static int done_init = 0; @@ -251,11 +251,11 @@ SuperHCPU *cpu_sh4_init(const char *cpu_model) cpu = SUPERH_CPU(object_new(TYPE_SUPERH_CPU)); env = &cpu->env; env->features = def->features; - sh4_translate_init(); env->cpu_model_str = cpu_model; - cpu_reset(CPU(cpu)); cpu_register(env, def); - qemu_init_vcpu(env); + + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); + return cpu; } diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h index 2a738ae360..89cd1cf2d3 100644 --- a/target-sparc/cpu-qom.h +++ b/target-sparc/cpu-qom.h @@ -38,6 +38,7 @@ /** * SPARCCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * A SPARC CPU model. @@ -47,6 +48,7 @@ typedef struct SPARCCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } SPARCCPUClass; diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c index 4bc1afc755..ef52df6d74 100644 --- a/target-sparc/cpu.c +++ b/target-sparc/cpu.c @@ -114,15 +114,12 @@ SPARCCPU *cpu_sparc_init(const char *cpu_model) cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU)); env = &cpu->env; - if (tcg_enabled()) { - gen_intermediate_code_init(env); - } - if (cpu_sparc_register(env, cpu_model) < 0) { object_unref(OBJECT(cpu)); return NULL; } - qemu_init_vcpu(env); + + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); return cpu; } @@ -851,12 +848,28 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "\n"); } +static void sparc_cpu_realizefn(DeviceState *dev, Error **errp) +{ + SPARCCPU *cpu = SPARC_CPU(dev); + SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev); + + qemu_init_vcpu(&cpu->env); + + scc->parent_realize(dev, errp); +} + static void sparc_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); SPARCCPU *cpu = SPARC_CPU(obj); CPUSPARCState *env = &cpu->env; + cs->env_ptr = env; cpu_exec_init(env); + + if (tcg_enabled()) { + gen_intermediate_code_init(env); + } } static void sparc_cpu_uninitfn(Object *obj) @@ -871,6 +884,10 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data) { SPARCCPUClass *scc = SPARC_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + scc->parent_realize = dc->realize; + dc->realize = sparc_cpu_realizefn; scc->parent_reset = cc->reset; cc->reset = sparc_cpu_reset; diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h index fe40b2d6a8..625c6143db 100644 --- a/target-unicore32/cpu-qom.h +++ b/target-unicore32/cpu-qom.h @@ -25,6 +25,7 @@ /** * UniCore32CPUClass: + * @parent_realize: The parent class' realize handler. * * A UniCore32 CPU model. */ @@ -32,6 +33,8 @@ typedef struct UniCore32CPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ + + DeviceRealize parent_realize; } UniCore32CPUClass; /** diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c index 4e4177fc57..b7024c85bb 100644 --- a/target-unicore32/cpu.c +++ b/target-unicore32/cpu.c @@ -81,11 +81,24 @@ static const UniCore32CPUInfo uc32_cpus[] = { { .name = "any", .instance_init = uc32_any_cpu_initfn }, }; +static void uc32_cpu_realizefn(DeviceState *dev, Error **errp) +{ + UniCore32CPU *cpu = UNICORE32_CPU(dev); + UniCore32CPUClass *ucc = UNICORE32_CPU_GET_CLASS(dev); + + qemu_init_vcpu(&cpu->env); + + ucc->parent_realize(dev, errp); +} + static void uc32_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); UniCore32CPU *cpu = UNICORE32_CPU(obj); CPUUniCore32State *env = &cpu->env; + static bool inited; + cs->env_ptr = env; cpu_exec_init(env); #ifdef CONFIG_USER_ONLY @@ -97,6 +110,11 @@ static void uc32_cpu_initfn(Object *obj) #endif tlb_flush(env, 1); + + if (tcg_enabled() && !inited) { + inited = true; + uc32_translate_init(); + } } static const VMStateDescription vmstate_uc32_cpu = { @@ -108,6 +126,10 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); + UniCore32CPUClass *ucc = UNICORE32_CPU_CLASS(oc); + + ucc->parent_realize = dc->realize; + dc->realize = uc32_cpu_realizefn; cc->class_by_name = uc32_cpu_class_by_name; dc->vmsd = &vmstate_uc32_cpu; diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c index 3a92232de5..7eeb9bc633 100644 --- a/target-unicore32/helper.c +++ b/target-unicore32/helper.c @@ -30,7 +30,6 @@ CPUUniCore32State *uc32_cpu_init(const char *cpu_model) UniCore32CPU *cpu; CPUUniCore32State *env; ObjectClass *oc; - static int inited = 1; oc = cpu_class_by_name(TYPE_UNICORE32_CPU, cpu_model); if (oc == NULL) { @@ -40,12 +39,8 @@ CPUUniCore32State *uc32_cpu_init(const char *cpu_model) env = &cpu->env; env->cpu_model_str = cpu_model; - if (inited) { - inited = 0; - uc32_translate_init(); - } + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); - qemu_init_vcpu(env); return env; } diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h index e344a9aa79..270de16583 100644 --- a/target-xtensa/cpu-qom.h +++ b/target-xtensa/cpu-qom.h @@ -43,6 +43,7 @@ /** * XtensaCPUClass: + * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. * * An Xtensa CPU model. @@ -52,6 +53,7 @@ typedef struct XtensaCPUClass { CPUClass parent_class; /*< public >*/ + DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); } XtensaCPUClass; diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c index ebc7e9979b..785e56d367 100644 --- a/target-xtensa/cpu.c +++ b/target-xtensa/cpu.c @@ -57,12 +57,31 @@ static void xtensa_cpu_reset(CPUState *s) reset_mmu(env); } +static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp) +{ + XtensaCPU *cpu = XTENSA_CPU(dev); + XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev); + + qemu_init_vcpu(&cpu->env); + + xcc->parent_realize(dev, errp); +} + static void xtensa_cpu_initfn(Object *obj) { + CPUState *cs = CPU(obj); XtensaCPU *cpu = XTENSA_CPU(obj); CPUXtensaState *env = &cpu->env; + static bool tcg_inited; + cs->env_ptr = env; cpu_exec_init(env); + + if (tcg_enabled() && !tcg_inited) { + tcg_inited = true; + xtensa_translate_init(); + cpu_set_debug_excp_handler(xtensa_breakpoint_handler); + } } static const VMStateDescription vmstate_xtensa_cpu = { @@ -76,6 +95,9 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) CPUClass *cc = CPU_CLASS(oc); XtensaCPUClass *xcc = XTENSA_CPU_CLASS(cc); + xcc->parent_realize = dc->realize; + dc->realize = xtensa_cpu_realizefn; + xcc->parent_reset = cc->reset; cc->reset = xtensa_cpu_reset; diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 5acf78c692..dece224478 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -385,6 +385,7 @@ static inline CPUXtensaState *cpu_init(const char *cpu_model) } void xtensa_translate_init(void); +void xtensa_breakpoint_handler(CPUXtensaState *env); int cpu_xtensa_exec(CPUXtensaState *s); void xtensa_register_core(XtensaConfigList *node); void do_interrupt(CPUXtensaState *s); diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 94c03a1d3c..a8a64932da 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -54,7 +54,7 @@ static uint32_t check_hw_breakpoints(CPUXtensaState *env) return 0; } -static void breakpoint_handler(CPUXtensaState *env) +void xtensa_breakpoint_handler(CPUXtensaState *env) { if (env->watchpoint_hit) { if (env->watchpoint_hit->flags & BP_CPU) { @@ -72,8 +72,6 @@ static void breakpoint_handler(CPUXtensaState *env) XtensaCPU *cpu_xtensa_init(const char *cpu_model) { - static int tcg_inited; - static int debug_handler_inited; XtensaCPU *cpu; CPUXtensaState *env; const XtensaConfig *config = NULL; @@ -93,18 +91,10 @@ XtensaCPU *cpu_xtensa_init(const char *cpu_model) env = &cpu->env; env->config = config; - if (!tcg_inited) { - tcg_inited = 1; - xtensa_translate_init(); - } + xtensa_irq_init(env); - if (!debug_handler_inited && tcg_enabled()) { - debug_handler_inited = 1; - cpu_set_debug_excp_handler(breakpoint_handler); - } + object_property_set_bool(OBJECT(cpu), true, "realized", NULL); - xtensa_irq_init(env); - qemu_init_vcpu(env); return cpu; } diff --git a/translate-all.c b/translate-all.c index efeb247add..b50fb89528 100644 --- a/translate-all.c +++ b/translate-all.c @@ -998,6 +998,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, { TranslationBlock *tb, *tb_next, *saved_tb; CPUArchState *env = cpu_single_env; + CPUState *cpu = NULL; tb_page_addr_t tb_start, tb_end; PageDesc *p; int n; @@ -1020,6 +1021,9 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, /* build code bitmap */ build_page_bitmap(p); } + if (env != NULL) { + cpu = ENV_GET_CPU(env); + } /* we remove all the TBs in the range [start, end[ */ /* XXX: see if in some cases it could be faster to invalidate all @@ -1066,14 +1070,14 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, /* we need to do that to handle the case where a signal occurs while doing tb_phys_invalidate() */ saved_tb = NULL; - if (env) { - saved_tb = env->current_tb; - env->current_tb = NULL; + if (cpu != NULL) { + saved_tb = cpu->current_tb; + cpu->current_tb = NULL; } tb_phys_invalidate(tb, -1); - if (env) { - env->current_tb = saved_tb; - if (env->interrupt_request && env->current_tb) { + if (cpu != NULL) { + cpu->current_tb = saved_tb; + if (env && env->interrupt_request && cpu->current_tb) { cpu_interrupt(env, env->interrupt_request); } } @@ -1094,7 +1098,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, /* we generate a block containing just the instruction modifying the memory. It will ensure that it cannot modify itself */ - env->current_tb = NULL; + cpu->current_tb = NULL; tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); cpu_resume_from_signal(env, NULL); } @@ -1142,6 +1146,7 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, #ifdef TARGET_HAS_PRECISE_SMC TranslationBlock *current_tb = NULL; CPUArchState *env = cpu_single_env; + CPUState *cpu = NULL; int current_tb_modified = 0; target_ulong current_pc = 0; target_ulong current_cs_base = 0; @@ -1158,6 +1163,9 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, if (tb && pc != 0) { current_tb = tb_find_pc(pc); } + if (env != NULL) { + cpu = ENV_GET_CPU(env); + } #endif while (tb != NULL) { n = (uintptr_t)tb & 3; @@ -1186,7 +1194,7 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, /* we generate a block containing just the instruction modifying the memory. It will ensure that it cannot modify itself */ - env->current_tb = NULL; + cpu->current_tb = NULL; tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); cpu_resume_from_signal(env, puc); } @@ -1408,7 +1416,7 @@ void tb_invalidate_phys_addr(hwaddr addr) } #endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */ -void cpu_unlink_tb(CPUArchState *env) +void cpu_unlink_tb(CPUState *cpu) { /* FIXME: TB unchaining isn't SMP safe. For now just ignore the problem and hope the cpu will stop of its own accord. For userspace @@ -1418,11 +1426,11 @@ void cpu_unlink_tb(CPUArchState *env) static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; spin_lock(&interrupt_lock); - tb = env->current_tb; + tb = cpu->current_tb; /* if the cpu is currently executing code, we must unlink it and all the potentially executing TB */ if (tb) { - env->current_tb = NULL; + cpu->current_tb = NULL; tb_reset_jump_recursive(tb); } spin_unlock(&interrupt_lock); @@ -1467,7 +1475,7 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask) cpu_abort(env, "Raised interrupt while not in I/O function"); } } else { - cpu_unlink_tb(env); + cpu_unlink_tb(cpu); } } @@ -1615,8 +1623,10 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) void cpu_interrupt(CPUArchState *env, int mask) { + CPUState *cpu = ENV_GET_CPU(env); + env->interrupt_request |= mask; - cpu_unlink_tb(env); + cpu_unlink_tb(cpu); } /* diff --git a/translate-all.h b/translate-all.h index b181fb48ad..5c38819eb8 100644 --- a/translate-all.h +++ b/translate-all.h @@ -28,7 +28,7 @@ /* translate-all.c */ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len); -void cpu_unlink_tb(CPUArchState *env); +void cpu_unlink_tb(CPUState *cpu); void tb_check_watchpoint(CPUArchState *env); #endif /* TRANSLATE_ALL_H */ |