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
  36#include "tcg-accel-ops.h"
  37#include "tcg-accel-ops-mttcg.h"
  38#include "tcg-accel-ops-rr.h"
  39#include "tcg-accel-ops-icount.h"
  40
  41/* common functionality among all TCG variants */
  42
  43void tcg_cpu_init_cflags(CPUState *cpu, bool parallel)
  44{
  45    uint32_t cflags = cpu->cluster_index << CF_CLUSTER_SHIFT;
  46    cflags |= parallel ? CF_PARALLEL : 0;
  47    cflags |= icount_enabled() ? CF_USE_ICOUNT : 0;
  48    cpu->tcg_cflags = cflags;
  49}
  50
  51void tcg_cpus_destroy(CPUState *cpu)
  52{
  53    cpu_thread_signal_destroyed(cpu);
  54}
  55
  56int tcg_cpus_exec(CPUState *cpu)
  57{
  58    int ret;
  59#ifdef CONFIG_PROFILER
  60    int64_t ti;
  61#endif
  62    assert(tcg_enabled());
  63#ifdef CONFIG_PROFILER
  64    ti = profile_getclock();
  65#endif
  66    cpu_exec_start(cpu);
  67    ret = cpu_exec(cpu);
  68    cpu_exec_end(cpu);
  69#ifdef CONFIG_PROFILER
  70    qatomic_set(&tcg_ctx->prof.cpu_exec_time,
  71                tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
  72#endif
  73    return ret;
  74}
  75
  76/* mask must never be zero, except for A20 change call */
  77void tcg_handle_interrupt(CPUState *cpu, int mask)
  78{
  79    g_assert(qemu_mutex_iothread_locked());
  80
  81    cpu->interrupt_request |= mask;
  82
  83    /*
  84     * If called from iothread context, wake the target cpu in
  85     * case its halted.
  86     */
  87    if (!qemu_cpu_is_self(cpu)) {
  88        qemu_cpu_kick(cpu);
  89    } else {
  90        qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
  91    }
  92}
  93
  94static void tcg_accel_ops_init(AccelOpsClass *ops)
  95{
  96    if (qemu_tcg_mttcg_enabled()) {
  97        ops->create_vcpu_thread = mttcg_start_vcpu_thread;
  98        ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
  99        ops->handle_interrupt = tcg_handle_interrupt;
 100    } else if (icount_enabled()) {
 101        ops->create_vcpu_thread = rr_start_vcpu_thread;
 102        ops->kick_vcpu_thread = rr_kick_vcpu_thread;
 103        ops->handle_interrupt = icount_handle_interrupt;
 104        ops->get_virtual_clock = icount_get;
 105        ops->get_elapsed_ticks = icount_get;
 106    } else {
 107        ops->create_vcpu_thread = rr_start_vcpu_thread;
 108        ops->kick_vcpu_thread = rr_kick_vcpu_thread;
 109        ops->handle_interrupt = tcg_handle_interrupt;
 110    }
 111}
 112
 113static void tcg_accel_ops_class_init(ObjectClass *oc, void *data)
 114{
 115    AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
 116
 117    ops->ops_init = tcg_accel_ops_init;
 118}
 119
 120static const TypeInfo tcg_accel_ops_type = {
 121    .name = ACCEL_OPS_NAME("tcg"),
 122
 123    .parent = TYPE_ACCEL_OPS,
 124    .class_init = tcg_accel_ops_class_init,
 125    .abstract = true,
 126};
 127module_obj(ACCEL_OPS_NAME("tcg"));
 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