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 170*1855002dSMark Johnston vm_raise_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg, 171*1855002dSMark Johnston int bus __unused, int slot __unused, int func __unused) 172*1855002dSMark Johnston { 173*1855002dSMark Johnston return (vm_lapic_msi(ctx, addr, msg)); 174*1855002dSMark Johnston } 175*1855002dSMark Johnston 176*1855002dSMark Johnston int 177e4656e10SMark Johnston vm_apicid2vcpu(struct vmctx *ctx __unused, int apicid) 178e4656e10SMark Johnston { 179e4656e10SMark Johnston /* 180e4656e10SMark Johnston * The apic id associated with the 'vcpu' has the same numerical value 181e4656e10SMark Johnston * as the 'vcpu' itself. 182e4656e10SMark Johnston */ 183e4656e10SMark Johnston return (apicid); 184e4656e10SMark Johnston } 185e4656e10SMark Johnston 186e4656e10SMark Johnston int 187e4656e10SMark Johnston vm_ioapic_assert_irq(struct vmctx *ctx, int irq) 188e4656e10SMark Johnston { 189e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq; 190e4656e10SMark Johnston 191e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq)); 192e4656e10SMark Johnston ioapic_irq.irq = irq; 193e4656e10SMark Johnston 194e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq)); 195e4656e10SMark Johnston } 196e4656e10SMark Johnston 197e4656e10SMark Johnston int 198e4656e10SMark Johnston vm_ioapic_deassert_irq(struct vmctx *ctx, int irq) 199e4656e10SMark Johnston { 200e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq; 201e4656e10SMark Johnston 202e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq)); 203e4656e10SMark Johnston ioapic_irq.irq = irq; 204e4656e10SMark Johnston 205e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq)); 206e4656e10SMark Johnston } 207e4656e10SMark Johnston 208e4656e10SMark Johnston int 209e4656e10SMark Johnston vm_ioapic_pulse_irq(struct vmctx *ctx, int irq) 210e4656e10SMark Johnston { 211e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq; 212e4656e10SMark Johnston 213e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq)); 214e4656e10SMark Johnston ioapic_irq.irq = irq; 215e4656e10SMark Johnston 216e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq)); 217e4656e10SMark Johnston } 218e4656e10SMark Johnston 219e4656e10SMark Johnston int 220e4656e10SMark Johnston vm_ioapic_pincount(struct vmctx *ctx, int *pincount) 221e4656e10SMark Johnston { 222e4656e10SMark Johnston 223e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount)); 224e4656e10SMark Johnston } 225e4656e10SMark Johnston 226e4656e10SMark Johnston int 227e4656e10SMark Johnston vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) 228e4656e10SMark Johnston { 229e4656e10SMark Johnston struct vm_isa_irq isa_irq; 230e4656e10SMark Johnston 231e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq)); 232e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq; 233e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq; 234e4656e10SMark Johnston 235e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq)); 236e4656e10SMark Johnston } 237e4656e10SMark Johnston 238e4656e10SMark Johnston int 239e4656e10SMark Johnston vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) 240e4656e10SMark Johnston { 241e4656e10SMark Johnston struct vm_isa_irq isa_irq; 242e4656e10SMark Johnston 243e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq)); 244e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq; 245e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq; 246e4656e10SMark Johnston 247e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq)); 248e4656e10SMark Johnston } 249e4656e10SMark Johnston 250e4656e10SMark Johnston int 251e4656e10SMark Johnston vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) 252e4656e10SMark Johnston { 253e4656e10SMark Johnston struct vm_isa_irq isa_irq; 254e4656e10SMark Johnston 255e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq)); 256e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq; 257e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq; 258e4656e10SMark Johnston 259e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq)); 260e4656e10SMark Johnston } 261e4656e10SMark Johnston 262e4656e10SMark Johnston int 263e4656e10SMark Johnston vm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq, 264e4656e10SMark Johnston enum vm_intr_trigger trigger) 265e4656e10SMark Johnston { 266e4656e10SMark Johnston struct vm_isa_irq_trigger isa_irq_trigger; 267e4656e10SMark Johnston 268e4656e10SMark Johnston bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger)); 269e4656e10SMark Johnston isa_irq_trigger.atpic_irq = atpic_irq; 270e4656e10SMark Johnston isa_irq_trigger.trigger = trigger; 271e4656e10SMark Johnston 272e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger)); 273e4656e10SMark Johnston } 274e4656e10SMark Johnston 275e4656e10SMark Johnston int 276e4656e10SMark Johnston vm_inject_nmi(struct vcpu *vcpu) 277e4656e10SMark Johnston { 278e4656e10SMark Johnston struct vm_nmi vmnmi; 279e4656e10SMark Johnston 280e4656e10SMark Johnston bzero(&vmnmi, sizeof(vmnmi)); 281e4656e10SMark Johnston 282e4656e10SMark Johnston return (vcpu_ioctl(vcpu, VM_INJECT_NMI, &vmnmi)); 283e4656e10SMark Johnston } 284e4656e10SMark Johnston 2853170dcaeSMark Johnston int 2863170dcaeSMark Johnston vm_inject_exception(struct vcpu *vcpu, int vector, int errcode_valid, 2873170dcaeSMark Johnston uint32_t errcode, int restart_instruction) 2883170dcaeSMark Johnston { 2893170dcaeSMark Johnston struct vm_exception exc; 2903170dcaeSMark Johnston 2913170dcaeSMark Johnston exc.vector = vector; 2923170dcaeSMark Johnston exc.error_code = errcode; 2933170dcaeSMark Johnston exc.error_code_valid = errcode_valid; 2943170dcaeSMark Johnston exc.restart_instruction = restart_instruction; 2953170dcaeSMark Johnston 2963170dcaeSMark Johnston return (vcpu_ioctl(vcpu, VM_INJECT_EXCEPTION, &exc)); 2973170dcaeSMark Johnston } 2983170dcaeSMark Johnston 2993170dcaeSMark Johnston int 3003170dcaeSMark Johnston vm_readwrite_kernemu_device(struct vcpu *vcpu, vm_paddr_t gpa, 3013170dcaeSMark Johnston bool write, int size, uint64_t *value) 3023170dcaeSMark Johnston { 3033170dcaeSMark Johnston struct vm_readwrite_kernemu_device irp = { 3043170dcaeSMark Johnston .access_width = fls(size) - 1, 3053170dcaeSMark Johnston .gpa = gpa, 3063170dcaeSMark Johnston .value = write ? *value : ~0ul, 3073170dcaeSMark Johnston }; 3083170dcaeSMark Johnston long cmd = (write ? VM_SET_KERNEMU_DEV : VM_GET_KERNEMU_DEV); 3093170dcaeSMark Johnston int rc; 3103170dcaeSMark Johnston 3113170dcaeSMark Johnston rc = vcpu_ioctl(vcpu, cmd, &irp); 3123170dcaeSMark Johnston if (rc == 0 && !write) 3133170dcaeSMark Johnston *value = irp.value; 3143170dcaeSMark Johnston return (rc); 3153170dcaeSMark Johnston } 3163170dcaeSMark Johnston 3173170dcaeSMark Johnston int 3183170dcaeSMark Johnston vm_get_x2apic_state(struct vcpu *vcpu, enum x2apic_state *state) 3193170dcaeSMark Johnston { 3203170dcaeSMark Johnston int error; 3213170dcaeSMark Johnston struct vm_x2apic x2apic; 3223170dcaeSMark Johnston 3233170dcaeSMark Johnston bzero(&x2apic, sizeof(x2apic)); 3243170dcaeSMark Johnston 3253170dcaeSMark Johnston error = vcpu_ioctl(vcpu, VM_GET_X2APIC_STATE, &x2apic); 3263170dcaeSMark Johnston *state = x2apic.state; 3273170dcaeSMark Johnston return (error); 3283170dcaeSMark Johnston } 3293170dcaeSMark Johnston 3303170dcaeSMark Johnston int 3313170dcaeSMark Johnston vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state) 3323170dcaeSMark Johnston { 3333170dcaeSMark Johnston int error; 3343170dcaeSMark Johnston struct vm_x2apic x2apic; 3353170dcaeSMark Johnston 3363170dcaeSMark Johnston bzero(&x2apic, sizeof(x2apic)); 3373170dcaeSMark Johnston x2apic.state = state; 3383170dcaeSMark Johnston 3393170dcaeSMark Johnston error = vcpu_ioctl(vcpu, VM_SET_X2APIC_STATE, &x2apic); 3403170dcaeSMark Johnston 3413170dcaeSMark Johnston return (error); 3423170dcaeSMark Johnston } 3433170dcaeSMark Johnston 3443170dcaeSMark Johnston int 3453170dcaeSMark Johnston vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities) 3463170dcaeSMark Johnston { 3473170dcaeSMark Johnston int error; 3483170dcaeSMark Johnston struct vm_hpet_cap cap; 3493170dcaeSMark Johnston 3503170dcaeSMark Johnston bzero(&cap, sizeof(struct vm_hpet_cap)); 3513170dcaeSMark Johnston error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap); 3523170dcaeSMark Johnston if (capabilities != NULL) 3533170dcaeSMark Johnston *capabilities = cap.capabilities; 3543170dcaeSMark Johnston return (error); 3553170dcaeSMark Johnston } 3563170dcaeSMark Johnston 3573170dcaeSMark Johnston int 3583170dcaeSMark Johnston vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value) 3593170dcaeSMark Johnston { 3603170dcaeSMark Johnston struct vm_rtc_data rtcdata; 3613170dcaeSMark Johnston int error; 3623170dcaeSMark Johnston 3633170dcaeSMark Johnston bzero(&rtcdata, sizeof(struct vm_rtc_data)); 3643170dcaeSMark Johnston rtcdata.offset = offset; 3653170dcaeSMark Johnston rtcdata.value = value; 3663170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata); 3673170dcaeSMark Johnston return (error); 3683170dcaeSMark Johnston } 3693170dcaeSMark Johnston 3703170dcaeSMark Johnston int 3713170dcaeSMark Johnston vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval) 3723170dcaeSMark Johnston { 3733170dcaeSMark Johnston struct vm_rtc_data rtcdata; 3743170dcaeSMark Johnston int error; 3753170dcaeSMark Johnston 3763170dcaeSMark Johnston bzero(&rtcdata, sizeof(struct vm_rtc_data)); 3773170dcaeSMark Johnston rtcdata.offset = offset; 3783170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata); 3793170dcaeSMark Johnston if (error == 0) 3803170dcaeSMark Johnston *retval = rtcdata.value; 3813170dcaeSMark Johnston return (error); 3823170dcaeSMark Johnston } 3833170dcaeSMark Johnston 3843170dcaeSMark Johnston int 3853170dcaeSMark Johnston vm_rtc_settime(struct vmctx *ctx, time_t secs) 3863170dcaeSMark Johnston { 3873170dcaeSMark Johnston struct vm_rtc_time rtctime; 3883170dcaeSMark Johnston int error; 3893170dcaeSMark Johnston 3903170dcaeSMark Johnston bzero(&rtctime, sizeof(struct vm_rtc_time)); 3913170dcaeSMark Johnston rtctime.secs = secs; 3923170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime); 3933170dcaeSMark Johnston return (error); 3943170dcaeSMark Johnston } 3953170dcaeSMark Johnston 3963170dcaeSMark Johnston int 3973170dcaeSMark Johnston vm_rtc_gettime(struct vmctx *ctx, time_t *secs) 3983170dcaeSMark Johnston { 3993170dcaeSMark Johnston struct vm_rtc_time rtctime; 4003170dcaeSMark Johnston int error; 4013170dcaeSMark Johnston 4023170dcaeSMark Johnston bzero(&rtctime, sizeof(struct vm_rtc_time)); 4033170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime); 4043170dcaeSMark Johnston if (error == 0) 4053170dcaeSMark Johnston *secs = rtctime.secs; 4063170dcaeSMark Johnston return (error); 4073170dcaeSMark Johnston } 4083170dcaeSMark Johnston 409967264cfSMark Johnston /* 410967264cfSMark Johnston * From Intel Vol 3a: 411967264cfSMark Johnston * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT 412967264cfSMark Johnston */ 413967264cfSMark Johnston int 414967264cfSMark Johnston vcpu_reset(struct vcpu *vcpu) 415967264cfSMark Johnston { 416967264cfSMark Johnston int error; 417967264cfSMark Johnston uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx; 418967264cfSMark Johnston uint32_t desc_access, desc_limit; 419967264cfSMark Johnston uint16_t sel; 420967264cfSMark Johnston 421967264cfSMark Johnston zero = 0; 422967264cfSMark Johnston 423967264cfSMark Johnston rflags = 0x2; 424967264cfSMark Johnston error = vm_set_register(vcpu, VM_REG_GUEST_RFLAGS, rflags); 425967264cfSMark Johnston if (error) 426967264cfSMark Johnston goto done; 427967264cfSMark Johnston 428967264cfSMark Johnston rip = 0xfff0; 429967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RIP, rip)) != 0) 430967264cfSMark Johnston goto done; 431967264cfSMark Johnston 432967264cfSMark Johnston /* 433967264cfSMark Johnston * According to Intels Software Developer Manual CR0 should be 434967264cfSMark Johnston * initialized with CR0_ET | CR0_NW | CR0_CD but that crashes some 435967264cfSMark Johnston * guests like Windows. 436967264cfSMark Johnston */ 437967264cfSMark Johnston cr0 = CR0_NE; 438967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR0, cr0)) != 0) 439967264cfSMark Johnston goto done; 440967264cfSMark Johnston 441967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR2, zero)) != 0) 442967264cfSMark Johnston goto done; 443967264cfSMark Johnston 444967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR3, zero)) != 0) 445967264cfSMark Johnston goto done; 446967264cfSMark Johnston 447967264cfSMark Johnston cr4 = 0; 448967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR4, cr4)) != 0) 449967264cfSMark Johnston goto done; 450967264cfSMark Johnston 451967264cfSMark Johnston /* 452967264cfSMark Johnston * CS: present, r/w, accessed, 16-bit, byte granularity, usable 453967264cfSMark Johnston */ 454967264cfSMark Johnston desc_base = 0xffff0000; 455967264cfSMark Johnston desc_limit = 0xffff; 456967264cfSMark Johnston desc_access = 0x0093; 457967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_CS, 458967264cfSMark Johnston desc_base, desc_limit, desc_access); 459967264cfSMark Johnston if (error) 460967264cfSMark Johnston goto done; 461967264cfSMark Johnston 462967264cfSMark Johnston sel = 0xf000; 463967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CS, sel)) != 0) 464967264cfSMark Johnston goto done; 465967264cfSMark Johnston 466967264cfSMark Johnston /* 467967264cfSMark Johnston * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity 468967264cfSMark Johnston */ 469967264cfSMark Johnston desc_base = 0; 470967264cfSMark Johnston desc_limit = 0xffff; 471967264cfSMark Johnston desc_access = 0x0093; 472967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_SS, 473967264cfSMark Johnston desc_base, desc_limit, desc_access); 474967264cfSMark Johnston if (error) 475967264cfSMark Johnston goto done; 476967264cfSMark Johnston 477967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_DS, 478967264cfSMark Johnston desc_base, desc_limit, desc_access); 479967264cfSMark Johnston if (error) 480967264cfSMark Johnston goto done; 481967264cfSMark Johnston 482967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_ES, 483967264cfSMark Johnston desc_base, desc_limit, desc_access); 484967264cfSMark Johnston if (error) 485967264cfSMark Johnston goto done; 486967264cfSMark Johnston 487967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_FS, 488967264cfSMark Johnston desc_base, desc_limit, desc_access); 489967264cfSMark Johnston if (error) 490967264cfSMark Johnston goto done; 491967264cfSMark Johnston 492967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_GS, 493967264cfSMark Johnston desc_base, desc_limit, desc_access); 494967264cfSMark Johnston if (error) 495967264cfSMark Johnston goto done; 496967264cfSMark Johnston 497967264cfSMark Johnston sel = 0; 498967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_SS, sel)) != 0) 499967264cfSMark Johnston goto done; 500967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DS, sel)) != 0) 501967264cfSMark Johnston goto done; 502967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_ES, sel)) != 0) 503967264cfSMark Johnston goto done; 504967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_FS, sel)) != 0) 505967264cfSMark Johnston goto done; 506967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_GS, sel)) != 0) 507967264cfSMark Johnston goto done; 508967264cfSMark Johnston 509967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_EFER, zero)) != 0) 510967264cfSMark Johnston goto done; 511967264cfSMark Johnston 512967264cfSMark Johnston /* General purpose registers */ 513967264cfSMark Johnston rdx = 0xf00; 514967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RAX, zero)) != 0) 515967264cfSMark Johnston goto done; 516967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBX, zero)) != 0) 517967264cfSMark Johnston goto done; 518967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RCX, zero)) != 0) 519967264cfSMark Johnston goto done; 520967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDX, rdx)) != 0) 521967264cfSMark Johnston goto done; 522967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSI, zero)) != 0) 523967264cfSMark Johnston goto done; 524967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDI, zero)) != 0) 525967264cfSMark Johnston goto done; 526967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBP, zero)) != 0) 527967264cfSMark Johnston goto done; 528967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSP, zero)) != 0) 529967264cfSMark Johnston goto done; 530967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R8, zero)) != 0) 531967264cfSMark Johnston goto done; 532967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R9, zero)) != 0) 533967264cfSMark Johnston goto done; 534967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R10, zero)) != 0) 535967264cfSMark Johnston goto done; 536967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R11, zero)) != 0) 537967264cfSMark Johnston goto done; 538967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R12, zero)) != 0) 539967264cfSMark Johnston goto done; 540967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R13, zero)) != 0) 541967264cfSMark Johnston goto done; 542967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R14, zero)) != 0) 543967264cfSMark Johnston goto done; 544967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R15, zero)) != 0) 545967264cfSMark Johnston goto done; 546967264cfSMark Johnston 547967264cfSMark Johnston /* GDTR, IDTR */ 548967264cfSMark Johnston desc_base = 0; 549967264cfSMark Johnston desc_limit = 0xffff; 550967264cfSMark Johnston desc_access = 0; 551967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_GDTR, 552967264cfSMark Johnston desc_base, desc_limit, desc_access); 553967264cfSMark Johnston if (error != 0) 554967264cfSMark Johnston goto done; 555967264cfSMark Johnston 556967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_IDTR, 557967264cfSMark Johnston desc_base, desc_limit, desc_access); 558967264cfSMark Johnston if (error != 0) 559967264cfSMark Johnston goto done; 560967264cfSMark Johnston 561967264cfSMark Johnston /* TR */ 562967264cfSMark Johnston desc_base = 0; 563967264cfSMark Johnston desc_limit = 0xffff; 564967264cfSMark Johnston desc_access = 0x0000008b; 565967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_TR, 0, 0, desc_access); 566967264cfSMark Johnston if (error) 567967264cfSMark Johnston goto done; 568967264cfSMark Johnston 569967264cfSMark Johnston sel = 0; 570967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_TR, sel)) != 0) 571967264cfSMark Johnston goto done; 572967264cfSMark Johnston 573967264cfSMark Johnston /* LDTR */ 574967264cfSMark Johnston desc_base = 0; 575967264cfSMark Johnston desc_limit = 0xffff; 576967264cfSMark Johnston desc_access = 0x00000082; 577967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_LDTR, desc_base, 578967264cfSMark Johnston desc_limit, desc_access); 579967264cfSMark Johnston if (error) 580967264cfSMark Johnston goto done; 581967264cfSMark Johnston 582967264cfSMark Johnston sel = 0; 583967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_LDTR, 0)) != 0) 584967264cfSMark Johnston goto done; 585967264cfSMark Johnston 586967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR6, 587967264cfSMark Johnston 0xffff0ff0)) != 0) 588967264cfSMark Johnston goto done; 589967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR7, 0x400)) != 590967264cfSMark Johnston 0) 591967264cfSMark Johnston goto done; 592967264cfSMark Johnston 593967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_INTR_SHADOW, 594967264cfSMark Johnston zero)) != 0) 595967264cfSMark Johnston goto done; 596967264cfSMark Johnston 597967264cfSMark Johnston error = 0; 598967264cfSMark Johnston done: 599967264cfSMark Johnston return (error); 600967264cfSMark Johnston } 601