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