void fbsdrun_set_capabilities(struct vmctx *ctx, int cpu) { int err, tmp; if (fbsdrun_vmexit_on_hlt()) { err = vm_get_capability(ctx, cpu, VM_CAP_HALT_EXIT, &tmp); if (err < 0) { fprintf(stderr, "VM exit on HLT not supported\n"); exit(1); } vm_set_capability(ctx, cpu, VM_CAP_HALT_EXIT, 1); if (cpu == BSP) handler[VM_EXITCODE_HLT] = vmexit_hlt; } if (fbsdrun_vmexit_on_pause()) { /* * pause exit support required for this mode */ err = vm_get_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, &tmp); if (err < 0) { fprintf(stderr, "SMP mux requested, no pause support\n"); exit(1); } vm_set_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, 1); if (cpu == BSP) handler[VM_EXITCODE_PAUSE] = vmexit_pause; } if (fbsdrun_disable_x2apic()) err = vm_set_x2apic_state(ctx, cpu, X2APIC_DISABLED); else err = vm_set_x2apic_state(ctx, cpu, X2APIC_ENABLED); if (err) { fprintf(stderr, "Unable to set x2apic state (%d)\n", err); exit(1); } vm_set_capability(ctx, cpu, VM_CAP_ENABLE_INVPCID, 1); }
int spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip) { int error; assert(newcpu != 0); assert(newcpu < guest_ncpus); error = vcpu_reset(ctx, newcpu); assert(error == 0); /* Set up capabilities */ if (fbsdrun_vmexit_on_hlt()) { error = vm_set_capability(ctx, newcpu, VM_CAP_HALT_EXIT, 1); assert(error == 0); } if (fbsdrun_vmexit_on_pause()) { error = vm_set_capability(ctx, newcpu, VM_CAP_PAUSE_EXIT, 1); assert(error == 0); } if (fbsdrun_disable_x2apic()) error = vm_set_x2apic_state(ctx, newcpu, X2APIC_DISABLED); else error = vm_set_x2apic_state(ctx, newcpu, X2APIC_ENABLED); assert(error == 0); /* * Enable the 'unrestricted guest' mode for 'newcpu'. * * Set up the processor state in power-on 16-bit mode, with the CS:IP * init'd to the specified low-mem 4K page. */ error = vm_set_capability(ctx, newcpu, VM_CAP_UNRESTRICTED_GUEST, 1); assert(error == 0); spinup_ap_realmode(ctx, newcpu, &rip); fbsdrun_addcpu(ctx, newcpu, rip); return (newcpu); }