]> Git Repo - qemu.git/blame - target/i386/hyperv.c
util/cutils: New qemu_strtosz_metric()
[qemu.git] / target / i386 / hyperv.c
CommitLineData
50efe82c
AS
1/*
2 * QEMU KVM Hyper-V support
3 *
4 * Copyright (C) 2015 Andrey Smetanin <[email protected]>
5 *
6 * Authors:
7 * Andrey Smetanin <[email protected]>
8 *
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.
11 *
12 */
13
b6a0aa05 14#include "qemu/osdep.h"
d6da1e9e 15#include "qemu/main-loop.h"
50efe82c
AS
16#include "hyperv.h"
17#include "standard-headers/asm-x86/hyperv.h"
18
19int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
20{
21 CPUX86State *env = &cpu->env;
22
23 switch (exit->type) {
24 case KVM_EXIT_HYPERV_SYNIC:
25 if (!cpu->hyperv_synic) {
26 return -1;
27 }
28
29 /*
30 * For now just track changes in SynIC control and msg/evt pages msr's.
31 * When SynIC messaging/events processing will be added in future
32 * here we will do messages queues flushing and pages remapping.
33 */
34 switch (exit->u.synic.msr) {
35 case HV_X64_MSR_SCONTROL:
36 env->msr_hv_synic_control = exit->u.synic.control;
37 break;
38 case HV_X64_MSR_SIMP:
39 env->msr_hv_synic_msg_page = exit->u.synic.msg_page;
40 break;
41 case HV_X64_MSR_SIEFP:
42 env->msr_hv_synic_evt_page = exit->u.synic.evt_page;
43 break;
44 default:
45 return -1;
46 }
47 return 0;
1b0d9b05
AS
48 case KVM_EXIT_HYPERV_HCALL: {
49 uint16_t code;
50
51 code = exit->u.hcall.input & 0xffff;
52 switch (code) {
53 case HVCALL_POST_MESSAGE:
54 case HVCALL_SIGNAL_EVENT:
55 default:
56 exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE;
57 return 0;
58 }
59 }
50efe82c
AS
60 default:
61 return -1;
62 }
63}
64
65static void kvm_hv_sint_ack_handler(EventNotifier *notifier)
66{
67 HvSintRoute *sint_route = container_of(notifier, HvSintRoute,
68 sint_ack_notifier);
69 event_notifier_test_and_clear(notifier);
70 if (sint_route->sint_ack_clb) {
71 sint_route->sint_ack_clb(sint_route);
72 }
73}
74
75HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
76 HvSintAckClb sint_ack_clb)
77{
78 HvSintRoute *sint_route;
79 int r, gsi;
80
81 sint_route = g_malloc0(sizeof(*sint_route));
82 r = event_notifier_init(&sint_route->sint_set_notifier, false);
83 if (r) {
84 goto err;
85 }
86
87 r = event_notifier_init(&sint_route->sint_ack_notifier, false);
88 if (r) {
89 goto err_sint_set_notifier;
90 }
91
d6da1e9e 92 event_notifier_set_handler(&sint_route->sint_ack_notifier,
50efe82c
AS
93 kvm_hv_sint_ack_handler);
94
95 gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vcpu_id, sint);
96 if (gsi < 0) {
97 goto err_gsi;
98 }
99
100 r = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state,
101 &sint_route->sint_set_notifier,
102 &sint_route->sint_ack_notifier, gsi);
103 if (r) {
104 goto err_irqfd;
105 }
106 sint_route->gsi = gsi;
107 sint_route->sint_ack_clb = sint_ack_clb;
108 sint_route->vcpu_id = vcpu_id;
109 sint_route->sint = sint;
110
111 return sint_route;
112
113err_irqfd:
114 kvm_irqchip_release_virq(kvm_state, gsi);
115err_gsi:
d6da1e9e 116 event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL);
50efe82c
AS
117 event_notifier_cleanup(&sint_route->sint_ack_notifier);
118err_sint_set_notifier:
119 event_notifier_cleanup(&sint_route->sint_set_notifier);
120err:
121 g_free(sint_route);
122
123 return NULL;
124}
125
126void kvm_hv_sint_route_destroy(HvSintRoute *sint_route)
127{
128 kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state,
129 &sint_route->sint_set_notifier,
130 sint_route->gsi);
131 kvm_irqchip_release_virq(kvm_state, sint_route->gsi);
d6da1e9e 132 event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL);
50efe82c
AS
133 event_notifier_cleanup(&sint_route->sint_ack_notifier);
134 event_notifier_cleanup(&sint_route->sint_set_notifier);
135 g_free(sint_route);
136}
137
138int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route)
139{
140 return event_notifier_set(&sint_route->sint_set_notifier);
141}
This page took 0.173388 seconds and 4 git commands to generate.