#include "qemu/osdep.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "internal.h"
+#include "kvm_s390x.h"
+#include "sysemu/kvm.h"
#include "qemu-common.h"
#include "qemu/cutils.h"
#include "qemu/timer.h"
#include "qemu/error-report.h"
#include "trace.h"
#include "qapi/visitor.h"
-#include "migration/vmstate.h"
#include "exec/exec-all.h"
+#include "hw/qdev-properties.h"
#ifndef CONFIG_USER_ONLY
#include "hw/hw.h"
#include "sysemu/arch_init.h"
#include "sysemu/sysemu.h"
-#include "hw/s390x/sclp.h"
#endif
#define CR0_RESET 0xE0UL
int i;
s390_cpu_reset(s);
- /* initial reset does not touch regs,fregs and aregs */
- memset(&env->fpc, 0, offsetof(CPUS390XState, end_reset_fields) -
- offsetof(CPUS390XState, fpc));
+ /* initial reset does not clear everything! */
+ memset(&env->start_initial_reset_fields, 0,
+ offsetof(CPUS390XState, end_reset_fields) -
+ offsetof(CPUS390XState, start_initial_reset_fields));
/* architectured initial values for CR 0 and 14 */
env->cregs[0] = CR0_RESET;
for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
env->io_index[i] = -1;
}
+ env->mchk_index = -1;
/* tininess for underflow is detected before rounding */
set_float_detect_tininess(float_tininess_before_rounding,
for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
env->io_index[i] = -1;
}
+ env->mchk_index = -1;
/* tininess for underflow is detected before rounding */
set_float_detect_tininess(float_tininess_before_rounding,
{
CPUState *cs = CPU(dev);
S390CPUClass *scc = S390_CPU_GET_CLASS(dev);
+#if !defined(CONFIG_USER_ONLY)
S390CPU *cpu = S390_CPU(dev);
- CPUS390XState *env = &cpu->env;
+#endif
Error *err = NULL;
/* the model has to be realized before qemu_init_vcpu() due to kvm */
}
#if !defined(CONFIG_USER_ONLY)
- if (cpu->id >= max_cpus) {
- error_setg(&err, "Unable to add CPU: %" PRIi64
- ", max allowed: %d", cpu->id, max_cpus - 1);
- goto out;
- }
-#endif
- if (cpu_exists(cpu->id)) {
- error_setg(&err, "Unable to add CPU: %" PRIi64
- ", it already exists", cpu->id);
+ if (cpu->env.core_id >= max_cpus) {
+ error_setg(&err, "Unable to add CPU with core-id: %" PRIu32
+ ", maximum core-id: %d", cpu->env.core_id,
+ max_cpus - 1);
goto out;
}
- if (cpu->id != scc->next_cpu_id) {
- error_setg(&err, "Unable to add CPU: %" PRIi64
- ", The next available id is %" PRIi64, cpu->id,
- scc->next_cpu_id);
+
+ if (cpu_exists(cpu->env.core_id)) {
+ error_setg(&err, "Unable to add CPU with core-id: %" PRIu32
+ ", it already exists", cpu->env.core_id);
goto out;
}
+ /* sync cs->cpu_index and env->core_id. The latter is needed for TCG. */
+ cs->cpu_index = cpu->env.core_id;
+#endif
+
cpu_exec_realizefn(cs, &err);
if (err != NULL) {
goto out;
}
- scc->next_cpu_id++;
#if !defined(CONFIG_USER_ONLY)
qemu_register_reset(s390_cpu_machine_reset_cb, cpu);
#endif
- env->cpu_num = cpu->id;
s390_cpu_gdb_init(cs);
qemu_init_vcpu(cs);
#if !defined(CONFIG_USER_ONLY)
#endif
scc->parent_realize(dev, &err);
-
-#if !defined(CONFIG_USER_ONLY)
- if (dev->hotplugged) {
- raise_irq_cpu_hotplug();
- }
-#endif
-
out:
error_propagate(errp, err);
}
-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);
-}
-
-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;
-}
-
static void s390_cpu_initfn(Object *obj)
{
CPUState *cs = CPU(obj);
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);
return s390_count_running_cpus();
}
+
+int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
+{
+ int r = 0;
+
+ if (kvm_enabled()) {
+ r = kvm_s390_get_clock_ext(tod_high, tod_low);
+ if (r == -ENXIO) {
+ return kvm_s390_get_clock(tod_high, tod_low);
+ }
+ } else {
+ /* Fixme TCG */
+ *tod_high = 0;
+ *tod_low = 0;
+ }
+
+ return r;
+}
+
+int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
+{
+ int r = 0;
+
+ if (kvm_enabled()) {
+ r = kvm_s390_set_clock_ext(tod_high, tod_low);
+ if (r == -ENXIO) {
+ return kvm_s390_set_clock(tod_high, tod_low);
+ }
+ }
+ /* Fixme TCG */
+ return r;
+}
+
+int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_set_mem_limit(new_limit, hw_limit);
+ }
+ return 0;
+}
+
+void s390_cmma_reset(void)
+{
+ if (kvm_enabled()) {
+ kvm_s390_cmma_reset();
+ }
+}
+
+int s390_cpu_restart(S390CPU *cpu)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_cpu_restart(cpu);
+ }
+ return -ENOSYS;
+}
+
+int s390_get_memslot_count(void)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_get_memslot_count();
+ } else {
+ return MAX_AVAIL_SLOTS;
+ }
+}
+
+int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
+ int vq, bool assign)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
+ } else {
+ return 0;
+ }
+}
+
+void s390_crypto_reset(void)
+{
+ if (kvm_enabled()) {
+ kvm_s390_crypto_reset();
+ }
+}
+
+bool s390_get_squash_mcss(void)
+{
+ if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
+ NULL)) {
+ return true;
+ }
+
+ return false;
+}
+
+void s390_enable_css_support(S390CPU *cpu)
+{
+ if (kvm_enabled()) {
+ kvm_s390_enable_css_support(cpu);
+ }
+}
#endif
static gchar *s390_gdb_arch_name(CPUState *cs)
return g_strdup("s390:64-bit");
}
+static Property s390x_cpu_properties[] = {
+#if !defined(CONFIG_USER_ONLY)
+ DEFINE_PROP_UINT32("core-id", S390CPU, env.core_id, 0),
+#endif
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void s390_cpu_class_init(ObjectClass *oc, void *data)
{
S390CPUClass *scc = S390_CPU_CLASS(oc);
CPUClass *cc = CPU_CLASS(scc);
DeviceClass *dc = DEVICE_CLASS(oc);
- scc->next_cpu_id = 0;
scc->parent_realize = dc->realize;
dc->realize = s390_cpu_realizefn;
+ dc->props = s390x_cpu_properties;
+ dc->user_creatable = true;
scc->parent_reset = cc->reset;
#if !defined(CONFIG_USER_ONLY)
cc->reset = s390_cpu_full_reset;
cc->class_by_name = s390_cpu_class_by_name,
cc->has_work = s390_cpu_has_work;
+#ifdef CONFIG_TCG
cc->do_interrupt = s390_cpu_do_interrupt;
+#endif
cc->dump_state = s390_cpu_dump_state;
cc->set_pc = s390_cpu_set_pc;
cc->gdb_read_register = s390_cpu_gdb_read_register;
cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_s390_cpu;
cc->write_elf64_note = s390_cpu_write_elf64_note;
+#ifdef CONFIG_TCG
cc->cpu_exec_interrupt = s390_cpu_exec_interrupt;
cc->debug_excp_handler = s390x_cpu_debug_excp_handler;
cc->do_unaligned_access = s390x_cpu_do_unaligned_access;
+#endif
#endif
cc->disas_set_info = s390_cpu_disas_set_info;