2 * QEMU KVM Hyper-V support
4 * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
7 * Andrey Smetanin <asmetanin@virtuozzo.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
15 #include "qemu/main-loop.h"
17 #include "hw/hyperv/hyperv.h"
18 #include "hyperv-proto.h"
20 int hyperv_x86_synic_add(X86CPU
*cpu
)
22 hyperv_synic_add(CPU(cpu
));
26 void hyperv_x86_synic_reset(X86CPU
*cpu
)
28 hyperv_synic_reset(CPU(cpu
));
31 void hyperv_x86_synic_update(X86CPU
*cpu
)
33 CPUX86State
*env
= &cpu
->env
;
34 bool enable
= env
->msr_hv_synic_control
& HV_SYNIC_ENABLE
;
35 hwaddr msg_page_addr
= (env
->msr_hv_synic_msg_page
& HV_SIMP_ENABLE
) ?
36 (env
->msr_hv_synic_msg_page
& TARGET_PAGE_MASK
) : 0;
37 hwaddr event_page_addr
= (env
->msr_hv_synic_evt_page
& HV_SIEFP_ENABLE
) ?
38 (env
->msr_hv_synic_evt_page
& TARGET_PAGE_MASK
) : 0;
39 hyperv_synic_update(CPU(cpu
), enable
, msg_page_addr
, event_page_addr
);
42 static void async_synic_update(CPUState
*cs
, run_on_cpu_data data
)
44 qemu_mutex_lock_iothread();
45 hyperv_x86_synic_update(X86_CPU(cs
));
46 qemu_mutex_unlock_iothread();
49 int kvm_hv_handle_exit(X86CPU
*cpu
, struct kvm_hyperv_exit
*exit
)
51 CPUX86State
*env
= &cpu
->env
;
54 case KVM_EXIT_HYPERV_SYNIC
:
55 if (!cpu
->hyperv_synic
) {
59 switch (exit
->u
.synic
.msr
) {
60 case HV_X64_MSR_SCONTROL
:
61 env
->msr_hv_synic_control
= exit
->u
.synic
.control
;
64 env
->msr_hv_synic_msg_page
= exit
->u
.synic
.msg_page
;
66 case HV_X64_MSR_SIEFP
:
67 env
->msr_hv_synic_evt_page
= exit
->u
.synic
.evt_page
;
74 * this will run in this cpu thread before it returns to KVM, but in a
75 * safe environment (i.e. when all cpus are quiescent) -- this is
76 * necessary because memory hierarchy is being changed
78 async_safe_run_on_cpu(CPU(cpu
), async_synic_update
, RUN_ON_CPU_NULL
);
81 case KVM_EXIT_HYPERV_HCALL
: {
82 uint16_t code
= exit
->u
.hcall
.input
& 0xffff;
83 bool fast
= exit
->u
.hcall
.input
& HV_HYPERCALL_FAST
;
84 uint64_t param
= exit
->u
.hcall
.params
[0];
88 exit
->u
.hcall
.result
= hyperv_hcall_post_message(param
, fast
);
91 exit
->u
.hcall
.result
= hyperv_hcall_signal_event(param
, fast
);
94 exit
->u
.hcall
.result
= HV_STATUS_INVALID_HYPERCALL_CODE
;