2 * Copyright (c) 2003-2008 Fabrice Bellard
3 * Copyright (C) 2016 Veertu Inc,
4 * Copyright (C) 2017 Google Inc,
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
22 #include "qemu-common.h"
27 #include "x86_descr.h"
28 #include "x86_decode.h"
29 #include "sysemu/hw_accel.h"
31 #include "hw/i386/apic_internal.h"
33 #include <Hypervisor/hv.h>
34 #include <Hypervisor/hv_vmx.h>
36 void hvf_set_segment(struct CPUState
*cpu
, struct vmx_segment
*vmx_seg
,
37 SegmentCache
*qseg
, bool is_tr
)
39 vmx_seg
->sel
= qseg
->selector
;
40 vmx_seg
->base
= qseg
->base
;
41 vmx_seg
->limit
= qseg
->limit
;
43 if (!qseg
->selector
&& !x86_is_real(cpu
) && !is_tr
) {
44 /* the TR register is usable after processor reset despite
45 * having a null selector */
46 vmx_seg
->ar
= 1 << 16;
49 vmx_seg
->ar
= (qseg
->flags
>> DESC_TYPE_SHIFT
) & 0xf;
50 vmx_seg
->ar
|= ((qseg
->flags
>> DESC_G_SHIFT
) & 1) << 15;
51 vmx_seg
->ar
|= ((qseg
->flags
>> DESC_B_SHIFT
) & 1) << 14;
52 vmx_seg
->ar
|= ((qseg
->flags
>> DESC_L_SHIFT
) & 1) << 13;
53 vmx_seg
->ar
|= ((qseg
->flags
>> DESC_AVL_SHIFT
) & 1) << 12;
54 vmx_seg
->ar
|= ((qseg
->flags
>> DESC_P_SHIFT
) & 1) << 7;
55 vmx_seg
->ar
|= ((qseg
->flags
>> DESC_DPL_SHIFT
) & 3) << 5;
56 vmx_seg
->ar
|= ((qseg
->flags
>> DESC_S_SHIFT
) & 1) << 4;
59 void hvf_get_segment(SegmentCache
*qseg
, struct vmx_segment
*vmx_seg
)
61 qseg
->limit
= vmx_seg
->limit
;
62 qseg
->base
= vmx_seg
->base
;
63 qseg
->selector
= vmx_seg
->sel
;
64 qseg
->flags
= ((vmx_seg
->ar
& 0xf) << DESC_TYPE_SHIFT
) |
65 (((vmx_seg
->ar
>> 4) & 1) << DESC_S_SHIFT
) |
66 (((vmx_seg
->ar
>> 5) & 3) << DESC_DPL_SHIFT
) |
67 (((vmx_seg
->ar
>> 7) & 1) << DESC_P_SHIFT
) |
68 (((vmx_seg
->ar
>> 12) & 1) << DESC_AVL_SHIFT
) |
69 (((vmx_seg
->ar
>> 13) & 1) << DESC_L_SHIFT
) |
70 (((vmx_seg
->ar
>> 14) & 1) << DESC_B_SHIFT
) |
71 (((vmx_seg
->ar
>> 15) & 1) << DESC_G_SHIFT
);
74 void hvf_put_xsave(CPUState
*cpu_state
)
77 struct X86XSaveArea
*xsave
;
79 xsave
= X86_CPU(cpu_state
)->env
.xsave_buf
;
81 x86_cpu_xsave_all_areas(X86_CPU(cpu_state
), xsave
);
83 if (hv_vcpu_write_fpstate(cpu_state
->hvf
->fd
, (void*)xsave
, 4096)) {
88 void hvf_put_segments(CPUState
*cpu_state
)
90 CPUX86State
*env
= &X86_CPU(cpu_state
)->env
;
91 struct vmx_segment seg
;
93 wvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_IDTR_LIMIT
, env
->idt
.limit
);
94 wvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_IDTR_BASE
, env
->idt
.base
);
96 wvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_GDTR_LIMIT
, env
->gdt
.limit
);
97 wvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_GDTR_BASE
, env
->gdt
.base
);
99 /* wvmcs(cpu_state->hvf->fd, VMCS_GUEST_CR2, env->cr[2]); */
100 wvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_CR3
, env
->cr
[3]);
101 vmx_update_tpr(cpu_state
);
102 wvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_IA32_EFER
, env
->efer
);
104 macvm_set_cr4(cpu_state
->hvf
->fd
, env
->cr
[4]);
105 macvm_set_cr0(cpu_state
->hvf
->fd
, env
->cr
[0]);
107 hvf_set_segment(cpu_state
, &seg
, &env
->segs
[R_CS
], false);
108 vmx_write_segment_descriptor(cpu_state
, &seg
, R_CS
);
110 hvf_set_segment(cpu_state
, &seg
, &env
->segs
[R_DS
], false);
111 vmx_write_segment_descriptor(cpu_state
, &seg
, R_DS
);
113 hvf_set_segment(cpu_state
, &seg
, &env
->segs
[R_ES
], false);
114 vmx_write_segment_descriptor(cpu_state
, &seg
, R_ES
);
116 hvf_set_segment(cpu_state
, &seg
, &env
->segs
[R_SS
], false);
117 vmx_write_segment_descriptor(cpu_state
, &seg
, R_SS
);
119 hvf_set_segment(cpu_state
, &seg
, &env
->segs
[R_FS
], false);
120 vmx_write_segment_descriptor(cpu_state
, &seg
, R_FS
);
122 hvf_set_segment(cpu_state
, &seg
, &env
->segs
[R_GS
], false);
123 vmx_write_segment_descriptor(cpu_state
, &seg
, R_GS
);
125 hvf_set_segment(cpu_state
, &seg
, &env
->tr
, true);
126 vmx_write_segment_descriptor(cpu_state
, &seg
, R_TR
);
128 hvf_set_segment(cpu_state
, &seg
, &env
->ldt
, false);
129 vmx_write_segment_descriptor(cpu_state
, &seg
, R_LDTR
);
131 hv_vcpu_flush(cpu_state
->hvf
->fd
);
134 void hvf_put_msrs(CPUState
*cpu_state
)
136 CPUX86State
*env
= &X86_CPU(cpu_state
)->env
;
138 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_IA32_SYSENTER_CS
,
140 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_IA32_SYSENTER_ESP
,
142 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_IA32_SYSENTER_EIP
,
145 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_STAR
, env
->star
);
148 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_CSTAR
, env
->cstar
);
149 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_KERNELGSBASE
, env
->kernelgsbase
);
150 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_FMASK
, env
->fmask
);
151 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_LSTAR
, env
->lstar
);
154 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_GSBASE
, env
->segs
[R_GS
].base
);
155 hv_vcpu_write_msr(cpu_state
->hvf
->fd
, MSR_FSBASE
, env
->segs
[R_FS
].base
);
159 void hvf_get_xsave(CPUState
*cpu_state
)
161 struct X86XSaveArea
*xsave
;
163 xsave
= X86_CPU(cpu_state
)->env
.xsave_buf
;
165 if (hv_vcpu_read_fpstate(cpu_state
->hvf
->fd
, (void*)xsave
, 4096)) {
169 x86_cpu_xrstor_all_areas(X86_CPU(cpu_state
), xsave
);
172 void hvf_get_segments(CPUState
*cpu_state
)
174 CPUX86State
*env
= &X86_CPU(cpu_state
)->env
;
176 struct vmx_segment seg
;
178 env
->interrupt_injected
= -1;
180 vmx_read_segment_descriptor(cpu_state
, &seg
, R_CS
);
181 hvf_get_segment(&env
->segs
[R_CS
], &seg
);
183 vmx_read_segment_descriptor(cpu_state
, &seg
, R_DS
);
184 hvf_get_segment(&env
->segs
[R_DS
], &seg
);
186 vmx_read_segment_descriptor(cpu_state
, &seg
, R_ES
);
187 hvf_get_segment(&env
->segs
[R_ES
], &seg
);
189 vmx_read_segment_descriptor(cpu_state
, &seg
, R_FS
);
190 hvf_get_segment(&env
->segs
[R_FS
], &seg
);
192 vmx_read_segment_descriptor(cpu_state
, &seg
, R_GS
);
193 hvf_get_segment(&env
->segs
[R_GS
], &seg
);
195 vmx_read_segment_descriptor(cpu_state
, &seg
, R_SS
);
196 hvf_get_segment(&env
->segs
[R_SS
], &seg
);
198 vmx_read_segment_descriptor(cpu_state
, &seg
, R_TR
);
199 hvf_get_segment(&env
->tr
, &seg
);
201 vmx_read_segment_descriptor(cpu_state
, &seg
, R_LDTR
);
202 hvf_get_segment(&env
->ldt
, &seg
);
204 env
->idt
.limit
= rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_IDTR_LIMIT
);
205 env
->idt
.base
= rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_IDTR_BASE
);
206 env
->gdt
.limit
= rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_GDTR_LIMIT
);
207 env
->gdt
.base
= rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_GDTR_BASE
);
209 env
->cr
[0] = rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_CR0
);
211 env
->cr
[3] = rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_CR3
);
212 env
->cr
[4] = rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_CR4
);
214 env
->efer
= rvmcs(cpu_state
->hvf
->fd
, VMCS_GUEST_IA32_EFER
);
217 void hvf_get_msrs(CPUState
*cpu_state
)
219 CPUX86State
*env
= &X86_CPU(cpu_state
)->env
;
222 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_IA32_SYSENTER_CS
, &tmp
);
223 env
->sysenter_cs
= tmp
;
225 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_IA32_SYSENTER_ESP
, &tmp
);
226 env
->sysenter_esp
= tmp
;
228 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_IA32_SYSENTER_EIP
, &tmp
);
229 env
->sysenter_eip
= tmp
;
231 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_STAR
, &env
->star
);
234 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_CSTAR
, &env
->cstar
);
235 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_KERNELGSBASE
, &env
->kernelgsbase
);
236 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_FMASK
, &env
->fmask
);
237 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_LSTAR
, &env
->lstar
);
240 hv_vcpu_read_msr(cpu_state
->hvf
->fd
, MSR_IA32_APICBASE
, &tmp
);
242 env
->tsc
= rdtscp() + rvmcs(cpu_state
->hvf
->fd
, VMCS_TSC_OFFSET
);
245 int hvf_put_registers(CPUState
*cpu_state
)
247 X86CPU
*x86cpu
= X86_CPU(cpu_state
);
248 CPUX86State
*env
= &x86cpu
->env
;
250 wreg(cpu_state
->hvf
->fd
, HV_X86_RAX
, env
->regs
[R_EAX
]);
251 wreg(cpu_state
->hvf
->fd
, HV_X86_RBX
, env
->regs
[R_EBX
]);
252 wreg(cpu_state
->hvf
->fd
, HV_X86_RCX
, env
->regs
[R_ECX
]);
253 wreg(cpu_state
->hvf
->fd
, HV_X86_RDX
, env
->regs
[R_EDX
]);
254 wreg(cpu_state
->hvf
->fd
, HV_X86_RBP
, env
->regs
[R_EBP
]);
255 wreg(cpu_state
->hvf
->fd
, HV_X86_RSP
, env
->regs
[R_ESP
]);
256 wreg(cpu_state
->hvf
->fd
, HV_X86_RSI
, env
->regs
[R_ESI
]);
257 wreg(cpu_state
->hvf
->fd
, HV_X86_RDI
, env
->regs
[R_EDI
]);
258 wreg(cpu_state
->hvf
->fd
, HV_X86_R8
, env
->regs
[8]);
259 wreg(cpu_state
->hvf
->fd
, HV_X86_R9
, env
->regs
[9]);
260 wreg(cpu_state
->hvf
->fd
, HV_X86_R10
, env
->regs
[10]);
261 wreg(cpu_state
->hvf
->fd
, HV_X86_R11
, env
->regs
[11]);
262 wreg(cpu_state
->hvf
->fd
, HV_X86_R12
, env
->regs
[12]);
263 wreg(cpu_state
->hvf
->fd
, HV_X86_R13
, env
->regs
[13]);
264 wreg(cpu_state
->hvf
->fd
, HV_X86_R14
, env
->regs
[14]);
265 wreg(cpu_state
->hvf
->fd
, HV_X86_R15
, env
->regs
[15]);
266 wreg(cpu_state
->hvf
->fd
, HV_X86_RFLAGS
, env
->eflags
);
267 wreg(cpu_state
->hvf
->fd
, HV_X86_RIP
, env
->eip
);
269 wreg(cpu_state
->hvf
->fd
, HV_X86_XCR0
, env
->xcr0
);
271 hvf_put_xsave(cpu_state
);
273 hvf_put_segments(cpu_state
);
275 hvf_put_msrs(cpu_state
);
277 wreg(cpu_state
->hvf
->fd
, HV_X86_DR0
, env
->dr
[0]);
278 wreg(cpu_state
->hvf
->fd
, HV_X86_DR1
, env
->dr
[1]);
279 wreg(cpu_state
->hvf
->fd
, HV_X86_DR2
, env
->dr
[2]);
280 wreg(cpu_state
->hvf
->fd
, HV_X86_DR3
, env
->dr
[3]);
281 wreg(cpu_state
->hvf
->fd
, HV_X86_DR4
, env
->dr
[4]);
282 wreg(cpu_state
->hvf
->fd
, HV_X86_DR5
, env
->dr
[5]);
283 wreg(cpu_state
->hvf
->fd
, HV_X86_DR6
, env
->dr
[6]);
284 wreg(cpu_state
->hvf
->fd
, HV_X86_DR7
, env
->dr
[7]);
289 int hvf_get_registers(CPUState
*cpu_state
)
291 X86CPU
*x86cpu
= X86_CPU(cpu_state
);
292 CPUX86State
*env
= &x86cpu
->env
;
294 env
->regs
[R_EAX
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RAX
);
295 env
->regs
[R_EBX
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RBX
);
296 env
->regs
[R_ECX
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RCX
);
297 env
->regs
[R_EDX
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RDX
);
298 env
->regs
[R_EBP
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RBP
);
299 env
->regs
[R_ESP
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RSP
);
300 env
->regs
[R_ESI
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RSI
);
301 env
->regs
[R_EDI
] = rreg(cpu_state
->hvf
->fd
, HV_X86_RDI
);
302 env
->regs
[8] = rreg(cpu_state
->hvf
->fd
, HV_X86_R8
);
303 env
->regs
[9] = rreg(cpu_state
->hvf
->fd
, HV_X86_R9
);
304 env
->regs
[10] = rreg(cpu_state
->hvf
->fd
, HV_X86_R10
);
305 env
->regs
[11] = rreg(cpu_state
->hvf
->fd
, HV_X86_R11
);
306 env
->regs
[12] = rreg(cpu_state
->hvf
->fd
, HV_X86_R12
);
307 env
->regs
[13] = rreg(cpu_state
->hvf
->fd
, HV_X86_R13
);
308 env
->regs
[14] = rreg(cpu_state
->hvf
->fd
, HV_X86_R14
);
309 env
->regs
[15] = rreg(cpu_state
->hvf
->fd
, HV_X86_R15
);
311 env
->eflags
= rreg(cpu_state
->hvf
->fd
, HV_X86_RFLAGS
);
312 env
->eip
= rreg(cpu_state
->hvf
->fd
, HV_X86_RIP
);
314 hvf_get_xsave(cpu_state
);
315 env
->xcr0
= rreg(cpu_state
->hvf
->fd
, HV_X86_XCR0
);
317 hvf_get_segments(cpu_state
);
318 hvf_get_msrs(cpu_state
);
320 env
->dr
[0] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR0
);
321 env
->dr
[1] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR1
);
322 env
->dr
[2] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR2
);
323 env
->dr
[3] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR3
);
324 env
->dr
[4] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR4
);
325 env
->dr
[5] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR5
);
326 env
->dr
[6] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR6
);
327 env
->dr
[7] = rreg(cpu_state
->hvf
->fd
, HV_X86_DR7
);
329 x86_update_hflags(env
);
333 static void vmx_set_int_window_exiting(CPUState
*cpu
)
336 val
= rvmcs(cpu
->hvf
->fd
, VMCS_PRI_PROC_BASED_CTLS
);
337 wvmcs(cpu
->hvf
->fd
, VMCS_PRI_PROC_BASED_CTLS
, val
|
338 VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING
);
341 void vmx_clear_int_window_exiting(CPUState
*cpu
)
344 val
= rvmcs(cpu
->hvf
->fd
, VMCS_PRI_PROC_BASED_CTLS
);
345 wvmcs(cpu
->hvf
->fd
, VMCS_PRI_PROC_BASED_CTLS
, val
&
346 ~VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING
);
349 bool hvf_inject_interrupts(CPUState
*cpu_state
)
351 X86CPU
*x86cpu
= X86_CPU(cpu_state
);
352 CPUX86State
*env
= &x86cpu
->env
;
356 bool have_event
= true;
357 if (env
->interrupt_injected
!= -1) {
358 vector
= env
->interrupt_injected
;
360 intr_type
= VMCS_INTR_T_SWINTR
;
362 intr_type
= VMCS_INTR_T_HWINTR
;
364 } else if (env
->exception_nr
!= -1) {
365 vector
= env
->exception_nr
;
366 if (vector
== EXCP03_INT3
|| vector
== EXCP04_INTO
) {
367 intr_type
= VMCS_INTR_T_SWEXCEPTION
;
369 intr_type
= VMCS_INTR_T_HWEXCEPTION
;
371 } else if (env
->nmi_injected
) {
373 intr_type
= VMCS_INTR_T_NMI
;
380 info
= vector
| intr_type
| VMCS_INTR_VALID
;
381 uint64_t reason
= rvmcs(cpu_state
->hvf
->fd
, VMCS_EXIT_REASON
);
382 if (env
->nmi_injected
&& reason
!= EXIT_REASON_TASK_SWITCH
) {
383 vmx_clear_nmi_blocking(cpu_state
);
386 if (!(env
->hflags2
& HF2_NMI_MASK
) || intr_type
!= VMCS_INTR_T_NMI
) {
387 info
&= ~(1 << 12); /* clear undefined bit */
388 if (intr_type
== VMCS_INTR_T_SWINTR
||
389 intr_type
== VMCS_INTR_T_SWEXCEPTION
) {
390 wvmcs(cpu_state
->hvf
->fd
, VMCS_ENTRY_INST_LENGTH
, env
->ins_len
);
393 if (env
->has_error_code
) {
394 wvmcs(cpu_state
->hvf
->fd
, VMCS_ENTRY_EXCEPTION_ERROR
,
396 /* Indicate that VMCS_ENTRY_EXCEPTION_ERROR is valid */
397 info
|= VMCS_INTR_DEL_ERRCODE
;
399 /*printf("reinject %lx err %d\n", info, err);*/
400 wvmcs(cpu_state
->hvf
->fd
, VMCS_ENTRY_INTR_INFO
, info
);
404 if (cpu_state
->interrupt_request
& CPU_INTERRUPT_NMI
) {
405 if (!(env
->hflags2
& HF2_NMI_MASK
) && !(info
& VMCS_INTR_VALID
)) {
406 cpu_state
->interrupt_request
&= ~CPU_INTERRUPT_NMI
;
407 info
= VMCS_INTR_VALID
| VMCS_INTR_T_NMI
| EXCP02_NMI
;
408 wvmcs(cpu_state
->hvf
->fd
, VMCS_ENTRY_INTR_INFO
, info
);
410 vmx_set_nmi_window_exiting(cpu_state
);
414 if (!(env
->hflags
& HF_INHIBIT_IRQ_MASK
) &&
415 (cpu_state
->interrupt_request
& CPU_INTERRUPT_HARD
) &&
416 (env
->eflags
& IF_MASK
) && !(info
& VMCS_INTR_VALID
)) {
417 int line
= cpu_get_pic_interrupt(&x86cpu
->env
);
418 cpu_state
->interrupt_request
&= ~CPU_INTERRUPT_HARD
;
420 wvmcs(cpu_state
->hvf
->fd
, VMCS_ENTRY_INTR_INFO
, line
|
421 VMCS_INTR_VALID
| VMCS_INTR_T_HWINTR
);
424 if (cpu_state
->interrupt_request
& CPU_INTERRUPT_HARD
) {
425 vmx_set_int_window_exiting(cpu_state
);
427 return (cpu_state
->interrupt_request
428 & (CPU_INTERRUPT_INIT
| CPU_INTERRUPT_TPR
));
431 int hvf_process_events(CPUState
*cpu_state
)
433 X86CPU
*cpu
= X86_CPU(cpu_state
);
434 CPUX86State
*env
= &cpu
->env
;
436 env
->eflags
= rreg(cpu_state
->hvf
->fd
, HV_X86_RFLAGS
);
438 if (cpu_state
->interrupt_request
& CPU_INTERRUPT_INIT
) {
439 cpu_synchronize_state(cpu_state
);
443 if (cpu_state
->interrupt_request
& CPU_INTERRUPT_POLL
) {
444 cpu_state
->interrupt_request
&= ~CPU_INTERRUPT_POLL
;
445 apic_poll_irq(cpu
->apic_state
);
447 if (((cpu_state
->interrupt_request
& CPU_INTERRUPT_HARD
) &&
448 (env
->eflags
& IF_MASK
)) ||
449 (cpu_state
->interrupt_request
& CPU_INTERRUPT_NMI
)) {
450 cpu_state
->halted
= 0;
452 if (cpu_state
->interrupt_request
& CPU_INTERRUPT_SIPI
) {
453 cpu_synchronize_state(cpu_state
);
456 if (cpu_state
->interrupt_request
& CPU_INTERRUPT_TPR
) {
457 cpu_state
->interrupt_request
&= ~CPU_INTERRUPT_TPR
;
458 cpu_synchronize_state(cpu_state
);
459 apic_handle_tpr_access_report(cpu
->apic_state
, env
->eip
,
460 env
->tpr_access_type
);
462 return cpu_state
->halted
;