2 * qemu/kvm integration, x86 specific code
4 * Copyright (C) 2006-2008 Qumranet Technologies
6 * Licensed under the terms of the GNU GPL version 2 or higher.
10 #include "config-host.h"
19 #include <sys/utsname.h>
20 #include <linux/kvm_para.h>
21 #include <sys/ioctl.h>
26 static int kvm_create_pit(kvm_context_t kvm
)
31 if (kvm_pit_in_kernel()) {
32 r
= kvm_vm_ioctl(kvm_state
, KVM_CREATE_PIT
);
34 fprintf(stderr
, "Create kernel PIC irqchip failed\n");
37 if (!kvm_pit_reinject
) {
38 r
= kvm_reinject_control(kvm_context
, 0);
41 "failure to disable in-kernel PIT reinjection\n");
50 #ifdef KVM_EXIT_TPR_ACCESS
52 static int kvm_handle_tpr_access(CPUState
*env
)
54 struct kvm_run
*run
= env
->kvm_run
;
55 kvm_tpr_access_report(env
,
57 run
->tpr_access
.is_write
);
62 int kvm_enable_vapic(CPUState
*env
, uint64_t vapic
)
64 struct kvm_vapic_addr va
= {
68 return kvm_vcpu_ioctl(env
, KVM_SET_VAPIC_ADDR
, &va
);
73 extern CPUState
*kvm_debug_cpu_requested
;
75 int kvm_arch_run(CPUState
*env
)
78 struct kvm_run
*run
= env
->kvm_run
;
80 switch (run
->exit_reason
) {
81 #ifdef KVM_EXIT_SET_TPR
82 case KVM_EXIT_SET_TPR
:
85 #ifdef KVM_EXIT_TPR_ACCESS
86 case KVM_EXIT_TPR_ACCESS
:
87 r
= kvm_handle_tpr_access(env
);
90 #ifdef KVM_CAP_SET_GUEST_DEBUG
92 DPRINTF("kvm_exit_debug\n");
93 r
= kvm_handle_debug(&run
->debug
.arch
);
94 if (r
== EXCP_DEBUG
) {
95 kvm_debug_cpu_requested
= env
;
99 #endif /* KVM_CAP_SET_GUEST_DEBUG */
108 #ifdef KVM_CAP_IRQCHIP
110 int kvm_get_lapic(CPUState
*env
, struct kvm_lapic_state
*s
)
114 if (!kvm_irqchip_in_kernel()) {
118 r
= kvm_vcpu_ioctl(env
, KVM_GET_LAPIC
, s
);
120 fprintf(stderr
, "KVM_GET_LAPIC failed\n");
125 int kvm_set_lapic(CPUState
*env
, struct kvm_lapic_state
*s
)
129 if (!kvm_irqchip_in_kernel()) {
133 r
= kvm_vcpu_ioctl(env
, KVM_SET_LAPIC
, s
);
136 fprintf(stderr
, "KVM_SET_LAPIC failed\n");
145 int kvm_get_pit(kvm_context_t kvm
, struct kvm_pit_state
*s
)
147 if (!kvm_pit_in_kernel()) {
150 return kvm_vm_ioctl(kvm_state
, KVM_GET_PIT
, s
);
153 int kvm_set_pit(kvm_context_t kvm
, struct kvm_pit_state
*s
)
155 if (!kvm_pit_in_kernel()) {
158 return kvm_vm_ioctl(kvm_state
, KVM_SET_PIT
, s
);
161 #ifdef KVM_CAP_PIT_STATE2
162 int kvm_get_pit2(kvm_context_t kvm
, struct kvm_pit_state2
*ps2
)
164 if (!kvm_pit_in_kernel()) {
167 return kvm_vm_ioctl(kvm_state
, KVM_GET_PIT2
, ps2
);
170 int kvm_set_pit2(kvm_context_t kvm
, struct kvm_pit_state2
*ps2
)
172 if (!kvm_pit_in_kernel()) {
175 return kvm_vm_ioctl(kvm_state
, KVM_SET_PIT2
, ps2
);
181 int kvm_has_pit_state2(kvm_context_t kvm
)
185 #ifdef KVM_CAP_PIT_STATE2
186 r
= kvm_check_extension(kvm_state
, KVM_CAP_PIT_STATE2
);
191 static void kvm_set_cr8(CPUState
*env
, uint64_t cr8
)
193 env
->kvm_run
->cr8
= cr8
;
197 static int kvm_enable_tpr_access_reporting(CPUState
*env
)
200 struct kvm_tpr_access_ctl tac
= { .enabled
= 1 };
202 r
= kvm_ioctl(env
->kvm_state
, KVM_CHECK_EXTENSION
, KVM_CAP_VAPIC
);
206 return kvm_vcpu_ioctl(env
, KVM_TPR_ACCESS_REPORTING
, &tac
);
210 static int _kvm_arch_init_vcpu(CPUState
*env
)
212 kvm_arch_reset_vcpu(env
);
214 #ifdef KVM_EXIT_TPR_ACCESS
215 kvm_enable_tpr_access_reporting(env
);
220 int kvm_arch_halt(CPUState
*env
)
223 if (!((env
->interrupt_request
& CPU_INTERRUPT_HARD
) &&
224 (env
->eflags
& IF_MASK
)) &&
225 !(env
->interrupt_request
& CPU_INTERRUPT_NMI
)) {
231 void kvm_arch_pre_run(CPUState
*env
, struct kvm_run
*run
)
233 if (!kvm_irqchip_in_kernel()) {
234 kvm_set_cr8(env
, cpu_get_apic_tpr(env
->apic_state
));
238 int kvm_arch_has_work(CPUState
*env
)
240 if (((env
->interrupt_request
& CPU_INTERRUPT_HARD
) &&
241 (env
->eflags
& IF_MASK
)) ||
242 (env
->interrupt_request
& CPU_INTERRUPT_NMI
)) {
248 int kvm_arch_try_push_interrupts(void *opaque
)
250 CPUState
*env
= cpu_single_env
;
253 if (kvm_is_ready_for_interrupt_injection(env
) &&
254 (env
->interrupt_request
& CPU_INTERRUPT_HARD
) &&
255 (env
->eflags
& IF_MASK
)) {
256 env
->interrupt_request
&= ~CPU_INTERRUPT_HARD
;
257 irq
= cpu_get_pic_interrupt(env
);
259 r
= kvm_inject_irq(env
, irq
);
261 printf("cpu %d fail inject %x\n", env
->cpu_index
, irq
);
266 return (env
->interrupt_request
& CPU_INTERRUPT_HARD
) != 0;
269 #ifdef KVM_CAP_USER_NMI
270 void kvm_arch_push_nmi(void)
272 CPUState
*env
= cpu_single_env
;
275 if (likely(!(env
->interrupt_request
& CPU_INTERRUPT_NMI
))) {
279 env
->interrupt_request
&= ~CPU_INTERRUPT_NMI
;
280 r
= kvm_inject_nmi(env
);
282 printf("cpu %d fail inject NMI\n", env
->cpu_index
);
285 #endif /* KVM_CAP_USER_NMI */
287 #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
288 void kvm_arch_do_ioperm(void *_data
)
290 struct ioperm_data
*data
= _data
;
291 ioperm(data
->start_port
, data
->num
, data
->turn_on
);
296 * Setup x86 specific IRQ routing
298 int kvm_arch_init_irq_routing(void)
302 if (kvm_irqchip
&& kvm_has_gsi_routing()) {
303 kvm_clear_gsi_routes();
304 for (i
= 0; i
< 8; ++i
) {
308 r
= kvm_add_irq_route(i
, KVM_IRQCHIP_PIC_MASTER
, i
);
313 for (i
= 8; i
< 16; ++i
) {
314 r
= kvm_add_irq_route(i
, KVM_IRQCHIP_PIC_SLAVE
, i
- 8);
319 for (i
= 0; i
< 24; ++i
) {
320 if (i
== 0 && irq0override
) {
321 r
= kvm_add_irq_route(i
, KVM_IRQCHIP_IOAPIC
, 2);
322 } else if (i
!= 2 || !irq0override
) {
323 r
= kvm_add_irq_route(i
, KVM_IRQCHIP_IOAPIC
, i
);
329 kvm_commit_irq_routes();
334 void kvm_arch_process_irqchip_events(CPUState
*env
)
336 if (env
->interrupt_request
& CPU_INTERRUPT_INIT
) {
337 kvm_cpu_synchronize_state(env
);
340 if (env
->interrupt_request
& CPU_INTERRUPT_SIPI
) {
341 kvm_cpu_synchronize_state(env
);
346 int kvm_arch_process_async_events(CPUState
*env
)
348 if (env
->interrupt_request
& CPU_INTERRUPT_MCE
) {
349 /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
350 assert(env
->mcg_cap
);
352 env
->interrupt_request
&= ~CPU_INTERRUPT_MCE
;
354 kvm_cpu_synchronize_state(env
);
356 if (env
->exception_injected
== EXCP08_DBLE
) {
357 /* this means triple fault */
358 qemu_system_reset_request();
359 env
->exit_request
= 1;
362 env
->exception_injected
= EXCP12_MCHK
;
363 env
->has_error_code
= 0;
366 if (kvm_irqchip_in_kernel() && env
->mp_state
== KVM_MP_STATE_HALTED
) {
367 env
->mp_state
= KVM_MP_STATE_RUNNABLE
;