qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

nvmm-all.c (35117B)


      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);