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