void qmp_inject_nmi(Error **errp) { #if defined(TARGET_I386) CPUState *cs; for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; if (!env->apic_state) { cpu_interrupt(cs, CPU_INTERRUPT_NMI); } else { apic_deliver_nmi(env->apic_state); } } #elif defined(TARGET_S390X) CPUState *cs; S390CPU *cpu; for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { cpu = S390_CPU(cs); if (cpu->env.cpu_num == monitor_get_cpu_index()) { if (s390_cpu_restart(S390_CPU(cs)) == -1) { error_set(errp, QERR_UNSUPPORTED); return; } break; } } #else error_set(errp, QERR_UNSUPPORTED); #endif }
static void s390_cpu_model_finalize(Object *obj) { S390CPU *cpu = S390_CPU(obj); g_free(cpu->model); cpu->model = NULL; }
/* 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_cpu_set_state(CPU_STATE_OPERATING, cpu); }
static void s390_ipl_reset(DeviceState *dev) { S390IPLState *ipl = S390_IPL(dev); S390CPU *cpu = S390_CPU(qemu_get_cpu(0)); CPUS390XState *env = &cpu->env; env->psw.addr = ipl->start_addr; env->psw.mask = IPL_PSW_MASK; if (!ipl->kernel) { /* Tell firmware, if there is a preferred boot device */ env->regs[7] = -1; DeviceState *dev_st = get_boot_device(0); if (dev_st) { VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast( OBJECT(qdev_get_parent_bus(dev_st)->parent), TYPE_VIRTIO_CCW_DEVICE); if (ccw_dev) { env->regs[7] = ccw_dev->sch->cssid << 24 | ccw_dev->sch->ssid << 16 | ccw_dev->sch->devno; } } } s390_add_running_cpu(cpu); }
/* 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 }
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); qemu_get_timedate(&tm, 0); 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); /* set CPUState::halted state to 1 to avoid decrementing the running * cpu counter in s390_cpu_reset to a negative number at * initial ipl */ cs->halted = 1; #endif env->cpu_num = cpu_num++; env->ext_index = -1; if (tcg_enabled() && !inited) { inited = true; s390x_translate_init(); } }
/* S390CPUClass::initial_reset() */ static void s390_cpu_initial_reset(CPUState *s) { S390CPU *cpu = S390_CPU(s); CPUS390XState *env = &cpu->env; int i; 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; /* architectured initial value for Breaking-Event-Address register */ env->gbea = 1; env->pfault_token = -1UL; env->ext_index = -1; for (i = 0; i < ARRAY_SIZE(env->io_index); i++) { env->io_index[i] = -1; } /* tininess for underflow is detected before rounding */ set_float_detect_tininess(float_tininess_before_rounding, &env->fpu_status); /* Reset state inside the kernel that we cannot access yet from QEMU. */ if (kvm_enabled()) { kvm_s390_reset_vcpu(cpu); } tlb_flush(s, 1); }
void s390x_cpu_debug_excp_handler(CPUState *cs) { S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; CPUWatchpoint *wp_hit = cs->watchpoint_hit; if (wp_hit && wp_hit->flags & BP_CPU) { /* FIXME: When the storage-alteration-space control bit is set, the exception should only be triggered if the memory access is done using an address space with the storage-alteration-event bit set. We have no way to detect that with the current watchpoint code. */ cs->watchpoint_hit = NULL; env->per_address = env->psw.addr; env->per_perc_atmid |= PER_CODE_EVENT_STORE | get_per_atmid(env); /* FIXME: We currently no way to detect the address space used to trigger the watchpoint. For now just consider it is the current default ASC. This turn to be true except when MVCP and MVCS instrutions are not used. */ env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46; /* Remove all watchpoints to re-execute the code. A PER exception will be triggered, it will call load_psw which will recompute the watchpoints. */ cpu_watchpoint_remove_all(cs, BP_CPU); cpu_resume_from_signal(cs, NULL); }
bool s390_has_feat(S390Feat feat) { static S390CPU *cpu; if (!cpu) { cpu = S390_CPU(qemu_get_cpu(0)); } if (!cpu || !cpu->model) { #ifdef CONFIG_KVM if (kvm_enabled()) { if (feat == S390_FEAT_VECTOR) { return kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS); } if (feat == S390_FEAT_RUNTIME_INSTRUMENTATION) { return kvm_s390_get_ri(); } if (feat == S390_FEAT_MSA_EXT_3) { return true; } } #endif return 0; } return test_bit(feat, cpu->model->features); }
static void set_feature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { S390Feat feat = (S390Feat) opaque; DeviceState *dev = DEVICE(obj); S390CPU *cpu = S390_CPU(obj); bool value; if (dev->realized) { error_setg(errp, "Attempt to set property '%s' on '%s' after " "it was realized", name, object_get_typename(obj)); return; } else if (!cpu->model) { error_setg(errp, "Details about the host CPU model are not available, " "features cannot be changed."); return; } visit_type_bool(v, name, &value, errp); if (*errp) { return; } if (value) { if (!test_bit(feat, cpu->model->def->full_feat)) { error_setg(errp, "Feature '%s' is not available for CPU model '%s'," " it was introduced with later models.", name, cpu->model->def->name); return; } set_bit(feat, cpu->model->features); } else { clear_bit(feat, cpu->model->features); } }
static void s390_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); S390CPU *cpu = S390_CPU(obj); CPUS390XState *env = &cpu->env; static bool inited; #if !defined(CONFIG_USER_ONLY) struct tm tm; #endif cs->env_ptr = env; cs->halted = 1; cs->exception_index = EXCP_HLT; object_property_add(OBJECT(cpu), "id", "int64_t", s390x_cpu_get_id, s390x_cpu_set_id, NULL, NULL, NULL); s390_cpu_model_register_props(obj); #if !defined(CONFIG_USER_ONLY) qemu_get_timedate(&tm, 0); env->tod_offset = TOD_UNIX_EPOCH + (time2tod(mktimegm(&tm)) * 1000000000ULL); env->tod_basetime = 0; 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); s390_cpu_set_state(CPU_STATE_STOPPED, cpu); #endif if (tcg_enabled() && !inited) { inited = true; s390x_translate_init(); } }
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); qemu_get_timedate(&tm, 0); env->tod_offset = TOD_UNIX_EPOCH + (time2tod(mktimegm(&tm)) * 1000000000ULL); env->tod_basetime = 0; 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); s390_cpu_set_state(CPU_STATE_STOPPED, cpu); #endif env->cpu_num = cpu_num++; if (tcg_enabled() && !inited) { inited = true; s390x_translate_init(); } }
/* 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; int i; scc->parent_reset(s); cpu->env.sigp_order = 0; s390_cpu_set_state(CPU_STATE_STOPPED, cpu); memset(env, 0, offsetof(CPUS390XState, end_reset_fields)); /* architectured initial values for CR 0 and 14 */ env->cregs[0] = CR0_RESET; env->cregs[14] = CR14_RESET; /* architectured initial value for Breaking-Event-Address register */ env->gbea = 1; env->pfault_token = -1UL; env->ext_index = -1; for (i = 0; i < ARRAY_SIZE(env->io_index); i++) { env->io_index[i] = -1; } /* tininess for underflow is detected before rounding */ set_float_detect_tininess(float_tininess_before_rounding, &env->fpu_status); /* Reset state inside the kernel that we cannot access yet from QEMU. */ if (kvm_enabled()) { kvm_s390_reset_vcpu(cpu); } }
static void s390x_cpu_set_id(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { S390CPU *cpu = S390_CPU(obj); DeviceState *dev = DEVICE(obj); const int64_t min = 0; const int64_t max = UINT32_MAX; Error *err = NULL; int64_t value; if (dev->realized) { error_setg(errp, "Attempt to set property '%s' on '%s' after " "it was realized", name, object_get_typename(obj)); return; } visit_type_int(v, name, &value, &err); if (err) { error_propagate(errp, err); return; } if (value < min || value > max) { error_setg(errp, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")" , object_get_typename(obj), name, value, min, max); return; } cpu->id = value; }
/* 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); }
/* 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, 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; if (kvm_enabled()) { kvm_s390_reset_vcpu(cpu); } #endif tlb_flush(s, 1); }
void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; int i; if (env->cc_op > 3) { cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n", env->psw.mask, env->psw.addr, cc_name(env->cc_op)); } else { cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n", env->psw.mask, env->psw.addr, env->cc_op); } for (i = 0; i < 16; i++) { cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]); if ((i % 4) == 3) { cpu_fprintf(f, "\n"); } else { cpu_fprintf(f, " "); } } if (flags & CPU_DUMP_FPU) { if (s390_has_feat(S390_FEAT_VECTOR)) { for (i = 0; i < 32; i++) { cpu_fprintf(f, "V%02d=%016" PRIx64 "%016" PRIx64 "%c", i, env->vregs[i][0].ll, env->vregs[i][1].ll, i % 2 ? '\n' : ' '); } } else { for (i = 0; i < 16; i++) { cpu_fprintf(f, "F%02d=%016" PRIx64 "%c", i, get_freg(env, i)->ll, (i % 4) == 3 ? '\n' : ' '); } } } #ifndef CONFIG_USER_ONLY for (i = 0; i < 16; i++) { cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]); if ((i % 4) == 3) { cpu_fprintf(f, "\n"); } else { cpu_fprintf(f, " "); } } #endif #ifdef DEBUG_INLINE_BRANCHES for (i = 0; i < CC_OP_MAX; i++) { cpu_fprintf(f, " %15s = %10ld\t%10ld\n", cc_name(i), inline_branch_miss[i], inline_branch_hit[i]); } #endif cpu_fprintf(f, "\n"); }
static void s390x_cpu_get_id(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { S390CPU *cpu = S390_CPU(obj); int64_t value = cpu->id; visit_type_int(v, name, &value, errp); }
void s390_nmi(NMIState *n, int cpu_index, Error **errp) { CPUState *cs = qemu_get_cpu(cpu_index); if (s390_cpu_restart(S390_CPU(cs))) { error_setg(errp, QERR_UNSUPPORTED); } }
S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp) { S390CPU *cpu; cpu = S390_CPU(object_new(TYPE_S390_CPU)); return cpu; }
static void s390_cpu_finalize(Object *obj) { #if !defined(CONFIG_USER_ONLY) S390CPU *cpu = S390_CPU(obj); qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu); #endif }
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); }
static void s390_cpu_realizefn(DeviceState *dev, Error **errp) { S390CPU *cpu = S390_CPU(dev); S390CPUClass *scc = S390_CPU_GET_CLASS(dev); cpu_reset(CPU(cpu)); scc->parent_realize(dev, errp); }
static void s390_ipl_cpu(uint64_t pswaddr) { S390CPU *cpu = S390_CPU(qemu_get_cpu(0)); CPUS390XState *env = &cpu->env; env->psw.addr = pswaddr; env->psw.mask = IPL_PSW_MASK; s390_add_running_cpu(cpu); }
static void s390_qemu_cpu_model_initfn(Object *obj) { S390CPU *cpu = S390_CPU(obj); cpu->model = g_malloc0(sizeof(*cpu->model)); /* TCG emulates a z900 */ cpu->model->def = &s390_cpu_defs[0]; bitmap_copy(cpu->model->features, cpu->model->def->default_feat, S390_FEAT_MAX); }
S390CPU *cpu_s390x_init(const char *cpu_model) { S390CPU *cpu; cpu = S390_CPU(object_new(TYPE_S390_CPU)); object_property_set_bool(OBJECT(cpu), true, "realized", NULL); return cpu; }
/* 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; scc->parent_reset(s); cpu->env.sigp_order = 0; s390_cpu_set_state(CPU_STATE_STOPPED, cpu); }
int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int mmu_idx) { S390CPU *cpu = S390_CPU(cs); cs->exception_index = EXCP_PGM; cpu->env.int_pgm_code = PGM_ADDRESSING; /* On real machines this value is dropped into LowMem. Since this is userland, simply put this someplace that cpu_loop can find it. */ cpu->env.__excp_addr = address; return 1; }
void s390_machine_reset(void) { S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0)); qemu_devices_reset(); s390_cmma_reset(); s390_crypto_reset(); /* all cpus are stopped - configure and start the ipl cpu only */ s390_ipl_prepare_cpu(ipl_cpu); s390_cpu_set_state(CPU_STATE_OPERATING, ipl_cpu); }
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque) { S390CPU *cpu = S390_CPU(cs); int r; r = s390x_write_elf64_notes("CORE", f, cpu, cpuid, opaque, note_core); if (r) { return r; } return s390x_write_elf64_notes("LINUX", f, cpu, cpuid, opaque, note_linux); }