1967264cfSMark Johnston /*- 2967264cfSMark Johnston * SPDX-License-Identifier: BSD-2-Clause 3967264cfSMark Johnston * 4967264cfSMark Johnston * Copyright (c) 2011 NetApp, Inc. 5967264cfSMark Johnston * All rights reserved. 6967264cfSMark Johnston * 7967264cfSMark Johnston * Redistribution and use in source and binary forms, with or without 8967264cfSMark Johnston * modification, are permitted provided that the following conditions 9967264cfSMark Johnston * are met: 10967264cfSMark Johnston * 1. Redistributions of source code must retain the above copyright 11967264cfSMark Johnston * notice, this list of conditions and the following disclaimer. 12967264cfSMark Johnston * 2. Redistributions in binary form must reproduce the above copyright 13967264cfSMark Johnston * notice, this list of conditions and the following disclaimer in the 14967264cfSMark Johnston * documentation and/or other materials provided with the distribution. 15967264cfSMark Johnston * 16967264cfSMark Johnston * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 17967264cfSMark Johnston * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18967264cfSMark Johnston * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19967264cfSMark Johnston * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 20967264cfSMark Johnston * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21967264cfSMark Johnston * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22967264cfSMark Johnston * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23967264cfSMark Johnston * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24967264cfSMark Johnston * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25967264cfSMark Johnston * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26967264cfSMark Johnston * SUCH DAMAGE. 27967264cfSMark Johnston */ 28967264cfSMark Johnston 29e4656e10SMark Johnston #include <sys/types.h> 30e4656e10SMark Johnston #include <sys/ioctl.h> 31e4656e10SMark Johnston 32967264cfSMark Johnston #include <machine/specialreg.h> 33e4656e10SMark Johnston #include <machine/vmm.h> 347f00e46bSMark Johnston #include <machine/vmm_dev.h> 357f00e46bSMark Johnston #include <machine/vmm_snapshot.h> 36e4656e10SMark Johnston 37e4656e10SMark Johnston #include <string.h> 38967264cfSMark Johnston 39967264cfSMark Johnston #include "vmmapi.h" 40967264cfSMark Johnston #include "internal.h" 41967264cfSMark Johnston 4285efb31dSMark Johnston const char *vm_capstrmap[] = { 4385efb31dSMark Johnston [VM_CAP_HALT_EXIT] = "hlt_exit", 4485efb31dSMark Johnston [VM_CAP_MTRAP_EXIT] = "mtrap_exit", 4585efb31dSMark Johnston [VM_CAP_PAUSE_EXIT] = "pause_exit", 4685efb31dSMark Johnston [VM_CAP_UNRESTRICTED_GUEST] = "unrestricted_guest", 4785efb31dSMark Johnston [VM_CAP_ENABLE_INVPCID] = "enable_invpcid", 4885efb31dSMark Johnston [VM_CAP_BPT_EXIT] = "bpt_exit", 4985efb31dSMark Johnston [VM_CAP_RDPID] = "rdpid", 5085efb31dSMark Johnston [VM_CAP_RDTSCP] = "rdtscp", 5185efb31dSMark Johnston [VM_CAP_IPI_EXIT] = "ipi_exit", 5285efb31dSMark Johnston [VM_CAP_MASK_HWINTR] = "mask_hwintr", 5385efb31dSMark Johnston [VM_CAP_RFLAGS_TF] = "rflags_tf", 5485efb31dSMark Johnston [VM_CAP_MAX] = NULL, 5585efb31dSMark Johnston }; 5685efb31dSMark Johnston 577f00e46bSMark Johnston #define VM_MD_IOCTLS \ 587f00e46bSMark Johnston VM_SET_SEGMENT_DESCRIPTOR, \ 597f00e46bSMark Johnston VM_GET_SEGMENT_DESCRIPTOR, \ 607f00e46bSMark Johnston VM_SET_KERNEMU_DEV, \ 617f00e46bSMark Johnston VM_GET_KERNEMU_DEV, \ 627f00e46bSMark Johnston VM_LAPIC_IRQ, \ 637f00e46bSMark Johnston VM_LAPIC_LOCAL_IRQ, \ 647f00e46bSMark Johnston VM_LAPIC_MSI, \ 657f00e46bSMark Johnston VM_IOAPIC_ASSERT_IRQ, \ 667f00e46bSMark Johnston VM_IOAPIC_DEASSERT_IRQ, \ 677f00e46bSMark Johnston VM_IOAPIC_PULSE_IRQ, \ 687f00e46bSMark Johnston VM_IOAPIC_PINCOUNT, \ 697f00e46bSMark Johnston VM_ISA_ASSERT_IRQ, \ 707f00e46bSMark Johnston VM_ISA_DEASSERT_IRQ, \ 717f00e46bSMark Johnston VM_ISA_PULSE_IRQ, \ 727f00e46bSMark Johnston VM_ISA_SET_IRQ_TRIGGER, \ 737f00e46bSMark Johnston VM_INJECT_NMI, \ 747f00e46bSMark Johnston VM_SET_X2APIC_STATE, \ 757f00e46bSMark Johnston VM_GET_X2APIC_STATE, \ 767f00e46bSMark Johnston VM_GET_HPET_CAPABILITIES, \ 777f00e46bSMark Johnston VM_RTC_WRITE, \ 787f00e46bSMark Johnston VM_RTC_READ, \ 797f00e46bSMark Johnston VM_RTC_SETTIME, \ 807f00e46bSMark Johnston VM_RTC_GETTIME 817f00e46bSMark Johnston 827f00e46bSMark Johnston const cap_ioctl_t vm_ioctl_cmds[] = { 837f00e46bSMark Johnston VM_COMMON_IOCTLS, 847f00e46bSMark Johnston VM_PPT_IOCTLS, 857f00e46bSMark Johnston VM_MD_IOCTLS, 867f00e46bSMark Johnston }; 877f00e46bSMark Johnston size_t vm_ioctl_ncmds = nitems(vm_ioctl_cmds); 887f00e46bSMark Johnston 89e4656e10SMark Johnston int 90e4656e10SMark Johnston vm_set_desc(struct vcpu *vcpu, int reg, 91e4656e10SMark Johnston uint64_t base, uint32_t limit, uint32_t access) 92e4656e10SMark Johnston { 93e4656e10SMark Johnston int error; 94e4656e10SMark Johnston struct vm_seg_desc vmsegdesc; 95e4656e10SMark Johnston 96e4656e10SMark Johnston bzero(&vmsegdesc, sizeof(vmsegdesc)); 97e4656e10SMark Johnston vmsegdesc.regnum = reg; 98e4656e10SMark Johnston vmsegdesc.desc.base = base; 99e4656e10SMark Johnston vmsegdesc.desc.limit = limit; 100e4656e10SMark Johnston vmsegdesc.desc.access = access; 101e4656e10SMark Johnston 102e4656e10SMark Johnston error = vcpu_ioctl(vcpu, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc); 103e4656e10SMark Johnston return (error); 104e4656e10SMark Johnston } 105e4656e10SMark Johnston 106e4656e10SMark Johnston int 107e4656e10SMark Johnston vm_get_desc(struct vcpu *vcpu, int reg, uint64_t *base, uint32_t *limit, 108e4656e10SMark Johnston uint32_t *access) 109e4656e10SMark Johnston { 110e4656e10SMark Johnston int error; 111e4656e10SMark Johnston struct vm_seg_desc vmsegdesc; 112e4656e10SMark Johnston 113e4656e10SMark Johnston bzero(&vmsegdesc, sizeof(vmsegdesc)); 114e4656e10SMark Johnston vmsegdesc.regnum = reg; 115e4656e10SMark Johnston 116e4656e10SMark Johnston error = vcpu_ioctl(vcpu, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc); 117e4656e10SMark Johnston if (error == 0) { 118e4656e10SMark Johnston *base = vmsegdesc.desc.base; 119e4656e10SMark Johnston *limit = vmsegdesc.desc.limit; 120e4656e10SMark Johnston *access = vmsegdesc.desc.access; 121e4656e10SMark Johnston } 122e4656e10SMark Johnston return (error); 123e4656e10SMark Johnston } 124e4656e10SMark Johnston 125e4656e10SMark Johnston int 126e4656e10SMark Johnston vm_get_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *seg_desc) 127e4656e10SMark Johnston { 128e4656e10SMark Johnston int error; 129e4656e10SMark Johnston 130e4656e10SMark Johnston error = vm_get_desc(vcpu, reg, &seg_desc->base, &seg_desc->limit, 131e4656e10SMark Johnston &seg_desc->access); 132e4656e10SMark Johnston return (error); 133e4656e10SMark Johnston } 134e4656e10SMark Johnston 135e4656e10SMark Johnston int 136e4656e10SMark Johnston vm_lapic_irq(struct vcpu *vcpu, int vector) 137e4656e10SMark Johnston { 138e4656e10SMark Johnston struct vm_lapic_irq vmirq; 139e4656e10SMark Johnston 140e4656e10SMark Johnston bzero(&vmirq, sizeof(vmirq)); 141e4656e10SMark Johnston vmirq.vector = vector; 142e4656e10SMark Johnston 143e4656e10SMark Johnston return (vcpu_ioctl(vcpu, VM_LAPIC_IRQ, &vmirq)); 144e4656e10SMark Johnston } 145e4656e10SMark Johnston 146e4656e10SMark Johnston int 147e4656e10SMark Johnston vm_lapic_local_irq(struct vcpu *vcpu, int vector) 148e4656e10SMark Johnston { 149e4656e10SMark Johnston struct vm_lapic_irq vmirq; 150e4656e10SMark Johnston 151e4656e10SMark Johnston bzero(&vmirq, sizeof(vmirq)); 152e4656e10SMark Johnston vmirq.vector = vector; 153e4656e10SMark Johnston 154e4656e10SMark Johnston return (vcpu_ioctl(vcpu, VM_LAPIC_LOCAL_IRQ, &vmirq)); 155e4656e10SMark Johnston } 156e4656e10SMark Johnston 157e4656e10SMark Johnston int 158e4656e10SMark Johnston vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg) 159e4656e10SMark Johnston { 160e4656e10SMark Johnston struct vm_lapic_msi vmmsi; 161e4656e10SMark Johnston 162e4656e10SMark Johnston bzero(&vmmsi, sizeof(vmmsi)); 163e4656e10SMark Johnston vmmsi.addr = addr; 164e4656e10SMark Johnston vmmsi.msg = msg; 165e4656e10SMark Johnston 166e4656e10SMark Johnston return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi)); 167e4656e10SMark Johnston } 168e4656e10SMark Johnston 169e4656e10SMark Johnston int 170e4656e10SMark Johnston vm_apicid2vcpu(struct vmctx *ctx __unused, int apicid) 171e4656e10SMark Johnston { 172e4656e10SMark Johnston /* 173e4656e10SMark Johnston * The apic id associated with the 'vcpu' has the same numerical value 174e4656e10SMark Johnston * as the 'vcpu' itself. 175e4656e10SMark Johnston */ 176e4656e10SMark Johnston return (apicid); 177e4656e10SMark Johnston } 178e4656e10SMark Johnston 179e4656e10SMark Johnston int 180e4656e10SMark Johnston vm_ioapic_assert_irq(struct vmctx *ctx, int irq) 181e4656e10SMark Johnston { 182e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq; 183e4656e10SMark Johnston 184e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq)); 185e4656e10SMark Johnston ioapic_irq.irq = irq; 186e4656e10SMark Johnston 187e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq)); 188e4656e10SMark Johnston } 189e4656e10SMark Johnston 190e4656e10SMark Johnston int 191e4656e10SMark Johnston vm_ioapic_deassert_irq(struct vmctx *ctx, int irq) 192e4656e10SMark Johnston { 193e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq; 194e4656e10SMark Johnston 195e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq)); 196e4656e10SMark Johnston ioapic_irq.irq = irq; 197e4656e10SMark Johnston 198e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq)); 199e4656e10SMark Johnston } 200e4656e10SMark Johnston 201e4656e10SMark Johnston int 202e4656e10SMark Johnston vm_ioapic_pulse_irq(struct vmctx *ctx, int irq) 203e4656e10SMark Johnston { 204e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq; 205e4656e10SMark Johnston 206e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq)); 207e4656e10SMark Johnston ioapic_irq.irq = irq; 208e4656e10SMark Johnston 209e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq)); 210e4656e10SMark Johnston } 211e4656e10SMark Johnston 212e4656e10SMark Johnston int 213e4656e10SMark Johnston vm_ioapic_pincount(struct vmctx *ctx, int *pincount) 214e4656e10SMark Johnston { 215e4656e10SMark Johnston 216e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount)); 217e4656e10SMark Johnston } 218e4656e10SMark Johnston 219e4656e10SMark Johnston int 220e4656e10SMark Johnston vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) 221e4656e10SMark Johnston { 222e4656e10SMark Johnston struct vm_isa_irq isa_irq; 223e4656e10SMark Johnston 224e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq)); 225e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq; 226e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq; 227e4656e10SMark Johnston 228e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq)); 229e4656e10SMark Johnston } 230e4656e10SMark Johnston 231e4656e10SMark Johnston int 232e4656e10SMark Johnston vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) 233e4656e10SMark Johnston { 234e4656e10SMark Johnston struct vm_isa_irq isa_irq; 235e4656e10SMark Johnston 236e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq)); 237e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq; 238e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq; 239e4656e10SMark Johnston 240e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq)); 241e4656e10SMark Johnston } 242e4656e10SMark Johnston 243e4656e10SMark Johnston int 244e4656e10SMark Johnston vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) 245e4656e10SMark Johnston { 246e4656e10SMark Johnston struct vm_isa_irq isa_irq; 247e4656e10SMark Johnston 248e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq)); 249e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq; 250e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq; 251e4656e10SMark Johnston 252e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq)); 253e4656e10SMark Johnston } 254e4656e10SMark Johnston 255e4656e10SMark Johnston int 256e4656e10SMark Johnston vm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq, 257e4656e10SMark Johnston enum vm_intr_trigger trigger) 258e4656e10SMark Johnston { 259e4656e10SMark Johnston struct vm_isa_irq_trigger isa_irq_trigger; 260e4656e10SMark Johnston 261e4656e10SMark Johnston bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger)); 262e4656e10SMark Johnston isa_irq_trigger.atpic_irq = atpic_irq; 263e4656e10SMark Johnston isa_irq_trigger.trigger = trigger; 264e4656e10SMark Johnston 265e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger)); 266e4656e10SMark Johnston } 267e4656e10SMark Johnston 268e4656e10SMark Johnston int 269e4656e10SMark Johnston vm_inject_nmi(struct vcpu *vcpu) 270e4656e10SMark Johnston { 271e4656e10SMark Johnston struct vm_nmi vmnmi; 272e4656e10SMark Johnston 273e4656e10SMark Johnston bzero(&vmnmi, sizeof(vmnmi)); 274e4656e10SMark Johnston 275e4656e10SMark Johnston return (vcpu_ioctl(vcpu, VM_INJECT_NMI, &vmnmi)); 276e4656e10SMark Johnston } 277e4656e10SMark Johnston 278*3170dcaeSMark Johnston int 279*3170dcaeSMark Johnston vm_inject_exception(struct vcpu *vcpu, int vector, int errcode_valid, 280*3170dcaeSMark Johnston uint32_t errcode, int restart_instruction) 281*3170dcaeSMark Johnston { 282*3170dcaeSMark Johnston struct vm_exception exc; 283*3170dcaeSMark Johnston 284*3170dcaeSMark Johnston exc.vector = vector; 285*3170dcaeSMark Johnston exc.error_code = errcode; 286*3170dcaeSMark Johnston exc.error_code_valid = errcode_valid; 287*3170dcaeSMark Johnston exc.restart_instruction = restart_instruction; 288*3170dcaeSMark Johnston 289*3170dcaeSMark Johnston return (vcpu_ioctl(vcpu, VM_INJECT_EXCEPTION, &exc)); 290*3170dcaeSMark Johnston } 291*3170dcaeSMark Johnston 292*3170dcaeSMark Johnston int 293*3170dcaeSMark Johnston vm_readwrite_kernemu_device(struct vcpu *vcpu, vm_paddr_t gpa, 294*3170dcaeSMark Johnston bool write, int size, uint64_t *value) 295*3170dcaeSMark Johnston { 296*3170dcaeSMark Johnston struct vm_readwrite_kernemu_device irp = { 297*3170dcaeSMark Johnston .access_width = fls(size) - 1, 298*3170dcaeSMark Johnston .gpa = gpa, 299*3170dcaeSMark Johnston .value = write ? *value : ~0ul, 300*3170dcaeSMark Johnston }; 301*3170dcaeSMark Johnston long cmd = (write ? VM_SET_KERNEMU_DEV : VM_GET_KERNEMU_DEV); 302*3170dcaeSMark Johnston int rc; 303*3170dcaeSMark Johnston 304*3170dcaeSMark Johnston rc = vcpu_ioctl(vcpu, cmd, &irp); 305*3170dcaeSMark Johnston if (rc == 0 && !write) 306*3170dcaeSMark Johnston *value = irp.value; 307*3170dcaeSMark Johnston return (rc); 308*3170dcaeSMark Johnston } 309*3170dcaeSMark Johnston 310*3170dcaeSMark Johnston int 311*3170dcaeSMark Johnston vm_get_x2apic_state(struct vcpu *vcpu, enum x2apic_state *state) 312*3170dcaeSMark Johnston { 313*3170dcaeSMark Johnston int error; 314*3170dcaeSMark Johnston struct vm_x2apic x2apic; 315*3170dcaeSMark Johnston 316*3170dcaeSMark Johnston bzero(&x2apic, sizeof(x2apic)); 317*3170dcaeSMark Johnston 318*3170dcaeSMark Johnston error = vcpu_ioctl(vcpu, VM_GET_X2APIC_STATE, &x2apic); 319*3170dcaeSMark Johnston *state = x2apic.state; 320*3170dcaeSMark Johnston return (error); 321*3170dcaeSMark Johnston } 322*3170dcaeSMark Johnston 323*3170dcaeSMark Johnston int 324*3170dcaeSMark Johnston vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state) 325*3170dcaeSMark Johnston { 326*3170dcaeSMark Johnston int error; 327*3170dcaeSMark Johnston struct vm_x2apic x2apic; 328*3170dcaeSMark Johnston 329*3170dcaeSMark Johnston bzero(&x2apic, sizeof(x2apic)); 330*3170dcaeSMark Johnston x2apic.state = state; 331*3170dcaeSMark Johnston 332*3170dcaeSMark Johnston error = vcpu_ioctl(vcpu, VM_SET_X2APIC_STATE, &x2apic); 333*3170dcaeSMark Johnston 334*3170dcaeSMark Johnston return (error); 335*3170dcaeSMark Johnston } 336*3170dcaeSMark Johnston 337*3170dcaeSMark Johnston int 338*3170dcaeSMark Johnston vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities) 339*3170dcaeSMark Johnston { 340*3170dcaeSMark Johnston int error; 341*3170dcaeSMark Johnston struct vm_hpet_cap cap; 342*3170dcaeSMark Johnston 343*3170dcaeSMark Johnston bzero(&cap, sizeof(struct vm_hpet_cap)); 344*3170dcaeSMark Johnston error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap); 345*3170dcaeSMark Johnston if (capabilities != NULL) 346*3170dcaeSMark Johnston *capabilities = cap.capabilities; 347*3170dcaeSMark Johnston return (error); 348*3170dcaeSMark Johnston } 349*3170dcaeSMark Johnston 350*3170dcaeSMark Johnston int 351*3170dcaeSMark Johnston vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value) 352*3170dcaeSMark Johnston { 353*3170dcaeSMark Johnston struct vm_rtc_data rtcdata; 354*3170dcaeSMark Johnston int error; 355*3170dcaeSMark Johnston 356*3170dcaeSMark Johnston bzero(&rtcdata, sizeof(struct vm_rtc_data)); 357*3170dcaeSMark Johnston rtcdata.offset = offset; 358*3170dcaeSMark Johnston rtcdata.value = value; 359*3170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata); 360*3170dcaeSMark Johnston return (error); 361*3170dcaeSMark Johnston } 362*3170dcaeSMark Johnston 363*3170dcaeSMark Johnston int 364*3170dcaeSMark Johnston vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval) 365*3170dcaeSMark Johnston { 366*3170dcaeSMark Johnston struct vm_rtc_data rtcdata; 367*3170dcaeSMark Johnston int error; 368*3170dcaeSMark Johnston 369*3170dcaeSMark Johnston bzero(&rtcdata, sizeof(struct vm_rtc_data)); 370*3170dcaeSMark Johnston rtcdata.offset = offset; 371*3170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata); 372*3170dcaeSMark Johnston if (error == 0) 373*3170dcaeSMark Johnston *retval = rtcdata.value; 374*3170dcaeSMark Johnston return (error); 375*3170dcaeSMark Johnston } 376*3170dcaeSMark Johnston 377*3170dcaeSMark Johnston int 378*3170dcaeSMark Johnston vm_rtc_settime(struct vmctx *ctx, time_t secs) 379*3170dcaeSMark Johnston { 380*3170dcaeSMark Johnston struct vm_rtc_time rtctime; 381*3170dcaeSMark Johnston int error; 382*3170dcaeSMark Johnston 383*3170dcaeSMark Johnston bzero(&rtctime, sizeof(struct vm_rtc_time)); 384*3170dcaeSMark Johnston rtctime.secs = secs; 385*3170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime); 386*3170dcaeSMark Johnston return (error); 387*3170dcaeSMark Johnston } 388*3170dcaeSMark Johnston 389*3170dcaeSMark Johnston int 390*3170dcaeSMark Johnston vm_rtc_gettime(struct vmctx *ctx, time_t *secs) 391*3170dcaeSMark Johnston { 392*3170dcaeSMark Johnston struct vm_rtc_time rtctime; 393*3170dcaeSMark Johnston int error; 394*3170dcaeSMark Johnston 395*3170dcaeSMark Johnston bzero(&rtctime, sizeof(struct vm_rtc_time)); 396*3170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime); 397*3170dcaeSMark Johnston if (error == 0) 398*3170dcaeSMark Johnston *secs = rtctime.secs; 399*3170dcaeSMark Johnston return (error); 400*3170dcaeSMark Johnston } 401*3170dcaeSMark Johnston 402967264cfSMark Johnston /* 403967264cfSMark Johnston * From Intel Vol 3a: 404967264cfSMark Johnston * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT 405967264cfSMark Johnston */ 406967264cfSMark Johnston int 407967264cfSMark Johnston vcpu_reset(struct vcpu *vcpu) 408967264cfSMark Johnston { 409967264cfSMark Johnston int error; 410967264cfSMark Johnston uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx; 411967264cfSMark Johnston uint32_t desc_access, desc_limit; 412967264cfSMark Johnston uint16_t sel; 413967264cfSMark Johnston 414967264cfSMark Johnston zero = 0; 415967264cfSMark Johnston 416967264cfSMark Johnston rflags = 0x2; 417967264cfSMark Johnston error = vm_set_register(vcpu, VM_REG_GUEST_RFLAGS, rflags); 418967264cfSMark Johnston if (error) 419967264cfSMark Johnston goto done; 420967264cfSMark Johnston 421967264cfSMark Johnston rip = 0xfff0; 422967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RIP, rip)) != 0) 423967264cfSMark Johnston goto done; 424967264cfSMark Johnston 425967264cfSMark Johnston /* 426967264cfSMark Johnston * According to Intels Software Developer Manual CR0 should be 427967264cfSMark Johnston * initialized with CR0_ET | CR0_NW | CR0_CD but that crashes some 428967264cfSMark Johnston * guests like Windows. 429967264cfSMark Johnston */ 430967264cfSMark Johnston cr0 = CR0_NE; 431967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR0, cr0)) != 0) 432967264cfSMark Johnston goto done; 433967264cfSMark Johnston 434967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR2, zero)) != 0) 435967264cfSMark Johnston goto done; 436967264cfSMark Johnston 437967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR3, zero)) != 0) 438967264cfSMark Johnston goto done; 439967264cfSMark Johnston 440967264cfSMark Johnston cr4 = 0; 441967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR4, cr4)) != 0) 442967264cfSMark Johnston goto done; 443967264cfSMark Johnston 444967264cfSMark Johnston /* 445967264cfSMark Johnston * CS: present, r/w, accessed, 16-bit, byte granularity, usable 446967264cfSMark Johnston */ 447967264cfSMark Johnston desc_base = 0xffff0000; 448967264cfSMark Johnston desc_limit = 0xffff; 449967264cfSMark Johnston desc_access = 0x0093; 450967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_CS, 451967264cfSMark Johnston desc_base, desc_limit, desc_access); 452967264cfSMark Johnston if (error) 453967264cfSMark Johnston goto done; 454967264cfSMark Johnston 455967264cfSMark Johnston sel = 0xf000; 456967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CS, sel)) != 0) 457967264cfSMark Johnston goto done; 458967264cfSMark Johnston 459967264cfSMark Johnston /* 460967264cfSMark Johnston * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity 461967264cfSMark Johnston */ 462967264cfSMark Johnston desc_base = 0; 463967264cfSMark Johnston desc_limit = 0xffff; 464967264cfSMark Johnston desc_access = 0x0093; 465967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_SS, 466967264cfSMark Johnston desc_base, desc_limit, desc_access); 467967264cfSMark Johnston if (error) 468967264cfSMark Johnston goto done; 469967264cfSMark Johnston 470967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_DS, 471967264cfSMark Johnston desc_base, desc_limit, desc_access); 472967264cfSMark Johnston if (error) 473967264cfSMark Johnston goto done; 474967264cfSMark Johnston 475967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_ES, 476967264cfSMark Johnston desc_base, desc_limit, desc_access); 477967264cfSMark Johnston if (error) 478967264cfSMark Johnston goto done; 479967264cfSMark Johnston 480967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_FS, 481967264cfSMark Johnston desc_base, desc_limit, desc_access); 482967264cfSMark Johnston if (error) 483967264cfSMark Johnston goto done; 484967264cfSMark Johnston 485967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_GS, 486967264cfSMark Johnston desc_base, desc_limit, desc_access); 487967264cfSMark Johnston if (error) 488967264cfSMark Johnston goto done; 489967264cfSMark Johnston 490967264cfSMark Johnston sel = 0; 491967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_SS, sel)) != 0) 492967264cfSMark Johnston goto done; 493967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DS, sel)) != 0) 494967264cfSMark Johnston goto done; 495967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_ES, sel)) != 0) 496967264cfSMark Johnston goto done; 497967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_FS, sel)) != 0) 498967264cfSMark Johnston goto done; 499967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_GS, sel)) != 0) 500967264cfSMark Johnston goto done; 501967264cfSMark Johnston 502967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_EFER, zero)) != 0) 503967264cfSMark Johnston goto done; 504967264cfSMark Johnston 505967264cfSMark Johnston /* General purpose registers */ 506967264cfSMark Johnston rdx = 0xf00; 507967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RAX, zero)) != 0) 508967264cfSMark Johnston goto done; 509967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBX, zero)) != 0) 510967264cfSMark Johnston goto done; 511967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RCX, zero)) != 0) 512967264cfSMark Johnston goto done; 513967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDX, rdx)) != 0) 514967264cfSMark Johnston goto done; 515967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSI, zero)) != 0) 516967264cfSMark Johnston goto done; 517967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDI, zero)) != 0) 518967264cfSMark Johnston goto done; 519967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBP, zero)) != 0) 520967264cfSMark Johnston goto done; 521967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSP, zero)) != 0) 522967264cfSMark Johnston goto done; 523967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R8, zero)) != 0) 524967264cfSMark Johnston goto done; 525967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R9, zero)) != 0) 526967264cfSMark Johnston goto done; 527967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R10, zero)) != 0) 528967264cfSMark Johnston goto done; 529967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R11, zero)) != 0) 530967264cfSMark Johnston goto done; 531967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R12, zero)) != 0) 532967264cfSMark Johnston goto done; 533967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R13, zero)) != 0) 534967264cfSMark Johnston goto done; 535967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R14, zero)) != 0) 536967264cfSMark Johnston goto done; 537967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R15, zero)) != 0) 538967264cfSMark Johnston goto done; 539967264cfSMark Johnston 540967264cfSMark Johnston /* GDTR, IDTR */ 541967264cfSMark Johnston desc_base = 0; 542967264cfSMark Johnston desc_limit = 0xffff; 543967264cfSMark Johnston desc_access = 0; 544967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_GDTR, 545967264cfSMark Johnston desc_base, desc_limit, desc_access); 546967264cfSMark Johnston if (error != 0) 547967264cfSMark Johnston goto done; 548967264cfSMark Johnston 549967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_IDTR, 550967264cfSMark Johnston desc_base, desc_limit, desc_access); 551967264cfSMark Johnston if (error != 0) 552967264cfSMark Johnston goto done; 553967264cfSMark Johnston 554967264cfSMark Johnston /* TR */ 555967264cfSMark Johnston desc_base = 0; 556967264cfSMark Johnston desc_limit = 0xffff; 557967264cfSMark Johnston desc_access = 0x0000008b; 558967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_TR, 0, 0, desc_access); 559967264cfSMark Johnston if (error) 560967264cfSMark Johnston goto done; 561967264cfSMark Johnston 562967264cfSMark Johnston sel = 0; 563967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_TR, sel)) != 0) 564967264cfSMark Johnston goto done; 565967264cfSMark Johnston 566967264cfSMark Johnston /* LDTR */ 567967264cfSMark Johnston desc_base = 0; 568967264cfSMark Johnston desc_limit = 0xffff; 569967264cfSMark Johnston desc_access = 0x00000082; 570967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_LDTR, desc_base, 571967264cfSMark Johnston desc_limit, desc_access); 572967264cfSMark Johnston if (error) 573967264cfSMark Johnston goto done; 574967264cfSMark Johnston 575967264cfSMark Johnston sel = 0; 576967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_LDTR, 0)) != 0) 577967264cfSMark Johnston goto done; 578967264cfSMark Johnston 579967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR6, 580967264cfSMark Johnston 0xffff0ff0)) != 0) 581967264cfSMark Johnston goto done; 582967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR7, 0x400)) != 583967264cfSMark Johnston 0) 584967264cfSMark Johnston goto done; 585967264cfSMark Johnston 586967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_INTR_SHADOW, 587967264cfSMark Johnston zero)) != 0) 588967264cfSMark Johnston goto done; 589967264cfSMark Johnston 590967264cfSMark Johnston error = 0; 591967264cfSMark Johnston done: 592967264cfSMark Johnston return (error); 593967264cfSMark Johnston } 594