cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

tcg-all.c (7257B)


      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);