diff options
-rw-r--r-- | sys/amd64/amd64/mp_machdep.c | 43 | ||||
-rw-r--r-- | usr.sbin/bhyve/bhyverun.c | 30 | ||||
-rw-r--r-- | usr.sbin/bhyve/spinup_ap.c | 81 |
3 files changed, 31 insertions, 123 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index f7423be..33e0814 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -145,26 +145,6 @@ struct cpu_info { int cpu_apic_ids[MAXCPU]; int apic_cpuids[MAX_APIC_ID + 1]; -/* - * Trampoline for hypervisor direct 64-bit jump. - * - * 0 - signature for guest->host verification - * 8 - virtual address of this page - * 16 - instruction virtual address - * 24 - stack pointer virtual address - * 32 - CR3, physical address of kernel page table - * 40 - 24-byte area for null/code/data GDT entries - */ -#define MP_V64T_SIG 0xcafebabecafebabeULL -struct mp_v64tramp { - uint64_t mt_sig; - uint64_t mt_virt; - uint64_t mt_eip; - uint64_t mt_rsp; - uint64_t mt_cr3; - uint64_t mt_gdtr[3]; -}; - /* Holds pending bitmap based IPIs per CPU */ static volatile u_int cpu_ipi_pending[MAXCPU]; @@ -967,29 +947,6 @@ start_all_aps(void) bootSTK = (char *)bootstacks[cpu] + KSTACK_PAGES * PAGE_SIZE - 8; bootAP = cpu; - /* - * If running in a VM that doesn't support the unrestricted - * guest 16-bit mode, forget most of the above and create - * the data block that allows the hypervisor to direct-jump - * into 64-bit mode. Copy this over the top of the 16-bit - * bootstrap. The startup-IPI informs the hypervisor which - * physical page this data block lies in. The hypervisor - * will then use the block to initialise register state of - * the AP in an almost identical fashion to how it builds - * the BSP initial register state. - */ - if (testenv("hw.use_bvm_mptramp")) { - struct mp_v64tramp mv; - - bzero(&mv, sizeof(mv)); - mv.mt_sig = MP_V64T_SIG; - mv.mt_virt = (uint64_t) va; - mv.mt_eip = (uint64_t) init_secondary; - mv.mt_rsp = (uint64_t) bootSTK; - mv.mt_cr3 = KPML4phys; - bcopy(&mv, (void *) va, sizeof(mv)); - } - /* attempt to start the Application Processor */ if (!start_ap(apic_id)) { /* restore the warmstart vector */ diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index fd3d8a2..999040f 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -573,11 +573,28 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip) fprintf(stderr, "vm_run error %d, errno %d\n", error, errno); } +static int +num_vcpus_allowed(struct vmctx *ctx) +{ + int tmp, error; + + error = vm_get_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, &tmp); + + /* + * The guest is allowed to spinup more than one processor only if the + * UNRESTRICTED_GUEST capability is available. + */ + if (error == 0) + return (VM_MAXCPU); + else + return (1); +} int main(int argc, char *argv[]) { int c, error, gdb_port, inject_bkpt, tmp, err, ioapic, bvmcons; + int max_vcpus; struct vmctx *ctx; uint64_t rip; @@ -660,12 +677,6 @@ main(int argc, char *argv[]) if (guest_ncpus <= 1) guest_vcpu_mux = 0; - if (guest_ncpus > VM_MAXCPU) { - fprintf(stderr, "%d vCPUs requested, max %d\n", - guest_ncpus, VM_MAXCPU); - exit(1); - } - /* vmexit on hlt if guest is muxed */ if (guest_vcpu_mux) { guest_vmexit_on_hlt = 1; @@ -680,6 +691,13 @@ main(int argc, char *argv[]) exit(1); } + max_vcpus = num_vcpus_allowed(ctx); + if (guest_ncpus > max_vcpus) { + fprintf(stderr, "%d vCPUs requested but only %d available\n", + guest_ncpus, max_vcpus); + exit(1); + } + if (fbsdrun_vmexit_on_hlt()) { err = vm_get_capability(ctx, BSP, VM_CAP_HALT_EXIT, &tmp); if (err < 0) { diff --git a/usr.sbin/bhyve/spinup_ap.c b/usr.sbin/bhyve/spinup_ap.c index b5e553f..2632aed 100644 --- a/usr.sbin/bhyve/spinup_ap.c +++ b/usr.sbin/bhyve/spinup_ap.c @@ -42,26 +42,6 @@ __FBSDID("$FreeBSD$"); #include "bhyverun.h" #include "spinup_ap.h" -/* - * Trampoline for hypervisor direct 64-bit jump. - * - * 0 - signature for guest->host verification - * 8 - kernel virtual address of trampoline - * 16 - instruction virtual address - * 24 - stack pointer virtual address - * 32 - CR3, physical address of kernel page table - * 40 - 24-byte area for null/code/data GDT entries - */ -#define MP_V64T_SIG 0xcafebabecafebabeULL -struct mp_v64tramp { - uint64_t mt_sig; - uint64_t mt_virt; - uint64_t mt_eip; - uint64_t mt_rsp; - uint64_t mt_cr3; - uint64_t mt_gdtr[3]; -}; - static void spinup_ap_realmode(struct vmctx *ctx, int newcpu, uint64_t *rip) { @@ -94,46 +74,6 @@ spinup_ap_realmode(struct vmctx *ctx, int newcpu, uint64_t *rip) assert(error == 0); } -static void -spinup_ap_direct64(struct vmctx *ctx, int newcpu, uint64_t *rip) -{ - struct mp_v64tramp *mvt; - char *errstr; - int error; - uint64_t gdtbase; - - mvt = paddr_guest2host(*rip); - - assert(mvt->mt_sig == MP_V64T_SIG); - - /* - * Set up the 3-entry GDT using memory supplied in the - * guest's trampoline structure. - */ - vm_setup_freebsd_gdt(mvt->mt_gdtr); - -#define CHECK_ERROR(msg) \ - if (error != 0) { \ - errstr = msg; \ - goto err_exit; \ - } - - /* entry point */ - *rip = mvt->mt_eip; - - /* Get the guest virtual address of the GDT */ - gdtbase = mvt->mt_virt + __offsetof(struct mp_v64tramp, mt_gdtr); - - error = vm_setup_freebsd_registers(ctx, newcpu, mvt->mt_eip, - mvt->mt_cr3, gdtbase, mvt->mt_rsp); - CHECK_ERROR("vm_setup_freebsd_registers"); - - return; -err_exit: - printf("spinup_ap_direct64: machine state error: %s", errstr); - exit(1); -} - int spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip) { @@ -163,22 +103,15 @@ spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip) assert(error == 0); /* - * There are 2 startup modes possible here: - * - if the CPU supports 'unrestricted guest' mode, the spinup can - * set up the processor state in power-on 16-bit mode, with the CS:IP - * init'd to the specified low-mem 4K page. - * - if the guest has requested a 64-bit trampoline in the low-mem 4K - * page by placing in the specified signature, set up the register - * state using register state in the signature. Note that this - * requires accessing guest physical memory to read the signature - * while 'unrestricted mode' does not. + * 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); - if (error) { - spinup_ap_direct64(ctx, newcpu, &rip); - } else { - spinup_ap_realmode(ctx, newcpu, &rip); - } + assert(error == 0); + + spinup_ap_realmode(ctx, newcpu, &rip); fbsdrun_addcpu(ctx, newcpu, rip); |