qemu/target/s390x/cpu.c
<<
>>
Prefs
   1/*
   2 * QEMU S/390 CPU
   3 *
   4 * Copyright (c) 2009 Ulrich Hecht
   5 * Copyright (c) 2011 Alexander Graf
   6 * Copyright (c) 2012 SUSE LINUX Products GmbH
   7 * Copyright (c) 2012 IBM Corp.
   8 *
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation; either
  12 * version 2.1 of the License, or (at your option) any later version.
  13 *
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, see
  21 * <http://www.gnu.org/licenses/lgpl-2.1.html>
  22 * Contributions after 2012-12-11 are licensed under the terms of the
  23 * GNU GPL, version 2 or (at your option) any later version.
  24 */
  25
  26#include "qemu/osdep.h"
  27#include "qapi/error.h"
  28#include "cpu.h"
  29#include "internal.h"
  30#include "kvm_s390x.h"
  31#include "sysemu/kvm.h"
  32#include "qemu-common.h"
  33#include "qemu/timer.h"
  34#include "qemu/error-report.h"
  35#include "trace.h"
  36#include "qapi/visitor.h"
  37#include "qapi/qapi-visit-misc.h"
  38#include "qapi/qapi-visit-run-state.h"
  39#include "sysemu/hw_accel.h"
  40#include "hw/qdev-properties.h"
  41#ifndef CONFIG_USER_ONLY
  42#include "hw/hw.h"
  43#include "sysemu/arch_init.h"
  44#include "sysemu/sysemu.h"
  45#endif
  46#include "fpu/softfloat.h"
  47
  48#define CR0_RESET       0xE0UL
  49#define CR14_RESET      0xC2000000UL;
  50
  51static void s390_cpu_set_pc(CPUState *cs, vaddr value)
  52{
  53    S390CPU *cpu = S390_CPU(cs);
  54
  55    cpu->env.psw.addr = value;
  56}
  57
  58static bool s390_cpu_has_work(CPUState *cs)
  59{
  60    S390CPU *cpu = S390_CPU(cs);
  61
  62    /* STOPPED cpus can never wake up */
  63    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD &&
  64        s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
  65        return false;
  66    }
  67
  68    if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
  69        return false;
  70    }
  71
  72    return s390_cpu_has_int(cpu);
  73}
  74
  75#if !defined(CONFIG_USER_ONLY)
  76/* S390CPUClass::load_normal() */
  77static void s390_cpu_load_normal(CPUState *s)
  78{
  79    S390CPU *cpu = S390_CPU(s);
  80    cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR;
  81    cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64;
  82    s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
  83}
  84#endif
  85
  86/* S390CPUClass::cpu_reset() */
  87static void s390_cpu_reset(CPUState *s)
  88{
  89    S390CPU *cpu = S390_CPU(s);
  90    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
  91    CPUS390XState *env = &cpu->env;
  92
  93    env->pfault_token = -1UL;
  94    env->bpbc = false;
  95    scc->parent_reset(s);
  96    cpu->env.sigp_order = 0;
  97    s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
  98}
  99
 100/* S390CPUClass::initial_reset() */
 101static void s390_cpu_initial_reset(CPUState *s)
 102{
 103    S390CPU *cpu = S390_CPU(s);
 104    CPUS390XState *env = &cpu->env;
 105
 106    s390_cpu_reset(s);
 107    /* initial reset does not clear everything! */
 108    memset(&env->start_initial_reset_fields, 0,
 109        offsetof(CPUS390XState, end_reset_fields) -
 110        offsetof(CPUS390XState, start_initial_reset_fields));
 111
 112    /* architectured initial values for CR 0 and 14 */
 113    env->cregs[0] = CR0_RESET;
 114    env->cregs[14] = CR14_RESET;
 115
 116    /* architectured initial value for Breaking-Event-Address register */
 117    env->gbea = 1;
 118
 119    env->pfault_token = -1UL;
 120
 121    /* tininess for underflow is detected before rounding */
 122    set_float_detect_tininess(float_tininess_before_rounding,
 123                              &env->fpu_status);
 124
 125    /* Reset state inside the kernel that we cannot access yet from QEMU. */
 126    if (kvm_enabled()) {
 127        kvm_s390_reset_vcpu(cpu);
 128    }
 129}
 130
 131/* CPUClass:reset() */
 132static void s390_cpu_full_reset(CPUState *s)
 133{
 134    S390CPU *cpu = S390_CPU(s);
 135    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
 136    CPUS390XState *env = &cpu->env;
 137
 138    scc->parent_reset(s);
 139    cpu->env.sigp_order = 0;
 140    s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
 141
 142    memset(env, 0, offsetof(CPUS390XState, end_reset_fields));
 143
 144    /* architectured initial values for CR 0 and 14 */
 145    env->cregs[0] = CR0_RESET;
 146    env->cregs[14] = CR14_RESET;
 147
 148    /* architectured initial value for Breaking-Event-Address register */
 149    env->gbea = 1;
 150
 151    env->pfault_token = -1UL;
 152
 153    /* tininess for underflow is detected before rounding */
 154    set_float_detect_tininess(float_tininess_before_rounding,
 155                              &env->fpu_status);
 156
 157    /* Reset state inside the kernel that we cannot access yet from QEMU. */
 158    if (kvm_enabled()) {
 159        kvm_s390_reset_vcpu(cpu);
 160    }
 161}
 162
 163#if !defined(CONFIG_USER_ONLY)
 164static void s390_cpu_machine_reset_cb(void *opaque)
 165{
 166    S390CPU *cpu = opaque;
 167
 168    run_on_cpu(CPU(cpu), s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
 169}
 170#endif
 171
 172static void s390_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
 173{
 174    info->mach = bfd_mach_s390_64;
 175    info->print_insn = print_insn_s390;
 176}
 177
 178static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
 179{
 180    CPUState *cs = CPU(dev);
 181    S390CPUClass *scc = S390_CPU_GET_CLASS(dev);
 182#if !defined(CONFIG_USER_ONLY)
 183    S390CPU *cpu = S390_CPU(dev);
 184#endif
 185    Error *err = NULL;
 186
 187    /* the model has to be realized before qemu_init_vcpu() due to kvm */
 188    s390_realize_cpu_model(cs, &err);
 189    if (err) {
 190        goto out;
 191    }
 192
 193#if !defined(CONFIG_USER_ONLY)
 194    if (cpu->env.core_id >= max_cpus) {
 195        error_setg(&err, "Unable to add CPU with core-id: %" PRIu32
 196                   ", maximum core-id: %d", cpu->env.core_id,
 197                   max_cpus - 1);
 198        goto out;
 199    }
 200
 201    if (cpu_exists(cpu->env.core_id)) {
 202        error_setg(&err, "Unable to add CPU with core-id: %" PRIu32
 203                   ", it already exists", cpu->env.core_id);
 204        goto out;
 205    }
 206
 207    /* sync cs->cpu_index and env->core_id. The latter is needed for TCG. */
 208    cs->cpu_index = cpu->env.core_id;
 209#endif
 210
 211    cpu_exec_realizefn(cs, &err);
 212    if (err != NULL) {
 213        goto out;
 214    }
 215
 216#if !defined(CONFIG_USER_ONLY)
 217    qemu_register_reset(s390_cpu_machine_reset_cb, cpu);
 218#endif
 219    s390_cpu_gdb_init(cs);
 220    qemu_init_vcpu(cs);
 221
 222    /*
 223     * KVM requires the initial CPU reset ioctl to be executed on the target
 224     * CPU thread. CPU hotplug under single-threaded TCG will not work with
 225     * run_on_cpu(), as run_on_cpu() will not work properly if called while
 226     * the main thread is already running but the CPU hasn't been realized.
 227     */
 228    if (kvm_enabled()) {
 229        run_on_cpu(cs, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
 230    } else {
 231        cpu_reset(cs);
 232    }
 233
 234    scc->parent_realize(dev, &err);
 235out:
 236    error_propagate(errp, err);
 237}
 238
 239static GuestPanicInformation *s390_cpu_get_crash_info(CPUState *cs)
 240{
 241    GuestPanicInformation *panic_info;
 242    S390CPU *cpu = S390_CPU(cs);
 243
 244    cpu_synchronize_state(cs);
 245    panic_info = g_malloc0(sizeof(GuestPanicInformation));
 246
 247    panic_info->type = GUEST_PANIC_INFORMATION_TYPE_S390;
 248#if !defined(CONFIG_USER_ONLY)
 249    panic_info->u.s390.core = cpu->env.core_id;
 250#else
 251    panic_info->u.s390.core = 0; /* sane default for non system emulation */
 252#endif
 253    panic_info->u.s390.psw_mask = cpu->env.psw.mask;
 254    panic_info->u.s390.psw_addr = cpu->env.psw.addr;
 255    panic_info->u.s390.reason = cpu->env.crash_reason;
 256
 257    return panic_info;
 258}
 259
 260static void s390_cpu_get_crash_info_qom(Object *obj, Visitor *v,
 261                                        const char *name, void *opaque,
 262                                        Error **errp)
 263{
 264    CPUState *cs = CPU(obj);
 265    GuestPanicInformation *panic_info;
 266
 267    if (!cs->crash_occurred) {
 268        error_setg(errp, "No crash occurred");
 269        return;
 270    }
 271
 272    panic_info = s390_cpu_get_crash_info(cs);
 273
 274    visit_type_GuestPanicInformation(v, "crash-information", &panic_info,
 275                                     errp);
 276    qapi_free_GuestPanicInformation(panic_info);
 277}
 278
 279static void s390_cpu_initfn(Object *obj)
 280{
 281    CPUState *cs = CPU(obj);
 282    S390CPU *cpu = S390_CPU(obj);
 283    CPUS390XState *env = &cpu->env;
 284
 285    cs->env_ptr = env;
 286    cs->halted = 1;
 287    cs->exception_index = EXCP_HLT;
 288    object_property_add(obj, "crash-information", "GuestPanicInformation",
 289                        s390_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL);
 290    s390_cpu_model_register_props(obj);
 291#if !defined(CONFIG_USER_ONLY)
 292    env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu);
 293    env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu);
 294    s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
 295#endif
 296}
 297
 298static void s390_cpu_finalize(Object *obj)
 299{
 300#if !defined(CONFIG_USER_ONLY)
 301    S390CPU *cpu = S390_CPU(obj);
 302
 303    qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu);
 304    g_free(cpu->irqstate);
 305#endif
 306}
 307
 308#if !defined(CONFIG_USER_ONLY)
 309static bool disabled_wait(CPUState *cpu)
 310{
 311    return cpu->halted && !(S390_CPU(cpu)->env.psw.mask &
 312                            (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK));
 313}
 314
 315static unsigned s390_count_running_cpus(void)
 316{
 317    CPUState *cpu;
 318    int nr_running = 0;
 319
 320    CPU_FOREACH(cpu) {
 321        uint8_t state = S390_CPU(cpu)->env.cpu_state;
 322        if (state == S390_CPU_STATE_OPERATING ||
 323            state == S390_CPU_STATE_LOAD) {
 324            if (!disabled_wait(cpu)) {
 325                nr_running++;
 326            }
 327        }
 328    }
 329
 330    return nr_running;
 331}
 332
 333unsigned int s390_cpu_halt(S390CPU *cpu)
 334{
 335    CPUState *cs = CPU(cpu);
 336    trace_cpu_halt(cs->cpu_index);
 337
 338    if (!cs->halted) {
 339        cs->halted = 1;
 340        cs->exception_index = EXCP_HLT;
 341    }
 342
 343    return s390_count_running_cpus();
 344}
 345
 346void s390_cpu_unhalt(S390CPU *cpu)
 347{
 348    CPUState *cs = CPU(cpu);
 349    trace_cpu_unhalt(cs->cpu_index);
 350
 351    if (cs->halted) {
 352        cs->halted = 0;
 353        cs->exception_index = -1;
 354    }
 355}
 356
 357unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
 358 {
 359    trace_cpu_set_state(CPU(cpu)->cpu_index, cpu_state);
 360
 361    switch (cpu_state) {
 362    case S390_CPU_STATE_STOPPED:
 363    case S390_CPU_STATE_CHECK_STOP:
 364        /* halt the cpu for common infrastructure */
 365        s390_cpu_halt(cpu);
 366        break;
 367    case S390_CPU_STATE_OPERATING:
 368    case S390_CPU_STATE_LOAD:
 369        /*
 370         * Starting a CPU with a PSW WAIT bit set:
 371         * KVM: handles this internally and triggers another WAIT exit.
 372         * TCG: will actually try to continue to run. Don't unhalt, will
 373         *      be done when the CPU actually has work (an interrupt).
 374         */
 375        if (!tcg_enabled() || !(cpu->env.psw.mask & PSW_MASK_WAIT)) {
 376            s390_cpu_unhalt(cpu);
 377        }
 378        break;
 379    default:
 380        error_report("Requested CPU state is not a valid S390 CPU state: %u",
 381                     cpu_state);
 382        exit(1);
 383    }
 384    if (kvm_enabled() && cpu->env.cpu_state != cpu_state) {
 385        kvm_s390_set_cpu_state(cpu, cpu_state);
 386    }
 387    cpu->env.cpu_state = cpu_state;
 388
 389    return s390_count_running_cpus();
 390}
 391
 392int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
 393{
 394    if (kvm_enabled()) {
 395        return kvm_s390_set_mem_limit(new_limit, hw_limit);
 396    }
 397    return 0;
 398}
 399
 400void s390_cmma_reset(void)
 401{
 402    if (kvm_enabled()) {
 403        kvm_s390_cmma_reset();
 404    }
 405}
 406
 407int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
 408                                int vq, bool assign)
 409{
 410    if (kvm_enabled()) {
 411        return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
 412    } else {
 413        return 0;
 414    }
 415}
 416
 417void s390_crypto_reset(void)
 418{
 419    if (kvm_enabled()) {
 420        kvm_s390_crypto_reset();
 421    }
 422}
 423
 424bool s390_get_squash_mcss(void)
 425{
 426    if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
 427                                 NULL)) {
 428        return true;
 429    }
 430
 431    return false;
 432}
 433
 434void s390_enable_css_support(S390CPU *cpu)
 435{
 436    if (kvm_enabled()) {
 437        kvm_s390_enable_css_support(cpu);
 438    }
 439}
 440#endif
 441
 442static gchar *s390_gdb_arch_name(CPUState *cs)
 443{
 444    return g_strdup("s390:64-bit");
 445}
 446
 447static Property s390x_cpu_properties[] = {
 448#if !defined(CONFIG_USER_ONLY)
 449    DEFINE_PROP_UINT32("core-id", S390CPU, env.core_id, 0),
 450#endif
 451    DEFINE_PROP_END_OF_LIST()
 452};
 453
 454static void s390_cpu_class_init(ObjectClass *oc, void *data)
 455{
 456    S390CPUClass *scc = S390_CPU_CLASS(oc);
 457    CPUClass *cc = CPU_CLASS(scc);
 458    DeviceClass *dc = DEVICE_CLASS(oc);
 459
 460    device_class_set_parent_realize(dc, s390_cpu_realizefn,
 461                                    &scc->parent_realize);
 462    dc->props = s390x_cpu_properties;
 463    dc->user_creatable = true;
 464
 465    scc->parent_reset = cc->reset;
 466#if !defined(CONFIG_USER_ONLY)
 467    scc->load_normal = s390_cpu_load_normal;
 468#endif
 469    scc->cpu_reset = s390_cpu_reset;
 470    scc->initial_cpu_reset = s390_cpu_initial_reset;
 471    cc->reset = s390_cpu_full_reset;
 472    cc->class_by_name = s390_cpu_class_by_name,
 473    cc->has_work = s390_cpu_has_work;
 474#ifdef CONFIG_TCG
 475    cc->do_interrupt = s390_cpu_do_interrupt;
 476#endif
 477    cc->dump_state = s390_cpu_dump_state;
 478    cc->get_crash_info = s390_cpu_get_crash_info;
 479    cc->set_pc = s390_cpu_set_pc;
 480    cc->gdb_read_register = s390_cpu_gdb_read_register;
 481    cc->gdb_write_register = s390_cpu_gdb_write_register;
 482#ifdef CONFIG_USER_ONLY
 483    cc->handle_mmu_fault = s390_cpu_handle_mmu_fault;
 484#else
 485    cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
 486    cc->vmsd = &vmstate_s390_cpu;
 487    cc->write_elf64_note = s390_cpu_write_elf64_note;
 488#ifdef CONFIG_TCG
 489    cc->cpu_exec_interrupt = s390_cpu_exec_interrupt;
 490    cc->debug_excp_handler = s390x_cpu_debug_excp_handler;
 491    cc->do_unaligned_access = s390x_cpu_do_unaligned_access;
 492#endif
 493#endif
 494    cc->disas_set_info = s390_cpu_disas_set_info;
 495#ifdef CONFIG_TCG
 496    cc->tcg_initialize = s390x_translate_init;
 497#endif
 498
 499    cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
 500    cc->gdb_core_xml_file = "s390x-core64.xml";
 501    cc->gdb_arch_name = s390_gdb_arch_name;
 502
 503    s390_cpu_model_class_register_props(oc);
 504}
 505
 506static const TypeInfo s390_cpu_type_info = {
 507    .name = TYPE_S390_CPU,
 508    .parent = TYPE_CPU,
 509    .instance_size = sizeof(S390CPU),
 510    .instance_init = s390_cpu_initfn,
 511    .instance_finalize = s390_cpu_finalize,
 512    .abstract = true,
 513    .class_size = sizeof(S390CPUClass),
 514    .class_init = s390_cpu_class_init,
 515};
 516
 517static void s390_cpu_register_types(void)
 518{
 519    type_register_static(&s390_cpu_type_info);
 520}
 521
 522type_init(s390_cpu_register_types)
 523