xref: /openbmc/qemu/target/i386/nvmm/nvmm-accel-ops.c (revision a4c2735f)
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