xref: /qemu/target/i386/hvf/x86hvf.c (revision f585195ec07fd2a6af5fc04c92caf1b71f34e16c)
1c97d6d2cSSergio Andres Gomez Del Real /*
2c97d6d2cSSergio Andres Gomez Del Real  * Copyright (c) 2003-2008 Fabrice Bellard
3c97d6d2cSSergio Andres Gomez Del Real  * Copyright (C) 2016 Veertu Inc,
4c97d6d2cSSergio Andres Gomez Del Real  * Copyright (C) 2017 Google Inc,
5c97d6d2cSSergio Andres Gomez Del Real  *
6c97d6d2cSSergio Andres Gomez Del Real  * This program is free software; you can redistribute it and/or
7996feed4SSergio Andres Gomez Del Real  * modify it under the terms of the GNU Lesser General Public
8996feed4SSergio Andres Gomez Del Real  * License as published by the Free Software Foundation; either
9996feed4SSergio Andres Gomez Del Real  * version 2 of the License, or (at your option) any later version.
10c97d6d2cSSergio Andres Gomez Del Real  *
11c97d6d2cSSergio Andres Gomez Del Real  * This program is distributed in the hope that it will be useful,
12c97d6d2cSSergio Andres Gomez Del Real  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13996feed4SSergio Andres Gomez Del Real  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14996feed4SSergio Andres Gomez Del Real  * Lesser General Public License for more details.
15c97d6d2cSSergio Andres Gomez Del Real  *
16996feed4SSergio Andres Gomez Del Real  * You should have received a copy of the GNU Lesser General Public
17996feed4SSergio Andres Gomez Del Real  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18c97d6d2cSSergio Andres Gomez Del Real  */
19c97d6d2cSSergio Andres Gomez Del Real 
20c97d6d2cSSergio Andres Gomez Del Real #include "qemu/osdep.h"
21c97d6d2cSSergio Andres Gomez Del Real #include "qemu-common.h"
22c97d6d2cSSergio Andres Gomez Del Real 
23c97d6d2cSSergio Andres Gomez Del Real #include "x86hvf.h"
24c97d6d2cSSergio Andres Gomez Del Real #include "vmx.h"
25c97d6d2cSSergio Andres Gomez Del Real #include "vmcs.h"
26c97d6d2cSSergio Andres Gomez Del Real #include "cpu.h"
27c97d6d2cSSergio Andres Gomez Del Real #include "x86_descr.h"
28c97d6d2cSSergio Andres Gomez Del Real #include "x86_decode.h"
29c97d6d2cSSergio Andres Gomez Del Real 
30c97d6d2cSSergio Andres Gomez Del Real #include "hw/i386/apic_internal.h"
31c97d6d2cSSergio Andres Gomez Del Real 
32c97d6d2cSSergio Andres Gomez Del Real #include <stdio.h>
33c97d6d2cSSergio Andres Gomez Del Real #include <stdlib.h>
34c97d6d2cSSergio Andres Gomez Del Real #include <Hypervisor/hv.h>
35c97d6d2cSSergio Andres Gomez Del Real #include <Hypervisor/hv_vmx.h>
36c97d6d2cSSergio Andres Gomez Del Real #include <stdint.h>
37c97d6d2cSSergio Andres Gomez Del Real 
38c97d6d2cSSergio Andres Gomez Del Real void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg,
39c97d6d2cSSergio Andres Gomez Del Real                      SegmentCache *qseg, bool is_tr)
40c97d6d2cSSergio Andres Gomez Del Real {
41c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->sel = qseg->selector;
42c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->base = qseg->base;
43c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->limit = qseg->limit;
44c97d6d2cSSergio Andres Gomez Del Real 
45c97d6d2cSSergio Andres Gomez Del Real     if (!qseg->selector && !x86_is_real(cpu) && !is_tr) {
46c97d6d2cSSergio Andres Gomez Del Real         /* the TR register is usable after processor reset despite
47c97d6d2cSSergio Andres Gomez Del Real          * having a null selector */
48c97d6d2cSSergio Andres Gomez Del Real         vmx_seg->ar = 1 << 16;
49c97d6d2cSSergio Andres Gomez Del Real         return;
50c97d6d2cSSergio Andres Gomez Del Real     }
51c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar = (qseg->flags >> DESC_TYPE_SHIFT) & 0xf;
52c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar |= ((qseg->flags >> DESC_G_SHIFT) & 1) << 15;
53c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar |= ((qseg->flags >> DESC_B_SHIFT) & 1) << 14;
54c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar |= ((qseg->flags >> DESC_L_SHIFT) & 1) << 13;
55c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar |= ((qseg->flags >> DESC_AVL_SHIFT) & 1) << 12;
56c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar |= ((qseg->flags >> DESC_P_SHIFT) & 1) << 7;
57c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar |= ((qseg->flags >> DESC_DPL_SHIFT) & 3) << 5;
58c97d6d2cSSergio Andres Gomez Del Real     vmx_seg->ar |= ((qseg->flags >> DESC_S_SHIFT) & 1) << 4;
59c97d6d2cSSergio Andres Gomez Del Real }
60c97d6d2cSSergio Andres Gomez Del Real 
61c97d6d2cSSergio Andres Gomez Del Real void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg)
62c97d6d2cSSergio Andres Gomez Del Real {
63c97d6d2cSSergio Andres Gomez Del Real     qseg->limit = vmx_seg->limit;
64c97d6d2cSSergio Andres Gomez Del Real     qseg->base = vmx_seg->base;
65c97d6d2cSSergio Andres Gomez Del Real     qseg->selector = vmx_seg->sel;
66c97d6d2cSSergio Andres Gomez Del Real     qseg->flags = ((vmx_seg->ar & 0xf) << DESC_TYPE_SHIFT) |
67c97d6d2cSSergio Andres Gomez Del Real                   (((vmx_seg->ar >> 4) & 1) << DESC_S_SHIFT) |
68c97d6d2cSSergio Andres Gomez Del Real                   (((vmx_seg->ar >> 5) & 3) << DESC_DPL_SHIFT) |
69c97d6d2cSSergio Andres Gomez Del Real                   (((vmx_seg->ar >> 7) & 1) << DESC_P_SHIFT) |
70c97d6d2cSSergio Andres Gomez Del Real                   (((vmx_seg->ar >> 12) & 1) << DESC_AVL_SHIFT) |
71c97d6d2cSSergio Andres Gomez Del Real                   (((vmx_seg->ar >> 13) & 1) << DESC_L_SHIFT) |
72c97d6d2cSSergio Andres Gomez Del Real                   (((vmx_seg->ar >> 14) & 1) << DESC_B_SHIFT) |
73c97d6d2cSSergio Andres Gomez Del Real                   (((vmx_seg->ar >> 15) & 1) << DESC_G_SHIFT);
74c97d6d2cSSergio Andres Gomez Del Real }
75c97d6d2cSSergio Andres Gomez Del Real 
76c97d6d2cSSergio Andres Gomez Del Real void hvf_put_xsave(CPUState *cpu_state)
77c97d6d2cSSergio Andres Gomez Del Real {
78c97d6d2cSSergio Andres Gomez Del Real 
79*f585195eSSergio Andres Gomez Del Real     struct X86XSaveArea *xsave;
80c97d6d2cSSergio Andres Gomez Del Real 
81c97d6d2cSSergio Andres Gomez Del Real     xsave = X86_CPU(cpu_state)->env.kvm_xsave_buf;
82c97d6d2cSSergio Andres Gomez Del Real 
83*f585195eSSergio Andres Gomez Del Real     x86_cpu_xsave_all_areas(X86_CPU(cpu_state), xsave);
84c97d6d2cSSergio Andres Gomez Del Real 
85*f585195eSSergio Andres Gomez Del Real     if (hv_vcpu_write_fpstate(cpu_state->hvf_fd, (void*)xsave, 4096)) {
86c97d6d2cSSergio Andres Gomez Del Real         abort();
87c97d6d2cSSergio Andres Gomez Del Real     }
88c97d6d2cSSergio Andres Gomez Del Real }
89c97d6d2cSSergio Andres Gomez Del Real 
90c97d6d2cSSergio Andres Gomez Del Real void hvf_put_segments(CPUState *cpu_state)
91c97d6d2cSSergio Andres Gomez Del Real {
92c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &X86_CPU(cpu_state)->env;
93c97d6d2cSSergio Andres Gomez Del Real     struct vmx_segment seg;
94c97d6d2cSSergio Andres Gomez Del Real 
95c97d6d2cSSergio Andres Gomez Del Real     wvmcs(cpu_state->hvf_fd, VMCS_GUEST_IDTR_LIMIT, env->idt.limit);
96c97d6d2cSSergio Andres Gomez Del Real     wvmcs(cpu_state->hvf_fd, VMCS_GUEST_IDTR_BASE, env->idt.base);
97c97d6d2cSSergio Andres Gomez Del Real 
98c97d6d2cSSergio Andres Gomez Del Real     wvmcs(cpu_state->hvf_fd, VMCS_GUEST_GDTR_LIMIT, env->gdt.limit);
99c97d6d2cSSergio Andres Gomez Del Real     wvmcs(cpu_state->hvf_fd, VMCS_GUEST_GDTR_BASE, env->gdt.base);
100c97d6d2cSSergio Andres Gomez Del Real 
101c97d6d2cSSergio Andres Gomez Del Real     /* wvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR2, env->cr[2]); */
102c97d6d2cSSergio Andres Gomez Del Real     wvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR3, env->cr[3]);
103c97d6d2cSSergio Andres Gomez Del Real     vmx_update_tpr(cpu_state);
104c97d6d2cSSergio Andres Gomez Del Real     wvmcs(cpu_state->hvf_fd, VMCS_GUEST_IA32_EFER, env->efer);
105c97d6d2cSSergio Andres Gomez Del Real 
106c97d6d2cSSergio Andres Gomez Del Real     macvm_set_cr4(cpu_state->hvf_fd, env->cr[4]);
107c97d6d2cSSergio Andres Gomez Del Real     macvm_set_cr0(cpu_state->hvf_fd, env->cr[0]);
108c97d6d2cSSergio Andres Gomez Del Real 
109c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->segs[R_CS], false);
110c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_CS);
111c97d6d2cSSergio Andres Gomez Del Real 
112c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->segs[R_DS], false);
113c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_DS);
114c97d6d2cSSergio Andres Gomez Del Real 
115c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->segs[R_ES], false);
116c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_ES);
117c97d6d2cSSergio Andres Gomez Del Real 
118c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->segs[R_SS], false);
119c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_SS);
120c97d6d2cSSergio Andres Gomez Del Real 
121c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->segs[R_FS], false);
122c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_FS);
123c97d6d2cSSergio Andres Gomez Del Real 
124c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->segs[R_GS], false);
125c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_GS);
126c97d6d2cSSergio Andres Gomez Del Real 
127c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->tr, true);
128c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_TR);
129c97d6d2cSSergio Andres Gomez Del Real 
130c97d6d2cSSergio Andres Gomez Del Real     hvf_set_segment(cpu_state, &seg, &env->ldt, false);
131c97d6d2cSSergio Andres Gomez Del Real     vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_LDTR);
132c97d6d2cSSergio Andres Gomez Del Real 
133c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_flush(cpu_state->hvf_fd);
134c97d6d2cSSergio Andres Gomez Del Real }
135c97d6d2cSSergio Andres Gomez Del Real 
136c97d6d2cSSergio Andres Gomez Del Real void hvf_put_msrs(CPUState *cpu_state)
137c97d6d2cSSergio Andres Gomez Del Real {
138c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &X86_CPU(cpu_state)->env;
139c97d6d2cSSergio Andres Gomez Del Real 
140c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_CS,
141c97d6d2cSSergio Andres Gomez Del Real                       env->sysenter_cs);
142c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_ESP,
143c97d6d2cSSergio Andres Gomez Del Real                       env->sysenter_esp);
144c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_EIP,
145c97d6d2cSSergio Andres Gomez Del Real                       env->sysenter_eip);
146c97d6d2cSSergio Andres Gomez Del Real 
147c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_STAR, env->star);
148c97d6d2cSSergio Andres Gomez Del Real 
149c97d6d2cSSergio Andres Gomez Del Real #ifdef TARGET_X86_64
150c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_CSTAR, env->cstar);
151c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_KERNELGSBASE, env->kernelgsbase);
152c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_FMASK, env->fmask);
153c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_LSTAR, env->lstar);
154c97d6d2cSSergio Andres Gomez Del Real #endif
155c97d6d2cSSergio Andres Gomez Del Real 
156c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_GSBASE, env->segs[R_GS].base);
157c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_FSBASE, env->segs[R_FS].base);
158c97d6d2cSSergio Andres Gomez Del Real 
159c97d6d2cSSergio Andres Gomez Del Real     /* if (!osx_is_sierra())
160c97d6d2cSSergio Andres Gomez Del Real          wvmcs(cpu_state->hvf_fd, VMCS_TSC_OFFSET, env->tsc - rdtscp());*/
161c97d6d2cSSergio Andres Gomez Del Real     hv_vm_sync_tsc(env->tsc);
162c97d6d2cSSergio Andres Gomez Del Real }
163c97d6d2cSSergio Andres Gomez Del Real 
164c97d6d2cSSergio Andres Gomez Del Real 
165c97d6d2cSSergio Andres Gomez Del Real void hvf_get_xsave(CPUState *cpu_state)
166c97d6d2cSSergio Andres Gomez Del Real {
167*f585195eSSergio Andres Gomez Del Real     struct X86XSaveArea *xsave;
168c97d6d2cSSergio Andres Gomez Del Real 
169c97d6d2cSSergio Andres Gomez Del Real     xsave = X86_CPU(cpu_state)->env.kvm_xsave_buf;
170c97d6d2cSSergio Andres Gomez Del Real 
171*f585195eSSergio Andres Gomez Del Real     if (hv_vcpu_read_fpstate(cpu_state->hvf_fd, (void*)xsave, 4096)) {
172c97d6d2cSSergio Andres Gomez Del Real         abort();
173c97d6d2cSSergio Andres Gomez Del Real     }
174c97d6d2cSSergio Andres Gomez Del Real 
175*f585195eSSergio Andres Gomez Del Real     x86_cpu_xrstor_all_areas(X86_CPU(cpu_state), xsave);
176c97d6d2cSSergio Andres Gomez Del Real }
177c97d6d2cSSergio Andres Gomez Del Real 
178c97d6d2cSSergio Andres Gomez Del Real void hvf_get_segments(CPUState *cpu_state)
179c97d6d2cSSergio Andres Gomez Del Real {
180c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &X86_CPU(cpu_state)->env;
181c97d6d2cSSergio Andres Gomez Del Real 
182c97d6d2cSSergio Andres Gomez Del Real     struct vmx_segment seg;
183c97d6d2cSSergio Andres Gomez Del Real 
184c97d6d2cSSergio Andres Gomez Del Real     env->interrupt_injected = -1;
185c97d6d2cSSergio Andres Gomez Del Real 
186c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_CS);
187c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->segs[R_CS], &seg);
188c97d6d2cSSergio Andres Gomez Del Real 
189c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_DS);
190c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->segs[R_DS], &seg);
191c97d6d2cSSergio Andres Gomez Del Real 
192c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_ES);
193c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->segs[R_ES], &seg);
194c97d6d2cSSergio Andres Gomez Del Real 
195c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_FS);
196c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->segs[R_FS], &seg);
197c97d6d2cSSergio Andres Gomez Del Real 
198c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_GS);
199c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->segs[R_GS], &seg);
200c97d6d2cSSergio Andres Gomez Del Real 
201c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_SS);
202c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->segs[R_SS], &seg);
203c97d6d2cSSergio Andres Gomez Del Real 
204c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_TR);
205c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->tr, &seg);
206c97d6d2cSSergio Andres Gomez Del Real 
207c97d6d2cSSergio Andres Gomez Del Real     vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_LDTR);
208c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segment(&env->ldt, &seg);
209c97d6d2cSSergio Andres Gomez Del Real 
210c97d6d2cSSergio Andres Gomez Del Real     env->idt.limit = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_IDTR_LIMIT);
211c97d6d2cSSergio Andres Gomez Del Real     env->idt.base = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_IDTR_BASE);
212c97d6d2cSSergio Andres Gomez Del Real     env->gdt.limit = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_GDTR_LIMIT);
213c97d6d2cSSergio Andres Gomez Del Real     env->gdt.base = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_GDTR_BASE);
214c97d6d2cSSergio Andres Gomez Del Real 
215c97d6d2cSSergio Andres Gomez Del Real     env->cr[0] = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR0);
216c97d6d2cSSergio Andres Gomez Del Real     env->cr[2] = 0;
217c97d6d2cSSergio Andres Gomez Del Real     env->cr[3] = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR3);
218c97d6d2cSSergio Andres Gomez Del Real     env->cr[4] = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR4);
219c97d6d2cSSergio Andres Gomez Del Real 
220c97d6d2cSSergio Andres Gomez Del Real     env->efer = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_IA32_EFER);
221c97d6d2cSSergio Andres Gomez Del Real }
222c97d6d2cSSergio Andres Gomez Del Real 
223c97d6d2cSSergio Andres Gomez Del Real void hvf_get_msrs(CPUState *cpu_state)
224c97d6d2cSSergio Andres Gomez Del Real {
225c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &X86_CPU(cpu_state)->env;
226c97d6d2cSSergio Andres Gomez Del Real     uint64_t tmp;
227c97d6d2cSSergio Andres Gomez Del Real 
228c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_CS, &tmp);
229c97d6d2cSSergio Andres Gomez Del Real     env->sysenter_cs = tmp;
230c97d6d2cSSergio Andres Gomez Del Real 
231c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_ESP, &tmp);
232c97d6d2cSSergio Andres Gomez Del Real     env->sysenter_esp = tmp;
233c97d6d2cSSergio Andres Gomez Del Real 
234c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_EIP, &tmp);
235c97d6d2cSSergio Andres Gomez Del Real     env->sysenter_eip = tmp;
236c97d6d2cSSergio Andres Gomez Del Real 
237c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_STAR, &env->star);
238c97d6d2cSSergio Andres Gomez Del Real 
239c97d6d2cSSergio Andres Gomez Del Real #ifdef TARGET_X86_64
240c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_CSTAR, &env->cstar);
241c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_KERNELGSBASE, &env->kernelgsbase);
242c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_FMASK, &env->fmask);
243c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_LSTAR, &env->lstar);
244c97d6d2cSSergio Andres Gomez Del Real #endif
245c97d6d2cSSergio Andres Gomez Del Real 
246c97d6d2cSSergio Andres Gomez Del Real     hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_IA32_APICBASE, &tmp);
247c97d6d2cSSergio Andres Gomez Del Real 
248c97d6d2cSSergio Andres Gomez Del Real     env->tsc = rdtscp() + rvmcs(cpu_state->hvf_fd, VMCS_TSC_OFFSET);
249c97d6d2cSSergio Andres Gomez Del Real }
250c97d6d2cSSergio Andres Gomez Del Real 
251c97d6d2cSSergio Andres Gomez Del Real int hvf_put_registers(CPUState *cpu_state)
252c97d6d2cSSergio Andres Gomez Del Real {
253c97d6d2cSSergio Andres Gomez Del Real     X86CPU *x86cpu = X86_CPU(cpu_state);
254c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &x86cpu->env;
255c97d6d2cSSergio Andres Gomez Del Real 
256c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RAX, env->regs[R_EAX]);
257c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RBX, env->regs[R_EBX]);
258c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RCX, env->regs[R_ECX]);
259c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RDX, env->regs[R_EDX]);
260c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RBP, env->regs[R_EBP]);
261c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RSP, env->regs[R_ESP]);
262c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RSI, env->regs[R_ESI]);
263c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RDI, env->regs[R_EDI]);
264c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R8, env->regs[8]);
265c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R9, env->regs[9]);
266c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R10, env->regs[10]);
267c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R11, env->regs[11]);
268c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R12, env->regs[12]);
269c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R13, env->regs[13]);
270c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R14, env->regs[14]);
271c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_R15, env->regs[15]);
272c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RFLAGS, env->eflags);
273c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_RIP, env->eip);
274c97d6d2cSSergio Andres Gomez Del Real 
275c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_XCR0, env->xcr0);
276c97d6d2cSSergio Andres Gomez Del Real 
277c97d6d2cSSergio Andres Gomez Del Real     hvf_put_xsave(cpu_state);
278c97d6d2cSSergio Andres Gomez Del Real 
279c97d6d2cSSergio Andres Gomez Del Real     hvf_put_segments(cpu_state);
280c97d6d2cSSergio Andres Gomez Del Real 
281c97d6d2cSSergio Andres Gomez Del Real     hvf_put_msrs(cpu_state);
282c97d6d2cSSergio Andres Gomez Del Real 
283c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR0, env->dr[0]);
284c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR1, env->dr[1]);
285c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR2, env->dr[2]);
286c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR3, env->dr[3]);
287c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR4, env->dr[4]);
288c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR5, env->dr[5]);
289c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR6, env->dr[6]);
290c97d6d2cSSergio Andres Gomez Del Real     wreg(cpu_state->hvf_fd, HV_X86_DR7, env->dr[7]);
291c97d6d2cSSergio Andres Gomez Del Real 
292c97d6d2cSSergio Andres Gomez Del Real     return 0;
293c97d6d2cSSergio Andres Gomez Del Real }
294c97d6d2cSSergio Andres Gomez Del Real 
295c97d6d2cSSergio Andres Gomez Del Real int hvf_get_registers(CPUState *cpu_state)
296c97d6d2cSSergio Andres Gomez Del Real {
297c97d6d2cSSergio Andres Gomez Del Real     X86CPU *x86cpu = X86_CPU(cpu_state);
298c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &x86cpu->env;
299c97d6d2cSSergio Andres Gomez Del Real 
300c97d6d2cSSergio Andres Gomez Del Real 
301c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_EAX] = rreg(cpu_state->hvf_fd, HV_X86_RAX);
302c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_EBX] = rreg(cpu_state->hvf_fd, HV_X86_RBX);
303c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_ECX] = rreg(cpu_state->hvf_fd, HV_X86_RCX);
304c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_EDX] = rreg(cpu_state->hvf_fd, HV_X86_RDX);
305c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_EBP] = rreg(cpu_state->hvf_fd, HV_X86_RBP);
306c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_ESP] = rreg(cpu_state->hvf_fd, HV_X86_RSP);
307c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_ESI] = rreg(cpu_state->hvf_fd, HV_X86_RSI);
308c97d6d2cSSergio Andres Gomez Del Real     env->regs[R_EDI] = rreg(cpu_state->hvf_fd, HV_X86_RDI);
309c97d6d2cSSergio Andres Gomez Del Real     env->regs[8] = rreg(cpu_state->hvf_fd, HV_X86_R8);
310c97d6d2cSSergio Andres Gomez Del Real     env->regs[9] = rreg(cpu_state->hvf_fd, HV_X86_R9);
311c97d6d2cSSergio Andres Gomez Del Real     env->regs[10] = rreg(cpu_state->hvf_fd, HV_X86_R10);
312c97d6d2cSSergio Andres Gomez Del Real     env->regs[11] = rreg(cpu_state->hvf_fd, HV_X86_R11);
313c97d6d2cSSergio Andres Gomez Del Real     env->regs[12] = rreg(cpu_state->hvf_fd, HV_X86_R12);
314c97d6d2cSSergio Andres Gomez Del Real     env->regs[13] = rreg(cpu_state->hvf_fd, HV_X86_R13);
315c97d6d2cSSergio Andres Gomez Del Real     env->regs[14] = rreg(cpu_state->hvf_fd, HV_X86_R14);
316c97d6d2cSSergio Andres Gomez Del Real     env->regs[15] = rreg(cpu_state->hvf_fd, HV_X86_R15);
317c97d6d2cSSergio Andres Gomez Del Real 
318c97d6d2cSSergio Andres Gomez Del Real     env->eflags = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS);
319c97d6d2cSSergio Andres Gomez Del Real     env->eip = rreg(cpu_state->hvf_fd, HV_X86_RIP);
320c97d6d2cSSergio Andres Gomez Del Real 
321c97d6d2cSSergio Andres Gomez Del Real     hvf_get_xsave(cpu_state);
322c97d6d2cSSergio Andres Gomez Del Real     env->xcr0 = rreg(cpu_state->hvf_fd, HV_X86_XCR0);
323c97d6d2cSSergio Andres Gomez Del Real 
324c97d6d2cSSergio Andres Gomez Del Real     hvf_get_segments(cpu_state);
325c97d6d2cSSergio Andres Gomez Del Real     hvf_get_msrs(cpu_state);
326c97d6d2cSSergio Andres Gomez Del Real 
327c97d6d2cSSergio Andres Gomez Del Real     env->dr[0] = rreg(cpu_state->hvf_fd, HV_X86_DR0);
328c97d6d2cSSergio Andres Gomez Del Real     env->dr[1] = rreg(cpu_state->hvf_fd, HV_X86_DR1);
329c97d6d2cSSergio Andres Gomez Del Real     env->dr[2] = rreg(cpu_state->hvf_fd, HV_X86_DR2);
330c97d6d2cSSergio Andres Gomez Del Real     env->dr[3] = rreg(cpu_state->hvf_fd, HV_X86_DR3);
331c97d6d2cSSergio Andres Gomez Del Real     env->dr[4] = rreg(cpu_state->hvf_fd, HV_X86_DR4);
332c97d6d2cSSergio Andres Gomez Del Real     env->dr[5] = rreg(cpu_state->hvf_fd, HV_X86_DR5);
333c97d6d2cSSergio Andres Gomez Del Real     env->dr[6] = rreg(cpu_state->hvf_fd, HV_X86_DR6);
334c97d6d2cSSergio Andres Gomez Del Real     env->dr[7] = rreg(cpu_state->hvf_fd, HV_X86_DR7);
335c97d6d2cSSergio Andres Gomez Del Real 
336c97d6d2cSSergio Andres Gomez Del Real     return 0;
337c97d6d2cSSergio Andres Gomez Del Real }
338c97d6d2cSSergio Andres Gomez Del Real 
339c97d6d2cSSergio Andres Gomez Del Real static void vmx_set_int_window_exiting(CPUState *cpu)
340c97d6d2cSSergio Andres Gomez Del Real {
341c97d6d2cSSergio Andres Gomez Del Real      uint64_t val;
342c97d6d2cSSergio Andres Gomez Del Real      val = rvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS);
343c97d6d2cSSergio Andres Gomez Del Real      wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val |
344c97d6d2cSSergio Andres Gomez Del Real              VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING);
345c97d6d2cSSergio Andres Gomez Del Real }
346c97d6d2cSSergio Andres Gomez Del Real 
347c97d6d2cSSergio Andres Gomez Del Real void vmx_clear_int_window_exiting(CPUState *cpu)
348c97d6d2cSSergio Andres Gomez Del Real {
349c97d6d2cSSergio Andres Gomez Del Real      uint64_t val;
350c97d6d2cSSergio Andres Gomez Del Real      val = rvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS);
351c97d6d2cSSergio Andres Gomez Del Real      wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val &
352c97d6d2cSSergio Andres Gomez Del Real              ~VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING);
353c97d6d2cSSergio Andres Gomez Del Real }
354c97d6d2cSSergio Andres Gomez Del Real 
355c97d6d2cSSergio Andres Gomez Del Real #define NMI_VEC 2
356c97d6d2cSSergio Andres Gomez Del Real 
357c97d6d2cSSergio Andres Gomez Del Real bool hvf_inject_interrupts(CPUState *cpu_state)
358c97d6d2cSSergio Andres Gomez Del Real {
359c97d6d2cSSergio Andres Gomez Del Real     int allow_nmi = !(rvmcs(cpu_state->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY) &
360c97d6d2cSSergio Andres Gomez Del Real                 VMCS_INTERRUPTIBILITY_NMI_BLOCKING);
361c97d6d2cSSergio Andres Gomez Del Real     X86CPU *x86cpu = X86_CPU(cpu_state);
362c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &x86cpu->env;
363c97d6d2cSSergio Andres Gomez Del Real 
364c97d6d2cSSergio Andres Gomez Del Real     uint64_t idt_info = rvmcs(cpu_state->hvf_fd, VMCS_IDT_VECTORING_INFO);
365c97d6d2cSSergio Andres Gomez Del Real     uint64_t info = 0;
366c97d6d2cSSergio Andres Gomez Del Real 
367c97d6d2cSSergio Andres Gomez Del Real     if (idt_info & VMCS_IDT_VEC_VALID) {
368c97d6d2cSSergio Andres Gomez Del Real         uint8_t vector = idt_info & 0xff;
369c97d6d2cSSergio Andres Gomez Del Real         uint64_t intr_type = idt_info & VMCS_INTR_T_MASK;
370c97d6d2cSSergio Andres Gomez Del Real         info = idt_info;
371c97d6d2cSSergio Andres Gomez Del Real 
372c97d6d2cSSergio Andres Gomez Del Real         uint64_t reason = rvmcs(cpu_state->hvf_fd, VMCS_EXIT_REASON);
373c97d6d2cSSergio Andres Gomez Del Real         if (intr_type == VMCS_INTR_T_NMI && reason != EXIT_REASON_TASK_SWITCH) {
374c97d6d2cSSergio Andres Gomez Del Real             allow_nmi = 1;
375c97d6d2cSSergio Andres Gomez Del Real             vmx_clear_nmi_blocking(cpu_state);
376c97d6d2cSSergio Andres Gomez Del Real         }
377c97d6d2cSSergio Andres Gomez Del Real 
378c97d6d2cSSergio Andres Gomez Del Real         if ((allow_nmi || intr_type != VMCS_INTR_T_NMI)) {
379c97d6d2cSSergio Andres Gomez Del Real             info &= ~(1 << 12); /* clear undefined bit */
380c97d6d2cSSergio Andres Gomez Del Real             if (intr_type == VMCS_INTR_T_SWINTR ||
381c97d6d2cSSergio Andres Gomez Del Real                 intr_type == VMCS_INTR_T_PRIV_SWEXCEPTION ||
382c97d6d2cSSergio Andres Gomez Del Real                 intr_type == VMCS_INTR_T_SWEXCEPTION) {
383c97d6d2cSSergio Andres Gomez Del Real                 uint64_t ins_len = rvmcs(cpu_state->hvf_fd,
384c97d6d2cSSergio Andres Gomez Del Real                                          VMCS_EXIT_INSTRUCTION_LENGTH);
385c97d6d2cSSergio Andres Gomez Del Real                 wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INST_LENGTH, ins_len);
386c97d6d2cSSergio Andres Gomez Del Real             }
387c97d6d2cSSergio Andres Gomez Del Real             if (vector == EXCEPTION_BP || vector == EXCEPTION_OF) {
388c97d6d2cSSergio Andres Gomez Del Real                 /*
389c97d6d2cSSergio Andres Gomez Del Real                  * VT-x requires #BP and #OF to be injected as software
390c97d6d2cSSergio Andres Gomez Del Real                  * exceptions.
391c97d6d2cSSergio Andres Gomez Del Real                  */
392c97d6d2cSSergio Andres Gomez Del Real                 info &= ~VMCS_INTR_T_MASK;
393c97d6d2cSSergio Andres Gomez Del Real                 info |= VMCS_INTR_T_SWEXCEPTION;
394c97d6d2cSSergio Andres Gomez Del Real                 uint64_t ins_len = rvmcs(cpu_state->hvf_fd,
395c97d6d2cSSergio Andres Gomez Del Real                                          VMCS_EXIT_INSTRUCTION_LENGTH);
396c97d6d2cSSergio Andres Gomez Del Real                 wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INST_LENGTH, ins_len);
397c97d6d2cSSergio Andres Gomez Del Real             }
398c97d6d2cSSergio Andres Gomez Del Real 
399c97d6d2cSSergio Andres Gomez Del Real             uint64_t err = 0;
400c97d6d2cSSergio Andres Gomez Del Real             if (idt_info & VMCS_INTR_DEL_ERRCODE) {
401c97d6d2cSSergio Andres Gomez Del Real                 err = rvmcs(cpu_state->hvf_fd, VMCS_IDT_VECTORING_ERROR);
402c97d6d2cSSergio Andres Gomez Del Real                 wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_EXCEPTION_ERROR, err);
403c97d6d2cSSergio Andres Gomez Del Real             }
404c97d6d2cSSergio Andres Gomez Del Real             /*printf("reinject  %lx err %d\n", info, err);*/
405c97d6d2cSSergio Andres Gomez Del Real             wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, info);
406c97d6d2cSSergio Andres Gomez Del Real         };
407c97d6d2cSSergio Andres Gomez Del Real     }
408c97d6d2cSSergio Andres Gomez Del Real 
409c97d6d2cSSergio Andres Gomez Del Real     if (cpu_state->interrupt_request & CPU_INTERRUPT_NMI) {
410c97d6d2cSSergio Andres Gomez Del Real         if (allow_nmi && !(info & VMCS_INTR_VALID)) {
411c97d6d2cSSergio Andres Gomez Del Real             cpu_state->interrupt_request &= ~CPU_INTERRUPT_NMI;
412c97d6d2cSSergio Andres Gomez Del Real             info = VMCS_INTR_VALID | VMCS_INTR_T_NMI | NMI_VEC;
413c97d6d2cSSergio Andres Gomez Del Real             wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, info);
414c97d6d2cSSergio Andres Gomez Del Real         } else {
415c97d6d2cSSergio Andres Gomez Del Real             vmx_set_nmi_window_exiting(cpu_state);
416c97d6d2cSSergio Andres Gomez Del Real         }
417c97d6d2cSSergio Andres Gomez Del Real     }
418c97d6d2cSSergio Andres Gomez Del Real 
419c97d6d2cSSergio Andres Gomez Del Real     if (env->hvf_emul->interruptable &&
420c97d6d2cSSergio Andres Gomez Del Real         (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) &&
421c97d6d2cSSergio Andres Gomez Del Real         (EFLAGS(env) & IF_MASK) && !(info & VMCS_INTR_VALID)) {
422c97d6d2cSSergio Andres Gomez Del Real         int line = cpu_get_pic_interrupt(&x86cpu->env);
423c97d6d2cSSergio Andres Gomez Del Real         cpu_state->interrupt_request &= ~CPU_INTERRUPT_HARD;
424c97d6d2cSSergio Andres Gomez Del Real         if (line >= 0) {
425c97d6d2cSSergio Andres Gomez Del Real             wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, line |
426c97d6d2cSSergio Andres Gomez Del Real                   VMCS_INTR_VALID | VMCS_INTR_T_HWINTR);
427c97d6d2cSSergio Andres Gomez Del Real         }
428c97d6d2cSSergio Andres Gomez Del Real     }
429c97d6d2cSSergio Andres Gomez Del Real     if (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) {
430c97d6d2cSSergio Andres Gomez Del Real         vmx_set_int_window_exiting(cpu_state);
431c97d6d2cSSergio Andres Gomez Del Real     }
432c97d6d2cSSergio Andres Gomez Del Real }
433c97d6d2cSSergio Andres Gomez Del Real 
434c97d6d2cSSergio Andres Gomez Del Real int hvf_process_events(CPUState *cpu_state)
435c97d6d2cSSergio Andres Gomez Del Real {
436c97d6d2cSSergio Andres Gomez Del Real     X86CPU *cpu = X86_CPU(cpu_state);
437c97d6d2cSSergio Andres Gomez Del Real     CPUX86State *env = &cpu->env;
438c97d6d2cSSergio Andres Gomez Del Real 
439c97d6d2cSSergio Andres Gomez Del Real     EFLAGS(env) = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS);
440c97d6d2cSSergio Andres Gomez Del Real 
441c97d6d2cSSergio Andres Gomez Del Real     if (cpu_state->interrupt_request & CPU_INTERRUPT_INIT) {
442c97d6d2cSSergio Andres Gomez Del Real         hvf_cpu_synchronize_state(cpu_state);
443c97d6d2cSSergio Andres Gomez Del Real         do_cpu_init(cpu);
444c97d6d2cSSergio Andres Gomez Del Real     }
445c97d6d2cSSergio Andres Gomez Del Real 
446c97d6d2cSSergio Andres Gomez Del Real     if (cpu_state->interrupt_request & CPU_INTERRUPT_POLL) {
447c97d6d2cSSergio Andres Gomez Del Real         cpu_state->interrupt_request &= ~CPU_INTERRUPT_POLL;
448c97d6d2cSSergio Andres Gomez Del Real         apic_poll_irq(cpu->apic_state);
449c97d6d2cSSergio Andres Gomez Del Real     }
450c97d6d2cSSergio Andres Gomez Del Real     if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) &&
451c97d6d2cSSergio Andres Gomez Del Real         (EFLAGS(env) & IF_MASK)) ||
452c97d6d2cSSergio Andres Gomez Del Real         (cpu_state->interrupt_request & CPU_INTERRUPT_NMI)) {
453c97d6d2cSSergio Andres Gomez Del Real         cpu_state->halted = 0;
454c97d6d2cSSergio Andres Gomez Del Real     }
455c97d6d2cSSergio Andres Gomez Del Real     if (cpu_state->interrupt_request & CPU_INTERRUPT_SIPI) {
456c97d6d2cSSergio Andres Gomez Del Real         hvf_cpu_synchronize_state(cpu_state);
457c97d6d2cSSergio Andres Gomez Del Real         do_cpu_sipi(cpu);
458c97d6d2cSSergio Andres Gomez Del Real     }
459c97d6d2cSSergio Andres Gomez Del Real     if (cpu_state->interrupt_request & CPU_INTERRUPT_TPR) {
460c97d6d2cSSergio Andres Gomez Del Real         cpu_state->interrupt_request &= ~CPU_INTERRUPT_TPR;
461c97d6d2cSSergio Andres Gomez Del Real         hvf_cpu_synchronize_state(cpu_state);
462c97d6d2cSSergio Andres Gomez Del Real         apic_handle_tpr_access_report(cpu->apic_state, env->eip,
463c97d6d2cSSergio Andres Gomez Del Real                                       env->tpr_access_type);
464c97d6d2cSSergio Andres Gomez Del Real     }
465c97d6d2cSSergio Andres Gomez Del Real     return cpu_state->halted;
466c97d6d2cSSergio Andres Gomez Del Real }
467