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
98af82b8eSChetan Pant * version 2.1 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
22c97d6d2cSSergio Andres Gomez Del Real #include "x86hvf.h"
23c97d6d2cSSergio Andres Gomez Del Real #include "vmx.h"
24c97d6d2cSSergio Andres Gomez Del Real #include "vmcs.h"
25c97d6d2cSSergio Andres Gomez Del Real #include "cpu.h"
26c97d6d2cSSergio Andres Gomez Del Real #include "x86_descr.h"
27*27458df8SWei Liu #include "emulate/x86_decode.h"
2832cad1ffSPhilippe Mathieu-Daudé #include "system/hw_accel.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 <Hypervisor/hv.h>
33c97d6d2cSSergio Andres Gomez Del Real #include <Hypervisor/hv_vmx.h>
34c97d6d2cSSergio Andres Gomez Del Real
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,
36c97d6d2cSSergio Andres Gomez Del Real SegmentCache *qseg, bool is_tr)
37c97d6d2cSSergio Andres Gomez Del Real {
38c97d6d2cSSergio Andres Gomez Del Real vmx_seg->sel = qseg->selector;
39c97d6d2cSSergio Andres Gomez Del Real vmx_seg->base = qseg->base;
40c97d6d2cSSergio Andres Gomez Del Real vmx_seg->limit = qseg->limit;
41c97d6d2cSSergio Andres Gomez Del Real
42a7159244SPhilippe Mathieu-Daudé if (!qseg->selector && !x86_is_real(cs) && !is_tr) {
43c97d6d2cSSergio Andres Gomez Del Real /* the TR register is usable after processor reset despite
44c97d6d2cSSergio Andres Gomez Del Real * having a null selector */
45c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar = 1 << 16;
46c97d6d2cSSergio Andres Gomez Del Real return;
47c97d6d2cSSergio Andres Gomez Del Real }
48c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar = (qseg->flags >> DESC_TYPE_SHIFT) & 0xf;
49c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar |= ((qseg->flags >> DESC_G_SHIFT) & 1) << 15;
50c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar |= ((qseg->flags >> DESC_B_SHIFT) & 1) << 14;
51c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar |= ((qseg->flags >> DESC_L_SHIFT) & 1) << 13;
52c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar |= ((qseg->flags >> DESC_AVL_SHIFT) & 1) << 12;
53c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar |= ((qseg->flags >> DESC_P_SHIFT) & 1) << 7;
54c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar |= ((qseg->flags >> DESC_DPL_SHIFT) & 3) << 5;
55c97d6d2cSSergio Andres Gomez Del Real vmx_seg->ar |= ((qseg->flags >> DESC_S_SHIFT) & 1) << 4;
56c97d6d2cSSergio Andres Gomez Del Real }
57c97d6d2cSSergio Andres Gomez Del Real
hvf_get_segment(SegmentCache * qseg,struct vmx_segment * vmx_seg)58c97d6d2cSSergio Andres Gomez Del Real void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg)
59c97d6d2cSSergio Andres Gomez Del Real {
60c97d6d2cSSergio Andres Gomez Del Real qseg->limit = vmx_seg->limit;
61c97d6d2cSSergio Andres Gomez Del Real qseg->base = vmx_seg->base;
62c97d6d2cSSergio Andres Gomez Del Real qseg->selector = vmx_seg->sel;
63c97d6d2cSSergio Andres Gomez Del Real qseg->flags = ((vmx_seg->ar & 0xf) << DESC_TYPE_SHIFT) |
64c97d6d2cSSergio Andres Gomez Del Real (((vmx_seg->ar >> 4) & 1) << DESC_S_SHIFT) |
65c97d6d2cSSergio Andres Gomez Del Real (((vmx_seg->ar >> 5) & 3) << DESC_DPL_SHIFT) |
66c97d6d2cSSergio Andres Gomez Del Real (((vmx_seg->ar >> 7) & 1) << DESC_P_SHIFT) |
67c97d6d2cSSergio Andres Gomez Del Real (((vmx_seg->ar >> 12) & 1) << DESC_AVL_SHIFT) |
68c97d6d2cSSergio Andres Gomez Del Real (((vmx_seg->ar >> 13) & 1) << DESC_L_SHIFT) |
69c97d6d2cSSergio Andres Gomez Del Real (((vmx_seg->ar >> 14) & 1) << DESC_B_SHIFT) |
70c97d6d2cSSergio Andres Gomez Del Real (((vmx_seg->ar >> 15) & 1) << DESC_G_SHIFT);
71c97d6d2cSSergio Andres Gomez Del Real }
72c97d6d2cSSergio Andres Gomez Del Real
hvf_put_xsave(CPUState * cs)73a7159244SPhilippe Mathieu-Daudé void hvf_put_xsave(CPUState *cs)
74c97d6d2cSSergio Andres Gomez Del Real {
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;
77c97d6d2cSSergio Andres Gomez Del Real
78a7159244SPhilippe Mathieu-Daudé x86_cpu_xsave_all_areas(X86_CPU(cs), xsave, xsave_len);
79c97d6d2cSSergio Andres Gomez Del Real
803b295bcbSPhilippe Mathieu-Daudé if (hv_vcpu_write_fpstate(cs->accel->fd, xsave, xsave_len)) {
81c97d6d2cSSergio Andres Gomez Del Real abort();
82c97d6d2cSSergio Andres Gomez Del Real }
83c97d6d2cSSergio Andres Gomez Del Real }
84c97d6d2cSSergio Andres Gomez Del Real
hvf_put_segments(CPUState * cs)85a7159244SPhilippe Mathieu-Daudé static void hvf_put_segments(CPUState *cs)
86c97d6d2cSSergio Andres Gomez Del Real {
87a7159244SPhilippe Mathieu-Daudé CPUX86State *env = &X86_CPU(cs)->env;
88c97d6d2cSSergio Andres Gomez Del Real struct vmx_segment seg;
89c97d6d2cSSergio Andres Gomez Del Real
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);
92c97d6d2cSSergio Andres Gomez Del Real
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);
95c97d6d2cSSergio Andres Gomez Del Real
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);
100c97d6d2cSSergio Andres Gomez Del Real
1013b295bcbSPhilippe Mathieu-Daudé macvm_set_cr4(cs->accel->fd, env->cr[4]);
1023b295bcbSPhilippe Mathieu-Daudé macvm_set_cr0(cs->accel->fd, env->cr[0]);
103c97d6d2cSSergio Andres Gomez Del Real
104a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->segs[R_CS], false);
105a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_CS);
106c97d6d2cSSergio Andres Gomez Del Real
107a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->segs[R_DS], false);
108a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_DS);
109c97d6d2cSSergio Andres Gomez Del Real
110a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->segs[R_ES], false);
111a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_ES);
112c97d6d2cSSergio Andres Gomez Del Real
113a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->segs[R_SS], false);
114a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_SS);
115c97d6d2cSSergio Andres Gomez Del Real
116a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->segs[R_FS], false);
117a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_FS);
118c97d6d2cSSergio Andres Gomez Del Real
119a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->segs[R_GS], false);
120a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_GS);
121c97d6d2cSSergio Andres Gomez Del Real
122a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->tr, true);
123a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_TR);
124c97d6d2cSSergio Andres Gomez Del Real
125a7159244SPhilippe Mathieu-Daudé hvf_set_segment(cs, &seg, &env->ldt, false);
126a7159244SPhilippe Mathieu-Daudé vmx_write_segment_descriptor(cs, &seg, R_LDTR);
127c97d6d2cSSergio Andres Gomez Del Real }
128c97d6d2cSSergio Andres Gomez Del Real
hvf_put_msrs(CPUState * cs)129a7159244SPhilippe Mathieu-Daudé void hvf_put_msrs(CPUState *cs)
130c97d6d2cSSergio Andres Gomez Del Real {
131a7159244SPhilippe Mathieu-Daudé CPUX86State *env = &X86_CPU(cs)->env;
132c97d6d2cSSergio Andres Gomez Del Real
1333b295bcbSPhilippe Mathieu-Daudé hv_vcpu_write_msr(cs->accel->fd, MSR_IA32_SYSENTER_CS,
134c97d6d2cSSergio Andres Gomez Del Real env->sysenter_cs);
1353b295bcbSPhilippe Mathieu-Daudé hv_vcpu_write_msr(cs->accel->fd, MSR_IA32_SYSENTER_ESP,
136c97d6d2cSSergio Andres Gomez Del Real env->sysenter_esp);
1373b295bcbSPhilippe Mathieu-Daudé hv_vcpu_write_msr(cs->accel->fd, MSR_IA32_SYSENTER_EIP,
138c97d6d2cSSergio Andres Gomez Del Real env->sysenter_eip);
139c97d6d2cSSergio Andres Gomez Del Real
1403b295bcbSPhilippe Mathieu-Daudé hv_vcpu_write_msr(cs->accel->fd, MSR_STAR, env->star);
141c97d6d2cSSergio Andres Gomez Del Real
142c97d6d2cSSergio Andres Gomez Del Real #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);
147c97d6d2cSSergio Andres Gomez Del Real #endif
148c97d6d2cSSergio Andres Gomez Del Real
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);
151c97d6d2cSSergio Andres Gomez Del Real }
152c97d6d2cSSergio Andres Gomez Del Real
153c97d6d2cSSergio Andres Gomez Del Real
hvf_get_xsave(CPUState * cs)154a7159244SPhilippe Mathieu-Daudé void hvf_get_xsave(CPUState *cs)
155c97d6d2cSSergio Andres Gomez Del Real {
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;
158c97d6d2cSSergio Andres Gomez Del Real
1593b295bcbSPhilippe Mathieu-Daudé if (hv_vcpu_read_fpstate(cs->accel->fd, xsave, xsave_len)) {
160c97d6d2cSSergio Andres Gomez Del Real abort();
161c97d6d2cSSergio Andres Gomez Del Real }
162c97d6d2cSSergio Andres Gomez Del Real
163a7159244SPhilippe Mathieu-Daudé x86_cpu_xrstor_all_areas(X86_CPU(cs), xsave, xsave_len);
164c97d6d2cSSergio Andres Gomez Del Real }
165c97d6d2cSSergio Andres Gomez Del Real
hvf_get_segments(CPUState * cs)166a7159244SPhilippe Mathieu-Daudé static void hvf_get_segments(CPUState *cs)
167c97d6d2cSSergio Andres Gomez Del Real {
168a7159244SPhilippe Mathieu-Daudé CPUX86State *env = &X86_CPU(cs)->env;
169c97d6d2cSSergio Andres Gomez Del Real
170c97d6d2cSSergio Andres Gomez Del Real struct vmx_segment seg;
171c97d6d2cSSergio Andres Gomez Del Real
172c97d6d2cSSergio Andres Gomez Del Real env->interrupt_injected = -1;
173c97d6d2cSSergio Andres Gomez Del Real
174a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_CS);
175c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->segs[R_CS], &seg);
176c97d6d2cSSergio Andres Gomez Del Real
177a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_DS);
178c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->segs[R_DS], &seg);
179c97d6d2cSSergio Andres Gomez Del Real
180a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_ES);
181c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->segs[R_ES], &seg);
182c97d6d2cSSergio Andres Gomez Del Real
183a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_FS);
184c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->segs[R_FS], &seg);
185c97d6d2cSSergio Andres Gomez Del Real
186a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_GS);
187c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->segs[R_GS], &seg);
188c97d6d2cSSergio Andres Gomez Del Real
189a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_SS);
190c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->segs[R_SS], &seg);
191c97d6d2cSSergio Andres Gomez Del Real
192a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_TR);
193c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->tr, &seg);
194c97d6d2cSSergio Andres Gomez Del Real
195a7159244SPhilippe Mathieu-Daudé vmx_read_segment_descriptor(cs, &seg, R_LDTR);
196c97d6d2cSSergio Andres Gomez Del Real hvf_get_segment(&env->ldt, &seg);
197c97d6d2cSSergio Andres Gomez Del Real
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);
202c97d6d2cSSergio Andres Gomez Del Real
2033b295bcbSPhilippe Mathieu-Daudé env->cr[0] = rvmcs(cs->accel->fd, VMCS_GUEST_CR0);
204c97d6d2cSSergio Andres Gomez Del Real 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);
207c97d6d2cSSergio Andres Gomez Del Real
2083b295bcbSPhilippe Mathieu-Daudé env->efer = rvmcs(cs->accel->fd, VMCS_GUEST_IA32_EFER);
209c97d6d2cSSergio Andres Gomez Del Real }
210c97d6d2cSSergio Andres Gomez Del Real
hvf_get_msrs(CPUState * cs)211a7159244SPhilippe Mathieu-Daudé void hvf_get_msrs(CPUState *cs)
212c97d6d2cSSergio Andres Gomez Del Real {
213a7159244SPhilippe Mathieu-Daudé CPUX86State *env = &X86_CPU(cs)->env;
214c97d6d2cSSergio Andres Gomez Del Real uint64_t tmp;
215c97d6d2cSSergio Andres Gomez Del Real
2163b295bcbSPhilippe Mathieu-Daudé hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_SYSENTER_CS, &tmp);
217c97d6d2cSSergio Andres Gomez Del Real env->sysenter_cs = tmp;
218c97d6d2cSSergio Andres Gomez Del Real
2193b295bcbSPhilippe Mathieu-Daudé hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_SYSENTER_ESP, &tmp);
220c97d6d2cSSergio Andres Gomez Del Real env->sysenter_esp = tmp;
221c97d6d2cSSergio Andres Gomez Del Real
2223b295bcbSPhilippe Mathieu-Daudé hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_SYSENTER_EIP, &tmp);
223c97d6d2cSSergio Andres Gomez Del Real env->sysenter_eip = tmp;
224c97d6d2cSSergio Andres Gomez Del Real
2253b295bcbSPhilippe Mathieu-Daudé hv_vcpu_read_msr(cs->accel->fd, MSR_STAR, &env->star);
226c97d6d2cSSergio Andres Gomez Del Real
227c97d6d2cSSergio Andres Gomez Del Real #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);
232c97d6d2cSSergio Andres Gomez Del Real #endif
233c97d6d2cSSergio Andres Gomez Del Real
2343b295bcbSPhilippe Mathieu-Daudé hv_vcpu_read_msr(cs->accel->fd, MSR_IA32_APICBASE, &tmp);
235c97d6d2cSSergio Andres Gomez Del Real
2363b295bcbSPhilippe Mathieu-Daudé env->tsc = rdtscp() + rvmcs(cs->accel->fd, VMCS_TSC_OFFSET);
237c97d6d2cSSergio Andres Gomez Del Real }
238c97d6d2cSSergio Andres Gomez Del Real
hvf_put_registers(CPUState * cs)239a7159244SPhilippe Mathieu-Daudé int hvf_put_registers(CPUState *cs)
240c97d6d2cSSergio Andres Gomez Del Real {
241a7159244SPhilippe Mathieu-Daudé X86CPU *x86cpu = X86_CPU(cs);
242c97d6d2cSSergio Andres Gomez Del Real CPUX86State *env = &x86cpu->env;
243c97d6d2cSSergio Andres Gomez Del Real
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);
262c97d6d2cSSergio Andres Gomez Del Real
2633b295bcbSPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_XCR0, env->xcr0);
264c97d6d2cSSergio Andres Gomez Del Real
265a7159244SPhilippe Mathieu-Daudé hvf_put_xsave(cs);
266c97d6d2cSSergio Andres Gomez Del Real
267a7159244SPhilippe Mathieu-Daudé hvf_put_segments(cs);
268c97d6d2cSSergio Andres Gomez Del Real
269a7159244SPhilippe Mathieu-Daudé hvf_put_msrs(cs);
270c97d6d2cSSergio Andres Gomez Del Real
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]);
279c97d6d2cSSergio Andres Gomez Del Real
280c97d6d2cSSergio Andres Gomez Del Real return 0;
281c97d6d2cSSergio Andres Gomez Del Real }
282c97d6d2cSSergio Andres Gomez Del Real
hvf_get_registers(CPUState * cs)283a7159244SPhilippe Mathieu-Daudé int hvf_get_registers(CPUState *cs)
284c97d6d2cSSergio Andres Gomez Del Real {
285a7159244SPhilippe Mathieu-Daudé X86CPU *x86cpu = X86_CPU(cs);
286c97d6d2cSSergio Andres Gomez Del Real CPUX86State *env = &x86cpu->env;
287c97d6d2cSSergio Andres Gomez Del Real
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);
304c97d6d2cSSergio Andres Gomez Del Real
3053b295bcbSPhilippe Mathieu-Daudé env->eflags = rreg(cs->accel->fd, HV_X86_RFLAGS);
3063b295bcbSPhilippe Mathieu-Daudé env->eip = rreg(cs->accel->fd, HV_X86_RIP);
307c97d6d2cSSergio Andres Gomez Del Real
308a7159244SPhilippe Mathieu-Daudé hvf_get_xsave(cs);
3093b295bcbSPhilippe Mathieu-Daudé env->xcr0 = rreg(cs->accel->fd, HV_X86_XCR0);
310c97d6d2cSSergio Andres Gomez Del Real
311a7159244SPhilippe Mathieu-Daudé hvf_get_segments(cs);
312a7159244SPhilippe Mathieu-Daudé hvf_get_msrs(cs);
313c97d6d2cSSergio Andres Gomez Del Real
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);
322c97d6d2cSSergio Andres Gomez Del Real
323809092f3SPaolo Bonzini x86_update_hflags(env);
324c97d6d2cSSergio Andres Gomez Del Real return 0;
325c97d6d2cSSergio Andres Gomez Del Real }
326c97d6d2cSSergio Andres Gomez Del Real
vmx_set_int_window_exiting(CPUState * cs)327a7159244SPhilippe Mathieu-Daudé static void vmx_set_int_window_exiting(CPUState *cs)
328c97d6d2cSSergio Andres Gomez Del Real {
329c97d6d2cSSergio Andres Gomez Del Real 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 |
332c97d6d2cSSergio Andres Gomez Del Real VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING);
333c97d6d2cSSergio Andres Gomez Del Real }
334c97d6d2cSSergio Andres Gomez Del Real
vmx_clear_int_window_exiting(CPUState * cs)335a7159244SPhilippe Mathieu-Daudé void vmx_clear_int_window_exiting(CPUState *cs)
336c97d6d2cSSergio Andres Gomez Del Real {
337c97d6d2cSSergio Andres Gomez Del Real 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 &
340c97d6d2cSSergio Andres Gomez Del Real ~VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING);
341c97d6d2cSSergio Andres Gomez Del Real }
342c97d6d2cSSergio Andres Gomez Del Real
hvf_inject_interrupts(CPUState * cs)343a7159244SPhilippe Mathieu-Daudé bool hvf_inject_interrupts(CPUState *cs)
344c97d6d2cSSergio Andres Gomez Del Real {
345a7159244SPhilippe Mathieu-Daudé X86CPU *x86cpu = X86_CPU(cs);
346c97d6d2cSSergio Andres Gomez Del Real CPUX86State *env = &x86cpu->env;
347c97d6d2cSSergio Andres Gomez Del Real
348b7394c83SSergio Andres Gomez Del Real uint8_t vector;
349b7394c83SSergio Andres Gomez Del Real uint64_t intr_type;
350b7394c83SSergio Andres Gomez Del Real bool have_event = true;
351b7394c83SSergio Andres Gomez Del Real if (env->interrupt_injected != -1) {
352b7394c83SSergio Andres Gomez Del Real vector = env->interrupt_injected;
35364bef038SCameron Esfahani if (env->ins_len) {
354b7394c83SSergio Andres Gomez Del Real 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;
360b7394c83SSergio Andres Gomez Del Real if (vector == EXCP03_INT3 || vector == EXCP04_INTO) {
361b7394c83SSergio Andres Gomez Del Real intr_type = VMCS_INTR_T_SWEXCEPTION;
362b7394c83SSergio Andres Gomez Del Real } else {
363b7394c83SSergio Andres Gomez Del Real intr_type = VMCS_INTR_T_HWEXCEPTION;
364b7394c83SSergio Andres Gomez Del Real }
365b7394c83SSergio Andres Gomez Del Real } else if (env->nmi_injected) {
36664bef038SCameron Esfahani vector = EXCP02_NMI;
367b7394c83SSergio Andres Gomez Del Real intr_type = VMCS_INTR_T_NMI;
368b7394c83SSergio Andres Gomez Del Real } else {
369b7394c83SSergio Andres Gomez Del Real have_event = false;
370b7394c83SSergio Andres Gomez Del Real }
371b7394c83SSergio Andres Gomez Del Real
372c97d6d2cSSergio Andres Gomez Del Real uint64_t info = 0;
373b7394c83SSergio Andres Gomez Del Real if (have_event) {
374b7394c83SSergio Andres Gomez Del Real info = vector | intr_type | VMCS_INTR_VALID;
3753b295bcbSPhilippe Mathieu-Daudé uint64_t reason = rvmcs(cs->accel->fd, VMCS_EXIT_REASON);
376b7394c83SSergio Andres Gomez Del Real if (env->nmi_injected && reason != EXIT_REASON_TASK_SWITCH) {
377a7159244SPhilippe Mathieu-Daudé vmx_clear_nmi_blocking(cs);
378c97d6d2cSSergio Andres Gomez Del Real }
379c97d6d2cSSergio Andres Gomez Del Real
380b7394c83SSergio Andres Gomez Del Real if (!(env->hflags2 & HF2_NMI_MASK) || intr_type != VMCS_INTR_T_NMI) {
381c97d6d2cSSergio Andres Gomez Del Real info &= ~(1 << 12); /* clear undefined bit */
382c97d6d2cSSergio Andres Gomez Del Real if (intr_type == VMCS_INTR_T_SWINTR ||
383c97d6d2cSSergio Andres Gomez Del Real intr_type == VMCS_INTR_T_SWEXCEPTION) {
3843b295bcbSPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_ENTRY_INST_LENGTH, env->ins_len);
385c97d6d2cSSergio Andres Gomez Del Real }
386c97d6d2cSSergio Andres Gomez Del Real
387b7394c83SSergio Andres Gomez Del Real if (env->has_error_code) {
3883b295bcbSPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_ENTRY_EXCEPTION_ERROR,
389b7394c83SSergio Andres Gomez Del Real env->error_code);
39064bef038SCameron Esfahani /* Indicate that VMCS_ENTRY_EXCEPTION_ERROR is valid */
39164bef038SCameron Esfahani info |= VMCS_INTR_DEL_ERRCODE;
392c97d6d2cSSergio Andres Gomez Del Real }
393c97d6d2cSSergio Andres Gomez Del Real /*printf("reinject %lx err %d\n", info, err);*/
3943b295bcbSPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_ENTRY_INTR_INFO, info);
395c97d6d2cSSergio Andres Gomez Del Real };
396c97d6d2cSSergio Andres Gomez Del Real }
397c97d6d2cSSergio Andres Gomez Del Real
398a7159244SPhilippe Mathieu-Daudé if (cs->interrupt_request & CPU_INTERRUPT_NMI) {
399b7394c83SSergio Andres Gomez Del Real 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);
403c97d6d2cSSergio Andres Gomez Del Real } else {
404a7159244SPhilippe Mathieu-Daudé vmx_set_nmi_window_exiting(cs);
405c97d6d2cSSergio Andres Gomez Del Real }
406c97d6d2cSSergio Andres Gomez Del Real }
407c97d6d2cSSergio Andres Gomez Del Real
408b7394c83SSergio Andres Gomez Del Real 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;
413c97d6d2cSSergio Andres Gomez Del Real if (line >= 0) {
4143b295bcbSPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_ENTRY_INTR_INFO, line |
415c97d6d2cSSergio Andres Gomez Del Real VMCS_INTR_VALID | VMCS_INTR_T_HWINTR);
416c97d6d2cSSergio Andres Gomez Del Real }
417c97d6d2cSSergio Andres Gomez Del Real }
418a7159244SPhilippe Mathieu-Daudé if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
419a7159244SPhilippe Mathieu-Daudé vmx_set_int_window_exiting(cs);
420c97d6d2cSSergio Andres Gomez Del Real }
421a7159244SPhilippe Mathieu-Daudé return (cs->interrupt_request
422b7394c83SSergio Andres Gomez Del Real & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR));
423c97d6d2cSSergio Andres Gomez Del Real }
424c97d6d2cSSergio Andres Gomez Del Real
hvf_process_events(CPUState * cs)425a7159244SPhilippe Mathieu-Daudé int hvf_process_events(CPUState *cs)
426c97d6d2cSSergio Andres Gomez Del Real {
427a7159244SPhilippe Mathieu-Daudé X86CPU *cpu = X86_CPU(cs);
428c97d6d2cSSergio Andres Gomez Del Real CPUX86State *env = &cpu->env;
429c97d6d2cSSergio Andres Gomez Del Real
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 }
434c97d6d2cSSergio Andres Gomez Del Real
435a7159244SPhilippe Mathieu-Daudé if (cs->interrupt_request & CPU_INTERRUPT_INIT) {
436a7159244SPhilippe Mathieu-Daudé cpu_synchronize_state(cs);
437c97d6d2cSSergio Andres Gomez Del Real do_cpu_init(cpu);
438c97d6d2cSSergio Andres Gomez Del Real }
439c97d6d2cSSergio Andres Gomez Del Real
440a7159244SPhilippe Mathieu-Daudé if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
441a7159244SPhilippe Mathieu-Daudé cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
442c97d6d2cSSergio Andres Gomez Del Real apic_poll_irq(cpu->apic_state);
443c97d6d2cSSergio Andres Gomez Del Real }
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;
448c97d6d2cSSergio Andres Gomez Del Real }
449a7159244SPhilippe Mathieu-Daudé if (cs->interrupt_request & CPU_INTERRUPT_SIPI) {
450a7159244SPhilippe Mathieu-Daudé cpu_synchronize_state(cs);
451c97d6d2cSSergio Andres Gomez Del Real do_cpu_sipi(cpu);
452c97d6d2cSSergio Andres Gomez Del Real }
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);
456c97d6d2cSSergio Andres Gomez Del Real apic_handle_tpr_access_report(cpu->apic_state, env->eip,
457c97d6d2cSSergio Andres Gomez Del Real env->tpr_access_type);
458c97d6d2cSSergio Andres Gomez Del Real }
459a7159244SPhilippe Mathieu-Daudé return cs->halted;
460c97d6d2cSSergio Andres Gomez Del Real }
461