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