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

nvmm-accel-ops.c (3022B)


      1/*
      2 * Copyright (c) 2018-2019 Maxime Villard, All rights reserved.
      3 *
      4 * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU.
      5 *
      6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
      7 * See the COPYING file in the top-level directory.
      8 */
      9
     10#include "qemu/osdep.h"
     11#include "sysemu/kvm_int.h"
     12#include "qemu/main-loop.h"
     13#include "sysemu/cpus.h"
     14#include "qemu/guest-random.h"
     15
     16#include "sysemu/nvmm.h"
     17#include "nvmm-accel-ops.h"
     18
     19static void *qemu_nvmm_cpu_thread_fn(void *arg)
     20{
     21    CPUState *cpu = arg;
     22    int r;
     23
     24    assert(nvmm_enabled());
     25
     26    rcu_register_thread();
     27
     28    qemu_mutex_lock_iothread();
     29    qemu_thread_get_self(cpu->thread);
     30    cpu->thread_id = qemu_get_thread_id();
     31    current_cpu = cpu;
     32
     33    r = nvmm_init_vcpu(cpu);
     34    if (r < 0) {
     35        fprintf(stderr, "nvmm_init_vcpu failed: %s\n", strerror(-r));
     36        exit(1);
     37    }
     38
     39    /* signal CPU creation */
     40    cpu_thread_signal_created(cpu);
     41    qemu_guest_random_seed_thread_part2(cpu->random_seed);
     42
     43    do {
     44        if (cpu_can_run(cpu)) {
     45            r = nvmm_vcpu_exec(cpu);
     46            if (r == EXCP_DEBUG) {
     47                cpu_handle_guest_debug(cpu);
     48            }
     49        }
     50        while (cpu_thread_is_idle(cpu)) {
     51            qemu_cond_wait_iothread(cpu->halt_cond);
     52        }
     53        qemu_wait_io_event_common(cpu);
     54    } while (!cpu->unplug || cpu_can_run(cpu));
     55
     56    nvmm_destroy_vcpu(cpu);
     57    cpu_thread_signal_destroyed(cpu);
     58    qemu_mutex_unlock_iothread();
     59    rcu_unregister_thread();
     60    return NULL;
     61}
     62
     63static void nvmm_start_vcpu_thread(CPUState *cpu)
     64{
     65    char thread_name[VCPU_THREAD_NAME_SIZE];
     66
     67    cpu->thread = g_malloc0(sizeof(QemuThread));
     68    cpu->halt_cond = g_malloc0(sizeof(QemuCond));
     69    qemu_cond_init(cpu->halt_cond);
     70    snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/NVMM",
     71             cpu->cpu_index);
     72    qemu_thread_create(cpu->thread, thread_name, qemu_nvmm_cpu_thread_fn,
     73                       cpu, QEMU_THREAD_JOINABLE);
     74}
     75
     76/*
     77 * Abort the call to run the virtual processor by another thread, and to
     78 * return the control to that thread.
     79 */
     80static void nvmm_kick_vcpu_thread(CPUState *cpu)
     81{
     82    cpu->exit_request = 1;
     83    cpus_kick_thread(cpu);
     84}
     85
     86static void nvmm_accel_ops_class_init(ObjectClass *oc, void *data)
     87{
     88    AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
     89
     90    ops->create_vcpu_thread = nvmm_start_vcpu_thread;
     91    ops->kick_vcpu_thread = nvmm_kick_vcpu_thread;
     92
     93    ops->synchronize_post_reset = nvmm_cpu_synchronize_post_reset;
     94    ops->synchronize_post_init = nvmm_cpu_synchronize_post_init;
     95    ops->synchronize_state = nvmm_cpu_synchronize_state;
     96    ops->synchronize_pre_loadvm = nvmm_cpu_synchronize_pre_loadvm;
     97}
     98
     99static const TypeInfo nvmm_accel_ops_type = {
    100    .name = ACCEL_OPS_NAME("nvmm"),
    101
    102    .parent = TYPE_ACCEL_OPS,
    103    .class_init = nvmm_accel_ops_class_init,
    104    .abstract = true,
    105};
    106
    107static void nvmm_accel_ops_register_types(void)
    108{
    109    type_register_static(&nvmm_accel_ops_type);
    110}
    111type_init(nvmm_accel_ops_register_types);