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