xref: /openbmc/qemu/target/i386/whpx/whpx-accel-ops.c (revision b86f59c71552591a17dd21ba8f09654bfa19a31e)
1*b86f59c7SClaudio Fontana /*
2*b86f59c7SClaudio Fontana  * QEMU Windows Hypervisor Platform accelerator (WHPX)
3*b86f59c7SClaudio Fontana  *
4*b86f59c7SClaudio Fontana  * Copyright Microsoft Corp. 2017
5*b86f59c7SClaudio Fontana  *
6*b86f59c7SClaudio Fontana  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7*b86f59c7SClaudio Fontana  * See the COPYING file in the top-level directory.
8*b86f59c7SClaudio Fontana  *
9*b86f59c7SClaudio Fontana  */
10*b86f59c7SClaudio Fontana 
11*b86f59c7SClaudio Fontana #include "qemu/osdep.h"
12*b86f59c7SClaudio Fontana #include "sysemu/kvm_int.h"
13*b86f59c7SClaudio Fontana #include "qemu/main-loop.h"
14*b86f59c7SClaudio Fontana #include "sysemu/cpus.h"
15*b86f59c7SClaudio Fontana #include "qemu/guest-random.h"
16*b86f59c7SClaudio Fontana 
17*b86f59c7SClaudio Fontana #include "sysemu/whpx.h"
18*b86f59c7SClaudio Fontana #include "whpx-internal.h"
19*b86f59c7SClaudio Fontana #include "whpx-accel-ops.h"
20*b86f59c7SClaudio Fontana 
21*b86f59c7SClaudio Fontana static void *whpx_cpu_thread_fn(void *arg)
22*b86f59c7SClaudio Fontana {
23*b86f59c7SClaudio Fontana     CPUState *cpu = arg;
24*b86f59c7SClaudio Fontana     int r;
25*b86f59c7SClaudio Fontana 
26*b86f59c7SClaudio Fontana     rcu_register_thread();
27*b86f59c7SClaudio Fontana 
28*b86f59c7SClaudio Fontana     qemu_mutex_lock_iothread();
29*b86f59c7SClaudio Fontana     qemu_thread_get_self(cpu->thread);
30*b86f59c7SClaudio Fontana     cpu->thread_id = qemu_get_thread_id();
31*b86f59c7SClaudio Fontana     current_cpu = cpu;
32*b86f59c7SClaudio Fontana 
33*b86f59c7SClaudio Fontana     r = whpx_init_vcpu(cpu);
34*b86f59c7SClaudio Fontana     if (r < 0) {
35*b86f59c7SClaudio Fontana         fprintf(stderr, "whpx_init_vcpu failed: %s\n", strerror(-r));
36*b86f59c7SClaudio Fontana         exit(1);
37*b86f59c7SClaudio Fontana     }
38*b86f59c7SClaudio Fontana 
39*b86f59c7SClaudio Fontana     /* signal CPU creation */
40*b86f59c7SClaudio Fontana     cpu_thread_signal_created(cpu);
41*b86f59c7SClaudio Fontana     qemu_guest_random_seed_thread_part2(cpu->random_seed);
42*b86f59c7SClaudio Fontana 
43*b86f59c7SClaudio Fontana     do {
44*b86f59c7SClaudio Fontana         if (cpu_can_run(cpu)) {
45*b86f59c7SClaudio Fontana             r = whpx_vcpu_exec(cpu);
46*b86f59c7SClaudio Fontana             if (r == EXCP_DEBUG) {
47*b86f59c7SClaudio Fontana                 cpu_handle_guest_debug(cpu);
48*b86f59c7SClaudio Fontana             }
49*b86f59c7SClaudio Fontana         }
50*b86f59c7SClaudio Fontana         while (cpu_thread_is_idle(cpu)) {
51*b86f59c7SClaudio Fontana             qemu_cond_wait_iothread(cpu->halt_cond);
52*b86f59c7SClaudio Fontana         }
53*b86f59c7SClaudio Fontana         qemu_wait_io_event_common(cpu);
54*b86f59c7SClaudio Fontana     } while (!cpu->unplug || cpu_can_run(cpu));
55*b86f59c7SClaudio Fontana 
56*b86f59c7SClaudio Fontana     whpx_destroy_vcpu(cpu);
57*b86f59c7SClaudio Fontana     cpu_thread_signal_destroyed(cpu);
58*b86f59c7SClaudio Fontana     qemu_mutex_unlock_iothread();
59*b86f59c7SClaudio Fontana     rcu_unregister_thread();
60*b86f59c7SClaudio Fontana     return NULL;
61*b86f59c7SClaudio Fontana }
62*b86f59c7SClaudio Fontana 
63*b86f59c7SClaudio Fontana static void whpx_start_vcpu_thread(CPUState *cpu)
64*b86f59c7SClaudio Fontana {
65*b86f59c7SClaudio Fontana     char thread_name[VCPU_THREAD_NAME_SIZE];
66*b86f59c7SClaudio Fontana 
67*b86f59c7SClaudio Fontana     cpu->thread = g_malloc0(sizeof(QemuThread));
68*b86f59c7SClaudio Fontana     cpu->halt_cond = g_malloc0(sizeof(QemuCond));
69*b86f59c7SClaudio Fontana     qemu_cond_init(cpu->halt_cond);
70*b86f59c7SClaudio Fontana     snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/WHPX",
71*b86f59c7SClaudio Fontana              cpu->cpu_index);
72*b86f59c7SClaudio Fontana     qemu_thread_create(cpu->thread, thread_name, whpx_cpu_thread_fn,
73*b86f59c7SClaudio Fontana                        cpu, QEMU_THREAD_JOINABLE);
74*b86f59c7SClaudio Fontana #ifdef _WIN32
75*b86f59c7SClaudio Fontana     cpu->hThread = qemu_thread_get_handle(cpu->thread);
76*b86f59c7SClaudio Fontana #endif
77*b86f59c7SClaudio Fontana }
78*b86f59c7SClaudio Fontana 
79*b86f59c7SClaudio Fontana static void whpx_kick_vcpu_thread(CPUState *cpu)
80*b86f59c7SClaudio Fontana {
81*b86f59c7SClaudio Fontana     if (!qemu_cpu_is_self(cpu)) {
82*b86f59c7SClaudio Fontana         whpx_vcpu_kick(cpu);
83*b86f59c7SClaudio Fontana     }
84*b86f59c7SClaudio Fontana }
85*b86f59c7SClaudio Fontana 
86*b86f59c7SClaudio Fontana static void whpx_accel_ops_class_init(ObjectClass *oc, void *data)
87*b86f59c7SClaudio Fontana {
88*b86f59c7SClaudio Fontana     AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
89*b86f59c7SClaudio Fontana 
90*b86f59c7SClaudio Fontana     ops->create_vcpu_thread = whpx_start_vcpu_thread;
91*b86f59c7SClaudio Fontana     ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
92*b86f59c7SClaudio Fontana 
93*b86f59c7SClaudio Fontana     ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset;
94*b86f59c7SClaudio Fontana     ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
95*b86f59c7SClaudio Fontana     ops->synchronize_state = whpx_cpu_synchronize_state;
96*b86f59c7SClaudio Fontana     ops->synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm;
97*b86f59c7SClaudio Fontana }
98*b86f59c7SClaudio Fontana 
99*b86f59c7SClaudio Fontana static const TypeInfo whpx_accel_ops_type = {
100*b86f59c7SClaudio Fontana     .name = ACCEL_OPS_NAME("whpx"),
101*b86f59c7SClaudio Fontana 
102*b86f59c7SClaudio Fontana     .parent = TYPE_ACCEL_OPS,
103*b86f59c7SClaudio Fontana     .class_init = whpx_accel_ops_class_init,
104*b86f59c7SClaudio Fontana     .abstract = true,
105*b86f59c7SClaudio Fontana };
106*b86f59c7SClaudio Fontana 
107*b86f59c7SClaudio Fontana static void whpx_accel_ops_register_types(void)
108*b86f59c7SClaudio Fontana {
109*b86f59c7SClaudio Fontana     type_register_static(&whpx_accel_ops_type);
110*b86f59c7SClaudio Fontana }
111*b86f59c7SClaudio Fontana type_init(whpx_accel_ops_register_types);
112