Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/bhyverun.c
Show First 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | |||||
#include "inout.h" | #include "inout.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "fwctl.h" | #include "fwctl.h" | ||||
#include "gdb.h" | #include "gdb.h" | ||||
#include "ioapic.h" | #include "ioapic.h" | ||||
#include "kernemu_dev.h" | #include "kernemu_dev.h" | ||||
#include "mem.h" | #include "mem.h" | ||||
#include "mevent.h" | #include "mevent.h" | ||||
#ifdef BHYVE_SNAPSHOT | |||||
#include "migration.h" | |||||
#endif | |||||
#include "mptbl.h" | #include "mptbl.h" | ||||
#include "pci_emul.h" | #include "pci_emul.h" | ||||
#include "pci_irq.h" | #include "pci_irq.h" | ||||
#include "pci_lpc.h" | #include "pci_lpc.h" | ||||
#include "smbiostbl.h" | #include "smbiostbl.h" | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
#include "snapshot.h" | #include "snapshot.h" | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | usage(int code) | ||||
" -k: key=value flat config file\n" | " -k: key=value flat config file\n" | ||||
" -l: LPC device configuration\n" | " -l: LPC device configuration\n" | ||||
" -m: memory size in MB\n" | " -m: memory size in MB\n" | ||||
" -o: set config 'var' to 'value'\n" | " -o: set config 'var' to 'value'\n" | ||||
" -P: vmexit from the guest on pause\n" | " -P: vmexit from the guest on pause\n" | ||||
" -p: pin 'vcpu' to 'hostcpu'\n" | " -p: pin 'vcpu' to 'hostcpu'\n" | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
" -r: path to checkpoint file\n" | " -r: path to checkpoint file\n" | ||||
" -R: <host,port> the source vm host and port for migration\n" | |||||
#endif | #endif | ||||
" -S: guest memory cannot be swapped\n" | " -S: guest memory cannot be swapped\n" | ||||
" -s: <slot,driver,configinfo> PCI slot config\n" | " -s: <slot,driver,configinfo> PCI slot config\n" | ||||
" -U: UUID\n" | " -U: UUID\n" | ||||
" -u: RTC keeps UTC time\n" | " -u: RTC keeps UTC time\n" | ||||
" -W: force virtio to use single-vector MSI\n" | " -W: force virtio to use single-vector MSI\n" | ||||
" -w: ignore unimplemented MSRs\n" | " -w: ignore unimplemented MSRs\n" | ||||
" -x: local APIC is in x2APIC mode\n" | " -x: local APIC is in x2APIC mode\n" | ||||
▲ Show 20 Lines • Show All 955 Lines • ▼ Show 20 Lines | main(int argc, char *argv[]) | ||||
int max_vcpus, memflags; | int max_vcpus, memflags; | ||||
struct vmctx *ctx; | struct vmctx *ctx; | ||||
uint64_t rip; | uint64_t rip; | ||||
size_t memsize; | size_t memsize; | ||||
const char *value, *vmname; | const char *value, *vmname; | ||||
char *optstr; | char *optstr; | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
char *restore_file; | char *restore_file; | ||||
char *receive_migration; | |||||
struct restore_state rstate; | struct restore_state rstate; | ||||
int vcpu; | int vcpu; | ||||
restore_file = NULL; | restore_file = NULL; | ||||
receive_migration = NULL; | |||||
#endif | #endif | ||||
init_config(); | init_config(); | ||||
set_defaults(); | set_defaults(); | ||||
progname = basename(argv[0]); | progname = basename(argv[0]); | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:U:r:"; | optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:U:r:R:"; | ||||
#else | #else | ||||
optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:U:"; | optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:U:"; | ||||
#endif | #endif | ||||
while ((c = getopt(argc, argv, optstr)) != -1) { | while ((c = getopt(argc, argv, optstr)) != -1) { | ||||
switch (c) { | switch (c) { | ||||
case 'a': | case 'a': | ||||
set_config_bool("x86.x2apic", false); | set_config_bool("x86.x2apic", false); | ||||
break; | break; | ||||
Show All 33 Lines | case 'l': | ||||
lpc_print_supported_devices(); | lpc_print_supported_devices(); | ||||
exit(0); | exit(0); | ||||
} else if (lpc_device_parse(optarg) != 0) { | } else if (lpc_device_parse(optarg) != 0) { | ||||
errx(EX_USAGE, "invalid lpc device " | errx(EX_USAGE, "invalid lpc device " | ||||
"configuration '%s'", optarg); | "configuration '%s'", optarg); | ||||
} | } | ||||
break; | break; | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
case 'r': | case 'r': | ||||
restore_file = optarg; | restore_file = optarg; | ||||
break; | break; | ||||
case 'R': | |||||
receive_migration = optarg; | |||||
break; | |||||
jrtc27: Should these be made mutually exclusive? | |||||
#endif | #endif | ||||
case 's': | case 's': | ||||
if (strncmp(optarg, "help", strlen(optarg)) == 0) { | if (strncmp(optarg, "help", strlen(optarg)) == 0) { | ||||
pci_print_supported_devices(); | pci_print_supported_devices(); | ||||
exit(0); | exit(0); | ||||
} else if (pci_parse_slot(optarg) != 0) | } else if (pci_parse_slot(optarg) != 0) | ||||
exit(4); | exit(4); | ||||
else | else | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | if (restore_file != NULL) { | ||||
} | } | ||||
fprintf(stdout, "Resuming pci devs...\r\n"); | fprintf(stdout, "Resuming pci devs...\r\n"); | ||||
if (vm_resume_user_devs(ctx) != 0) { | if (vm_resume_user_devs(ctx) != 0) { | ||||
fprintf(stderr, "Failed to resume PCI device state.\n"); | fprintf(stderr, "Failed to resume PCI device state.\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
} | } | ||||
#endif | |||||
if (receive_migration != NULL) { | |||||
if (vm_pause_user_devs(ctx) != 0) { | |||||
jrtc27Unsubmitted Not Done Inline ActionsThe pause and resume are shared by both restore and migration. Can that be shared, so you have: generic preparation if (restore) { restore code } if (migrate) { migrate code } generic resume jrtc27: The pause and resume are shared by both restore and migration. Can that be shared, so you have… | |||||
fprintf(stderr, "Failed to pause PCI device state.\n"); | |||||
exit(1); | |||||
} | |||||
fprintf(stdout, "Starting the migration process...\r\n"); | |||||
if (receive_vm_migration(ctx, receive_migration) != 0) { | |||||
fprintf(stderr, "Failed to migrate the vm.\r\n"); | |||||
exit(1); | |||||
} | |||||
if (vm_resume_user_devs(ctx) != 0) { | |||||
fprintf(stderr, "Failed to resume PCI device state.\n"); | |||||
exit(1); | |||||
} | |||||
} | |||||
#endif /* BHYVE_SNAPSHOT */ | |||||
error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip); | error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip); | ||||
assert(error == 0); | assert(error == 0); | ||||
/* | /* | ||||
* build the guest tables, MP etc. | * build the guest tables, MP etc. | ||||
*/ | */ | ||||
if (get_config_bool_default("x86.mptable", true)) { | if (get_config_bool_default("x86.mptable", true)) { | ||||
error = mptable_build(ctx, guest_ncpus); | error = mptable_build(ctx, guest_ncpus); | ||||
Show All 37 Lines | #ifdef BHYVE_SNAPSHOT | ||||
init_snapshot(); | init_snapshot(); | ||||
/* | /* | ||||
* checkpointing thread for communication with bhyvectl | * checkpointing thread for communication with bhyvectl | ||||
*/ | */ | ||||
if (init_checkpoint_thread(ctx) < 0) | if (init_checkpoint_thread(ctx) < 0) | ||||
printf("Failed to start checkpoint thread!\r\n"); | printf("Failed to start checkpoint thread!\r\n"); | ||||
if (restore_file != NULL) | if ((restore_file != NULL) || (receive_migration != NULL)) | ||||
jrtc27Unsubmitted Not Done Inline ActionsMight be better to have a variable that means "any kind of restore"? Especially if you follow my suggestion above, you'll need two more uses of this construct otherwise. jrtc27: Might be better to have a variable that means "any kind of restore"? Especially if you follow… | |||||
vm_restore_time(ctx); | vm_restore_time(ctx); | ||||
#endif | #endif | ||||
/* | /* | ||||
* Add CPU 0 | * Add CPU 0 | ||||
*/ | */ | ||||
fbsdrun_addcpu(ctx, BSP, BSP, rip); | fbsdrun_addcpu(ctx, BSP, BSP, rip); | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
/* | /* | ||||
* If we restore a VM, start all vCPUs now (including APs), otherwise, | * If we restore a VM, start all vCPUs now (including APs), otherwise, | ||||
* let the guest OS to spin them up later via vmexits. | * let the guest OS to spin them up later via vmexits. | ||||
*/ | */ | ||||
if (restore_file != NULL) { | if ((restore_file != NULL) || (receive_migration != NULL)) { | ||||
for (vcpu = 0; vcpu < guest_ncpus; vcpu++) { | for (vcpu = 0; vcpu < guest_ncpus; vcpu++) { | ||||
if (vcpu == BSP) | if (vcpu == BSP) | ||||
continue; | continue; | ||||
fprintf(stdout, "spinning up vcpu no %d...\r\n", vcpu); | fprintf(stdout, "spinning up vcpu no %d...\r\n", vcpu); | ||||
spinup_vcpu(ctx, vcpu); | spinup_vcpu(ctx, vcpu); | ||||
} | } | ||||
} | } | ||||
Show All 9 Lines |
Should these be made mutually exclusive?