qemu/accel/tcg/tcg-all.c
<<
>>
Prefs
   1/*
   2 * QEMU System Emulator, accelerator interfaces
   3 *
   4 * Copyright (c) 2003-2008 Fabrice Bellard
   5 * Copyright (c) 2014 Red Hat Inc.
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25
  26#include "qemu/osdep.h"
  27#include "qemu-common.h"
  28#include "sysemu/tcg.h"
  29#include "sysemu/cpu-timers.h"
  30#include "tcg/tcg.h"
  31#include "qapi/error.h"
  32#include "qemu/error-report.h"
  33#include "qemu/accel.h"
  34#include "qapi/qapi-builtin-visit.h"
  35#include "qemu/units.h"
  36#if !defined(CONFIG_USER_ONLY)
  37#include "hw/boards.h"
  38#endif
  39#include "internal.h"
  40
  41struct TCGState {
  42    AccelState parent_obj;
  43
  44    bool mttcg_enabled;
  45    int splitwx_enabled;
  46    unsigned long tb_size;
  47};
  48typedef struct TCGState TCGState;
  49
  50#define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
  51
  52DECLARE_INSTANCE_CHECKER(TCGState, TCG_STATE,
  53                         TYPE_TCG_ACCEL)
  54
  55/*
  56 * We default to false if we know other options have been enabled
  57 * which are currently incompatible with MTTCG. Otherwise when each
  58 * guest (target) has been updated to support:
  59 *   - atomic instructions
  60 *   - memory ordering primitives (barriers)
  61 * they can set the appropriate CONFIG flags in ${target}-softmmu.mak
  62 *
  63 * Once a guest architecture has been converted to the new primitives
  64 * there are two remaining limitations to check.
  65 *
  66 * - The guest can't be oversized (e.g. 64 bit guest on 32 bit host)
  67 * - The host must have a stronger memory order than the guest
  68 *
  69 * It may be possible in future to support strong guests on weak hosts
  70 * but that will require tagging all load/stores in a guest with their
  71 * implicit memory order requirements which would likely slow things
  72 * down a lot.
  73 */
  74
  75static bool check_tcg_memory_orders_compatible(void)
  76{
  77#if defined(TCG_GUEST_DEFAULT_MO) && defined(TCG_TARGET_DEFAULT_MO)
  78    return (TCG_GUEST_DEFAULT_MO & ~TCG_TARGET_DEFAULT_MO) == 0;
  79#else
  80    return false;
  81#endif
  82}
  83
  84static bool default_mttcg_enabled(void)
  85{
  86    if (icount_enabled() || TCG_OVERSIZED_GUEST) {
  87        return false;
  88    } else {
  89#ifdef TARGET_SUPPORTS_MTTCG
  90        return check_tcg_memory_orders_compatible();
  91#else
  92        return false;
  93#endif
  94    }
  95}
  96
  97static void tcg_accel_instance_init(Object *obj)
  98{
  99    TCGState *s = TCG_STATE(obj);
 100
 101    s->mttcg_enabled = default_mttcg_enabled();
 102
 103    /* If debugging enabled, default "auto on", otherwise off. */
 104#if defined(CONFIG_DEBUG_TCG) && !defined(CONFIG_USER_ONLY)
 105    s->splitwx_enabled = -1;
 106#else
 107    s->splitwx_enabled = 0;
 108#endif
 109}
 110
 111bool mttcg_enabled;
 112
 113static int tcg_init_machine(MachineState *ms)
 114{
 115    TCGState *s = TCG_STATE(current_accel());
 116#ifdef CONFIG_USER_ONLY
 117    unsigned max_cpus = 1;
 118#else
 119    unsigned max_cpus = ms->smp.max_cpus;
 120#endif
 121
 122    tcg_allowed = true;
 123    mttcg_enabled = s->mttcg_enabled;
 124
 125    page_init();
 126    tb_htable_init();
 127    tcg_init(s->tb_size * MiB, s->splitwx_enabled, max_cpus);
 128
 129#if defined(CONFIG_SOFTMMU)
 130    /*
 131     * There's no guest base to take into account, so go ahead and
 132     * initialize the prologue now.
 133     */
 134    tcg_prologue_init(tcg_ctx);
 135#endif
 136
 137    return 0;
 138}
 139
 140static char *tcg_get_thread(Object *obj, Error **errp)
 141{
 142    TCGState *s = TCG_STATE(obj);
 143
 144    return g_strdup(s->mttcg_enabled ? "multi" : "single");
 145}
 146
 147static void tcg_set_thread(Object *obj, const char *value, Error **errp)
 148{
 149    TCGState *s = TCG_STATE(obj);
 150
 151    if (strcmp(value, "multi") == 0) {
 152        if (TCG_OVERSIZED_GUEST) {
 153            error_setg(errp, "No MTTCG when guest word size > hosts");
 154        } else if (icount_enabled()) {
 155            error_setg(errp, "No MTTCG when icount is enabled");
 156        } else {
 157#ifndef TARGET_SUPPORTS_MTTCG
 158            warn_report("Guest not yet converted to MTTCG - "
 159                        "you may get unexpected results");
 160#endif
 161            if (!check_tcg_memory_orders_compatible()) {
 162                warn_report("Guest expects a stronger memory ordering "
 163                            "than the host provides");
 164                error_printf("This may cause strange/hard to debug errors\n");
 165            }
 166            s->mttcg_enabled = true;
 167        }
 168    } else if (strcmp(value, "single") == 0) {
 169        s->mttcg_enabled = false;
 170    } else {
 171        error_setg(errp, "Invalid 'thread' setting %s", value);
 172    }
 173}
 174
 175static void tcg_get_tb_size(Object *obj, Visitor *v,
 176                            const char *name, void *opaque,
 177                            Error **errp)
 178{
 179    TCGState *s = TCG_STATE(obj);
 180    uint32_t value = s->tb_size;
 181
 182    visit_type_uint32(v, name, &value, errp);
 183}
 184
 185static void tcg_set_tb_size(Object *obj, Visitor *v,
 186                            const char *name, void *opaque,
 187                            Error **errp)
 188{
 189    TCGState *s = TCG_STATE(obj);
 190    uint32_t value;
 191
 192    if (!visit_type_uint32(v, name, &value, errp)) {
 193        return;
 194    }
 195
 196    s->tb_size = value;
 197}
 198
 199static bool tcg_get_splitwx(Object *obj, Error **errp)
 200{
 201    TCGState *s = TCG_STATE(obj);
 202    return s->splitwx_enabled;
 203}
 204
 205static void tcg_set_splitwx(Object *obj, bool value, Error **errp)
 206{
 207    TCGState *s = TCG_STATE(obj);
 208    s->splitwx_enabled = value;
 209}
 210
 211static void tcg_accel_class_init(ObjectClass *oc, void *data)
 212{
 213    AccelClass *ac = ACCEL_CLASS(oc);
 214    ac->name = "tcg";
 215    ac->init_machine = tcg_init_machine;
 216    ac->allowed = &tcg_allowed;
 217
 218    object_class_property_add_str(oc, "thread",
 219                                  tcg_get_thread,
 220                                  tcg_set_thread);
 221
 222    object_class_property_add(oc, "tb-size", "int",
 223        tcg_get_tb_size, tcg_set_tb_size,
 224        NULL, NULL);
 225    object_class_property_set_description(oc, "tb-size",
 226        "TCG translation block cache size");
 227
 228    object_class_property_add_bool(oc, "split-wx",
 229        tcg_get_splitwx, tcg_set_splitwx);
 230    object_class_property_set_description(oc, "split-wx",
 231        "Map jit pages into separate RW and RX regions");
 232}
 233
 234static const TypeInfo tcg_accel_type = {
 235    .name = TYPE_TCG_ACCEL,
 236    .parent = TYPE_ACCEL,
 237    .instance_init = tcg_accel_instance_init,
 238    .class_init = tcg_accel_class_init,
 239    .instance_size = sizeof(TCGState),
 240};
 241module_obj(TYPE_TCG_ACCEL);
 242
 243static void register_accel_types(void)
 244{
 245    type_register_static(&tcg_accel_type);
 246}
 247
 248type_init(register_accel_types);
 249