qemu/accel/tcg/tcg-accel-ops.c
<<
>>
Prefs
   1/*
   2 * QEMU TCG vCPU common functionality
   3 *
   4 * Functionality common to all TCG vCPU variants: mttcg, rr and icount.
   5 *
   6 * Copyright (c) 2003-2008 Fabrice Bellard
   7 * Copyright (c) 2014 Red Hat Inc.
   8 *
   9 * Permission is hereby granted, free of charge, to any person obtaining a copy
  10 * of this software and associated documentation files (the "Software"), to deal
  11 * in the Software without restriction, including without limitation the rights
  12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13 * copies of the Software, and to permit persons to whom the Software is
  14 * furnished to do so, subject to the following conditions:
  15 *
  16 * The above copyright notice and this permission notice shall be included in
  17 * all copies or substantial portions of the Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25 * THE SOFTWARE.
  26 */
  27
  28#include "qemu/osdep.h"
  29#include "qemu-common.h"
  30#include "sysemu/tcg.h"
  31#include "sysemu/replay.h"
  32#include "qemu/main-loop.h"
  33#include "qemu/guest-random.h"
  34#include "exec/exec-all.h"
  35#include "hw/boards.h"
  36
  37#include "tcg-accel-ops.h"
  38#include "tcg-accel-ops-mttcg.h"
  39#include "tcg-accel-ops-rr.h"
  40#include "tcg-accel-ops-icount.h"
  41
  42/* common functionality among all TCG variants */
  43
  44void tcg_cpu_init_cflags(CPUState *cpu, bool parallel)
  45{
  46    uint32_t cflags = cpu->cluster_index << CF_CLUSTER_SHIFT;
  47    cflags |= parallel ? CF_PARALLEL : 0;
  48    cflags |= icount_enabled() ? CF_USE_ICOUNT : 0;
  49    cpu->tcg_cflags = cflags;
  50}
  51
  52void tcg_cpus_destroy(CPUState *cpu)
  53{
  54    cpu_thread_signal_destroyed(cpu);
  55}
  56
  57int tcg_cpus_exec(CPUState *cpu)
  58{
  59    int ret;
  60#ifdef CONFIG_PROFILER
  61    int64_t ti;
  62#endif
  63    assert(tcg_enabled());
  64#ifdef CONFIG_PROFILER
  65    ti = profile_getclock();
  66#endif
  67    cpu_exec_start(cpu);
  68    ret = cpu_exec(cpu);
  69    cpu_exec_end(cpu);
  70#ifdef CONFIG_PROFILER
  71    qatomic_set(&tcg_ctx->prof.cpu_exec_time,
  72                tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
  73#endif
  74    return ret;
  75}
  76
  77/* mask must never be zero, except for A20 change call */
  78void tcg_handle_interrupt(CPUState *cpu, int mask)
  79{
  80    g_assert(qemu_mutex_iothread_locked());
  81
  82    cpu->interrupt_request |= mask;
  83
  84    /*
  85     * If called from iothread context, wake the target cpu in
  86     * case its halted.
  87     */
  88    if (!qemu_cpu_is_self(cpu)) {
  89        qemu_cpu_kick(cpu);
  90    } else {
  91        qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
  92    }
  93}
  94
  95static void tcg_accel_ops_init(AccelOpsClass *ops)
  96{
  97    if (qemu_tcg_mttcg_enabled()) {
  98        ops->create_vcpu_thread = mttcg_start_vcpu_thread;
  99        ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
 100        ops->handle_interrupt = tcg_handle_interrupt;
 101    } else if (icount_enabled()) {
 102        ops->create_vcpu_thread = rr_start_vcpu_thread;
 103        ops->kick_vcpu_thread = rr_kick_vcpu_thread;
 104        ops->handle_interrupt = icount_handle_interrupt;
 105        ops->get_virtual_clock = icount_get;
 106        ops->get_elapsed_ticks = icount_get;
 107    } else {
 108        ops->create_vcpu_thread = rr_start_vcpu_thread;
 109        ops->kick_vcpu_thread = rr_kick_vcpu_thread;
 110        ops->handle_interrupt = tcg_handle_interrupt;
 111    }
 112}
 113
 114static void tcg_accel_ops_class_init(ObjectClass *oc, void *data)
 115{
 116    AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
 117
 118    ops->ops_init = tcg_accel_ops_init;
 119}
 120
 121static const TypeInfo tcg_accel_ops_type = {
 122    .name = ACCEL_OPS_NAME("tcg"),
 123
 124    .parent = TYPE_ACCEL_OPS,
 125    .class_init = tcg_accel_ops_class_init,
 126    .abstract = true,
 127};
 128
 129static void tcg_accel_ops_register_types(void)
 130{
 131    type_register_static(&tcg_accel_ops_type);
 132}
 133type_init(tcg_accel_ops_register_types);
 134