xref: /qemu/target/i386/hvf/x86hvf.c (revision e6203636)
169e0a03cSPaolo Bonzini /*
269e0a03cSPaolo Bonzini  * Copyright (c) 2003-2008 Fabrice Bellard
369e0a03cSPaolo Bonzini  * Copyright (C) 2016 Veertu Inc,
469e0a03cSPaolo Bonzini  * Copyright (C) 2017 Google Inc,
569e0a03cSPaolo Bonzini  *
669e0a03cSPaolo Bonzini  * This program is free software; you can redistribute it and/or
769e0a03cSPaolo Bonzini  * modify it under the terms of the GNU Lesser General Public
869e0a03cSPaolo Bonzini  * License as published by the Free Software Foundation; either
98af82b8eSChetan Pant  * version 2.1 of the License, or (at your option) any later version.
1069e0a03cSPaolo Bonzini  *
1169e0a03cSPaolo Bonzini  * This program is distributed in the hope that it will be useful,
1269e0a03cSPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1369e0a03cSPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1469e0a03cSPaolo Bonzini  * Lesser General Public License for more details.
1569e0a03cSPaolo Bonzini  *
1669e0a03cSPaolo Bonzini  * You should have received a copy of the GNU Lesser General Public
1769e0a03cSPaolo Bonzini  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
1869e0a03cSPaolo Bonzini  */
1969e0a03cSPaolo Bonzini 
2069e0a03cSPaolo Bonzini #include "qemu/osdep.h"
2169e0a03cSPaolo Bonzini 
2269e0a03cSPaolo Bonzini #include "x86hvf.h"
2369e0a03cSPaolo Bonzini #include "vmx.h"
2469e0a03cSPaolo Bonzini #include "vmcs.h"
2569e0a03cSPaolo Bonzini #include "cpu.h"
2669e0a03cSPaolo Bonzini #include "x86_descr.h"
2769e0a03cSPaolo Bonzini #include "x86_decode.h"
2865c725b5SAlexander Graf #include "sysemu/hw_accel.h"
2969e0a03cSPaolo Bonzini 
3069e0a03cSPaolo Bonzini #include "hw/i386/apic_internal.h"
3169e0a03cSPaolo Bonzini 
3269e0a03cSPaolo Bonzini #include <Hypervisor/hv.h>
3369e0a03cSPaolo Bonzini #include <Hypervisor/hv_vmx.h>
3469e0a03cSPaolo Bonzini 
hvf_set_segment(CPUState * cs,struct vmx_segment * vmx_seg,SegmentCache * qseg,bool is_tr)35a7159244SPhilippe Mathieu-Daudé void hvf_set_segment(CPUState *cs, struct vmx_segment *vmx_seg,
3669e0a03cSPaolo Bonzini                      SegmentCache *qseg, bool is_tr)
3769e0a03cSPaolo Bonzini {
3869e0a03cSPaolo Bonzini     vmx_seg->sel = qseg->selector;
3969e0a03cSPaolo Bonzini     vmx_seg->base = qseg->base;
4069e0a03cSPaolo Bonzini     vmx_seg->limit = qseg->limit;
4169e0a03cSPaolo Bonzini 
42a7159244SPhilippe Mathieu-Daudé     if (!qseg->selector && !x86_is_real(cs) && !is_tr) {
4369e0a03cSPaolo Bonzini         /* the TR register is usable after processor reset despite
4469e0a03cSPaolo Bonzini          * having a null selector */
4569e0a03cSPaolo Bonzini         vmx_seg->ar = 1 << 16;
4669e0a03cSPaolo Bonzini         return;
4769e0a03cSPaolo Bonzini     }
4869e0a03cSPaolo Bonzini     vmx_seg->ar = (qseg->flags >> DESC_TYPE_SHIFT) & 0xf;
4969e0a03cSPaolo Bonzini     vmx_seg->ar |= ((qseg->flags >> DESC_G_SHIFT) & 1) << 15;
5069e0a03cSPaolo Bonzini     vmx_seg->ar |= ((qseg->flags >> DESC_B_SHIFT) & 1) << 14;
5169e0a03cSPaolo Bonzini     vmx_seg->ar |= ((qseg->flags >> DESC_L_SHIFT) & 1) << 13;
5269e0a03cSPaolo Bonzini     vmx_seg->ar |= ((qseg->flags >> DESC_AVL_SHIFT) & 1) << 12;
5369e0a03cSPaolo Bonzini     vmx_seg->ar |= ((qseg->flags >> DESC_P_SHIFT) & 1) << 7;
5469e0a03cSPaolo Bonzini     vmx_seg->ar |= ((qseg->flags >> DESC_DPL_SHIFT) & 3) << 5;
5569e0a03cSPaolo Bonzini     vmx_seg->ar |= ((qseg->flags >> DESC_S_SHIFT) & 1) << 4;
5669e0a03cSPaolo Bonzini }
5769e0a03cSPaolo Bonzini 
hvf_get_segment(SegmentCache * qseg,struct vmx_segment * vmx_seg)5869e0a03cSPaolo Bonzini void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg)
5969e0a03cSPaolo Bonzini {
6069e0a03cSPaolo Bonzini     qseg->limit = vmx_seg->limit;
6169e0a03cSPaolo Bonzini     qseg->base = vmx_seg->base;
6269e0a03cSPaolo Bonzini     qseg->selector = vmx_seg->sel;
6369e0a03cSPaolo Bonzini     qseg->flags = ((vmx_seg->ar & 0xf) << DESC_TYPE_SHIFT) |
6469e0a03cSPaolo Bonzini                   (((vmx_seg->ar >> 4) & 1) << DESC_S_SHIFT) |
6569e0a03cSPaolo Bonzini                   (((vmx_seg->ar >> 5) & 3) << DESC_DPL_SHIFT) |
6669e0a03cSPaolo Bonzini                   (((vmx_seg->ar >> 7) & 1) << DESC_P_SHIFT) |
6769e0a03cSPaolo Bonzini                   (((vmx_seg->ar >> 12) & 1) << DESC_AVL_SHIFT) |
6869e0a03cSPaolo Bonzini                   (((vmx_seg->ar >> 13) & 1) << DESC_L_SHIFT) |
6969e0a03cSPaolo Bonzini                   (((vmx_seg->ar >> 14) & 1) << DESC_B_SHIFT) |
7069e0a03cSPaolo Bonzini                   (((vmx_seg->ar >> 15) & 1) << DESC_G_SHIFT);
7169e0a03cSPaolo Bonzini }
7269e0a03cSPaolo Bonzini 
hvf_put_xsave(CPUState * cs)73a7159244SPhilippe Mathieu-Daudé void hvf_put_xsave(CPUState *cs)
7469e0a03cSPaolo Bonzini {
75a7159244SPhilippe Mathieu-Daudé     void *xsave = X86_CPU(cs)->env.xsave_buf;
76a7159244SPhilippe Mathieu-Daudé     uint32_t xsave_len = X86_CPU(cs)->env.xsave_buf_len;
7769e0a03cSPaolo Bonzini 
78a7159244SPhilippe Mathieu-Daudé     x86_cpu_xsave_all_areas(X86_CPU(cs), xsave, xsave_len);
7969e0a03cSPaolo Bonzini 
803b295bcbSPhilippe Mathieu-Daudé     if (hv_vcpu_write_fpstate(cs->accel->fd, xsave, xsave_len)) {
8169e0a03cSPaolo Bonzini         abort();
8269e0a03cSPaolo Bonzini     }
8369e0a03cSPaolo Bonzini }
8469e0a03cSPaolo Bonzini 
hvf_put_segments(CPUState * cs)85a7159244SPhilippe Mathieu-Daudé static void hvf_put_segments(CPUState *cs)
8669e0a03cSPaolo Bonzini {
87a7159244SPhilippe Mathieu-Daudé     CPUX86State *env = &X86_CPU(cs)->env;
8869e0a03cSPaolo Bonzini     struct vmx_segment seg;
8969e0a03cSPaolo Bonzini 
903b295bcbSPhilippe Mathieu-Daudé     wvmcs(cs->accel->fd, VMCS_GUEST_IDTR_LIMIT, env->idt.limit);
913b295bcbSPhilippe Mathieu-Daudé     wvmcs(cs->accel->fd, VMCS_GUEST_IDTR_BASE, env->idt.base);
9269e0a03cSPaolo Bonzini 
933b295bcbSPhilippe Mathieu-Daudé     wvmcs(cs->accel->fd, VMCS_GUEST_GDTR_LIMIT, env->gdt.limit);
943b295bcbSPhilippe Mathieu-Daudé     wvmcs(cs->accel->fd, VMCS_GUEST_GDTR_BASE, env->gdt.base);
9569e0a03cSPaolo Bonzini 
963b295bcbSPhilippe Mathieu-Daudé     /* wvmcs(cs->accel->fd, VMCS_GUEST_CR2, env->cr[2]); */
973b295bcbSPhilippe Mathieu-Daudé     wvmcs(cs->accel->fd, VMCS_GUEST_CR3, env->cr[3]);
98a7159244SPhilippe Mathieu-Daudé     vmx_update_tpr(cs);
993b295bcbSPhilippe Mathieu-Daudé     wvmcs(cs->accel->fd, VMCS_GUEST_IA32_EFER, env->efer);
10069e0a03cSPaolo Bonzini 
1013b295bcbSPhilippe Mathieu-Daudé     macvm_set_cr4(cs->accel->fd, env->cr[4]);
1023b295bcbSPhilippe Mathieu-Daudé     macvm_set_cr0(cs->accel->fd, env->cr[0]);
10369e0a03cSPaolo Bonzini 
104a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->segs[R_CS], false);
105a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_CS);
10669e0a03cSPaolo Bonzini 
107a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->segs[R_DS], false);
108a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_DS);
10969e0a03cSPaolo Bonzini 
110a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->segs[R_ES], false);
111a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_ES);
11269e0a03cSPaolo Bonzini 
113a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->segs[R_SS], false);
114a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_SS);
11569e0a03cSPaolo Bonzini 
116a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->segs[R_FS], false);
117a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_FS);
11869e0a03cSPaolo Bonzini 
119a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->segs[R_GS], false);
120a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_GS);
12169e0a03cSPaolo Bonzini 
122a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->tr, true);
123a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_TR);
12469e0a03cSPaolo Bonzini 
125a7159244SPhilippe Mathieu-Daudé     hvf_set_segment(cs, &seg, &env->ldt, false);
126a7159244SPhilippe Mathieu-Daudé     vmx_write_segment_descriptor(cs, &seg, R_LDTR);
12769e0a03cSPaolo Bonzini }
12869e0a03cSPaolo Bonzini 
hvf_put_msrs(CPUState * cs)129a7159244SPhilippe Mathieu-Daudé void hvf_put_msrs(CPUState *cs)
13069e0a03cSPaolo Bonzini {
131a7159244SPhilippe Mathieu-Daudé     CPUX86State *env = &X86_CPU(cs)->env;
13269e0a03cSPaolo Bonzini 
1333b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_IA32_SYSENTER_CS,
13469e0a03cSPaolo Bonzini                       env->sysenter_cs);
1353b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_IA32_SYSENTER_ESP,
13669e0a03cSPaolo Bonzini                       env->sysenter_esp);
1373b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_IA32_SYSENTER_EIP,
13869e0a03cSPaolo Bonzini                       env->sysenter_eip);
13969e0a03cSPaolo Bonzini 
1403b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_STAR, env->star);
14169e0a03cSPaolo Bonzini 
14269e0a03cSPaolo Bonzini #ifdef TARGET_X86_64
1433b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_CSTAR, env->cstar);
1443b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_KERNELGSBASE, env->kernelgsbase);
1453b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_FMASK, env->fmask);
1463b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_LSTAR, env->lstar);
14769e0a03cSPaolo Bonzini #endif
14869e0a03cSPaolo Bonzini 
1493b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_GSBASE, env->segs[R_GS].base);
1503b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_write_msr(cs->accel->fd, MSR_FSBASE, env->segs[R_FS].base);
15169e0a03cSPaolo Bonzini }
15269e0a03cSPaolo Bonzini 
15369e0a03cSPaolo Bonzini 
hvf_get_xsave(CPUState * cs)154a7159244SPhilippe Mathieu-Daudé void hvf_get_xsave(CPUState *cs)
15569e0a03cSPaolo Bonzini {
156a7159244SPhilippe Mathieu-Daudé     void *xsave = X86_CPU(cs)->env.xsave_buf;
157a7159244SPhilippe Mathieu-Daudé     uint32_t xsave_len = X86_CPU(cs)->env.xsave_buf_len;
15869e0a03cSPaolo Bonzini 
1593b295bcbSPhilippe Mathieu-Daudé     if (hv_vcpu_read_fpstate(cs->accel->fd, xsave, xsave_len)) {
16069e0a03cSPaolo Bonzini         abort();
16169e0a03cSPaolo Bonzini     }
16269e0a03cSPaolo Bonzini 
163a7159244SPhilippe Mathieu-Daudé     x86_cpu_xrstor_all_areas(X86_CPU(cs), xsave, xsave_len);
16469e0a03cSPaolo Bonzini }
16569e0a03cSPaolo Bonzini 
hvf_get_segments(CPUState * cs)166a7159244SPhilippe Mathieu-Daudé static void hvf_get_segments(CPUState *cs)
16769e0a03cSPaolo Bonzini {
168a7159244SPhilippe Mathieu-Daudé     CPUX86State *env = &X86_CPU(cs)->env;
16969e0a03cSPaolo Bonzini 
17069e0a03cSPaolo Bonzini     struct vmx_segment seg;
17169e0a03cSPaolo Bonzini 
17269e0a03cSPaolo Bonzini     env->interrupt_injected = -1;
17369e0a03cSPaolo Bonzini 
174a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_CS);
17569e0a03cSPaolo Bonzini     hvf_get_segment(&env->segs[R_CS], &seg);
17669e0a03cSPaolo Bonzini 
177a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_DS);
17869e0a03cSPaolo Bonzini     hvf_get_segment(&env->segs[R_DS], &seg);
17969e0a03cSPaolo Bonzini 
180a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_ES);
18169e0a03cSPaolo Bonzini     hvf_get_segment(&env->segs[R_ES], &seg);
18269e0a03cSPaolo Bonzini 
183a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_FS);
18469e0a03cSPaolo Bonzini     hvf_get_segment(&env->segs[R_FS], &seg);
18569e0a03cSPaolo Bonzini 
186a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_GS);
18769e0a03cSPaolo Bonzini     hvf_get_segment(&env->segs[R_GS], &seg);
18869e0a03cSPaolo Bonzini 
189a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_SS);
19069e0a03cSPaolo Bonzini     hvf_get_segment(&env->segs[R_SS], &seg);
19169e0a03cSPaolo Bonzini 
192a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_TR);
19369e0a03cSPaolo Bonzini     hvf_get_segment(&env->tr, &seg);
19469e0a03cSPaolo Bonzini 
195a7159244SPhilippe Mathieu-Daudé     vmx_read_segment_descriptor(cs, &seg, R_LDTR);
19669e0a03cSPaolo Bonzini     hvf_get_segment(&env->ldt, &seg);
19769e0a03cSPaolo Bonzini 
1983b295bcbSPhilippe Mathieu-Daudé     env->idt.limit = rvmcs(cs->accel->fd, VMCS_GUEST_IDTR_LIMIT);
1993b295bcbSPhilippe Mathieu-Daudé     env->idt.base = rvmcs(cs->accel->fd, VMCS_GUEST_IDTR_BASE);
2003b295bcbSPhilippe Mathieu-Daudé     env->gdt.limit = rvmcs(cs->accel->fd, VMCS_GUEST_GDTR_LIMIT);
2013b295bcbSPhilippe Mathieu-Daudé     env->gdt.base = rvmcs(cs->accel->fd, VMCS_GUEST_GDTR_BASE);
20269e0a03cSPaolo Bonzini 
2033b295bcbSPhilippe Mathieu-Daudé     env->cr[0] = rvmcs(cs->accel->fd, VMCS_GUEST_CR0);
20469e0a03cSPaolo Bonzini     env->cr[2] = 0;
2053b295bcbSPhilippe Mathieu-Daudé     env->cr[3] = rvmcs(cs->accel->fd, VMCS_GUEST_CR3);
2063b295bcbSPhilippe Mathieu-Daudé     env->cr[4] = rvmcs(cs->accel->fd, VMCS_GUEST_CR4);
20769e0a03cSPaolo Bonzini 
2083b295bcbSPhilippe Mathieu-Daudé     env->efer = rvmcs(cs->accel->fd, VMCS_GUEST_IA32_EFER);
20969e0a03cSPaolo Bonzini }
21069e0a03cSPaolo Bonzini 
hvf_get_msrs(CPUState * cs)211a7159244SPhilippe Mathieu-Daudé void hvf_get_msrs(CPUState *cs)
21269e0a03cSPaolo Bonzini {
213a7159244SPhilippe Mathieu-Daudé     CPUX86State *env = &X86_CPU(cs)->env;
21469e0a03cSPaolo Bonzini     uint64_t tmp;
21569e0a03cSPaolo Bonzini 
2163b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_SYSENTER_CS, &tmp);
21769e0a03cSPaolo Bonzini     env->sysenter_cs = tmp;
21869e0a03cSPaolo Bonzini 
2193b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_SYSENTER_ESP, &tmp);
22069e0a03cSPaolo Bonzini     env->sysenter_esp = tmp;
22169e0a03cSPaolo Bonzini 
2223b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_SYSENTER_EIP, &tmp);
22369e0a03cSPaolo Bonzini     env->sysenter_eip = tmp;
22469e0a03cSPaolo Bonzini 
2253b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_STAR, &env->star);
22669e0a03cSPaolo Bonzini 
22769e0a03cSPaolo Bonzini #ifdef TARGET_X86_64
2283b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_CSTAR, &env->cstar);
2293b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_KERNELGSBASE, &env->kernelgsbase);
2303b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_FMASK, &env->fmask);
2313b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_LSTAR, &env->lstar);
23269e0a03cSPaolo Bonzini #endif
23369e0a03cSPaolo Bonzini 
2343b295bcbSPhilippe Mathieu-Daudé     hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_APICBASE, &tmp);
23569e0a03cSPaolo Bonzini 
2363b295bcbSPhilippe Mathieu-Daudé     env->tsc = rdtscp() + rvmcs(cs->accel->fd, VMCS_TSC_OFFSET);
23769e0a03cSPaolo Bonzini }
23869e0a03cSPaolo Bonzini 
hvf_put_registers(CPUState * cs)239a7159244SPhilippe Mathieu-Daudé int hvf_put_registers(CPUState *cs)
24069e0a03cSPaolo Bonzini {
241a7159244SPhilippe Mathieu-Daudé     X86CPU *x86cpu = X86_CPU(cs);
24269e0a03cSPaolo Bonzini     CPUX86State *env = &x86cpu->env;
24369e0a03cSPaolo Bonzini 
2443b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RAX, env->regs[R_EAX]);
2453b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RBX, env->regs[R_EBX]);
2463b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RCX, env->regs[R_ECX]);
2473b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RDX, env->regs[R_EDX]);
2483b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RBP, env->regs[R_EBP]);
2493b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RSP, env->regs[R_ESP]);
2503b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RSI, env->regs[R_ESI]);
2513b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RDI, env->regs[R_EDI]);
2523b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R8, env->regs[8]);
2533b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R9, env->regs[9]);
2543b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R10, env->regs[10]);
2553b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R11, env->regs[11]);
2563b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R12, env->regs[12]);
2573b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R13, env->regs[13]);
2583b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R14, env->regs[14]);
2593b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_R15, env->regs[15]);
2603b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RFLAGS, env->eflags);
2613b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_RIP, env->eip);
26269e0a03cSPaolo Bonzini 
2633b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_XCR0, env->xcr0);
26469e0a03cSPaolo Bonzini 
265a7159244SPhilippe Mathieu-Daudé     hvf_put_xsave(cs);
26669e0a03cSPaolo Bonzini 
267a7159244SPhilippe Mathieu-Daudé     hvf_put_segments(cs);
26869e0a03cSPaolo Bonzini 
269a7159244SPhilippe Mathieu-Daudé     hvf_put_msrs(cs);
27069e0a03cSPaolo Bonzini 
2713b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR0, env->dr[0]);
2723b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR1, env->dr[1]);
2733b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR2, env->dr[2]);
2743b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR3, env->dr[3]);
2753b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR4, env->dr[4]);
2763b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR5, env->dr[5]);
2773b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR6, env->dr[6]);
2783b295bcbSPhilippe Mathieu-Daudé     wreg(cs->accel->fd, HV_X86_DR7, env->dr[7]);
27969e0a03cSPaolo Bonzini 
28069e0a03cSPaolo Bonzini     return 0;
28169e0a03cSPaolo Bonzini }
28269e0a03cSPaolo Bonzini 
hvf_get_registers(CPUState * cs)283a7159244SPhilippe Mathieu-Daudé int hvf_get_registers(CPUState *cs)
28469e0a03cSPaolo Bonzini {
285a7159244SPhilippe Mathieu-Daudé     X86CPU *x86cpu = X86_CPU(cs);
28669e0a03cSPaolo Bonzini     CPUX86State *env = &x86cpu->env;
28769e0a03cSPaolo Bonzini 
2883b295bcbSPhilippe Mathieu-Daudé     env->regs[R_EAX] = rreg(cs->accel->fd, HV_X86_RAX);
2893b295bcbSPhilippe Mathieu-Daudé     env->regs[R_EBX] = rreg(cs->accel->fd, HV_X86_RBX);
2903b295bcbSPhilippe Mathieu-Daudé     env->regs[R_ECX] = rreg(cs->accel->fd, HV_X86_RCX);
2913b295bcbSPhilippe Mathieu-Daudé     env->regs[R_EDX] = rreg(cs->accel->fd, HV_X86_RDX);
2923b295bcbSPhilippe Mathieu-Daudé     env->regs[R_EBP] = rreg(cs->accel->fd, HV_X86_RBP);
2933b295bcbSPhilippe Mathieu-Daudé     env->regs[R_ESP] = rreg(cs->accel->fd, HV_X86_RSP);
2943b295bcbSPhilippe Mathieu-Daudé     env->regs[R_ESI] = rreg(cs->accel->fd, HV_X86_RSI);
2953b295bcbSPhilippe Mathieu-Daudé     env->regs[R_EDI] = rreg(cs->accel->fd, HV_X86_RDI);
2963b295bcbSPhilippe Mathieu-Daudé     env->regs[8] = rreg(cs->accel->fd, HV_X86_R8);
2973b295bcbSPhilippe Mathieu-Daudé     env->regs[9] = rreg(cs->accel->fd, HV_X86_R9);
2983b295bcbSPhilippe Mathieu-Daudé     env->regs[10] = rreg(cs->accel->fd, HV_X86_R10);
2993b295bcbSPhilippe Mathieu-Daudé     env->regs[11] = rreg(cs->accel->fd, HV_X86_R11);
3003b295bcbSPhilippe Mathieu-Daudé     env->regs[12] = rreg(cs->accel->fd, HV_X86_R12);
3013b295bcbSPhilippe Mathieu-Daudé     env->regs[13] = rreg(cs->accel->fd, HV_X86_R13);
3023b295bcbSPhilippe Mathieu-Daudé     env->regs[14] = rreg(cs->accel->fd, HV_X86_R14);
3033b295bcbSPhilippe Mathieu-Daudé     env->regs[15] = rreg(cs->accel->fd, HV_X86_R15);
30469e0a03cSPaolo Bonzini 
3053b295bcbSPhilippe Mathieu-Daudé     env->eflags = rreg(cs->accel->fd, HV_X86_RFLAGS);
3063b295bcbSPhilippe Mathieu-Daudé     env->eip = rreg(cs->accel->fd, HV_X86_RIP);
30769e0a03cSPaolo Bonzini 
308a7159244SPhilippe Mathieu-Daudé     hvf_get_xsave(cs);
3093b295bcbSPhilippe Mathieu-Daudé     env->xcr0 = rreg(cs->accel->fd, HV_X86_XCR0);
31069e0a03cSPaolo Bonzini 
311a7159244SPhilippe Mathieu-Daudé     hvf_get_segments(cs);
312a7159244SPhilippe Mathieu-Daudé     hvf_get_msrs(cs);
31369e0a03cSPaolo Bonzini 
3143b295bcbSPhilippe Mathieu-Daudé     env->dr[0] = rreg(cs->accel->fd, HV_X86_DR0);
3153b295bcbSPhilippe Mathieu-Daudé     env->dr[1] = rreg(cs->accel->fd, HV_X86_DR1);
3163b295bcbSPhilippe Mathieu-Daudé     env->dr[2] = rreg(cs->accel->fd, HV_X86_DR2);
3173b295bcbSPhilippe Mathieu-Daudé     env->dr[3] = rreg(cs->accel->fd, HV_X86_DR3);
3183b295bcbSPhilippe Mathieu-Daudé     env->dr[4] = rreg(cs->accel->fd, HV_X86_DR4);
3193b295bcbSPhilippe Mathieu-Daudé     env->dr[5] = rreg(cs->accel->fd, HV_X86_DR5);
3203b295bcbSPhilippe Mathieu-Daudé     env->dr[6] = rreg(cs->accel->fd, HV_X86_DR6);
3213b295bcbSPhilippe Mathieu-Daudé     env->dr[7] = rreg(cs->accel->fd, HV_X86_DR7);
32269e0a03cSPaolo Bonzini 
323809092f3SPaolo Bonzini     x86_update_hflags(env);
32469e0a03cSPaolo Bonzini     return 0;
32569e0a03cSPaolo Bonzini }
32669e0a03cSPaolo Bonzini 
vmx_set_int_window_exiting(CPUState * cs)327a7159244SPhilippe Mathieu-Daudé static void vmx_set_int_window_exiting(CPUState *cs)
32869e0a03cSPaolo Bonzini {
32969e0a03cSPaolo Bonzini      uint64_t val;
3303b295bcbSPhilippe Mathieu-Daudé      val = rvmcs(cs->accel->fd, VMCS_PRI_PROC_BASED_CTLS);
3313b295bcbSPhilippe Mathieu-Daudé      wvmcs(cs->accel->fd, VMCS_PRI_PROC_BASED_CTLS, val |
33269e0a03cSPaolo Bonzini              VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING);
33369e0a03cSPaolo Bonzini }
33469e0a03cSPaolo Bonzini 
vmx_clear_int_window_exiting(CPUState * cs)335a7159244SPhilippe Mathieu-Daudé void vmx_clear_int_window_exiting(CPUState *cs)
33669e0a03cSPaolo Bonzini {
33769e0a03cSPaolo Bonzini      uint64_t val;
3383b295bcbSPhilippe Mathieu-Daudé      val = rvmcs(cs->accel->fd, VMCS_PRI_PROC_BASED_CTLS);
3393b295bcbSPhilippe Mathieu-Daudé      wvmcs(cs->accel->fd, VMCS_PRI_PROC_BASED_CTLS, val &
34069e0a03cSPaolo Bonzini              ~VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING);
34169e0a03cSPaolo Bonzini }
34269e0a03cSPaolo Bonzini 
hvf_inject_interrupts(CPUState * cs)343a7159244SPhilippe Mathieu-Daudé bool hvf_inject_interrupts(CPUState *cs)
34469e0a03cSPaolo Bonzini {
345a7159244SPhilippe Mathieu-Daudé     X86CPU *x86cpu = X86_CPU(cs);
34669e0a03cSPaolo Bonzini     CPUX86State *env = &x86cpu->env;
34769e0a03cSPaolo Bonzini 
34869e0a03cSPaolo Bonzini     uint8_t vector;
34969e0a03cSPaolo Bonzini     uint64_t intr_type;
35069e0a03cSPaolo Bonzini     bool have_event = true;
35169e0a03cSPaolo Bonzini     if (env->interrupt_injected != -1) {
35269e0a03cSPaolo Bonzini         vector = env->interrupt_injected;
35364bef038SCameron Esfahani         if (env->ins_len) {
35469e0a03cSPaolo Bonzini             intr_type = VMCS_INTR_T_SWINTR;
35564bef038SCameron Esfahani         } else {
35664bef038SCameron Esfahani             intr_type = VMCS_INTR_T_HWINTR;
35764bef038SCameron Esfahani         }
358fd13f23bSLiran Alon     } else if (env->exception_nr != -1) {
359fd13f23bSLiran Alon         vector = env->exception_nr;
36069e0a03cSPaolo Bonzini         if (vector == EXCP03_INT3 || vector == EXCP04_INTO) {
36169e0a03cSPaolo Bonzini             intr_type = VMCS_INTR_T_SWEXCEPTION;
36269e0a03cSPaolo Bonzini         } else {
36369e0a03cSPaolo Bonzini             intr_type = VMCS_INTR_T_HWEXCEPTION;
36469e0a03cSPaolo Bonzini         }
36569e0a03cSPaolo Bonzini     } else if (env->nmi_injected) {
36664bef038SCameron Esfahani         vector = EXCP02_NMI;
36769e0a03cSPaolo Bonzini         intr_type = VMCS_INTR_T_NMI;
36869e0a03cSPaolo Bonzini     } else {
36969e0a03cSPaolo Bonzini         have_event = false;
37069e0a03cSPaolo Bonzini     }
37169e0a03cSPaolo Bonzini 
37269e0a03cSPaolo Bonzini     uint64_t info = 0;
37369e0a03cSPaolo Bonzini     if (have_event) {
37469e0a03cSPaolo Bonzini         info = vector | intr_type | VMCS_INTR_VALID;
3753b295bcbSPhilippe Mathieu-Daudé         uint64_t reason = rvmcs(cs->accel->fd, VMCS_EXIT_REASON);
37669e0a03cSPaolo Bonzini         if (env->nmi_injected && reason != EXIT_REASON_TASK_SWITCH) {
377a7159244SPhilippe Mathieu-Daudé             vmx_clear_nmi_blocking(cs);
37869e0a03cSPaolo Bonzini         }
37969e0a03cSPaolo Bonzini 
38069e0a03cSPaolo Bonzini         if (!(env->hflags2 & HF2_NMI_MASK) || intr_type != VMCS_INTR_T_NMI) {
38169e0a03cSPaolo Bonzini             info &= ~(1 << 12); /* clear undefined bit */
38269e0a03cSPaolo Bonzini             if (intr_type == VMCS_INTR_T_SWINTR ||
38369e0a03cSPaolo Bonzini                 intr_type == VMCS_INTR_T_SWEXCEPTION) {
3843b295bcbSPhilippe Mathieu-Daudé                 wvmcs(cs->accel->fd, VMCS_ENTRY_INST_LENGTH, env->ins_len);
38569e0a03cSPaolo Bonzini             }
38669e0a03cSPaolo Bonzini 
38769e0a03cSPaolo Bonzini             if (env->has_error_code) {
3883b295bcbSPhilippe Mathieu-Daudé                 wvmcs(cs->accel->fd, VMCS_ENTRY_EXCEPTION_ERROR,
38969e0a03cSPaolo Bonzini                       env->error_code);
39064bef038SCameron Esfahani                 /* Indicate that VMCS_ENTRY_EXCEPTION_ERROR is valid */
39164bef038SCameron Esfahani                 info |= VMCS_INTR_DEL_ERRCODE;
39269e0a03cSPaolo Bonzini             }
39369e0a03cSPaolo Bonzini             /*printf("reinject  %lx err %d\n", info, err);*/
3943b295bcbSPhilippe Mathieu-Daudé             wvmcs(cs->accel->fd, VMCS_ENTRY_INTR_INFO, info);
39569e0a03cSPaolo Bonzini         };
39669e0a03cSPaolo Bonzini     }
39769e0a03cSPaolo Bonzini 
398a7159244SPhilippe Mathieu-Daudé     if (cs->interrupt_request & CPU_INTERRUPT_NMI) {
39969e0a03cSPaolo Bonzini         if (!(env->hflags2 & HF2_NMI_MASK) && !(info & VMCS_INTR_VALID)) {
400a7159244SPhilippe Mathieu-Daudé             cs->interrupt_request &= ~CPU_INTERRUPT_NMI;
40164bef038SCameron Esfahani             info = VMCS_INTR_VALID | VMCS_INTR_T_NMI | EXCP02_NMI;
4023b295bcbSPhilippe Mathieu-Daudé             wvmcs(cs->accel->fd, VMCS_ENTRY_INTR_INFO, info);
40369e0a03cSPaolo Bonzini         } else {
404a7159244SPhilippe Mathieu-Daudé             vmx_set_nmi_window_exiting(cs);
40569e0a03cSPaolo Bonzini         }
40669e0a03cSPaolo Bonzini     }
40769e0a03cSPaolo Bonzini 
40869e0a03cSPaolo Bonzini     if (!(env->hflags & HF_INHIBIT_IRQ_MASK) &&
409a7159244SPhilippe Mathieu-Daudé         (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
410967f4da2SRoman Bolshakov         (env->eflags & IF_MASK) && !(info & VMCS_INTR_VALID)) {
411ee1004bbSPhilippe Mathieu-Daudé         int line = cpu_get_pic_interrupt(env);
412a7159244SPhilippe Mathieu-Daudé         cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
41369e0a03cSPaolo Bonzini         if (line >= 0) {
4143b295bcbSPhilippe Mathieu-Daudé             wvmcs(cs->accel->fd, VMCS_ENTRY_INTR_INFO, line |
41569e0a03cSPaolo Bonzini                   VMCS_INTR_VALID | VMCS_INTR_T_HWINTR);
41669e0a03cSPaolo Bonzini         }
41769e0a03cSPaolo Bonzini     }
418a7159244SPhilippe Mathieu-Daudé     if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
419a7159244SPhilippe Mathieu-Daudé         vmx_set_int_window_exiting(cs);
42069e0a03cSPaolo Bonzini     }
421a7159244SPhilippe Mathieu-Daudé     return (cs->interrupt_request
42269e0a03cSPaolo Bonzini             & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR));
42369e0a03cSPaolo Bonzini }
42469e0a03cSPaolo Bonzini 
hvf_process_events(CPUState * cs)425a7159244SPhilippe Mathieu-Daudé int hvf_process_events(CPUState *cs)
42669e0a03cSPaolo Bonzini {
427a7159244SPhilippe Mathieu-Daudé     X86CPU *cpu = X86_CPU(cs);
42869e0a03cSPaolo Bonzini     CPUX86State *env = &cpu->env;
42969e0a03cSPaolo Bonzini 
430e6203636SPhilippe Mathieu-Daudé     if (!cs->accel->dirty) {
431bac969efSAlexander Graf         /* light weight sync for CPU_INTERRUPT_HARD and IF_MASK */
4323b295bcbSPhilippe Mathieu-Daudé         env->eflags = rreg(cs->accel->fd, HV_X86_RFLAGS);
433bac969efSAlexander Graf     }
43469e0a03cSPaolo Bonzini 
435a7159244SPhilippe Mathieu-Daudé     if (cs->interrupt_request & CPU_INTERRUPT_INIT) {
436a7159244SPhilippe Mathieu-Daudé         cpu_synchronize_state(cs);
43769e0a03cSPaolo Bonzini         do_cpu_init(cpu);
43869e0a03cSPaolo Bonzini     }
43969e0a03cSPaolo Bonzini 
440a7159244SPhilippe Mathieu-Daudé     if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
441a7159244SPhilippe Mathieu-Daudé         cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
44269e0a03cSPaolo Bonzini         apic_poll_irq(cpu->apic_state);
44369e0a03cSPaolo Bonzini     }
444a7159244SPhilippe Mathieu-Daudé     if (((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
445967f4da2SRoman Bolshakov         (env->eflags & IF_MASK)) ||
446a7159244SPhilippe Mathieu-Daudé         (cs->interrupt_request & CPU_INTERRUPT_NMI)) {
447a7159244SPhilippe Mathieu-Daudé         cs->halted = 0;
44869e0a03cSPaolo Bonzini     }
449a7159244SPhilippe Mathieu-Daudé     if (cs->interrupt_request & CPU_INTERRUPT_SIPI) {
450a7159244SPhilippe Mathieu-Daudé         cpu_synchronize_state(cs);
45169e0a03cSPaolo Bonzini         do_cpu_sipi(cpu);
45269e0a03cSPaolo Bonzini     }
453a7159244SPhilippe Mathieu-Daudé     if (cs->interrupt_request & CPU_INTERRUPT_TPR) {
454a7159244SPhilippe Mathieu-Daudé         cs->interrupt_request &= ~CPU_INTERRUPT_TPR;
455a7159244SPhilippe Mathieu-Daudé         cpu_synchronize_state(cs);
45669e0a03cSPaolo Bonzini         apic_handle_tpr_access_report(cpu->apic_state, env->eip,
45769e0a03cSPaolo Bonzini                                       env->tpr_access_type);
45869e0a03cSPaolo Bonzini     }
459a7159244SPhilippe Mathieu-Daudé     return cs->halted;
46069e0a03cSPaolo Bonzini }
461