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