xref: /openbmc/qemu/target/i386/nvmm/nvmm-all.c (revision 97c872276d147c882296f5da245bd8432f1582f6)
1fdc8635eSReinoud Zandijk /*
2fdc8635eSReinoud Zandijk  * Copyright (c) 2018-2019 Maxime Villard, All rights reserved.
3fdc8635eSReinoud Zandijk  *
4fdc8635eSReinoud Zandijk  * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU.
5fdc8635eSReinoud Zandijk  *
6fdc8635eSReinoud Zandijk  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7fdc8635eSReinoud Zandijk  * See the COPYING file in the top-level directory.
8fdc8635eSReinoud Zandijk  */
9fdc8635eSReinoud Zandijk 
10fdc8635eSReinoud Zandijk #include "qemu/osdep.h"
11fdc8635eSReinoud Zandijk #include "cpu.h"
12fdc8635eSReinoud Zandijk #include "exec/address-spaces.h"
13fdc8635eSReinoud Zandijk #include "exec/ioport.h"
14fdc8635eSReinoud Zandijk #include "qemu/accel.h"
15fdc8635eSReinoud Zandijk #include "sysemu/nvmm.h"
16fdc8635eSReinoud Zandijk #include "sysemu/cpus.h"
17fdc8635eSReinoud Zandijk #include "sysemu/runstate.h"
18fdc8635eSReinoud Zandijk #include "qemu/main-loop.h"
19fdc8635eSReinoud Zandijk #include "qemu/error-report.h"
20fdc8635eSReinoud Zandijk #include "qapi/error.h"
21fdc8635eSReinoud Zandijk #include "qemu/queue.h"
22fdc8635eSReinoud Zandijk #include "migration/blocker.h"
23fdc8635eSReinoud Zandijk #include "strings.h"
24fdc8635eSReinoud Zandijk 
25fdc8635eSReinoud Zandijk #include "nvmm-accel-ops.h"
26fdc8635eSReinoud Zandijk 
27fdc8635eSReinoud Zandijk #include <nvmm.h>
28fdc8635eSReinoud Zandijk 
29c5beb26aSPhilippe Mathieu-Daudé struct AccelCPUState {
30fdc8635eSReinoud Zandijk     struct nvmm_vcpu vcpu;
31fdc8635eSReinoud Zandijk     uint8_t tpr;
32fdc8635eSReinoud Zandijk     bool stop;
3379f1926bSPhilippe Mathieu-Daudé     bool dirty;
34fdc8635eSReinoud Zandijk 
35fdc8635eSReinoud Zandijk     /* Window-exiting for INTs/NMIs. */
36fdc8635eSReinoud Zandijk     bool int_window_exit;
37fdc8635eSReinoud Zandijk     bool nmi_window_exit;
38fdc8635eSReinoud Zandijk 
39fdc8635eSReinoud Zandijk     /* The guest is in an interrupt shadow (POP SS, etc). */
40fdc8635eSReinoud Zandijk     bool int_shadow;
41fdc8635eSReinoud Zandijk };
42fdc8635eSReinoud Zandijk 
43fdc8635eSReinoud Zandijk struct qemu_machine {
44fdc8635eSReinoud Zandijk     struct nvmm_capability cap;
45fdc8635eSReinoud Zandijk     struct nvmm_machine mach;
46fdc8635eSReinoud Zandijk };
47fdc8635eSReinoud Zandijk 
48fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
49fdc8635eSReinoud Zandijk 
50fdc8635eSReinoud Zandijk static bool nvmm_allowed;
51fdc8635eSReinoud Zandijk static struct qemu_machine qemu_mach;
52fdc8635eSReinoud Zandijk 
53fdc8635eSReinoud Zandijk static struct nvmm_machine *
get_nvmm_mach(void)54fdc8635eSReinoud Zandijk get_nvmm_mach(void)
55fdc8635eSReinoud Zandijk {
56fdc8635eSReinoud Zandijk     return &qemu_mach.mach;
57fdc8635eSReinoud Zandijk }
58fdc8635eSReinoud Zandijk 
59fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
60fdc8635eSReinoud Zandijk 
61fdc8635eSReinoud Zandijk static void
nvmm_set_segment(struct nvmm_x64_state_seg * nseg,const SegmentCache * qseg)62fdc8635eSReinoud Zandijk nvmm_set_segment(struct nvmm_x64_state_seg *nseg, const SegmentCache *qseg)
63fdc8635eSReinoud Zandijk {
64fdc8635eSReinoud Zandijk     uint32_t attrib = qseg->flags;
65fdc8635eSReinoud Zandijk 
66fdc8635eSReinoud Zandijk     nseg->selector = qseg->selector;
67fdc8635eSReinoud Zandijk     nseg->limit = qseg->limit;
68fdc8635eSReinoud Zandijk     nseg->base = qseg->base;
69fdc8635eSReinoud Zandijk     nseg->attrib.type = __SHIFTOUT(attrib, DESC_TYPE_MASK);
70fdc8635eSReinoud Zandijk     nseg->attrib.s = __SHIFTOUT(attrib, DESC_S_MASK);
71fdc8635eSReinoud Zandijk     nseg->attrib.dpl = __SHIFTOUT(attrib, DESC_DPL_MASK);
72fdc8635eSReinoud Zandijk     nseg->attrib.p = __SHIFTOUT(attrib, DESC_P_MASK);
73fdc8635eSReinoud Zandijk     nseg->attrib.avl = __SHIFTOUT(attrib, DESC_AVL_MASK);
74fdc8635eSReinoud Zandijk     nseg->attrib.l = __SHIFTOUT(attrib, DESC_L_MASK);
75fdc8635eSReinoud Zandijk     nseg->attrib.def = __SHIFTOUT(attrib, DESC_B_MASK);
76fdc8635eSReinoud Zandijk     nseg->attrib.g = __SHIFTOUT(attrib, DESC_G_MASK);
77fdc8635eSReinoud Zandijk }
78fdc8635eSReinoud Zandijk 
79fdc8635eSReinoud Zandijk static void
nvmm_set_registers(CPUState * cpu)80fdc8635eSReinoud Zandijk nvmm_set_registers(CPUState *cpu)
81fdc8635eSReinoud Zandijk {
82b77af26eSRichard Henderson     CPUX86State *env = cpu_env(cpu);
83fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
842f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
85fdc8635eSReinoud Zandijk     struct nvmm_vcpu *vcpu = &qcpu->vcpu;
86fdc8635eSReinoud Zandijk     struct nvmm_x64_state *state = vcpu->state;
87fdc8635eSReinoud Zandijk     uint64_t bitmap;
88fdc8635eSReinoud Zandijk     size_t i;
89fdc8635eSReinoud Zandijk     int ret;
90fdc8635eSReinoud Zandijk 
91fdc8635eSReinoud Zandijk     assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
92fdc8635eSReinoud Zandijk 
93fdc8635eSReinoud Zandijk     /* GPRs. */
94fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RAX] = env->regs[R_EAX];
95fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RCX] = env->regs[R_ECX];
96fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RDX] = env->regs[R_EDX];
97fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RBX] = env->regs[R_EBX];
98fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RSP] = env->regs[R_ESP];
99fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RBP] = env->regs[R_EBP];
100fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RSI] = env->regs[R_ESI];
101fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RDI] = env->regs[R_EDI];
102fdc8635eSReinoud Zandijk #ifdef TARGET_X86_64
103fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R8]  = env->regs[R_R8];
104fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R9]  = env->regs[R_R9];
105fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R10] = env->regs[R_R10];
106fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R11] = env->regs[R_R11];
107fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R12] = env->regs[R_R12];
108fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R13] = env->regs[R_R13];
109fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R14] = env->regs[R_R14];
110fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_R15] = env->regs[R_R15];
111fdc8635eSReinoud Zandijk #endif
112fdc8635eSReinoud Zandijk 
113fdc8635eSReinoud Zandijk     /* RIP and RFLAGS. */
114fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RIP] = env->eip;
115fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RFLAGS] = env->eflags;
116fdc8635eSReinoud Zandijk 
117fdc8635eSReinoud Zandijk     /* Segments. */
118fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_CS], &env->segs[R_CS]);
119fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_DS], &env->segs[R_DS]);
120fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_ES], &env->segs[R_ES]);
121fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_FS], &env->segs[R_FS]);
122fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_GS], &env->segs[R_GS]);
123fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_SS], &env->segs[R_SS]);
124fdc8635eSReinoud Zandijk 
125fdc8635eSReinoud Zandijk     /* Special segments. */
126fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_GDT], &env->gdt);
127fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_LDT], &env->ldt);
128fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_TR], &env->tr);
129fdc8635eSReinoud Zandijk     nvmm_set_segment(&state->segs[NVMM_X64_SEG_IDT], &env->idt);
130fdc8635eSReinoud Zandijk 
131fdc8635eSReinoud Zandijk     /* Control registers. */
132fdc8635eSReinoud Zandijk     state->crs[NVMM_X64_CR_CR0] = env->cr[0];
133fdc8635eSReinoud Zandijk     state->crs[NVMM_X64_CR_CR2] = env->cr[2];
134fdc8635eSReinoud Zandijk     state->crs[NVMM_X64_CR_CR3] = env->cr[3];
135fdc8635eSReinoud Zandijk     state->crs[NVMM_X64_CR_CR4] = env->cr[4];
136fdc8635eSReinoud Zandijk     state->crs[NVMM_X64_CR_CR8] = qcpu->tpr;
137fdc8635eSReinoud Zandijk     state->crs[NVMM_X64_CR_XCR0] = env->xcr0;
138fdc8635eSReinoud Zandijk 
139fdc8635eSReinoud Zandijk     /* Debug registers. */
140fdc8635eSReinoud Zandijk     state->drs[NVMM_X64_DR_DR0] = env->dr[0];
141fdc8635eSReinoud Zandijk     state->drs[NVMM_X64_DR_DR1] = env->dr[1];
142fdc8635eSReinoud Zandijk     state->drs[NVMM_X64_DR_DR2] = env->dr[2];
143fdc8635eSReinoud Zandijk     state->drs[NVMM_X64_DR_DR3] = env->dr[3];
144fdc8635eSReinoud Zandijk     state->drs[NVMM_X64_DR_DR6] = env->dr[6];
145fdc8635eSReinoud Zandijk     state->drs[NVMM_X64_DR_DR7] = env->dr[7];
146fdc8635eSReinoud Zandijk 
147fdc8635eSReinoud Zandijk     /* FPU. */
148fdc8635eSReinoud Zandijk     state->fpu.fx_cw = env->fpuc;
149fdc8635eSReinoud Zandijk     state->fpu.fx_sw = (env->fpus & ~0x3800) | ((env->fpstt & 0x7) << 11);
150fdc8635eSReinoud Zandijk     state->fpu.fx_tw = 0;
151fdc8635eSReinoud Zandijk     for (i = 0; i < 8; i++) {
152fdc8635eSReinoud Zandijk         state->fpu.fx_tw |= (!env->fptags[i]) << i;
153fdc8635eSReinoud Zandijk     }
154fdc8635eSReinoud Zandijk     state->fpu.fx_opcode = env->fpop;
155fdc8635eSReinoud Zandijk     state->fpu.fx_ip.fa_64 = env->fpip;
156fdc8635eSReinoud Zandijk     state->fpu.fx_dp.fa_64 = env->fpdp;
157fdc8635eSReinoud Zandijk     state->fpu.fx_mxcsr = env->mxcsr;
158fdc8635eSReinoud Zandijk     state->fpu.fx_mxcsr_mask = 0x0000FFFF;
159fdc8635eSReinoud Zandijk     assert(sizeof(state->fpu.fx_87_ac) == sizeof(env->fpregs));
160fdc8635eSReinoud Zandijk     memcpy(state->fpu.fx_87_ac, env->fpregs, sizeof(env->fpregs));
161fdc8635eSReinoud Zandijk     for (i = 0; i < CPU_NB_REGS; i++) {
162fdc8635eSReinoud Zandijk         memcpy(&state->fpu.fx_xmm[i].xmm_bytes[0],
163fdc8635eSReinoud Zandijk             &env->xmm_regs[i].ZMM_Q(0), 8);
164fdc8635eSReinoud Zandijk         memcpy(&state->fpu.fx_xmm[i].xmm_bytes[8],
165fdc8635eSReinoud Zandijk             &env->xmm_regs[i].ZMM_Q(1), 8);
166fdc8635eSReinoud Zandijk     }
167fdc8635eSReinoud Zandijk 
168fdc8635eSReinoud Zandijk     /* MSRs. */
169fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_EFER] = env->efer;
170fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_STAR] = env->star;
171fdc8635eSReinoud Zandijk #ifdef TARGET_X86_64
172fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_LSTAR] = env->lstar;
173fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_CSTAR] = env->cstar;
174fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_SFMASK] = env->fmask;
175fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_KERNELGSBASE] = env->kernelgsbase;
176fdc8635eSReinoud Zandijk #endif
177fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_SYSENTER_CS]  = env->sysenter_cs;
178fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_SYSENTER_ESP] = env->sysenter_esp;
179fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_SYSENTER_EIP] = env->sysenter_eip;
180fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_PAT] = env->pat;
181fdc8635eSReinoud Zandijk     state->msrs[NVMM_X64_MSR_TSC] = env->tsc;
182fdc8635eSReinoud Zandijk 
183fdc8635eSReinoud Zandijk     bitmap =
184fdc8635eSReinoud Zandijk         NVMM_X64_STATE_SEGS |
185fdc8635eSReinoud Zandijk         NVMM_X64_STATE_GPRS |
186fdc8635eSReinoud Zandijk         NVMM_X64_STATE_CRS  |
187fdc8635eSReinoud Zandijk         NVMM_X64_STATE_DRS  |
188fdc8635eSReinoud Zandijk         NVMM_X64_STATE_MSRS |
189fdc8635eSReinoud Zandijk         NVMM_X64_STATE_FPU;
190fdc8635eSReinoud Zandijk 
191fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_setstate(mach, vcpu, bitmap);
192fdc8635eSReinoud Zandijk     if (ret == -1) {
193fdc8635eSReinoud Zandijk         error_report("NVMM: Failed to set virtual processor context,"
194fdc8635eSReinoud Zandijk             " error=%d", errno);
195fdc8635eSReinoud Zandijk     }
196fdc8635eSReinoud Zandijk }
197fdc8635eSReinoud Zandijk 
198fdc8635eSReinoud Zandijk static void
nvmm_get_segment(SegmentCache * qseg,const struct nvmm_x64_state_seg * nseg)199fdc8635eSReinoud Zandijk nvmm_get_segment(SegmentCache *qseg, const struct nvmm_x64_state_seg *nseg)
200fdc8635eSReinoud Zandijk {
201fdc8635eSReinoud Zandijk     qseg->selector = nseg->selector;
202fdc8635eSReinoud Zandijk     qseg->limit = nseg->limit;
203fdc8635eSReinoud Zandijk     qseg->base = nseg->base;
204fdc8635eSReinoud Zandijk 
205fdc8635eSReinoud Zandijk     qseg->flags =
206fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.type, DESC_TYPE_MASK) |
207fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.s, DESC_S_MASK) |
208fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.dpl, DESC_DPL_MASK) |
209fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.p, DESC_P_MASK) |
210fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.avl, DESC_AVL_MASK) |
211fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.l, DESC_L_MASK) |
212fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.def, DESC_B_MASK) |
213fdc8635eSReinoud Zandijk         __SHIFTIN((uint32_t)nseg->attrib.g, DESC_G_MASK);
214fdc8635eSReinoud Zandijk }
215fdc8635eSReinoud Zandijk 
216fdc8635eSReinoud Zandijk static void
nvmm_get_registers(CPUState * cpu)217fdc8635eSReinoud Zandijk nvmm_get_registers(CPUState *cpu)
218fdc8635eSReinoud Zandijk {
219b77af26eSRichard Henderson     CPUX86State *env = cpu_env(cpu);
220fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
2212f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
222fdc8635eSReinoud Zandijk     struct nvmm_vcpu *vcpu = &qcpu->vcpu;
223fdc8635eSReinoud Zandijk     X86CPU *x86_cpu = X86_CPU(cpu);
224fdc8635eSReinoud Zandijk     struct nvmm_x64_state *state = vcpu->state;
225fdc8635eSReinoud Zandijk     uint64_t bitmap, tpr;
226fdc8635eSReinoud Zandijk     size_t i;
227fdc8635eSReinoud Zandijk     int ret;
228fdc8635eSReinoud Zandijk 
229fdc8635eSReinoud Zandijk     assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
230fdc8635eSReinoud Zandijk 
231fdc8635eSReinoud Zandijk     bitmap =
232fdc8635eSReinoud Zandijk         NVMM_X64_STATE_SEGS |
233fdc8635eSReinoud Zandijk         NVMM_X64_STATE_GPRS |
234fdc8635eSReinoud Zandijk         NVMM_X64_STATE_CRS  |
235fdc8635eSReinoud Zandijk         NVMM_X64_STATE_DRS  |
236fdc8635eSReinoud Zandijk         NVMM_X64_STATE_MSRS |
237fdc8635eSReinoud Zandijk         NVMM_X64_STATE_FPU;
238fdc8635eSReinoud Zandijk 
239fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_getstate(mach, vcpu, bitmap);
240fdc8635eSReinoud Zandijk     if (ret == -1) {
241fdc8635eSReinoud Zandijk         error_report("NVMM: Failed to get virtual processor context,"
242fdc8635eSReinoud Zandijk             " error=%d", errno);
243fdc8635eSReinoud Zandijk     }
244fdc8635eSReinoud Zandijk 
245fdc8635eSReinoud Zandijk     /* GPRs. */
246fdc8635eSReinoud Zandijk     env->regs[R_EAX] = state->gprs[NVMM_X64_GPR_RAX];
247fdc8635eSReinoud Zandijk     env->regs[R_ECX] = state->gprs[NVMM_X64_GPR_RCX];
248fdc8635eSReinoud Zandijk     env->regs[R_EDX] = state->gprs[NVMM_X64_GPR_RDX];
249fdc8635eSReinoud Zandijk     env->regs[R_EBX] = state->gprs[NVMM_X64_GPR_RBX];
250fdc8635eSReinoud Zandijk     env->regs[R_ESP] = state->gprs[NVMM_X64_GPR_RSP];
251fdc8635eSReinoud Zandijk     env->regs[R_EBP] = state->gprs[NVMM_X64_GPR_RBP];
252fdc8635eSReinoud Zandijk     env->regs[R_ESI] = state->gprs[NVMM_X64_GPR_RSI];
253fdc8635eSReinoud Zandijk     env->regs[R_EDI] = state->gprs[NVMM_X64_GPR_RDI];
254fdc8635eSReinoud Zandijk #ifdef TARGET_X86_64
255fdc8635eSReinoud Zandijk     env->regs[R_R8]  = state->gprs[NVMM_X64_GPR_R8];
256fdc8635eSReinoud Zandijk     env->regs[R_R9]  = state->gprs[NVMM_X64_GPR_R9];
257fdc8635eSReinoud Zandijk     env->regs[R_R10] = state->gprs[NVMM_X64_GPR_R10];
258fdc8635eSReinoud Zandijk     env->regs[R_R11] = state->gprs[NVMM_X64_GPR_R11];
259fdc8635eSReinoud Zandijk     env->regs[R_R12] = state->gprs[NVMM_X64_GPR_R12];
260fdc8635eSReinoud Zandijk     env->regs[R_R13] = state->gprs[NVMM_X64_GPR_R13];
261fdc8635eSReinoud Zandijk     env->regs[R_R14] = state->gprs[NVMM_X64_GPR_R14];
262fdc8635eSReinoud Zandijk     env->regs[R_R15] = state->gprs[NVMM_X64_GPR_R15];
263fdc8635eSReinoud Zandijk #endif
264fdc8635eSReinoud Zandijk 
265fdc8635eSReinoud Zandijk     /* RIP and RFLAGS. */
266fdc8635eSReinoud Zandijk     env->eip = state->gprs[NVMM_X64_GPR_RIP];
267fdc8635eSReinoud Zandijk     env->eflags = state->gprs[NVMM_X64_GPR_RFLAGS];
268fdc8635eSReinoud Zandijk 
269fdc8635eSReinoud Zandijk     /* Segments. */
270fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->segs[R_ES], &state->segs[NVMM_X64_SEG_ES]);
271fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->segs[R_CS], &state->segs[NVMM_X64_SEG_CS]);
272fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->segs[R_SS], &state->segs[NVMM_X64_SEG_SS]);
273fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->segs[R_DS], &state->segs[NVMM_X64_SEG_DS]);
274fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->segs[R_FS], &state->segs[NVMM_X64_SEG_FS]);
275fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->segs[R_GS], &state->segs[NVMM_X64_SEG_GS]);
276fdc8635eSReinoud Zandijk 
277fdc8635eSReinoud Zandijk     /* Special segments. */
278fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->gdt, &state->segs[NVMM_X64_SEG_GDT]);
279fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->ldt, &state->segs[NVMM_X64_SEG_LDT]);
280fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->tr, &state->segs[NVMM_X64_SEG_TR]);
281fdc8635eSReinoud Zandijk     nvmm_get_segment(&env->idt, &state->segs[NVMM_X64_SEG_IDT]);
282fdc8635eSReinoud Zandijk 
283fdc8635eSReinoud Zandijk     /* Control registers. */
284fdc8635eSReinoud Zandijk     env->cr[0] = state->crs[NVMM_X64_CR_CR0];
285fdc8635eSReinoud Zandijk     env->cr[2] = state->crs[NVMM_X64_CR_CR2];
286fdc8635eSReinoud Zandijk     env->cr[3] = state->crs[NVMM_X64_CR_CR3];
287fdc8635eSReinoud Zandijk     env->cr[4] = state->crs[NVMM_X64_CR_CR4];
288fdc8635eSReinoud Zandijk     tpr = state->crs[NVMM_X64_CR_CR8];
289fdc8635eSReinoud Zandijk     if (tpr != qcpu->tpr) {
290fdc8635eSReinoud Zandijk         qcpu->tpr = tpr;
291fdc8635eSReinoud Zandijk         cpu_set_apic_tpr(x86_cpu->apic_state, tpr);
292fdc8635eSReinoud Zandijk     }
293fdc8635eSReinoud Zandijk     env->xcr0 = state->crs[NVMM_X64_CR_XCR0];
294fdc8635eSReinoud Zandijk 
295fdc8635eSReinoud Zandijk     /* Debug registers. */
296fdc8635eSReinoud Zandijk     env->dr[0] = state->drs[NVMM_X64_DR_DR0];
297fdc8635eSReinoud Zandijk     env->dr[1] = state->drs[NVMM_X64_DR_DR1];
298fdc8635eSReinoud Zandijk     env->dr[2] = state->drs[NVMM_X64_DR_DR2];
299fdc8635eSReinoud Zandijk     env->dr[3] = state->drs[NVMM_X64_DR_DR3];
300fdc8635eSReinoud Zandijk     env->dr[6] = state->drs[NVMM_X64_DR_DR6];
301fdc8635eSReinoud Zandijk     env->dr[7] = state->drs[NVMM_X64_DR_DR7];
302fdc8635eSReinoud Zandijk 
303fdc8635eSReinoud Zandijk     /* FPU. */
304fdc8635eSReinoud Zandijk     env->fpuc = state->fpu.fx_cw;
305fdc8635eSReinoud Zandijk     env->fpstt = (state->fpu.fx_sw >> 11) & 0x7;
306fdc8635eSReinoud Zandijk     env->fpus = state->fpu.fx_sw & ~0x3800;
307fdc8635eSReinoud Zandijk     for (i = 0; i < 8; i++) {
308fdc8635eSReinoud Zandijk         env->fptags[i] = !((state->fpu.fx_tw >> i) & 1);
309fdc8635eSReinoud Zandijk     }
310fdc8635eSReinoud Zandijk     env->fpop = state->fpu.fx_opcode;
311fdc8635eSReinoud Zandijk     env->fpip = state->fpu.fx_ip.fa_64;
312fdc8635eSReinoud Zandijk     env->fpdp = state->fpu.fx_dp.fa_64;
313fdc8635eSReinoud Zandijk     env->mxcsr = state->fpu.fx_mxcsr;
314fdc8635eSReinoud Zandijk     assert(sizeof(state->fpu.fx_87_ac) == sizeof(env->fpregs));
315fdc8635eSReinoud Zandijk     memcpy(env->fpregs, state->fpu.fx_87_ac, sizeof(env->fpregs));
316fdc8635eSReinoud Zandijk     for (i = 0; i < CPU_NB_REGS; i++) {
317fdc8635eSReinoud Zandijk         memcpy(&env->xmm_regs[i].ZMM_Q(0),
318fdc8635eSReinoud Zandijk             &state->fpu.fx_xmm[i].xmm_bytes[0], 8);
319fdc8635eSReinoud Zandijk         memcpy(&env->xmm_regs[i].ZMM_Q(1),
320fdc8635eSReinoud Zandijk             &state->fpu.fx_xmm[i].xmm_bytes[8], 8);
321fdc8635eSReinoud Zandijk     }
322fdc8635eSReinoud Zandijk 
323fdc8635eSReinoud Zandijk     /* MSRs. */
324fdc8635eSReinoud Zandijk     env->efer = state->msrs[NVMM_X64_MSR_EFER];
325fdc8635eSReinoud Zandijk     env->star = state->msrs[NVMM_X64_MSR_STAR];
326fdc8635eSReinoud Zandijk #ifdef TARGET_X86_64
327fdc8635eSReinoud Zandijk     env->lstar = state->msrs[NVMM_X64_MSR_LSTAR];
328fdc8635eSReinoud Zandijk     env->cstar = state->msrs[NVMM_X64_MSR_CSTAR];
329fdc8635eSReinoud Zandijk     env->fmask = state->msrs[NVMM_X64_MSR_SFMASK];
330fdc8635eSReinoud Zandijk     env->kernelgsbase = state->msrs[NVMM_X64_MSR_KERNELGSBASE];
331fdc8635eSReinoud Zandijk #endif
332fdc8635eSReinoud Zandijk     env->sysenter_cs  = state->msrs[NVMM_X64_MSR_SYSENTER_CS];
333fdc8635eSReinoud Zandijk     env->sysenter_esp = state->msrs[NVMM_X64_MSR_SYSENTER_ESP];
334fdc8635eSReinoud Zandijk     env->sysenter_eip = state->msrs[NVMM_X64_MSR_SYSENTER_EIP];
335fdc8635eSReinoud Zandijk     env->pat = state->msrs[NVMM_X64_MSR_PAT];
336fdc8635eSReinoud Zandijk     env->tsc = state->msrs[NVMM_X64_MSR_TSC];
337fdc8635eSReinoud Zandijk 
338fdc8635eSReinoud Zandijk     x86_update_hflags(env);
339fdc8635eSReinoud Zandijk }
340fdc8635eSReinoud Zandijk 
341fdc8635eSReinoud Zandijk static bool
nvmm_can_take_int(CPUState * cpu)342fdc8635eSReinoud Zandijk nvmm_can_take_int(CPUState *cpu)
343fdc8635eSReinoud Zandijk {
3442f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
345fdc8635eSReinoud Zandijk     struct nvmm_vcpu *vcpu = &qcpu->vcpu;
346fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
347fdc8635eSReinoud Zandijk 
348fdc8635eSReinoud Zandijk     if (qcpu->int_window_exit) {
349fdc8635eSReinoud Zandijk         return false;
350fdc8635eSReinoud Zandijk     }
351fdc8635eSReinoud Zandijk 
35294956d7bSPhilippe Mathieu-Daudé     if (qcpu->int_shadow || !(cpu_env(cpu)->eflags & IF_MASK)) {
353fdc8635eSReinoud Zandijk         struct nvmm_x64_state *state = vcpu->state;
354fdc8635eSReinoud Zandijk 
355fdc8635eSReinoud Zandijk         /* Exit on interrupt window. */
356fdc8635eSReinoud Zandijk         nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_INTR);
357fdc8635eSReinoud Zandijk         state->intr.int_window_exiting = 1;
358fdc8635eSReinoud Zandijk         nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_INTR);
359fdc8635eSReinoud Zandijk 
360fdc8635eSReinoud Zandijk         return false;
361fdc8635eSReinoud Zandijk     }
362fdc8635eSReinoud Zandijk 
363fdc8635eSReinoud Zandijk     return true;
364fdc8635eSReinoud Zandijk }
365fdc8635eSReinoud Zandijk 
366fdc8635eSReinoud Zandijk static bool
nvmm_can_take_nmi(CPUState * cpu)367fdc8635eSReinoud Zandijk nvmm_can_take_nmi(CPUState *cpu)
368fdc8635eSReinoud Zandijk {
3692f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
370fdc8635eSReinoud Zandijk 
371fdc8635eSReinoud Zandijk     /*
372fdc8635eSReinoud Zandijk      * Contrary to INTs, NMIs always schedule an exit when they are
373fdc8635eSReinoud Zandijk      * completed. Therefore, if window-exiting is enabled, it means
374fdc8635eSReinoud Zandijk      * NMIs are blocked.
375fdc8635eSReinoud Zandijk      */
376fdc8635eSReinoud Zandijk     if (qcpu->nmi_window_exit) {
377fdc8635eSReinoud Zandijk         return false;
378fdc8635eSReinoud Zandijk     }
379fdc8635eSReinoud Zandijk 
380fdc8635eSReinoud Zandijk     return true;
381fdc8635eSReinoud Zandijk }
382fdc8635eSReinoud Zandijk 
383fdc8635eSReinoud Zandijk /*
384fdc8635eSReinoud Zandijk  * Called before the VCPU is run. We inject events generated by the I/O
385fdc8635eSReinoud Zandijk  * thread, and synchronize the guest TPR.
386fdc8635eSReinoud Zandijk  */
387fdc8635eSReinoud Zandijk static void
nvmm_vcpu_pre_run(CPUState * cpu)388fdc8635eSReinoud Zandijk nvmm_vcpu_pre_run(CPUState *cpu)
389fdc8635eSReinoud Zandijk {
390b77af26eSRichard Henderson     CPUX86State *env = cpu_env(cpu);
391fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
3922f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
393fdc8635eSReinoud Zandijk     struct nvmm_vcpu *vcpu = &qcpu->vcpu;
394fdc8635eSReinoud Zandijk     X86CPU *x86_cpu = X86_CPU(cpu);
395fdc8635eSReinoud Zandijk     struct nvmm_x64_state *state = vcpu->state;
396fdc8635eSReinoud Zandijk     struct nvmm_vcpu_event *event = vcpu->event;
397fdc8635eSReinoud Zandijk     bool has_event = false;
398fdc8635eSReinoud Zandijk     bool sync_tpr = false;
399fdc8635eSReinoud Zandijk     uint8_t tpr;
400fdc8635eSReinoud Zandijk     int ret;
401fdc8635eSReinoud Zandijk 
402195801d7SStefan Hajnoczi     bql_lock();
403fdc8635eSReinoud Zandijk 
404fdc8635eSReinoud Zandijk     tpr = cpu_get_apic_tpr(x86_cpu->apic_state);
405fdc8635eSReinoud Zandijk     if (tpr != qcpu->tpr) {
406fdc8635eSReinoud Zandijk         qcpu->tpr = tpr;
407fdc8635eSReinoud Zandijk         sync_tpr = true;
408fdc8635eSReinoud Zandijk     }
409fdc8635eSReinoud Zandijk 
410fdc8635eSReinoud Zandijk     /*
411fdc8635eSReinoud Zandijk      * Force the VCPU out of its inner loop to process any INIT requests
412fdc8635eSReinoud Zandijk      * or commit pending TPR access.
413fdc8635eSReinoud Zandijk      */
414fdc8635eSReinoud Zandijk     if (cpu->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
415fdc8635eSReinoud Zandijk         cpu->exit_request = 1;
416fdc8635eSReinoud Zandijk     }
417fdc8635eSReinoud Zandijk 
418fdc8635eSReinoud Zandijk     if (!has_event && (cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
419fdc8635eSReinoud Zandijk         if (nvmm_can_take_nmi(cpu)) {
420fdc8635eSReinoud Zandijk             cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
421fdc8635eSReinoud Zandijk             event->type = NVMM_VCPU_EVENT_INTR;
422fdc8635eSReinoud Zandijk             event->vector = 2;
423fdc8635eSReinoud Zandijk             has_event = true;
424fdc8635eSReinoud Zandijk         }
425fdc8635eSReinoud Zandijk     }
426fdc8635eSReinoud Zandijk 
427fdc8635eSReinoud Zandijk     if (!has_event && (cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
428fdc8635eSReinoud Zandijk         if (nvmm_can_take_int(cpu)) {
429fdc8635eSReinoud Zandijk             cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
430fdc8635eSReinoud Zandijk             event->type = NVMM_VCPU_EVENT_INTR;
431fdc8635eSReinoud Zandijk             event->vector = cpu_get_pic_interrupt(env);
432fdc8635eSReinoud Zandijk             has_event = true;
433fdc8635eSReinoud Zandijk         }
434fdc8635eSReinoud Zandijk     }
435fdc8635eSReinoud Zandijk 
436fdc8635eSReinoud Zandijk     /* Don't want SMIs. */
437fdc8635eSReinoud Zandijk     if (cpu->interrupt_request & CPU_INTERRUPT_SMI) {
438fdc8635eSReinoud Zandijk         cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
439fdc8635eSReinoud Zandijk     }
440fdc8635eSReinoud Zandijk 
441fdc8635eSReinoud Zandijk     if (sync_tpr) {
442fdc8635eSReinoud Zandijk         ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_CRS);
443fdc8635eSReinoud Zandijk         if (ret == -1) {
444fdc8635eSReinoud Zandijk             error_report("NVMM: Failed to get CPU state,"
445fdc8635eSReinoud Zandijk                 " error=%d", errno);
446fdc8635eSReinoud Zandijk         }
447fdc8635eSReinoud Zandijk 
448fdc8635eSReinoud Zandijk         state->crs[NVMM_X64_CR_CR8] = qcpu->tpr;
449fdc8635eSReinoud Zandijk 
450fdc8635eSReinoud Zandijk         ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_CRS);
451fdc8635eSReinoud Zandijk         if (ret == -1) {
452fdc8635eSReinoud Zandijk             error_report("NVMM: Failed to set CPU state,"
453fdc8635eSReinoud Zandijk                 " error=%d", errno);
454fdc8635eSReinoud Zandijk         }
455fdc8635eSReinoud Zandijk     }
456fdc8635eSReinoud Zandijk 
457fdc8635eSReinoud Zandijk     if (has_event) {
458fdc8635eSReinoud Zandijk         ret = nvmm_vcpu_inject(mach, vcpu);
459fdc8635eSReinoud Zandijk         if (ret == -1) {
460fdc8635eSReinoud Zandijk             error_report("NVMM: Failed to inject event,"
461fdc8635eSReinoud Zandijk                 " error=%d", errno);
462fdc8635eSReinoud Zandijk         }
463fdc8635eSReinoud Zandijk     }
464fdc8635eSReinoud Zandijk 
465195801d7SStefan Hajnoczi     bql_unlock();
466fdc8635eSReinoud Zandijk }
467fdc8635eSReinoud Zandijk 
468fdc8635eSReinoud Zandijk /*
469fdc8635eSReinoud Zandijk  * Called after the VCPU ran. We synchronize the host view of the TPR and
470fdc8635eSReinoud Zandijk  * RFLAGS.
471fdc8635eSReinoud Zandijk  */
472fdc8635eSReinoud Zandijk static void
nvmm_vcpu_post_run(CPUState * cpu,struct nvmm_vcpu_exit * exit)473fdc8635eSReinoud Zandijk nvmm_vcpu_post_run(CPUState *cpu, struct nvmm_vcpu_exit *exit)
474fdc8635eSReinoud Zandijk {
4752f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
476fdc8635eSReinoud Zandijk     X86CPU *x86_cpu = X86_CPU(cpu);
477b77af26eSRichard Henderson     CPUX86State *env = &x86_cpu->env;
478fdc8635eSReinoud Zandijk     uint64_t tpr;
479fdc8635eSReinoud Zandijk 
480fdc8635eSReinoud Zandijk     env->eflags = exit->exitstate.rflags;
481fdc8635eSReinoud Zandijk     qcpu->int_shadow = exit->exitstate.int_shadow;
482fdc8635eSReinoud Zandijk     qcpu->int_window_exit = exit->exitstate.int_window_exiting;
483fdc8635eSReinoud Zandijk     qcpu->nmi_window_exit = exit->exitstate.nmi_window_exiting;
484fdc8635eSReinoud Zandijk 
485fdc8635eSReinoud Zandijk     tpr = exit->exitstate.cr8;
486fdc8635eSReinoud Zandijk     if (qcpu->tpr != tpr) {
487fdc8635eSReinoud Zandijk         qcpu->tpr = tpr;
488195801d7SStefan Hajnoczi         bql_lock();
489fdc8635eSReinoud Zandijk         cpu_set_apic_tpr(x86_cpu->apic_state, qcpu->tpr);
490195801d7SStefan Hajnoczi         bql_unlock();
491fdc8635eSReinoud Zandijk     }
492fdc8635eSReinoud Zandijk }
493fdc8635eSReinoud Zandijk 
494fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
495fdc8635eSReinoud Zandijk 
496fdc8635eSReinoud Zandijk static void
nvmm_io_callback(struct nvmm_io * io)497fdc8635eSReinoud Zandijk nvmm_io_callback(struct nvmm_io *io)
498fdc8635eSReinoud Zandijk {
499fdc8635eSReinoud Zandijk     MemTxAttrs attrs = { 0 };
500fdc8635eSReinoud Zandijk     int ret;
501fdc8635eSReinoud Zandijk 
502fdc8635eSReinoud Zandijk     ret = address_space_rw(&address_space_io, io->port, attrs, io->data,
503fdc8635eSReinoud Zandijk         io->size, !io->in);
504fdc8635eSReinoud Zandijk     if (ret != MEMTX_OK) {
505fdc8635eSReinoud Zandijk         error_report("NVMM: I/O Transaction Failed "
506fdc8635eSReinoud Zandijk             "[%s, port=%u, size=%zu]", (io->in ? "in" : "out"),
507fdc8635eSReinoud Zandijk             io->port, io->size);
508fdc8635eSReinoud Zandijk     }
509fdc8635eSReinoud Zandijk 
510fdc8635eSReinoud Zandijk     /* Needed, otherwise infinite loop. */
51179f1926bSPhilippe Mathieu-Daudé     current_cpu->accel->dirty = false;
512fdc8635eSReinoud Zandijk }
513fdc8635eSReinoud Zandijk 
514fdc8635eSReinoud Zandijk static void
nvmm_mem_callback(struct nvmm_mem * mem)515fdc8635eSReinoud Zandijk nvmm_mem_callback(struct nvmm_mem *mem)
516fdc8635eSReinoud Zandijk {
517fdc8635eSReinoud Zandijk     cpu_physical_memory_rw(mem->gpa, mem->data, mem->size, mem->write);
518fdc8635eSReinoud Zandijk 
519fdc8635eSReinoud Zandijk     /* Needed, otherwise infinite loop. */
52079f1926bSPhilippe Mathieu-Daudé     current_cpu->accel->dirty = false;
521fdc8635eSReinoud Zandijk }
522fdc8635eSReinoud Zandijk 
523fdc8635eSReinoud Zandijk static struct nvmm_assist_callbacks nvmm_callbacks = {
524fdc8635eSReinoud Zandijk     .io = nvmm_io_callback,
525fdc8635eSReinoud Zandijk     .mem = nvmm_mem_callback
526fdc8635eSReinoud Zandijk };
527fdc8635eSReinoud Zandijk 
528fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
529fdc8635eSReinoud Zandijk 
530fdc8635eSReinoud Zandijk static int
nvmm_handle_mem(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)531fdc8635eSReinoud Zandijk nvmm_handle_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
532fdc8635eSReinoud Zandijk {
533fdc8635eSReinoud Zandijk     int ret;
534fdc8635eSReinoud Zandijk 
535fdc8635eSReinoud Zandijk     ret = nvmm_assist_mem(mach, vcpu);
536fdc8635eSReinoud Zandijk     if (ret == -1) {
537fdc8635eSReinoud Zandijk         error_report("NVMM: Mem Assist Failed [gpa=%p]",
538fdc8635eSReinoud Zandijk             (void *)vcpu->exit->u.mem.gpa);
539fdc8635eSReinoud Zandijk     }
540fdc8635eSReinoud Zandijk 
541fdc8635eSReinoud Zandijk     return ret;
542fdc8635eSReinoud Zandijk }
543fdc8635eSReinoud Zandijk 
544fdc8635eSReinoud Zandijk static int
nvmm_handle_io(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)545fdc8635eSReinoud Zandijk nvmm_handle_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
546fdc8635eSReinoud Zandijk {
547fdc8635eSReinoud Zandijk     int ret;
548fdc8635eSReinoud Zandijk 
549fdc8635eSReinoud Zandijk     ret = nvmm_assist_io(mach, vcpu);
550fdc8635eSReinoud Zandijk     if (ret == -1) {
551fdc8635eSReinoud Zandijk         error_report("NVMM: I/O Assist Failed [port=%d]",
552fdc8635eSReinoud Zandijk             (int)vcpu->exit->u.io.port);
553fdc8635eSReinoud Zandijk     }
554fdc8635eSReinoud Zandijk 
555fdc8635eSReinoud Zandijk     return ret;
556fdc8635eSReinoud Zandijk }
557fdc8635eSReinoud Zandijk 
558fdc8635eSReinoud Zandijk static int
nvmm_handle_rdmsr(struct nvmm_machine * mach,CPUState * cpu,struct nvmm_vcpu_exit * exit)559fdc8635eSReinoud Zandijk nvmm_handle_rdmsr(struct nvmm_machine *mach, CPUState *cpu,
560fdc8635eSReinoud Zandijk     struct nvmm_vcpu_exit *exit)
561fdc8635eSReinoud Zandijk {
5622f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
563fdc8635eSReinoud Zandijk     struct nvmm_vcpu *vcpu = &qcpu->vcpu;
564fdc8635eSReinoud Zandijk     X86CPU *x86_cpu = X86_CPU(cpu);
565fdc8635eSReinoud Zandijk     struct nvmm_x64_state *state = vcpu->state;
566fdc8635eSReinoud Zandijk     uint64_t val;
567fdc8635eSReinoud Zandijk     int ret;
568fdc8635eSReinoud Zandijk 
569fdc8635eSReinoud Zandijk     switch (exit->u.rdmsr.msr) {
570fdc8635eSReinoud Zandijk     case MSR_IA32_APICBASE:
571fdc8635eSReinoud Zandijk         val = cpu_get_apic_base(x86_cpu->apic_state);
572fdc8635eSReinoud Zandijk         break;
573fdc8635eSReinoud Zandijk     case MSR_MTRRcap:
574fdc8635eSReinoud Zandijk     case MSR_MTRRdefType:
575fdc8635eSReinoud Zandijk     case MSR_MCG_CAP:
576fdc8635eSReinoud Zandijk     case MSR_MCG_STATUS:
577fdc8635eSReinoud Zandijk         val = 0;
578fdc8635eSReinoud Zandijk         break;
579fdc8635eSReinoud Zandijk     default: /* More MSRs to add? */
580fdc8635eSReinoud Zandijk         val = 0;
581fdc8635eSReinoud Zandijk         error_report("NVMM: Unexpected RDMSR 0x%x, ignored",
582fdc8635eSReinoud Zandijk             exit->u.rdmsr.msr);
583fdc8635eSReinoud Zandijk         break;
584fdc8635eSReinoud Zandijk     }
585fdc8635eSReinoud Zandijk 
586fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS);
587fdc8635eSReinoud Zandijk     if (ret == -1) {
588fdc8635eSReinoud Zandijk         return -1;
589fdc8635eSReinoud Zandijk     }
590fdc8635eSReinoud Zandijk 
591fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RAX] = (val & 0xFFFFFFFF);
592fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
593fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RIP] = exit->u.rdmsr.npc;
594fdc8635eSReinoud Zandijk 
595fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS);
596fdc8635eSReinoud Zandijk     if (ret == -1) {
597fdc8635eSReinoud Zandijk         return -1;
598fdc8635eSReinoud Zandijk     }
599fdc8635eSReinoud Zandijk 
600fdc8635eSReinoud Zandijk     return 0;
601fdc8635eSReinoud Zandijk }
602fdc8635eSReinoud Zandijk 
603fdc8635eSReinoud Zandijk static int
nvmm_handle_wrmsr(struct nvmm_machine * mach,CPUState * cpu,struct nvmm_vcpu_exit * exit)604fdc8635eSReinoud Zandijk nvmm_handle_wrmsr(struct nvmm_machine *mach, CPUState *cpu,
605fdc8635eSReinoud Zandijk     struct nvmm_vcpu_exit *exit)
606fdc8635eSReinoud Zandijk {
6072f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
608fdc8635eSReinoud Zandijk     struct nvmm_vcpu *vcpu = &qcpu->vcpu;
609fdc8635eSReinoud Zandijk     X86CPU *x86_cpu = X86_CPU(cpu);
610fdc8635eSReinoud Zandijk     struct nvmm_x64_state *state = vcpu->state;
611fdc8635eSReinoud Zandijk     uint64_t val;
612fdc8635eSReinoud Zandijk     int ret;
613fdc8635eSReinoud Zandijk 
614fdc8635eSReinoud Zandijk     val = exit->u.wrmsr.val;
615fdc8635eSReinoud Zandijk 
616fdc8635eSReinoud Zandijk     switch (exit->u.wrmsr.msr) {
617fdc8635eSReinoud Zandijk     case MSR_IA32_APICBASE:
618fdc8635eSReinoud Zandijk         cpu_set_apic_base(x86_cpu->apic_state, val);
619fdc8635eSReinoud Zandijk         break;
620fdc8635eSReinoud Zandijk     case MSR_MTRRdefType:
621fdc8635eSReinoud Zandijk     case MSR_MCG_STATUS:
622fdc8635eSReinoud Zandijk         break;
623fdc8635eSReinoud Zandijk     default: /* More MSRs to add? */
624fdc8635eSReinoud Zandijk         error_report("NVMM: Unexpected WRMSR 0x%x [val=0x%lx], ignored",
625fdc8635eSReinoud Zandijk             exit->u.wrmsr.msr, val);
626fdc8635eSReinoud Zandijk         break;
627fdc8635eSReinoud Zandijk     }
628fdc8635eSReinoud Zandijk 
629fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS);
630fdc8635eSReinoud Zandijk     if (ret == -1) {
631fdc8635eSReinoud Zandijk         return -1;
632fdc8635eSReinoud Zandijk     }
633fdc8635eSReinoud Zandijk 
634fdc8635eSReinoud Zandijk     state->gprs[NVMM_X64_GPR_RIP] = exit->u.wrmsr.npc;
635fdc8635eSReinoud Zandijk 
636fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS);
637fdc8635eSReinoud Zandijk     if (ret == -1) {
638fdc8635eSReinoud Zandijk         return -1;
639fdc8635eSReinoud Zandijk     }
640fdc8635eSReinoud Zandijk 
641fdc8635eSReinoud Zandijk     return 0;
642fdc8635eSReinoud Zandijk }
643fdc8635eSReinoud Zandijk 
644fdc8635eSReinoud Zandijk static int
nvmm_handle_halted(struct nvmm_machine * mach,CPUState * cpu,struct nvmm_vcpu_exit * exit)645fdc8635eSReinoud Zandijk nvmm_handle_halted(struct nvmm_machine *mach, CPUState *cpu,
646fdc8635eSReinoud Zandijk     struct nvmm_vcpu_exit *exit)
647fdc8635eSReinoud Zandijk {
648fdc8635eSReinoud Zandijk     int ret = 0;
649fdc8635eSReinoud Zandijk 
650195801d7SStefan Hajnoczi     bql_lock();
651fdc8635eSReinoud Zandijk 
652fdc8635eSReinoud Zandijk     if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
65394956d7bSPhilippe Mathieu-Daudé           (cpu_env(cpu)->eflags & IF_MASK)) &&
654fdc8635eSReinoud Zandijk         !(cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
655fdc8635eSReinoud Zandijk         cpu->exception_index = EXCP_HLT;
656fdc8635eSReinoud Zandijk         cpu->halted = true;
657fdc8635eSReinoud Zandijk         ret = 1;
658fdc8635eSReinoud Zandijk     }
659fdc8635eSReinoud Zandijk 
660195801d7SStefan Hajnoczi     bql_unlock();
661fdc8635eSReinoud Zandijk 
662fdc8635eSReinoud Zandijk     return ret;
663fdc8635eSReinoud Zandijk }
664fdc8635eSReinoud Zandijk 
665fdc8635eSReinoud Zandijk static int
nvmm_inject_ud(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)666fdc8635eSReinoud Zandijk nvmm_inject_ud(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
667fdc8635eSReinoud Zandijk {
668fdc8635eSReinoud Zandijk     struct nvmm_vcpu_event *event = vcpu->event;
669fdc8635eSReinoud Zandijk 
670fdc8635eSReinoud Zandijk     event->type = NVMM_VCPU_EVENT_EXCP;
671fdc8635eSReinoud Zandijk     event->vector = 6;
672fdc8635eSReinoud Zandijk     event->u.excp.error = 0;
673fdc8635eSReinoud Zandijk 
674fdc8635eSReinoud Zandijk     return nvmm_vcpu_inject(mach, vcpu);
675fdc8635eSReinoud Zandijk }
676fdc8635eSReinoud Zandijk 
677fdc8635eSReinoud Zandijk static int
nvmm_vcpu_loop(CPUState * cpu)678fdc8635eSReinoud Zandijk nvmm_vcpu_loop(CPUState *cpu)
679fdc8635eSReinoud Zandijk {
680fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
6812f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
682fdc8635eSReinoud Zandijk     struct nvmm_vcpu *vcpu = &qcpu->vcpu;
683fdc8635eSReinoud Zandijk     X86CPU *x86_cpu = X86_CPU(cpu);
684b77af26eSRichard Henderson     CPUX86State *env = &x86_cpu->env;
685fdc8635eSReinoud Zandijk     struct nvmm_vcpu_exit *exit = vcpu->exit;
686fdc8635eSReinoud Zandijk     int ret;
687fdc8635eSReinoud Zandijk 
688fdc8635eSReinoud Zandijk     /*
689fdc8635eSReinoud Zandijk      * Some asynchronous events must be handled outside of the inner
690fdc8635eSReinoud Zandijk      * VCPU loop. They are handled here.
691fdc8635eSReinoud Zandijk      */
692fdc8635eSReinoud Zandijk     if (cpu->interrupt_request & CPU_INTERRUPT_INIT) {
693fdc8635eSReinoud Zandijk         nvmm_cpu_synchronize_state(cpu);
694fdc8635eSReinoud Zandijk         do_cpu_init(x86_cpu);
695fdc8635eSReinoud Zandijk         /* set int/nmi windows back to the reset state */
696fdc8635eSReinoud Zandijk     }
697fdc8635eSReinoud Zandijk     if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
698fdc8635eSReinoud Zandijk         cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
699fdc8635eSReinoud Zandijk         apic_poll_irq(x86_cpu->apic_state);
700fdc8635eSReinoud Zandijk     }
701fdc8635eSReinoud Zandijk     if (((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
702fdc8635eSReinoud Zandijk          (env->eflags & IF_MASK)) ||
703fdc8635eSReinoud Zandijk         (cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
704fdc8635eSReinoud Zandijk         cpu->halted = false;
705fdc8635eSReinoud Zandijk     }
706fdc8635eSReinoud Zandijk     if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) {
707fdc8635eSReinoud Zandijk         nvmm_cpu_synchronize_state(cpu);
708fdc8635eSReinoud Zandijk         do_cpu_sipi(x86_cpu);
709fdc8635eSReinoud Zandijk     }
710fdc8635eSReinoud Zandijk     if (cpu->interrupt_request & CPU_INTERRUPT_TPR) {
711fdc8635eSReinoud Zandijk         cpu->interrupt_request &= ~CPU_INTERRUPT_TPR;
712fdc8635eSReinoud Zandijk         nvmm_cpu_synchronize_state(cpu);
713fdc8635eSReinoud Zandijk         apic_handle_tpr_access_report(x86_cpu->apic_state, env->eip,
714fdc8635eSReinoud Zandijk             env->tpr_access_type);
715fdc8635eSReinoud Zandijk     }
716fdc8635eSReinoud Zandijk 
717fdc8635eSReinoud Zandijk     if (cpu->halted) {
718fdc8635eSReinoud Zandijk         cpu->exception_index = EXCP_HLT;
719fdc8635eSReinoud Zandijk         qatomic_set(&cpu->exit_request, false);
720fdc8635eSReinoud Zandijk         return 0;
721fdc8635eSReinoud Zandijk     }
722fdc8635eSReinoud Zandijk 
723195801d7SStefan Hajnoczi     bql_unlock();
724fdc8635eSReinoud Zandijk     cpu_exec_start(cpu);
725fdc8635eSReinoud Zandijk 
726fdc8635eSReinoud Zandijk     /*
727fdc8635eSReinoud Zandijk      * Inner VCPU loop.
728fdc8635eSReinoud Zandijk      */
729fdc8635eSReinoud Zandijk     do {
73079f1926bSPhilippe Mathieu-Daudé         if (cpu->accel->dirty) {
731fdc8635eSReinoud Zandijk             nvmm_set_registers(cpu);
73279f1926bSPhilippe Mathieu-Daudé             cpu->accel->dirty = false;
733fdc8635eSReinoud Zandijk         }
734fdc8635eSReinoud Zandijk 
735fdc8635eSReinoud Zandijk         if (qcpu->stop) {
736fdc8635eSReinoud Zandijk             cpu->exception_index = EXCP_INTERRUPT;
737fdc8635eSReinoud Zandijk             qcpu->stop = false;
738fdc8635eSReinoud Zandijk             ret = 1;
739fdc8635eSReinoud Zandijk             break;
740fdc8635eSReinoud Zandijk         }
741fdc8635eSReinoud Zandijk 
742fdc8635eSReinoud Zandijk         nvmm_vcpu_pre_run(cpu);
743fdc8635eSReinoud Zandijk 
744fdc8635eSReinoud Zandijk         if (qatomic_read(&cpu->exit_request)) {
7450cc49650Snia #if NVMM_USER_VERSION >= 2
746fdc8635eSReinoud Zandijk             nvmm_vcpu_stop(vcpu);
7470cc49650Snia #else
7480cc49650Snia             qemu_cpu_kick_self();
7490cc49650Snia #endif
750fdc8635eSReinoud Zandijk         }
751fdc8635eSReinoud Zandijk 
752fdc8635eSReinoud Zandijk         /* Read exit_request before the kernel reads the immediate exit flag */
753fdc8635eSReinoud Zandijk         smp_rmb();
754fdc8635eSReinoud Zandijk         ret = nvmm_vcpu_run(mach, vcpu);
755fdc8635eSReinoud Zandijk         if (ret == -1) {
756fdc8635eSReinoud Zandijk             error_report("NVMM: Failed to exec a virtual processor,"
757fdc8635eSReinoud Zandijk                 " error=%d", errno);
758fdc8635eSReinoud Zandijk             break;
759fdc8635eSReinoud Zandijk         }
760fdc8635eSReinoud Zandijk 
761fdc8635eSReinoud Zandijk         nvmm_vcpu_post_run(cpu, exit);
762fdc8635eSReinoud Zandijk 
763fdc8635eSReinoud Zandijk         switch (exit->reason) {
764fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_NONE:
765fdc8635eSReinoud Zandijk             break;
7660cc49650Snia #if NVMM_USER_VERSION >= 2
767fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_STOPPED:
768fdc8635eSReinoud Zandijk             /*
769fdc8635eSReinoud Zandijk              * The kernel cleared the immediate exit flag; cpu->exit_request
770fdc8635eSReinoud Zandijk              * must be cleared after
771fdc8635eSReinoud Zandijk              */
772fdc8635eSReinoud Zandijk             smp_wmb();
773fdc8635eSReinoud Zandijk             qcpu->stop = true;
774fdc8635eSReinoud Zandijk             break;
7750cc49650Snia #endif
776fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_MEMORY:
777fdc8635eSReinoud Zandijk             ret = nvmm_handle_mem(mach, vcpu);
778fdc8635eSReinoud Zandijk             break;
779fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_IO:
780fdc8635eSReinoud Zandijk             ret = nvmm_handle_io(mach, vcpu);
781fdc8635eSReinoud Zandijk             break;
782fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_INT_READY:
783fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_NMI_READY:
784fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_TPR_CHANGED:
785fdc8635eSReinoud Zandijk             break;
786fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_HALTED:
787fdc8635eSReinoud Zandijk             ret = nvmm_handle_halted(mach, cpu, exit);
788fdc8635eSReinoud Zandijk             break;
789fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_SHUTDOWN:
790fdc8635eSReinoud Zandijk             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
791fdc8635eSReinoud Zandijk             cpu->exception_index = EXCP_INTERRUPT;
792fdc8635eSReinoud Zandijk             ret = 1;
793fdc8635eSReinoud Zandijk             break;
794fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_RDMSR:
795fdc8635eSReinoud Zandijk             ret = nvmm_handle_rdmsr(mach, cpu, exit);
796fdc8635eSReinoud Zandijk             break;
797fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_WRMSR:
798fdc8635eSReinoud Zandijk             ret = nvmm_handle_wrmsr(mach, cpu, exit);
799fdc8635eSReinoud Zandijk             break;
800fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_MONITOR:
801fdc8635eSReinoud Zandijk         case NVMM_VCPU_EXIT_MWAIT:
802fdc8635eSReinoud Zandijk             ret = nvmm_inject_ud(mach, vcpu);
803fdc8635eSReinoud Zandijk             break;
804fdc8635eSReinoud Zandijk         default:
805fdc8635eSReinoud Zandijk             error_report("NVMM: Unexpected VM exit code 0x%lx [hw=0x%lx]",
806fdc8635eSReinoud Zandijk                 exit->reason, exit->u.inv.hwcode);
807fdc8635eSReinoud Zandijk             nvmm_get_registers(cpu);
808195801d7SStefan Hajnoczi             bql_lock();
809fdc8635eSReinoud Zandijk             qemu_system_guest_panicked(cpu_get_crash_info(cpu));
810195801d7SStefan Hajnoczi             bql_unlock();
811fdc8635eSReinoud Zandijk             ret = -1;
812fdc8635eSReinoud Zandijk             break;
813fdc8635eSReinoud Zandijk         }
814fdc8635eSReinoud Zandijk     } while (ret == 0);
815fdc8635eSReinoud Zandijk 
816fdc8635eSReinoud Zandijk     cpu_exec_end(cpu);
817195801d7SStefan Hajnoczi     bql_lock();
818fdc8635eSReinoud Zandijk 
819fdc8635eSReinoud Zandijk     qatomic_set(&cpu->exit_request, false);
820fdc8635eSReinoud Zandijk 
821fdc8635eSReinoud Zandijk     return ret < 0;
822fdc8635eSReinoud Zandijk }
823fdc8635eSReinoud Zandijk 
824fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
825fdc8635eSReinoud Zandijk 
826fdc8635eSReinoud Zandijk static void
do_nvmm_cpu_synchronize_state(CPUState * cpu,run_on_cpu_data arg)827fdc8635eSReinoud Zandijk do_nvmm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
828fdc8635eSReinoud Zandijk {
829fdc8635eSReinoud Zandijk     nvmm_get_registers(cpu);
83079f1926bSPhilippe Mathieu-Daudé     cpu->accel->dirty = true;
831fdc8635eSReinoud Zandijk }
832fdc8635eSReinoud Zandijk 
833fdc8635eSReinoud Zandijk static void
do_nvmm_cpu_synchronize_post_reset(CPUState * cpu,run_on_cpu_data arg)834fdc8635eSReinoud Zandijk do_nvmm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg)
835fdc8635eSReinoud Zandijk {
836fdc8635eSReinoud Zandijk     nvmm_set_registers(cpu);
83779f1926bSPhilippe Mathieu-Daudé     cpu->accel->dirty = false;
838fdc8635eSReinoud Zandijk }
839fdc8635eSReinoud Zandijk 
840fdc8635eSReinoud Zandijk static void
do_nvmm_cpu_synchronize_post_init(CPUState * cpu,run_on_cpu_data arg)841fdc8635eSReinoud Zandijk do_nvmm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
842fdc8635eSReinoud Zandijk {
843fdc8635eSReinoud Zandijk     nvmm_set_registers(cpu);
84479f1926bSPhilippe Mathieu-Daudé     cpu->accel->dirty = false;
845fdc8635eSReinoud Zandijk }
846fdc8635eSReinoud Zandijk 
847fdc8635eSReinoud Zandijk static void
do_nvmm_cpu_synchronize_pre_loadvm(CPUState * cpu,run_on_cpu_data arg)848fdc8635eSReinoud Zandijk do_nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
849fdc8635eSReinoud Zandijk {
85079f1926bSPhilippe Mathieu-Daudé     cpu->accel->dirty = true;
851fdc8635eSReinoud Zandijk }
852fdc8635eSReinoud Zandijk 
nvmm_cpu_synchronize_state(CPUState * cpu)853fdc8635eSReinoud Zandijk void nvmm_cpu_synchronize_state(CPUState *cpu)
854fdc8635eSReinoud Zandijk {
85579f1926bSPhilippe Mathieu-Daudé     if (!cpu->accel->dirty) {
856fdc8635eSReinoud Zandijk         run_on_cpu(cpu, do_nvmm_cpu_synchronize_state, RUN_ON_CPU_NULL);
857fdc8635eSReinoud Zandijk     }
858fdc8635eSReinoud Zandijk }
859fdc8635eSReinoud Zandijk 
nvmm_cpu_synchronize_post_reset(CPUState * cpu)860fdc8635eSReinoud Zandijk void nvmm_cpu_synchronize_post_reset(CPUState *cpu)
861fdc8635eSReinoud Zandijk {
862fdc8635eSReinoud Zandijk     run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_reset, RUN_ON_CPU_NULL);
863fdc8635eSReinoud Zandijk }
864fdc8635eSReinoud Zandijk 
nvmm_cpu_synchronize_post_init(CPUState * cpu)865fdc8635eSReinoud Zandijk void nvmm_cpu_synchronize_post_init(CPUState *cpu)
866fdc8635eSReinoud Zandijk {
867fdc8635eSReinoud Zandijk     run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
868fdc8635eSReinoud Zandijk }
869fdc8635eSReinoud Zandijk 
nvmm_cpu_synchronize_pre_loadvm(CPUState * cpu)870fdc8635eSReinoud Zandijk void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu)
871fdc8635eSReinoud Zandijk {
872fdc8635eSReinoud Zandijk     run_on_cpu(cpu, do_nvmm_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);
873fdc8635eSReinoud Zandijk }
874fdc8635eSReinoud Zandijk 
875fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
876fdc8635eSReinoud Zandijk 
877fdc8635eSReinoud Zandijk static Error *nvmm_migration_blocker;
878fdc8635eSReinoud Zandijk 
879fdc8635eSReinoud Zandijk /*
880fdc8635eSReinoud Zandijk  * The nvmm_vcpu_stop() mechanism breaks races between entering the VMM
881fdc8635eSReinoud Zandijk  * and another thread signaling the vCPU thread to exit.
882fdc8635eSReinoud Zandijk  */
883fdc8635eSReinoud Zandijk 
884fdc8635eSReinoud Zandijk static void
nvmm_ipi_signal(int sigcpu)885fdc8635eSReinoud Zandijk nvmm_ipi_signal(int sigcpu)
886fdc8635eSReinoud Zandijk {
887fdc8635eSReinoud Zandijk     if (current_cpu) {
8882f642b1cSPhilippe Mathieu-Daudé         AccelCPUState *qcpu = current_cpu->accel;
8890cc49650Snia #if NVMM_USER_VERSION >= 2
890fdc8635eSReinoud Zandijk         struct nvmm_vcpu *vcpu = &qcpu->vcpu;
891fdc8635eSReinoud Zandijk         nvmm_vcpu_stop(vcpu);
8920cc49650Snia #else
8930cc49650Snia         qcpu->stop = true;
8940cc49650Snia #endif
895fdc8635eSReinoud Zandijk     }
896fdc8635eSReinoud Zandijk }
897fdc8635eSReinoud Zandijk 
898fdc8635eSReinoud Zandijk static void
nvmm_init_cpu_signals(void)899fdc8635eSReinoud Zandijk nvmm_init_cpu_signals(void)
900fdc8635eSReinoud Zandijk {
901fdc8635eSReinoud Zandijk     struct sigaction sigact;
902fdc8635eSReinoud Zandijk     sigset_t set;
903fdc8635eSReinoud Zandijk 
904fdc8635eSReinoud Zandijk     /* Install the IPI handler. */
905fdc8635eSReinoud Zandijk     memset(&sigact, 0, sizeof(sigact));
906fdc8635eSReinoud Zandijk     sigact.sa_handler = nvmm_ipi_signal;
907fdc8635eSReinoud Zandijk     sigaction(SIG_IPI, &sigact, NULL);
908fdc8635eSReinoud Zandijk 
909fdc8635eSReinoud Zandijk     /* Allow IPIs on the current thread. */
910fdc8635eSReinoud Zandijk     sigprocmask(SIG_BLOCK, NULL, &set);
911fdc8635eSReinoud Zandijk     sigdelset(&set, SIG_IPI);
912fdc8635eSReinoud Zandijk     pthread_sigmask(SIG_SETMASK, &set, NULL);
913fdc8635eSReinoud Zandijk }
914fdc8635eSReinoud Zandijk 
915fdc8635eSReinoud Zandijk int
nvmm_init_vcpu(CPUState * cpu)916fdc8635eSReinoud Zandijk nvmm_init_vcpu(CPUState *cpu)
917fdc8635eSReinoud Zandijk {
918fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
919fdc8635eSReinoud Zandijk     struct nvmm_vcpu_conf_cpuid cpuid;
920fdc8635eSReinoud Zandijk     struct nvmm_vcpu_conf_tpr tpr;
921fdc8635eSReinoud Zandijk     Error *local_error = NULL;
922c5beb26aSPhilippe Mathieu-Daudé     AccelCPUState *qcpu;
923fdc8635eSReinoud Zandijk     int ret, err;
924fdc8635eSReinoud Zandijk 
925fdc8635eSReinoud Zandijk     nvmm_init_cpu_signals();
926fdc8635eSReinoud Zandijk 
927fdc8635eSReinoud Zandijk     if (nvmm_migration_blocker == NULL) {
928fdc8635eSReinoud Zandijk         error_setg(&nvmm_migration_blocker,
929fdc8635eSReinoud Zandijk             "NVMM: Migration not supported");
930fdc8635eSReinoud Zandijk 
931c8a7fc51SSteve Sistare         if (migrate_add_blocker(&nvmm_migration_blocker, &local_error) < 0) {
932fdc8635eSReinoud Zandijk             error_report_err(local_error);
933fdc8635eSReinoud Zandijk             return -EINVAL;
934fdc8635eSReinoud Zandijk         }
935fdc8635eSReinoud Zandijk     }
936fdc8635eSReinoud Zandijk 
937c5beb26aSPhilippe Mathieu-Daudé     qcpu = g_new0(AccelCPUState, 1);
938fdc8635eSReinoud Zandijk 
939fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_create(mach, cpu->cpu_index, &qcpu->vcpu);
940fdc8635eSReinoud Zandijk     if (ret == -1) {
941fdc8635eSReinoud Zandijk         err = errno;
942fdc8635eSReinoud Zandijk         error_report("NVMM: Failed to create a virtual processor,"
943fdc8635eSReinoud Zandijk             " error=%d", err);
944fdc8635eSReinoud Zandijk         g_free(qcpu);
945fdc8635eSReinoud Zandijk         return -err;
946fdc8635eSReinoud Zandijk     }
947fdc8635eSReinoud Zandijk 
948fdc8635eSReinoud Zandijk     memset(&cpuid, 0, sizeof(cpuid));
949fdc8635eSReinoud Zandijk     cpuid.mask = 1;
950fdc8635eSReinoud Zandijk     cpuid.leaf = 0x00000001;
951fdc8635eSReinoud Zandijk     cpuid.u.mask.set.edx = CPUID_MCE | CPUID_MCA | CPUID_MTRR;
952fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_CPUID,
953fdc8635eSReinoud Zandijk         &cpuid);
954fdc8635eSReinoud Zandijk     if (ret == -1) {
955fdc8635eSReinoud Zandijk         err = errno;
956fdc8635eSReinoud Zandijk         error_report("NVMM: Failed to configure a virtual processor,"
957fdc8635eSReinoud Zandijk             " error=%d", err);
958fdc8635eSReinoud Zandijk         g_free(qcpu);
959fdc8635eSReinoud Zandijk         return -err;
960fdc8635eSReinoud Zandijk     }
961fdc8635eSReinoud Zandijk 
962fdc8635eSReinoud Zandijk     ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_CALLBACKS,
963fdc8635eSReinoud Zandijk         &nvmm_callbacks);
964fdc8635eSReinoud Zandijk     if (ret == -1) {
965fdc8635eSReinoud Zandijk         err = errno;
966fdc8635eSReinoud Zandijk         error_report("NVMM: Failed to configure a virtual processor,"
967fdc8635eSReinoud Zandijk             " error=%d", err);
968fdc8635eSReinoud Zandijk         g_free(qcpu);
969fdc8635eSReinoud Zandijk         return -err;
970fdc8635eSReinoud Zandijk     }
971fdc8635eSReinoud Zandijk 
972fdc8635eSReinoud Zandijk     if (qemu_mach.cap.arch.vcpu_conf_support & NVMM_CAP_ARCH_VCPU_CONF_TPR) {
973fdc8635eSReinoud Zandijk         memset(&tpr, 0, sizeof(tpr));
974fdc8635eSReinoud Zandijk         tpr.exit_changed = 1;
975fdc8635eSReinoud Zandijk         ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_TPR, &tpr);
976fdc8635eSReinoud Zandijk         if (ret == -1) {
977fdc8635eSReinoud Zandijk             err = errno;
978fdc8635eSReinoud Zandijk             error_report("NVMM: Failed to configure a virtual processor,"
979fdc8635eSReinoud Zandijk                 " error=%d", err);
980fdc8635eSReinoud Zandijk             g_free(qcpu);
981fdc8635eSReinoud Zandijk             return -err;
982fdc8635eSReinoud Zandijk         }
983fdc8635eSReinoud Zandijk     }
984fdc8635eSReinoud Zandijk 
985*61653b4aSPhilippe Mathieu-Daudé     qcpu->dirty = true;
986f861b3f3SPhilippe Mathieu-Daudé     cpu->accel = qcpu;
987fdc8635eSReinoud Zandijk 
988fdc8635eSReinoud Zandijk     return 0;
989fdc8635eSReinoud Zandijk }
990fdc8635eSReinoud Zandijk 
991fdc8635eSReinoud Zandijk int
nvmm_vcpu_exec(CPUState * cpu)992fdc8635eSReinoud Zandijk nvmm_vcpu_exec(CPUState *cpu)
993fdc8635eSReinoud Zandijk {
994fdc8635eSReinoud Zandijk     int ret, fatal;
995fdc8635eSReinoud Zandijk 
996fdc8635eSReinoud Zandijk     while (1) {
997fdc8635eSReinoud Zandijk         if (cpu->exception_index >= EXCP_INTERRUPT) {
998fdc8635eSReinoud Zandijk             ret = cpu->exception_index;
999fdc8635eSReinoud Zandijk             cpu->exception_index = -1;
1000fdc8635eSReinoud Zandijk             break;
1001fdc8635eSReinoud Zandijk         }
1002fdc8635eSReinoud Zandijk 
1003fdc8635eSReinoud Zandijk         fatal = nvmm_vcpu_loop(cpu);
1004fdc8635eSReinoud Zandijk 
1005fdc8635eSReinoud Zandijk         if (fatal) {
1006fdc8635eSReinoud Zandijk             error_report("NVMM: Failed to execute a VCPU.");
1007fdc8635eSReinoud Zandijk             abort();
1008fdc8635eSReinoud Zandijk         }
1009fdc8635eSReinoud Zandijk     }
1010fdc8635eSReinoud Zandijk 
1011fdc8635eSReinoud Zandijk     return ret;
1012fdc8635eSReinoud Zandijk }
1013fdc8635eSReinoud Zandijk 
1014fdc8635eSReinoud Zandijk void
nvmm_destroy_vcpu(CPUState * cpu)1015fdc8635eSReinoud Zandijk nvmm_destroy_vcpu(CPUState *cpu)
1016fdc8635eSReinoud Zandijk {
1017fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
10182f642b1cSPhilippe Mathieu-Daudé     AccelCPUState *qcpu = cpu->accel;
1019fdc8635eSReinoud Zandijk 
1020fdc8635eSReinoud Zandijk     nvmm_vcpu_destroy(mach, &qcpu->vcpu);
10216ecd2cd0SPhilippe Mathieu-Daudé     g_free(cpu->accel);
1022fdc8635eSReinoud Zandijk }
1023fdc8635eSReinoud Zandijk 
1024fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
1025fdc8635eSReinoud Zandijk 
1026fdc8635eSReinoud Zandijk static void
nvmm_update_mapping(hwaddr start_pa,ram_addr_t size,uintptr_t hva,bool add,bool rom,const char * name)1027fdc8635eSReinoud Zandijk nvmm_update_mapping(hwaddr start_pa, ram_addr_t size, uintptr_t hva,
1028fdc8635eSReinoud Zandijk     bool add, bool rom, const char *name)
1029fdc8635eSReinoud Zandijk {
1030fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
1031fdc8635eSReinoud Zandijk     int ret, prot;
1032fdc8635eSReinoud Zandijk 
1033fdc8635eSReinoud Zandijk     if (add) {
1034fdc8635eSReinoud Zandijk         prot = PROT_READ | PROT_EXEC;
1035fdc8635eSReinoud Zandijk         if (!rom) {
1036fdc8635eSReinoud Zandijk             prot |= PROT_WRITE;
1037fdc8635eSReinoud Zandijk         }
1038fdc8635eSReinoud Zandijk         ret = nvmm_gpa_map(mach, hva, start_pa, size, prot);
1039fdc8635eSReinoud Zandijk     } else {
1040fdc8635eSReinoud Zandijk         ret = nvmm_gpa_unmap(mach, hva, start_pa, size);
1041fdc8635eSReinoud Zandijk     }
1042fdc8635eSReinoud Zandijk 
1043fdc8635eSReinoud Zandijk     if (ret == -1) {
1044fdc8635eSReinoud Zandijk         error_report("NVMM: Failed to %s GPA range '%s' PA:%p, "
1045fdc8635eSReinoud Zandijk             "Size:%p bytes, HostVA:%p, error=%d",
1046fdc8635eSReinoud Zandijk             (add ? "map" : "unmap"), name, (void *)(uintptr_t)start_pa,
1047fdc8635eSReinoud Zandijk             (void *)size, (void *)hva, errno);
1048fdc8635eSReinoud Zandijk     }
1049fdc8635eSReinoud Zandijk }
1050fdc8635eSReinoud Zandijk 
1051fdc8635eSReinoud Zandijk static void
nvmm_process_section(MemoryRegionSection * section,int add)1052fdc8635eSReinoud Zandijk nvmm_process_section(MemoryRegionSection *section, int add)
1053fdc8635eSReinoud Zandijk {
1054fdc8635eSReinoud Zandijk     MemoryRegion *mr = section->mr;
1055fdc8635eSReinoud Zandijk     hwaddr start_pa = section->offset_within_address_space;
1056fdc8635eSReinoud Zandijk     ram_addr_t size = int128_get64(section->size);
1057fdc8635eSReinoud Zandijk     unsigned int delta;
1058fdc8635eSReinoud Zandijk     uintptr_t hva;
1059fdc8635eSReinoud Zandijk 
1060fdc8635eSReinoud Zandijk     if (!memory_region_is_ram(mr)) {
1061fdc8635eSReinoud Zandijk         return;
1062fdc8635eSReinoud Zandijk     }
1063fdc8635eSReinoud Zandijk 
1064fdc8635eSReinoud Zandijk     /* Adjust start_pa and size so that they are page-aligned. */
10658e3b0cbbSMarc-André Lureau     delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask());
10668e3b0cbbSMarc-André Lureau     delta &= ~qemu_real_host_page_mask();
1067fdc8635eSReinoud Zandijk     if (delta > size) {
1068fdc8635eSReinoud Zandijk         return;
1069fdc8635eSReinoud Zandijk     }
1070fdc8635eSReinoud Zandijk     start_pa += delta;
1071fdc8635eSReinoud Zandijk     size -= delta;
10728e3b0cbbSMarc-André Lureau     size &= qemu_real_host_page_mask();
10738e3b0cbbSMarc-André Lureau     if (!size || (start_pa & ~qemu_real_host_page_mask())) {
1074fdc8635eSReinoud Zandijk         return;
1075fdc8635eSReinoud Zandijk     }
1076fdc8635eSReinoud Zandijk 
1077fdc8635eSReinoud Zandijk     hva = (uintptr_t)memory_region_get_ram_ptr(mr) +
1078fdc8635eSReinoud Zandijk         section->offset_within_region + delta;
1079fdc8635eSReinoud Zandijk 
1080fdc8635eSReinoud Zandijk     nvmm_update_mapping(start_pa, size, hva, add,
1081fdc8635eSReinoud Zandijk         memory_region_is_rom(mr), mr->name);
1082fdc8635eSReinoud Zandijk }
1083fdc8635eSReinoud Zandijk 
1084fdc8635eSReinoud Zandijk static void
nvmm_region_add(MemoryListener * listener,MemoryRegionSection * section)1085fdc8635eSReinoud Zandijk nvmm_region_add(MemoryListener *listener, MemoryRegionSection *section)
1086fdc8635eSReinoud Zandijk {
1087fdc8635eSReinoud Zandijk     memory_region_ref(section->mr);
1088fdc8635eSReinoud Zandijk     nvmm_process_section(section, 1);
1089fdc8635eSReinoud Zandijk }
1090fdc8635eSReinoud Zandijk 
1091fdc8635eSReinoud Zandijk static void
nvmm_region_del(MemoryListener * listener,MemoryRegionSection * section)1092fdc8635eSReinoud Zandijk nvmm_region_del(MemoryListener *listener, MemoryRegionSection *section)
1093fdc8635eSReinoud Zandijk {
1094fdc8635eSReinoud Zandijk     nvmm_process_section(section, 0);
1095fdc8635eSReinoud Zandijk     memory_region_unref(section->mr);
1096fdc8635eSReinoud Zandijk }
1097fdc8635eSReinoud Zandijk 
1098fdc8635eSReinoud Zandijk static void
nvmm_transaction_begin(MemoryListener * listener)1099fdc8635eSReinoud Zandijk nvmm_transaction_begin(MemoryListener *listener)
1100fdc8635eSReinoud Zandijk {
1101fdc8635eSReinoud Zandijk     /* nothing */
1102fdc8635eSReinoud Zandijk }
1103fdc8635eSReinoud Zandijk 
1104fdc8635eSReinoud Zandijk static void
nvmm_transaction_commit(MemoryListener * listener)1105fdc8635eSReinoud Zandijk nvmm_transaction_commit(MemoryListener *listener)
1106fdc8635eSReinoud Zandijk {
1107fdc8635eSReinoud Zandijk     /* nothing */
1108fdc8635eSReinoud Zandijk }
1109fdc8635eSReinoud Zandijk 
1110fdc8635eSReinoud Zandijk static void
nvmm_log_sync(MemoryListener * listener,MemoryRegionSection * section)1111fdc8635eSReinoud Zandijk nvmm_log_sync(MemoryListener *listener, MemoryRegionSection *section)
1112fdc8635eSReinoud Zandijk {
1113fdc8635eSReinoud Zandijk     MemoryRegion *mr = section->mr;
1114fdc8635eSReinoud Zandijk 
1115fdc8635eSReinoud Zandijk     if (!memory_region_is_ram(mr)) {
1116fdc8635eSReinoud Zandijk         return;
1117fdc8635eSReinoud Zandijk     }
1118fdc8635eSReinoud Zandijk 
1119fdc8635eSReinoud Zandijk     memory_region_set_dirty(mr, 0, int128_get64(section->size));
1120fdc8635eSReinoud Zandijk }
1121fdc8635eSReinoud Zandijk 
1122fdc8635eSReinoud Zandijk static MemoryListener nvmm_memory_listener = {
1123142518bdSPeter Xu     .name = "nvmm",
1124fdc8635eSReinoud Zandijk     .begin = nvmm_transaction_begin,
1125fdc8635eSReinoud Zandijk     .commit = nvmm_transaction_commit,
1126fdc8635eSReinoud Zandijk     .region_add = nvmm_region_add,
1127fdc8635eSReinoud Zandijk     .region_del = nvmm_region_del,
1128fdc8635eSReinoud Zandijk     .log_sync = nvmm_log_sync,
11295369a36cSIsaku Yamahata     .priority = MEMORY_LISTENER_PRIORITY_ACCEL,
1130fdc8635eSReinoud Zandijk };
1131fdc8635eSReinoud Zandijk 
1132fdc8635eSReinoud Zandijk static void
nvmm_ram_block_added(RAMBlockNotifier * n,void * host,size_t size,size_t max_size)11338d4cd3ddSReinoud Zandijk nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
11348d4cd3ddSReinoud Zandijk                      size_t max_size)
1135fdc8635eSReinoud Zandijk {
1136fdc8635eSReinoud Zandijk     struct nvmm_machine *mach = get_nvmm_mach();
1137fdc8635eSReinoud Zandijk     uintptr_t hva = (uintptr_t)host;
1138fdc8635eSReinoud Zandijk     int ret;
1139fdc8635eSReinoud Zandijk 
11408d4cd3ddSReinoud Zandijk     ret = nvmm_hva_map(mach, hva, max_size);
1141fdc8635eSReinoud Zandijk 
1142fdc8635eSReinoud Zandijk     if (ret == -1) {
1143fdc8635eSReinoud Zandijk         error_report("NVMM: Failed to map HVA, HostVA:%p "
1144fdc8635eSReinoud Zandijk             "Size:%p bytes, error=%d",
1145fdc8635eSReinoud Zandijk             (void *)hva, (void *)size, errno);
1146fdc8635eSReinoud Zandijk     }
1147fdc8635eSReinoud Zandijk }
1148fdc8635eSReinoud Zandijk 
1149fdc8635eSReinoud Zandijk static struct RAMBlockNotifier nvmm_ram_notifier = {
1150fdc8635eSReinoud Zandijk     .ram_block_added = nvmm_ram_block_added
1151fdc8635eSReinoud Zandijk };
1152fdc8635eSReinoud Zandijk 
1153fdc8635eSReinoud Zandijk /* -------------------------------------------------------------------------- */
1154fdc8635eSReinoud Zandijk 
1155fdc8635eSReinoud Zandijk static int
nvmm_accel_init(MachineState * ms)1156fdc8635eSReinoud Zandijk nvmm_accel_init(MachineState *ms)
1157fdc8635eSReinoud Zandijk {
1158fdc8635eSReinoud Zandijk     int ret, err;
1159fdc8635eSReinoud Zandijk 
1160fdc8635eSReinoud Zandijk     ret = nvmm_init();
1161fdc8635eSReinoud Zandijk     if (ret == -1) {
1162fdc8635eSReinoud Zandijk         err = errno;
1163fdc8635eSReinoud Zandijk         error_report("NVMM: Initialization failed, error=%d", errno);
1164fdc8635eSReinoud Zandijk         return -err;
1165fdc8635eSReinoud Zandijk     }
1166fdc8635eSReinoud Zandijk 
1167fdc8635eSReinoud Zandijk     ret = nvmm_capability(&qemu_mach.cap);
1168fdc8635eSReinoud Zandijk     if (ret == -1) {
1169fdc8635eSReinoud Zandijk         err = errno;
1170fdc8635eSReinoud Zandijk         error_report("NVMM: Unable to fetch capability, error=%d", errno);
1171fdc8635eSReinoud Zandijk         return -err;
1172fdc8635eSReinoud Zandijk     }
1173fdc8635eSReinoud Zandijk     if (qemu_mach.cap.version < NVMM_KERN_VERSION) {
1174fdc8635eSReinoud Zandijk         error_report("NVMM: Unsupported version %u", qemu_mach.cap.version);
1175fdc8635eSReinoud Zandijk         return -EPROGMISMATCH;
1176fdc8635eSReinoud Zandijk     }
1177fdc8635eSReinoud Zandijk     if (qemu_mach.cap.state_size != sizeof(struct nvmm_x64_state)) {
1178fdc8635eSReinoud Zandijk         error_report("NVMM: Wrong state size %u", qemu_mach.cap.state_size);
1179fdc8635eSReinoud Zandijk         return -EPROGMISMATCH;
1180fdc8635eSReinoud Zandijk     }
1181fdc8635eSReinoud Zandijk 
1182fdc8635eSReinoud Zandijk     ret = nvmm_machine_create(&qemu_mach.mach);
1183fdc8635eSReinoud Zandijk     if (ret == -1) {
1184fdc8635eSReinoud Zandijk         err = errno;
1185fdc8635eSReinoud Zandijk         error_report("NVMM: Machine creation failed, error=%d", errno);
1186fdc8635eSReinoud Zandijk         return -err;
1187fdc8635eSReinoud Zandijk     }
1188fdc8635eSReinoud Zandijk 
1189fdc8635eSReinoud Zandijk     memory_listener_register(&nvmm_memory_listener, &address_space_memory);
1190fdc8635eSReinoud Zandijk     ram_block_notifier_add(&nvmm_ram_notifier);
1191fdc8635eSReinoud Zandijk 
1192fdc8635eSReinoud Zandijk     printf("NetBSD Virtual Machine Monitor accelerator is operational\n");
1193fdc8635eSReinoud Zandijk     return 0;
1194fdc8635eSReinoud Zandijk }
1195fdc8635eSReinoud Zandijk 
1196fdc8635eSReinoud Zandijk int
nvmm_enabled(void)1197fdc8635eSReinoud Zandijk nvmm_enabled(void)
1198fdc8635eSReinoud Zandijk {
1199fdc8635eSReinoud Zandijk     return nvmm_allowed;
1200fdc8635eSReinoud Zandijk }
1201fdc8635eSReinoud Zandijk 
1202fdc8635eSReinoud Zandijk static void
nvmm_accel_class_init(ObjectClass * oc,void * data)1203fdc8635eSReinoud Zandijk nvmm_accel_class_init(ObjectClass *oc, void *data)
1204fdc8635eSReinoud Zandijk {
1205fdc8635eSReinoud Zandijk     AccelClass *ac = ACCEL_CLASS(oc);
1206fdc8635eSReinoud Zandijk     ac->name = "NVMM";
1207fdc8635eSReinoud Zandijk     ac->init_machine = nvmm_accel_init;
1208fdc8635eSReinoud Zandijk     ac->allowed = &nvmm_allowed;
1209fdc8635eSReinoud Zandijk }
1210fdc8635eSReinoud Zandijk 
1211fdc8635eSReinoud Zandijk static const TypeInfo nvmm_accel_type = {
1212fdc8635eSReinoud Zandijk     .name = ACCEL_CLASS_NAME("nvmm"),
1213fdc8635eSReinoud Zandijk     .parent = TYPE_ACCEL,
1214fdc8635eSReinoud Zandijk     .class_init = nvmm_accel_class_init,
1215fdc8635eSReinoud Zandijk };
1216fdc8635eSReinoud Zandijk 
1217fdc8635eSReinoud Zandijk static void
nvmm_type_init(void)1218fdc8635eSReinoud Zandijk nvmm_type_init(void)
1219fdc8635eSReinoud Zandijk {
1220fdc8635eSReinoud Zandijk     type_register_static(&nvmm_accel_type);
1221fdc8635eSReinoud Zandijk }
1222fdc8635eSReinoud Zandijk 
1223fdc8635eSReinoud Zandijk type_init(nvmm_type_init);
1224