diff options
Diffstat (limited to 'target-s390x/cpu.c')
-rw-r--r-- | target-s390x/cpu.c | 89 |
1 files changed, 81 insertions, 8 deletions
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 6be6c084a..dfd83e8ae 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -65,29 +65,95 @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.psw.addr = value; } -/* CPUClass::reset() */ +static bool s390_cpu_has_work(CPUState *cs) +{ + S390CPU *cpu = S390_CPU(cs); + CPUS390XState *env = &cpu->env; + + return (cs->interrupt_request & CPU_INTERRUPT_HARD) && + (env->psw.mask & PSW_MASK_EXT); +} + +#if !defined(CONFIG_USER_ONLY) +/* S390CPUClass::load_normal() */ +static void s390_cpu_load_normal(CPUState *s) +{ + S390CPU *cpu = S390_CPU(s); + cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR; + cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64; + s390_add_running_cpu(cpu); +} +#endif + +/* S390CPUClass::cpu_reset() */ static void s390_cpu_reset(CPUState *s) { S390CPU *cpu = S390_CPU(s); S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); CPUS390XState *env = &cpu->env; + env->pfault_token = -1UL; + s390_del_running_cpu(cpu); + scc->parent_reset(s); +#if !defined(CONFIG_USER_ONLY) + s->halted = 1; +#endif + tlb_flush(s, 1); +} + +/* S390CPUClass::initial_reset() */ +static void s390_cpu_initial_reset(CPUState *s) +{ + S390CPU *cpu = S390_CPU(s); + CPUS390XState *env = &cpu->env; + + s390_cpu_reset(s); + /* initial reset does not touch regs,fregs and aregs */ + memset(&env->fpc, 0, offsetof(CPUS390XState, cpu_num) - + offsetof(CPUS390XState, fpc)); + + /* architectured initial values for CR 0 and 14 */ + env->cregs[0] = CR0_RESET; + env->cregs[14] = CR14_RESET; + + env->pfault_token = -1UL; + +#if defined(CONFIG_KVM) + /* Reset state inside the kernel that we cannot access yet from QEMU. */ + if (kvm_enabled()) { + if (kvm_vcpu_ioctl(s, KVM_S390_INITIAL_RESET, NULL)) { + perror("Initial CPU reset failed"); + } + } +#endif +} + +/* CPUClass:reset() */ +static void s390_cpu_full_reset(CPUState *s) +{ + S390CPU *cpu = S390_CPU(s); + S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); + CPUS390XState *env = &cpu->env; + s390_del_running_cpu(cpu); scc->parent_reset(s); - memset(env, 0, offsetof(CPUS390XState, breakpoints)); + memset(env, 0, offsetof(CPUS390XState, cpu_num)); /* architectured initial values for CR 0 and 14 */ env->cregs[0] = CR0_RESET; env->cregs[14] = CR14_RESET; + + env->pfault_token = -1UL; + /* set halted to 1 to make sure we can add the cpu in * s390_ipl_cpu code, where CPUState::halted is set back to 0 * after incrementing the cpu counter */ #if !defined(CONFIG_USER_ONLY) s->halted = 1; #endif - tlb_flush(env, 1); + tlb_flush(s, 1); } #if !defined(CONFIG_USER_ONLY) @@ -129,8 +195,8 @@ static void s390_cpu_initfn(Object *obj) env->tod_offset = TOD_UNIX_EPOCH + (time2tod(mktimegm(&tm)) * 1000000000ULL); env->tod_basetime = 0; - env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu); - env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu); + env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu); + env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu); /* set CPUState::halted state to 1 to avoid decrementing the running * cpu counter in s390_cpu_reset to a negative number at * initial ipl */ @@ -169,14 +235,21 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) dc->realize = s390_cpu_realizefn; scc->parent_reset = cc->reset; - cc->reset = s390_cpu_reset; - +#if !defined(CONFIG_USER_ONLY) + scc->load_normal = s390_cpu_load_normal; +#endif + scc->cpu_reset = s390_cpu_reset; + scc->initial_cpu_reset = s390_cpu_initial_reset; + cc->reset = s390_cpu_full_reset; + cc->has_work = s390_cpu_has_work; cc->do_interrupt = s390_cpu_do_interrupt; cc->dump_state = s390_cpu_dump_state; cc->set_pc = s390_cpu_set_pc; cc->gdb_read_register = s390_cpu_gdb_read_register; cc->gdb_write_register = s390_cpu_gdb_write_register; -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY + cc->handle_mmu_fault = s390_cpu_handle_mmu_fault; +#else cc->get_phys_page_debug = s390_cpu_get_phys_page_debug; cc->write_elf64_note = s390_cpu_write_elf64_note; cc->write_elf64_qemunote = s390_cpu_write_elf64_qemunote; |