1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2011 NetApp, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "opt_bhyve_snapshot.h" 30 31 #include <sys/param.h> 32 #include <sys/kernel.h> 33 #include <sys/conf.h> 34 #include <sys/libkern.h> 35 #include <sys/ioccom.h> 36 #include <sys/mman.h> 37 #include <sys/uio.h> 38 #include <sys/proc.h> 39 40 #include <vm/vm.h> 41 #include <vm/pmap.h> 42 #include <vm/vm_map.h> 43 44 #include <machine/vmparam.h> 45 #include <machine/vmm.h> 46 #include <machine/vmm_instruction_emul.h> 47 #include <machine/vmm_snapshot.h> 48 #include <x86/apicreg.h> 49 50 #include <dev/vmm/vmm_dev.h> 51 #include <dev/vmm/vmm_mem.h> 52 #include <dev/vmm/vmm_stat.h> 53 54 #include "vmm_lapic.h" 55 #include "vmm_mem.h" 56 #include "io/ppt.h" 57 #include "io/vatpic.h" 58 #include "io/vioapic.h" 59 #include "io/vhpet.h" 60 #include "io/vrtc.h" 61 62 #ifdef COMPAT_FREEBSD13 63 struct vm_stats_13 { 64 int cpuid; /* in */ 65 int num_entries; /* out */ 66 struct timeval tv; 67 uint64_t statbuf[MAX_VM_STATS]; 68 }; 69 70 #define VM_STATS_13 _IOWR('v', IOCNUM_VM_STATS, struct vm_stats_13) 71 72 struct vm_snapshot_meta_13 { 73 void *ctx; /* unused */ 74 void *dev_data; 75 const char *dev_name; /* identify userspace devices */ 76 enum snapshot_req dev_req; /* identify kernel structs */ 77 78 struct vm_snapshot_buffer buffer; 79 80 enum vm_snapshot_op op; 81 }; 82 83 #define VM_SNAPSHOT_REQ_13 \ 84 _IOWR('v', IOCNUM_SNAPSHOT_REQ, struct vm_snapshot_meta_13) 85 86 struct vm_exit_ipi_13 { 87 uint32_t mode; 88 uint8_t vector; 89 __BITSET_DEFINE(, 256) dmask; 90 }; 91 92 struct vm_exit_13 { 93 uint32_t exitcode; 94 int32_t inst_length; 95 uint64_t rip; 96 uint64_t u[120 / sizeof(uint64_t)]; 97 }; 98 99 struct vm_run_13 { 100 int cpuid; 101 struct vm_exit_13 vm_exit; 102 }; 103 104 #define VM_RUN_13 \ 105 _IOWR('v', IOCNUM_RUN, struct vm_run_13) 106 107 #endif /* COMPAT_FREEBSD13 */ 108 109 const struct vmmdev_ioctl vmmdev_machdep_ioctls[] = { 110 VMMDEV_IOCTL(VM_RUN, VMMDEV_IOCTL_LOCK_ONE_VCPU), 111 #ifdef COMPAT_FREEBSD13 112 VMMDEV_IOCTL(VM_RUN_13, VMMDEV_IOCTL_LOCK_ONE_VCPU), 113 #endif 114 VMMDEV_IOCTL(VM_GET_SEGMENT_DESCRIPTOR, VMMDEV_IOCTL_LOCK_ONE_VCPU), 115 VMMDEV_IOCTL(VM_SET_SEGMENT_DESCRIPTOR, VMMDEV_IOCTL_LOCK_ONE_VCPU), 116 VMMDEV_IOCTL(VM_INJECT_EXCEPTION, VMMDEV_IOCTL_LOCK_ONE_VCPU), 117 VMMDEV_IOCTL(VM_SET_X2APIC_STATE, VMMDEV_IOCTL_LOCK_ONE_VCPU), 118 VMMDEV_IOCTL(VM_GLA2GPA, VMMDEV_IOCTL_LOCK_ONE_VCPU), 119 VMMDEV_IOCTL(VM_GLA2GPA_NOFAULT, VMMDEV_IOCTL_LOCK_ONE_VCPU), 120 VMMDEV_IOCTL(VM_SET_INTINFO, VMMDEV_IOCTL_LOCK_ONE_VCPU), 121 VMMDEV_IOCTL(VM_GET_INTINFO, VMMDEV_IOCTL_LOCK_ONE_VCPU), 122 VMMDEV_IOCTL(VM_RESTART_INSTRUCTION, VMMDEV_IOCTL_LOCK_ONE_VCPU), 123 VMMDEV_IOCTL(VM_GET_KERNEMU_DEV, VMMDEV_IOCTL_LOCK_ONE_VCPU), 124 VMMDEV_IOCTL(VM_SET_KERNEMU_DEV, VMMDEV_IOCTL_LOCK_ONE_VCPU), 125 126 VMMDEV_IOCTL(VM_BIND_PPTDEV, 127 VMMDEV_IOCTL_XLOCK_MEMSEGS | VMMDEV_IOCTL_LOCK_ALL_VCPUS | 128 VMMDEV_IOCTL_PRIV_CHECK_DRIVER), 129 VMMDEV_IOCTL(VM_UNBIND_PPTDEV, 130 VMMDEV_IOCTL_XLOCK_MEMSEGS | VMMDEV_IOCTL_LOCK_ALL_VCPUS | 131 VMMDEV_IOCTL_PRIV_CHECK_DRIVER), 132 133 VMMDEV_IOCTL(VM_MAP_PPTDEV_MMIO, VMMDEV_IOCTL_LOCK_ALL_VCPUS | 134 VMMDEV_IOCTL_PRIV_CHECK_DRIVER), 135 VMMDEV_IOCTL(VM_UNMAP_PPTDEV_MMIO, VMMDEV_IOCTL_LOCK_ALL_VCPUS | 136 VMMDEV_IOCTL_PRIV_CHECK_DRIVER), 137 #ifdef BHYVE_SNAPSHOT 138 #ifdef COMPAT_FREEBSD13 139 VMMDEV_IOCTL(VM_SNAPSHOT_REQ_13, VMMDEV_IOCTL_LOCK_ALL_VCPUS), 140 #endif 141 VMMDEV_IOCTL(VM_SNAPSHOT_REQ, VMMDEV_IOCTL_LOCK_ALL_VCPUS), 142 VMMDEV_IOCTL(VM_RESTORE_TIME, VMMDEV_IOCTL_LOCK_ALL_VCPUS), 143 #endif 144 145 #ifdef COMPAT_FREEBSD13 146 VMMDEV_IOCTL(VM_STATS_13, VMMDEV_IOCTL_LOCK_ONE_VCPU), 147 #endif 148 VMMDEV_IOCTL(VM_INJECT_NMI, VMMDEV_IOCTL_LOCK_ONE_VCPU), 149 VMMDEV_IOCTL(VM_LAPIC_IRQ, VMMDEV_IOCTL_LOCK_ONE_VCPU), 150 VMMDEV_IOCTL(VM_GET_X2APIC_STATE, VMMDEV_IOCTL_LOCK_ONE_VCPU), 151 152 VMMDEV_IOCTL(VM_LAPIC_LOCAL_IRQ, VMMDEV_IOCTL_MAYBE_ALLOC_VCPU), 153 154 VMMDEV_IOCTL(VM_PPTDEV_MSI, VMMDEV_IOCTL_PRIV_CHECK_DRIVER), 155 VMMDEV_IOCTL(VM_PPTDEV_MSIX, VMMDEV_IOCTL_PRIV_CHECK_DRIVER), 156 VMMDEV_IOCTL(VM_PPTDEV_DISABLE_MSIX, VMMDEV_IOCTL_PRIV_CHECK_DRIVER), 157 VMMDEV_IOCTL(VM_LAPIC_MSI, 0), 158 VMMDEV_IOCTL(VM_IOAPIC_ASSERT_IRQ, 0), 159 VMMDEV_IOCTL(VM_IOAPIC_DEASSERT_IRQ, 0), 160 VMMDEV_IOCTL(VM_IOAPIC_PULSE_IRQ, 0), 161 VMMDEV_IOCTL(VM_IOAPIC_PINCOUNT, 0), 162 VMMDEV_IOCTL(VM_ISA_ASSERT_IRQ, 0), 163 VMMDEV_IOCTL(VM_ISA_DEASSERT_IRQ, 0), 164 VMMDEV_IOCTL(VM_ISA_PULSE_IRQ, 0), 165 VMMDEV_IOCTL(VM_ISA_SET_IRQ_TRIGGER, 0), 166 VMMDEV_IOCTL(VM_GET_GPA_PMAP, 0), 167 VMMDEV_IOCTL(VM_GET_HPET_CAPABILITIES, 0), 168 VMMDEV_IOCTL(VM_RTC_READ, 0), 169 VMMDEV_IOCTL(VM_RTC_WRITE, 0), 170 VMMDEV_IOCTL(VM_RTC_GETTIME, 0), 171 VMMDEV_IOCTL(VM_RTC_SETTIME, 0), 172 }; 173 const size_t vmmdev_machdep_ioctl_count = nitems(vmmdev_machdep_ioctls); 174 175 int 176 vmmdev_machdep_ioctl(struct vm *vm, struct vcpu *vcpu, u_long cmd, caddr_t data, 177 int fflag, struct thread *td) 178 { 179 int error; 180 181 error = 0; 182 switch (cmd) { 183 case VM_RUN: { 184 struct vm_exit *vme; 185 struct vm_run *vmrun; 186 187 vmrun = (struct vm_run *)data; 188 vme = vm_exitinfo(vcpu); 189 190 error = vm_run(vcpu); 191 if (error != 0) 192 break; 193 194 error = copyout(vme, vmrun->vm_exit, sizeof(*vme)); 195 if (error != 0) 196 break; 197 if (vme->exitcode == VM_EXITCODE_IPI) { 198 error = copyout(vm_exitinfo_cpuset(vcpu), 199 vmrun->cpuset, 200 min(vmrun->cpusetsize, sizeof(cpuset_t))); 201 if (error != 0) 202 break; 203 if (sizeof(cpuset_t) < vmrun->cpusetsize) { 204 uint8_t *p; 205 206 p = (uint8_t *)vmrun->cpuset + 207 sizeof(cpuset_t); 208 while (p < (uint8_t *)vmrun->cpuset + 209 vmrun->cpusetsize) { 210 if (subyte(p++, 0) != 0) { 211 error = EFAULT; 212 break; 213 } 214 } 215 } 216 } 217 break; 218 } 219 #ifdef COMPAT_FREEBSD13 220 case VM_RUN_13: { 221 struct vm_exit *vme; 222 struct vm_exit_13 *vme_13; 223 struct vm_run_13 *vmrun_13; 224 225 vmrun_13 = (struct vm_run_13 *)data; 226 vme_13 = &vmrun_13->vm_exit; 227 vme = vm_exitinfo(vcpu); 228 229 error = vm_run(vcpu); 230 if (error == 0) { 231 vme_13->exitcode = vme->exitcode; 232 vme_13->inst_length = vme->inst_length; 233 vme_13->rip = vme->rip; 234 memcpy(vme_13->u, &vme->u, sizeof(vme_13->u)); 235 if (vme->exitcode == VM_EXITCODE_IPI) { 236 struct vm_exit_ipi_13 *ipi; 237 cpuset_t *dmask; 238 int cpu; 239 240 dmask = vm_exitinfo_cpuset(vcpu); 241 ipi = (struct vm_exit_ipi_13 *)&vme_13->u[0]; 242 BIT_ZERO(256, &ipi->dmask); 243 CPU_FOREACH_ISSET(cpu, dmask) { 244 if (cpu >= 256) 245 break; 246 BIT_SET(256, cpu, &ipi->dmask); 247 } 248 } 249 } 250 break; 251 } 252 case VM_STATS_13: { 253 struct vm_stats_13 *vmstats_13; 254 255 vmstats_13 = (struct vm_stats_13 *)data; 256 getmicrotime(&vmstats_13->tv); 257 error = vmm_stat_copy(vcpu, 0, nitems(vmstats_13->statbuf), 258 &vmstats_13->num_entries, vmstats_13->statbuf); 259 break; 260 } 261 #endif 262 case VM_PPTDEV_MSI: { 263 struct vm_pptdev_msi *pptmsi; 264 265 pptmsi = (struct vm_pptdev_msi *)data; 266 error = ppt_setup_msi(vm, pptmsi->bus, pptmsi->slot, 267 pptmsi->func, pptmsi->addr, pptmsi->msg, pptmsi->numvec); 268 break; 269 } 270 case VM_PPTDEV_MSIX: { 271 struct vm_pptdev_msix *pptmsix; 272 273 pptmsix = (struct vm_pptdev_msix *)data; 274 error = ppt_setup_msix(vm, pptmsix->bus, pptmsix->slot, 275 pptmsix->func, pptmsix->idx, pptmsix->addr, pptmsix->msg, 276 pptmsix->vector_control); 277 break; 278 } 279 case VM_PPTDEV_DISABLE_MSIX: { 280 struct vm_pptdev *pptdev; 281 282 pptdev = (struct vm_pptdev *)data; 283 error = ppt_disable_msix(vm, pptdev->bus, pptdev->slot, 284 pptdev->func); 285 break; 286 } 287 case VM_MAP_PPTDEV_MMIO: { 288 struct vm_pptdev_mmio *pptmmio; 289 290 pptmmio = (struct vm_pptdev_mmio *)data; 291 error = ppt_map_mmio(vm, pptmmio->bus, pptmmio->slot, 292 pptmmio->func, pptmmio->gpa, pptmmio->len, pptmmio->hpa); 293 break; 294 } 295 case VM_UNMAP_PPTDEV_MMIO: { 296 struct vm_pptdev_mmio *pptmmio; 297 298 pptmmio = (struct vm_pptdev_mmio *)data; 299 error = ppt_unmap_mmio(vm, pptmmio->bus, pptmmio->slot, 300 pptmmio->func, pptmmio->gpa, pptmmio->len); 301 break; 302 } 303 case VM_BIND_PPTDEV: { 304 struct vm_pptdev *pptdev; 305 306 pptdev = (struct vm_pptdev *)data; 307 error = vm_assign_pptdev(vm, pptdev->bus, pptdev->slot, 308 pptdev->func); 309 break; 310 } 311 case VM_UNBIND_PPTDEV: { 312 struct vm_pptdev *pptdev; 313 314 pptdev = (struct vm_pptdev *)data; 315 error = vm_unassign_pptdev(vm, pptdev->bus, pptdev->slot, 316 pptdev->func); 317 break; 318 } 319 case VM_INJECT_EXCEPTION: { 320 struct vm_exception *vmexc; 321 322 vmexc = (struct vm_exception *)data; 323 error = vm_inject_exception(vcpu, 324 vmexc->vector, vmexc->error_code_valid, vmexc->error_code, 325 vmexc->restart_instruction); 326 break; 327 } 328 case VM_INJECT_NMI: 329 error = vm_inject_nmi(vcpu); 330 break; 331 case VM_LAPIC_IRQ: { 332 struct vm_lapic_irq *vmirq; 333 334 vmirq = (struct vm_lapic_irq *)data; 335 error = lapic_intr_edge(vcpu, vmirq->vector); 336 break; 337 } 338 case VM_LAPIC_LOCAL_IRQ: { 339 struct vm_lapic_irq *vmirq; 340 341 vmirq = (struct vm_lapic_irq *)data; 342 error = lapic_set_local_intr(vm, vcpu, vmirq->vector); 343 break; 344 } 345 case VM_LAPIC_MSI: { 346 struct vm_lapic_msi *vmmsi; 347 348 vmmsi = (struct vm_lapic_msi *)data; 349 error = lapic_intr_msi(vm, vmmsi->addr, vmmsi->msg); 350 break; 351 } 352 case VM_IOAPIC_ASSERT_IRQ: { 353 struct vm_ioapic_irq *ioapic_irq; 354 355 ioapic_irq = (struct vm_ioapic_irq *)data; 356 error = vioapic_assert_irq(vm, ioapic_irq->irq); 357 break; 358 } 359 case VM_IOAPIC_DEASSERT_IRQ: { 360 struct vm_ioapic_irq *ioapic_irq; 361 362 ioapic_irq = (struct vm_ioapic_irq *)data; 363 error = vioapic_deassert_irq(vm, ioapic_irq->irq); 364 break; 365 } 366 case VM_IOAPIC_PULSE_IRQ: { 367 struct vm_ioapic_irq *ioapic_irq; 368 369 ioapic_irq = (struct vm_ioapic_irq *)data; 370 error = vioapic_pulse_irq(vm, ioapic_irq->irq); 371 break; 372 } 373 case VM_IOAPIC_PINCOUNT: 374 *(int *)data = vioapic_pincount(vm); 375 break; 376 case VM_SET_KERNEMU_DEV: 377 case VM_GET_KERNEMU_DEV: { 378 struct vm_readwrite_kernemu_device *kernemu; 379 mem_region_write_t mwrite; 380 mem_region_read_t mread; 381 int size; 382 bool arg; 383 384 kernemu = (void *)data; 385 386 if (kernemu->access_width > 0) 387 size = (1u << kernemu->access_width); 388 else 389 size = 1; 390 391 if (kernemu->gpa >= DEFAULT_APIC_BASE && 392 kernemu->gpa < DEFAULT_APIC_BASE + PAGE_SIZE) { 393 mread = lapic_mmio_read; 394 mwrite = lapic_mmio_write; 395 } else if (kernemu->gpa >= VIOAPIC_BASE && 396 kernemu->gpa < VIOAPIC_BASE + VIOAPIC_SIZE) { 397 mread = vioapic_mmio_read; 398 mwrite = vioapic_mmio_write; 399 } else if (kernemu->gpa >= VHPET_BASE && 400 kernemu->gpa < VHPET_BASE + VHPET_SIZE) { 401 mread = vhpet_mmio_read; 402 mwrite = vhpet_mmio_write; 403 } else { 404 error = EINVAL; 405 break; 406 } 407 408 if (cmd == VM_SET_KERNEMU_DEV) 409 error = mwrite(vcpu, kernemu->gpa, 410 kernemu->value, size, &arg); 411 else 412 error = mread(vcpu, kernemu->gpa, 413 &kernemu->value, size, &arg); 414 break; 415 } 416 case VM_ISA_ASSERT_IRQ: { 417 struct vm_isa_irq *isa_irq; 418 419 isa_irq = (struct vm_isa_irq *)data; 420 error = vatpic_assert_irq(vm, isa_irq->atpic_irq); 421 if (error == 0 && isa_irq->ioapic_irq != -1) 422 error = vioapic_assert_irq(vm, isa_irq->ioapic_irq); 423 break; 424 } 425 case VM_ISA_DEASSERT_IRQ: { 426 struct vm_isa_irq *isa_irq; 427 428 isa_irq = (struct vm_isa_irq *)data; 429 error = vatpic_deassert_irq(vm, isa_irq->atpic_irq); 430 if (error == 0 && isa_irq->ioapic_irq != -1) 431 error = vioapic_deassert_irq(vm, isa_irq->ioapic_irq); 432 break; 433 } 434 case VM_ISA_PULSE_IRQ: { 435 struct vm_isa_irq *isa_irq; 436 437 isa_irq = (struct vm_isa_irq *)data; 438 error = vatpic_pulse_irq(vm, isa_irq->atpic_irq); 439 if (error == 0 && isa_irq->ioapic_irq != -1) 440 error = vioapic_pulse_irq(vm, isa_irq->ioapic_irq); 441 break; 442 } 443 case VM_ISA_SET_IRQ_TRIGGER: { 444 struct vm_isa_irq_trigger *isa_irq_trigger; 445 446 isa_irq_trigger = (struct vm_isa_irq_trigger *)data; 447 error = vatpic_set_irq_trigger(vm, 448 isa_irq_trigger->atpic_irq, isa_irq_trigger->trigger); 449 break; 450 } 451 case VM_SET_SEGMENT_DESCRIPTOR: { 452 struct vm_seg_desc *vmsegdesc; 453 454 vmsegdesc = (struct vm_seg_desc *)data; 455 error = vm_set_seg_desc(vcpu, vmsegdesc->regnum, 456 &vmsegdesc->desc); 457 break; 458 } 459 case VM_GET_SEGMENT_DESCRIPTOR: { 460 struct vm_seg_desc *vmsegdesc; 461 462 vmsegdesc = (struct vm_seg_desc *)data; 463 error = vm_get_seg_desc(vcpu, vmsegdesc->regnum, 464 &vmsegdesc->desc); 465 break; 466 } 467 case VM_SET_X2APIC_STATE: { 468 struct vm_x2apic *x2apic; 469 470 x2apic = (struct vm_x2apic *)data; 471 error = vm_set_x2apic_state(vcpu, x2apic->state); 472 break; 473 } 474 case VM_GET_X2APIC_STATE: { 475 struct vm_x2apic *x2apic; 476 477 x2apic = (struct vm_x2apic *)data; 478 error = vm_get_x2apic_state(vcpu, &x2apic->state); 479 break; 480 } 481 case VM_GET_GPA_PMAP: { 482 struct vm_gpa_pte *gpapte; 483 484 gpapte = (struct vm_gpa_pte *)data; 485 pmap_get_mapping(vmspace_pmap(vm_vmspace(vm)), gpapte->gpa, 486 gpapte->pte, &gpapte->ptenum); 487 break; 488 } 489 case VM_GET_HPET_CAPABILITIES: 490 error = vhpet_getcap((struct vm_hpet_cap *)data); 491 break; 492 case VM_GLA2GPA: { 493 struct vm_gla2gpa *gg; 494 495 CTASSERT(PROT_READ == VM_PROT_READ); 496 CTASSERT(PROT_WRITE == VM_PROT_WRITE); 497 CTASSERT(PROT_EXEC == VM_PROT_EXECUTE); 498 gg = (struct vm_gla2gpa *)data; 499 error = vm_gla2gpa(vcpu, &gg->paging, gg->gla, 500 gg->prot, &gg->gpa, &gg->fault); 501 KASSERT(error == 0 || error == EFAULT, 502 ("%s: vm_gla2gpa unknown error %d", __func__, error)); 503 break; 504 } 505 case VM_GLA2GPA_NOFAULT: { 506 struct vm_gla2gpa *gg; 507 508 gg = (struct vm_gla2gpa *)data; 509 error = vm_gla2gpa_nofault(vcpu, &gg->paging, gg->gla, 510 gg->prot, &gg->gpa, &gg->fault); 511 KASSERT(error == 0 || error == EFAULT, 512 ("%s: vm_gla2gpa unknown error %d", __func__, error)); 513 break; 514 } 515 case VM_SET_INTINFO: { 516 struct vm_intinfo *vmii; 517 518 vmii = (struct vm_intinfo *)data; 519 error = vm_exit_intinfo(vcpu, vmii->info1); 520 break; 521 } 522 case VM_GET_INTINFO: { 523 struct vm_intinfo *vmii; 524 525 vmii = (struct vm_intinfo *)data; 526 error = vm_get_intinfo(vcpu, &vmii->info1, &vmii->info2); 527 break; 528 } 529 case VM_RTC_WRITE: { 530 struct vm_rtc_data *rtcdata; 531 532 rtcdata = (struct vm_rtc_data *)data; 533 error = vrtc_nvram_write(vm, rtcdata->offset, 534 rtcdata->value); 535 break; 536 } 537 case VM_RTC_READ: { 538 struct vm_rtc_data *rtcdata; 539 540 rtcdata = (struct vm_rtc_data *)data; 541 error = vrtc_nvram_read(vm, rtcdata->offset, 542 &rtcdata->value); 543 break; 544 } 545 case VM_RTC_SETTIME: { 546 struct vm_rtc_time *rtctime; 547 548 rtctime = (struct vm_rtc_time *)data; 549 error = vrtc_set_time(vm, rtctime->secs); 550 break; 551 } 552 case VM_RTC_GETTIME: { 553 struct vm_rtc_time *rtctime; 554 555 rtctime = (struct vm_rtc_time *)data; 556 rtctime->secs = vrtc_get_time(vm); 557 break; 558 } 559 case VM_RESTART_INSTRUCTION: 560 error = vm_restart_instruction(vcpu); 561 break; 562 #ifdef BHYVE_SNAPSHOT 563 case VM_SNAPSHOT_REQ: { 564 struct vm_snapshot_meta *snapshot_meta; 565 566 snapshot_meta = (struct vm_snapshot_meta *)data; 567 error = vm_snapshot_req(vm, snapshot_meta); 568 break; 569 } 570 #ifdef COMPAT_FREEBSD13 571 case VM_SNAPSHOT_REQ_13: { 572 struct vm_snapshot_meta *snapshot_meta; 573 struct vm_snapshot_meta_13 *snapshot_13; 574 575 /* 576 * The old structure just has an additional pointer at 577 * the start that is ignored. 578 */ 579 snapshot_13 = (struct vm_snapshot_meta_13 *)data; 580 snapshot_meta = 581 (struct vm_snapshot_meta *)&snapshot_13->dev_data; 582 error = vm_snapshot_req(vm, snapshot_meta); 583 break; 584 } 585 #endif 586 case VM_RESTORE_TIME: 587 error = vm_restore_time(vm); 588 break; 589 #endif 590 default: 591 error = ENOTTY; 592 break; 593 } 594 595 return (error); 596 } 597